fix: descending ladder triggers nav fall recovery
nav: various fixes to player avoiding build: fix cmake postfix when building as part of cs16-client Co-Authored-By: Max <161382234+dyspose@users.noreply.github.com>
This commit is contained in:
parent
ecb1f20303
commit
c322e36d9b
6 changed files with 105 additions and 89 deletions
|
|
@ -145,6 +145,10 @@ target_include_directories(${PROJECT_NAME} PRIVATE
|
|||
"ext/linkage"
|
||||
)
|
||||
|
||||
if(COMMAND set_target_postfix)
|
||||
set_target_postfix(${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
install(TARGETS ${PROJECT_NAME}
|
||||
DESTINATION "${GAME_DIR}/${SERVER_INSTALL_DIR}/"
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
|
||||
|
|
|
|||
|
|
@ -365,6 +365,7 @@ private:
|
|||
CountdownTimer m_forgetLastVictimTimer {}; // time to forget last victim position ?
|
||||
CountdownTimer m_approachingLadderTimer {}; // bot is approaching ladder
|
||||
CountdownTimer m_lostReachableNodeTimer {}; // bot's issuing next node, probably he's lost
|
||||
CountdownTimer m_fixFallTimer {}; // timer we're fixed fall last time
|
||||
|
||||
private:
|
||||
int pickBestWeapon (Array <int> &vec, int moneySave);
|
||||
|
|
|
|||
|
|
@ -2942,20 +2942,22 @@ void Bot::checkParachute () {
|
|||
void Bot::frame () {
|
||||
pev->flags |= FL_CLIENT | FL_FAKECLIENT; // restore fake client bit, just in case
|
||||
|
||||
if (m_thinkDelay.time <= game.time ()) {
|
||||
const auto timestamp = game.time ();
|
||||
|
||||
if (m_thinkDelay.time <= timestamp) {
|
||||
update ();
|
||||
|
||||
// delay next execution for thinking
|
||||
m_thinkDelay.time = game.time () + m_thinkDelay.interval;
|
||||
m_thinkDelay.time = timestamp + m_thinkDelay.interval;
|
||||
}
|
||||
|
||||
// run bot command on twice speed
|
||||
if (m_commandDelay.time <= game.time ()) {
|
||||
if (m_commandDelay.time <= timestamp) {
|
||||
runMovement ();
|
||||
m_commandDelay.time = game.time () + m_commandDelay.interval;
|
||||
}
|
||||
m_commandDelay.time = timestamp + m_commandDelay.interval;
|
||||
}
|
||||
|
||||
if (m_slowFrameTimestamp > game.time ()) {
|
||||
if (m_slowFrameTimestamp > timestamp) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -3162,7 +3164,7 @@ void Bot::checkSpawnConditions () {
|
|||
|
||||
// switch to knife if time to do this
|
||||
if (m_checkKnifeSwitch && m_buyingFinished && m_spawnTime + rg (5.0f, 7.5f) < game.time ()) {
|
||||
if (rg (1, 100) < 30 && cv_spraypaints) {
|
||||
if (rg (1, 100) < 30 && cv_spraypaints && pev->groundentity == game.getStartEntity ()) {
|
||||
startTask (Task::Spraypaint, TaskPri::Spraypaint, kInvalidNodeIndex, game.time () + 1.0f, false);
|
||||
}
|
||||
|
||||
|
|
@ -3249,7 +3251,7 @@ void Bot::logic () {
|
|||
|
||||
// save current position as previous
|
||||
m_prevOrigin = pev->origin;
|
||||
m_prevTime = game.time () + 0.2f;
|
||||
m_prevTime = game.time () + (0.2f - m_frameInterval * 2.0f);
|
||||
}
|
||||
|
||||
// if there's some radio message to respond, check it
|
||||
|
|
@ -3920,7 +3922,7 @@ uint8_t Bot::computeMsec () {
|
|||
const Vector &Bot::getRpmAngles () {
|
||||
// get angles to pass to run player move function
|
||||
|
||||
if (!m_approachingLadderTimer.elapsed () || getCurrentTaskId () == Task::Attack) {
|
||||
if (m_isStuck || !m_approachingLadderTimer.elapsed () || getCurrentTaskId () == Task::Attack) {
|
||||
return pev->v_angle;
|
||||
}
|
||||
return m_moveAngles;
|
||||
|
|
|
|||
|
|
@ -1571,6 +1571,7 @@ void Bot::newRound () {
|
|||
m_approachingLadderTimer.invalidate ();
|
||||
m_forgetLastVictimTimer.invalidate ();
|
||||
m_lostReachableNodeTimer.invalidate ();
|
||||
m_fixFallTimer.invalidate ();
|
||||
|
||||
for (auto &timer : m_chatterTimes) {
|
||||
timer = kMaxChatterRepeatInterval;
|
||||
|
|
|
|||
161
src/navigate.cpp
161
src/navigate.cpp
|
|
@ -577,7 +577,10 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
const auto tid = getCurrentTaskId ();
|
||||
|
||||
// standing still, no need to check?
|
||||
if (m_lastCollTime < game.time () && tid != Task::Attack && tid != Task::Camp) {
|
||||
if ((m_moveSpeed >= 10 || m_strafeSpeed >= 10)
|
||||
&& m_lastCollTime < game.time ()
|
||||
&& tid != Task::Attack
|
||||
&& tid != Task::Camp) {
|
||||
// didn't we move enough previously?
|
||||
if (movedDistance < kMinMovedDistance && m_prevSpeed > 20.0f) {
|
||||
m_prevTime = game.time (); // then consider being stuck
|
||||
|
|
@ -653,78 +656,11 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
Vector src {}, dst {};
|
||||
|
||||
// first 4 entries hold the possible collision states
|
||||
state[i++] = CollisionState::Jump;
|
||||
state[i++] = CollisionState::StrafeLeft;
|
||||
state[i++] = CollisionState::StrafeRight;
|
||||
state[i++] = CollisionState::Jump;
|
||||
state[i++] = CollisionState::Duck;
|
||||
|
||||
if (bits & CollisionProbe::Strafe) {
|
||||
state[i] = 0;
|
||||
state[i + 1] = 0;
|
||||
|
||||
// to start strafing, we have to first figure out if the target is on the left side or right side
|
||||
Vector right {}, forward {};
|
||||
m_moveAngles.angleVectors (&forward, &right, nullptr);
|
||||
|
||||
const Vector &dirToPoint = (pev->origin - m_destOrigin).normalize2d_apx ();
|
||||
const Vector &rightSide = right.normalize2d_apx ();
|
||||
|
||||
bool dirRight = false;
|
||||
bool dirLeft = false;
|
||||
bool blockedLeft = false;
|
||||
bool blockedRight = false;
|
||||
|
||||
if ((dirToPoint | rightSide) > 0.0f) {
|
||||
dirRight = true;
|
||||
}
|
||||
else {
|
||||
dirLeft = true;
|
||||
}
|
||||
const auto &testDir = m_moveSpeed > 0.0f ? forward : -forward;
|
||||
constexpr float kBlockDistance = 52.0f;
|
||||
|
||||
// now check which side is blocked
|
||||
src = pev->origin + right * kBlockDistance;
|
||||
dst = src + testDir * kBlockDistance;
|
||||
|
||||
game.testHull (src, dst, TraceIgnore::Monsters, head_hull, ent (), &tr);
|
||||
|
||||
if (!cr::fequal (tr.flFraction, 1.0f)) {
|
||||
blockedRight = true;
|
||||
}
|
||||
src = pev->origin - right * kBlockDistance;
|
||||
dst = src + testDir * kBlockDistance;
|
||||
|
||||
game.testHull (src, dst, TraceIgnore::Monsters, head_hull, ent (), &tr);
|
||||
|
||||
if (!cr::fequal (tr.flFraction, 1.0f)) {
|
||||
blockedLeft = true;
|
||||
}
|
||||
|
||||
if (dirLeft) {
|
||||
state[i] += 5;
|
||||
}
|
||||
else {
|
||||
state[i] -= 5;
|
||||
}
|
||||
|
||||
if (blockedLeft) {
|
||||
state[i] -= 5;
|
||||
}
|
||||
++i;
|
||||
|
||||
if (dirRight) {
|
||||
state[i] += 5;
|
||||
}
|
||||
else {
|
||||
state[i] -= 5;
|
||||
}
|
||||
|
||||
if (blockedRight) {
|
||||
state[i] -= 5;
|
||||
}
|
||||
}
|
||||
|
||||
// now weight all possible states
|
||||
if (bits & CollisionProbe::Jump) {
|
||||
state[i] = 0;
|
||||
|
|
@ -774,6 +710,74 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
}
|
||||
++i;
|
||||
|
||||
|
||||
if (bits & CollisionProbe::Strafe) {
|
||||
state[i] = 0;
|
||||
state[i + 1] = 0;
|
||||
|
||||
// to start strafing, we have to first figure out if the target is on the left side or right side
|
||||
Vector right {}, forward {};
|
||||
m_moveAngles.angleVectors (&forward, &right, nullptr);
|
||||
|
||||
const Vector &dirToPoint = (pev->origin - m_destOrigin).normalize2d_apx ();
|
||||
const Vector &rightSide = right.normalize2d_apx ();
|
||||
|
||||
bool dirRight = false;
|
||||
bool dirLeft = false;
|
||||
bool blockedLeft = false;
|
||||
bool blockedRight = false;
|
||||
|
||||
if ((dirToPoint | rightSide) > 0.0f) {
|
||||
dirRight = true;
|
||||
}
|
||||
else {
|
||||
dirLeft = true;
|
||||
}
|
||||
const auto &testDir = m_moveSpeed > 0.0f ? forward : -forward;
|
||||
constexpr float kBlockDistance = 32.0f;
|
||||
|
||||
// now check which side is blocked
|
||||
src = pev->origin + right * kBlockDistance;
|
||||
dst = src + testDir * kBlockDistance;
|
||||
|
||||
game.testHull (src, dst, TraceIgnore::Monsters, head_hull, ent (), &tr);
|
||||
|
||||
if (!cr::fequal (tr.flFraction, 1.0f)) {
|
||||
blockedRight = true;
|
||||
}
|
||||
src = pev->origin - right * kBlockDistance;
|
||||
dst = src + testDir * kBlockDistance;
|
||||
|
||||
game.testHull (src, dst, TraceIgnore::Monsters, head_hull, ent (), &tr);
|
||||
|
||||
if (!cr::fequal (tr.flFraction, 1.0f)) {
|
||||
blockedLeft = true;
|
||||
}
|
||||
|
||||
if (dirLeft) {
|
||||
state[i] += 5;
|
||||
}
|
||||
else {
|
||||
state[i] -= 5;
|
||||
}
|
||||
|
||||
if (blockedLeft) {
|
||||
state[i] -= 5;
|
||||
}
|
||||
++i;
|
||||
|
||||
if (dirRight) {
|
||||
state[i] += 5;
|
||||
}
|
||||
else {
|
||||
state[i] -= 5;
|
||||
}
|
||||
|
||||
if (blockedRight) {
|
||||
state[i] -= 5;
|
||||
}
|
||||
}
|
||||
|
||||
if (bits & CollisionProbe::Duck) {
|
||||
state[i] = 0;
|
||||
|
||||
|
|
@ -881,13 +885,13 @@ void Bot::checkFall () {
|
|||
}
|
||||
}
|
||||
else if (!isOnLadder () && !isInWater ()) {
|
||||
if (!m_checkFallPoint[0].empty () || !m_checkFallPoint[1].empty ()) {
|
||||
if (!m_checkFallPoint[0].empty () && !m_checkFallPoint[1].empty ()) {
|
||||
m_checkFall = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_checkFall || !isOnFloor ()) {
|
||||
if (!m_checkFall || !isOnFloor () || !m_fixFallTimer.elapsed ()) {
|
||||
return;
|
||||
}
|
||||
m_checkFall = false;
|
||||
|
|
@ -897,22 +901,25 @@ void Bot::checkFall () {
|
|||
const float nowDistanceSq = pev->origin.distanceSq (m_checkFallPoint[1]);
|
||||
|
||||
if (nowDistanceSq > baseDistanceSq
|
||||
&& (nowDistanceSq > baseDistanceSq * 1.2f || nowDistanceSq > baseDistanceSq + 200.0f)
|
||||
&& baseDistanceSq >= cr::sqrf (80.0f) && nowDistanceSq >= cr::sqrf (100.0f)) {
|
||||
&& (nowDistanceSq > baseDistanceSq * 1.8f || nowDistanceSq > baseDistanceSq + 260.0f)
|
||||
&& baseDistanceSq >= cr::sqrf (124.0f) && nowDistanceSq >= cr::sqrf (146.0f)) {
|
||||
fixFall = true;
|
||||
}
|
||||
else if (m_checkFallPoint[1].z > pev->origin.z + 128.0f || m_checkFallPoint[0].z > pev->origin.z + 128.0f) {
|
||||
else if (cr::abs (m_checkFallPoint[1].z) > cr::abs (pev->origin.z) + 138.0f
|
||||
|| cr::abs (m_checkFallPoint[0].z) > cr::abs (pev->origin.z) + 138.0f) {
|
||||
fixFall = true;
|
||||
}
|
||||
else if (m_currentNodeIndex != kInvalidNodeIndex
|
||||
&& nowDistanceSq > cr::sqrf (16.0f)
|
||||
&& m_checkFallPoint[1].z > pev->origin.z + 62.0f) {
|
||||
&& nowDistanceSq > cr::sqrf (32.0f)
|
||||
&& cr::abs (m_checkFallPoint[1].z) > cr::abs (pev->origin.z) + 72.0f) {
|
||||
fixFall = true;
|
||||
}
|
||||
|
||||
if (fixFall) {
|
||||
m_currentNodeIndex = kInvalidNodeIndex;
|
||||
findValidNode ();
|
||||
|
||||
m_fixFallTimer.start (1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1119,7 +1126,7 @@ bool Bot::updateNavigation () {
|
|||
if (!isOnLadder ()) {
|
||||
pev->button &= ~IN_DUCK;
|
||||
}
|
||||
m_approachingLadderTimer.start (m_frameInterval * 4.0f);
|
||||
m_approachingLadderTimer.start (m_frameInterval * 6.0f);
|
||||
}
|
||||
|
||||
if (!isOnLadder () && isOnFloor () && !isDucking ()) {
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ void Bot::normal_ () {
|
|||
&& m_reloadState == Reload::None
|
||||
&& m_timeLogoSpray < game.time ()
|
||||
&& cv_spraypaints
|
||||
&& pev->groundentity == game.getStartEntity ()
|
||||
&& m_moveSpeed >= getShiftSpeed ()
|
||||
&& game.isNullEntity (m_pickupItem)) {
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue