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"
|
"ext/linkage"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(COMMAND set_target_postfix)
|
||||||
|
set_target_postfix(${PROJECT_NAME})
|
||||||
|
endif()
|
||||||
|
|
||||||
install(TARGETS ${PROJECT_NAME}
|
install(TARGETS ${PROJECT_NAME}
|
||||||
DESTINATION "${GAME_DIR}/${SERVER_INSTALL_DIR}/"
|
DESTINATION "${GAME_DIR}/${SERVER_INSTALL_DIR}/"
|
||||||
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
|
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
|
||||||
|
|
|
||||||
|
|
@ -365,6 +365,7 @@ private:
|
||||||
CountdownTimer m_forgetLastVictimTimer {}; // time to forget last victim position ?
|
CountdownTimer m_forgetLastVictimTimer {}; // time to forget last victim position ?
|
||||||
CountdownTimer m_approachingLadderTimer {}; // bot is approaching ladder
|
CountdownTimer m_approachingLadderTimer {}; // bot is approaching ladder
|
||||||
CountdownTimer m_lostReachableNodeTimer {}; // bot's issuing next node, probably he's lost
|
CountdownTimer m_lostReachableNodeTimer {}; // bot's issuing next node, probably he's lost
|
||||||
|
CountdownTimer m_fixFallTimer {}; // timer we're fixed fall last time
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int pickBestWeapon (Array <int> &vec, int moneySave);
|
int pickBestWeapon (Array <int> &vec, int moneySave);
|
||||||
|
|
|
||||||
|
|
@ -2942,20 +2942,22 @@ void Bot::checkParachute () {
|
||||||
void Bot::frame () {
|
void Bot::frame () {
|
||||||
pev->flags |= FL_CLIENT | FL_FAKECLIENT; // restore fake client bit, just in case
|
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 ();
|
update ();
|
||||||
|
|
||||||
// delay next execution for thinking
|
// 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
|
// run bot command on twice speed
|
||||||
if (m_commandDelay.time <= game.time ()) {
|
if (m_commandDelay.time <= timestamp) {
|
||||||
runMovement ();
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3162,7 +3164,7 @@ void Bot::checkSpawnConditions () {
|
||||||
|
|
||||||
// switch to knife if time to do this
|
// switch to knife if time to do this
|
||||||
if (m_checkKnifeSwitch && m_buyingFinished && m_spawnTime + rg (5.0f, 7.5f) < game.time ()) {
|
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);
|
startTask (Task::Spraypaint, TaskPri::Spraypaint, kInvalidNodeIndex, game.time () + 1.0f, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3249,7 +3251,7 @@ void Bot::logic () {
|
||||||
|
|
||||||
// save current position as previous
|
// save current position as previous
|
||||||
m_prevOrigin = pev->origin;
|
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
|
// if there's some radio message to respond, check it
|
||||||
|
|
@ -3920,7 +3922,7 @@ uint8_t Bot::computeMsec () {
|
||||||
const Vector &Bot::getRpmAngles () {
|
const Vector &Bot::getRpmAngles () {
|
||||||
// get angles to pass to run player move function
|
// 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 pev->v_angle;
|
||||||
}
|
}
|
||||||
return m_moveAngles;
|
return m_moveAngles;
|
||||||
|
|
|
||||||
|
|
@ -1571,6 +1571,7 @@ void Bot::newRound () {
|
||||||
m_approachingLadderTimer.invalidate ();
|
m_approachingLadderTimer.invalidate ();
|
||||||
m_forgetLastVictimTimer.invalidate ();
|
m_forgetLastVictimTimer.invalidate ();
|
||||||
m_lostReachableNodeTimer.invalidate ();
|
m_lostReachableNodeTimer.invalidate ();
|
||||||
|
m_fixFallTimer.invalidate ();
|
||||||
|
|
||||||
for (auto &timer : m_chatterTimes) {
|
for (auto &timer : m_chatterTimes) {
|
||||||
timer = kMaxChatterRepeatInterval;
|
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 ();
|
const auto tid = getCurrentTaskId ();
|
||||||
|
|
||||||
// standing still, no need to check?
|
// 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?
|
// didn't we move enough previously?
|
||||||
if (movedDistance < kMinMovedDistance && m_prevSpeed > 20.0f) {
|
if (movedDistance < kMinMovedDistance && m_prevSpeed > 20.0f) {
|
||||||
m_prevTime = game.time (); // then consider being stuck
|
m_prevTime = game.time (); // then consider being stuck
|
||||||
|
|
@ -653,78 +656,11 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
||||||
Vector src {}, dst {};
|
Vector src {}, dst {};
|
||||||
|
|
||||||
// first 4 entries hold the possible collision states
|
// first 4 entries hold the possible collision states
|
||||||
|
state[i++] = CollisionState::Jump;
|
||||||
state[i++] = CollisionState::StrafeLeft;
|
state[i++] = CollisionState::StrafeLeft;
|
||||||
state[i++] = CollisionState::StrafeRight;
|
state[i++] = CollisionState::StrafeRight;
|
||||||
state[i++] = CollisionState::Jump;
|
|
||||||
state[i++] = CollisionState::Duck;
|
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
|
// now weight all possible states
|
||||||
if (bits & CollisionProbe::Jump) {
|
if (bits & CollisionProbe::Jump) {
|
||||||
state[i] = 0;
|
state[i] = 0;
|
||||||
|
|
@ -774,6 +710,74 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
||||||
}
|
}
|
||||||
++i;
|
++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) {
|
if (bits & CollisionProbe::Duck) {
|
||||||
state[i] = 0;
|
state[i] = 0;
|
||||||
|
|
||||||
|
|
@ -881,13 +885,13 @@ void Bot::checkFall () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!isOnLadder () && !isInWater ()) {
|
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;
|
m_checkFall = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_checkFall || !isOnFloor ()) {
|
if (!m_checkFall || !isOnFloor () || !m_fixFallTimer.elapsed ()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_checkFall = false;
|
m_checkFall = false;
|
||||||
|
|
@ -897,22 +901,25 @@ void Bot::checkFall () {
|
||||||
const float nowDistanceSq = pev->origin.distanceSq (m_checkFallPoint[1]);
|
const float nowDistanceSq = pev->origin.distanceSq (m_checkFallPoint[1]);
|
||||||
|
|
||||||
if (nowDistanceSq > baseDistanceSq
|
if (nowDistanceSq > baseDistanceSq
|
||||||
&& (nowDistanceSq > baseDistanceSq * 1.2f || nowDistanceSq > baseDistanceSq + 200.0f)
|
&& (nowDistanceSq > baseDistanceSq * 1.8f || nowDistanceSq > baseDistanceSq + 260.0f)
|
||||||
&& baseDistanceSq >= cr::sqrf (80.0f) && nowDistanceSq >= cr::sqrf (100.0f)) {
|
&& baseDistanceSq >= cr::sqrf (124.0f) && nowDistanceSq >= cr::sqrf (146.0f)) {
|
||||||
fixFall = true;
|
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;
|
fixFall = true;
|
||||||
}
|
}
|
||||||
else if (m_currentNodeIndex != kInvalidNodeIndex
|
else if (m_currentNodeIndex != kInvalidNodeIndex
|
||||||
&& nowDistanceSq > cr::sqrf (16.0f)
|
&& nowDistanceSq > cr::sqrf (32.0f)
|
||||||
&& m_checkFallPoint[1].z > pev->origin.z + 62.0f) {
|
&& cr::abs (m_checkFallPoint[1].z) > cr::abs (pev->origin.z) + 72.0f) {
|
||||||
fixFall = true;
|
fixFall = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fixFall) {
|
if (fixFall) {
|
||||||
m_currentNodeIndex = kInvalidNodeIndex;
|
m_currentNodeIndex = kInvalidNodeIndex;
|
||||||
findValidNode ();
|
findValidNode ();
|
||||||
|
|
||||||
|
m_fixFallTimer.start (1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1119,7 +1126,7 @@ bool Bot::updateNavigation () {
|
||||||
if (!isOnLadder ()) {
|
if (!isOnLadder ()) {
|
||||||
pev->button &= ~IN_DUCK;
|
pev->button &= ~IN_DUCK;
|
||||||
}
|
}
|
||||||
m_approachingLadderTimer.start (m_frameInterval * 4.0f);
|
m_approachingLadderTimer.start (m_frameInterval * 6.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isOnLadder () && isOnFloor () && !isDucking ()) {
|
if (!isOnLadder () && isOnFloor () && !isDucking ()) {
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,7 @@ void Bot::normal_ () {
|
||||||
&& m_reloadState == Reload::None
|
&& m_reloadState == Reload::None
|
||||||
&& m_timeLogoSpray < game.time ()
|
&& m_timeLogoSpray < game.time ()
|
||||||
&& cv_spraypaints
|
&& cv_spraypaints
|
||||||
|
&& pev->groundentity == game.getStartEntity ()
|
||||||
&& m_moveSpeed >= getShiftSpeed ()
|
&& m_moveSpeed >= getShiftSpeed ()
|
||||||
&& game.isNullEntity (m_pickupItem)) {
|
&& game.isNullEntity (m_pickupItem)) {
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue