fix: hide chatter icon even for players that changed team

fix: mark bot as finished buying on csdm spawn (ref #734)
fix: do not start any map analysis if already analyzing (ref #726)
combat: improved head/body aiming (ref #734)
This commit is contained in:
jeefo 2025-09-10 15:32:40 +03:00
commit 6604145481
No known key found for this signature in database
GPG key ID: D696786B81B667C8
6 changed files with 53 additions and 19 deletions

View file

@ -520,7 +520,7 @@ private:
void setPathOrigin ();
void fireWeapons ();
void doFireWeapons ();
void selectWeapons (float distance, int index, int id, int choosen);
void handleWeapons (float distance, int index, int id, int choosen);
void focusEnemy ();
void selectBestWeapon ();
void selectSecondary ();

View file

@ -17,6 +17,10 @@ ConVar cv_graph_analyze_optimize_nodes_on_finish ("graph_analyze_optimize_nodes_
ConVar cv_graph_analyze_mark_goals_on_finish ("graph_analyze_mark_goals_on_finish", "1", "Specifies if the analyzer should mark nodes as map goals automatically upon finishing.");
void GraphAnalyze::start () {
if (m_isAnalyzing) {
return;
}
// start analyzer in few seconds after level initialized
if (cv_graph_analyze_auto_start) {
m_updateInterval = game.time () + 3.0f;

View file

@ -881,7 +881,9 @@ void Bot::showChatterIcon (bool show, bool disconnect) const {
// do not respect timers while disconnecting bot
for (auto &client : util.getClients ()) {
if (!(client.flags & ClientFlags::Used) || (client.ent->v.flags & FL_FAKECLIENT) || client.team != m_team) {
if (!(client.flags & ClientFlags::Used)
|| (client.ent->v.flags & FL_FAKECLIENT)
|| (client.team != m_team && !disconnect)) {
continue;
}
@ -891,7 +893,7 @@ void Bot::showChatterIcon (bool show, bool disconnect) const {
}
// do not respect timers while disconnecting bot
if (!show && (client.iconFlags[ownIndex] & ClientFlags::Icon) && (disconnect || client.iconTimestamp[ownIndex] < game.time ())) {
if (!show && (disconnect || (client.iconFlags[ownIndex] & ClientFlags::Icon)) && (disconnect || client.iconTimestamp[ownIndex] < game.time ())) {
sendBotVoice (false, client.ent, entindex ());
client.iconTimestamp[ownIndex] = 0.0f;
@ -1828,7 +1830,9 @@ void Bot::syncUpdatePredictedIndex () {
const float distToBotSq = botOrigin.distanceSq (graph[index].origin);
if (vistab.visible (currentNodeIndex, index) && distToBotSq < cr::sqrf (2048.0f)) {
if (vistab.visible (currentNodeIndex, index)
&& distToBotSq < cr::sqrf (2048.0f)
&& distToBotSq > cr::sqrf (128.0f)) {
bestIndex = index;
return false;
}
@ -3283,9 +3287,17 @@ void Bot::checkSpawnConditions () {
dropCurrentWeapon ();
}
else {
bool switchToKnife = true;
if (m_currentWeapon == Weapon::Scout) {
switchToKnife = rg.chance (25);
}
if (switchToKnife) {
selectWeaponById (Weapon::Knife);
}
}
}
m_checkKnifeSwitch = false;
if (rg.chance (cv_user_follow_percent.as <int> ()) && game.isNullEntity (m_targetEntity) && !m_isLeader && !m_hasC4 && rg.chance (50)) {
@ -3474,6 +3486,8 @@ void Bot::spawned () {
if (game.is (GameFlags::CSDM | GameFlags::ZombieMod)) {
newRound ();
clearTasks ();
m_buyingFinished = true;
}
}

View file

@ -710,6 +710,11 @@ Vector Bot::getEnemyBodyOffset () {
compensation.clear ();
}
// get the correct head origin
const auto &headOrigin = [&] (edict_t *e, const float distance) -> Vector {
return Vector { e->v.origin.x, e->v.origin.y, e->v.absmin.z + e->v.size.z * 0.81f } + getCustomHeight (distance);
};
// if we only suspect an enemy behind a wall take the worst skill
if (!m_enemyParts && (m_states & Sense::SuspectEnemy)) {
spot += getBodyOffsetError (distance);
@ -728,11 +733,13 @@ Vector Bot::getEnemyBodyOffset () {
}
// now check is our skill match to aim at head, else aim at enemy body
if (m_enemyBodyPartSet == m_enemy || rg.chance (headshotPct)) {
spot = m_enemyOrigin + getCustomHeight (distance);
if (m_enemyBodyPartSet == m_enemy
|| ((m_enemyBodyPartSet != m_enemy) && rg.chance (headshotPct))) {
spot = headOrigin (m_enemy, distance);
if (usesSniper ()) {
spot.z -= pev->view_ofs.z * 0.5f;
spot.z -= pev->view_ofs.z * 0.35f;
}
// set's the enemy shooting spot to head, if headshot pct allows, and use head for that
@ -741,6 +748,10 @@ Vector Bot::getEnemyBodyOffset () {
}
else {
spot = m_enemy->v.origin;
if (m_difficulty == Difficulty::Expert) {
spot.z += pev->view_ofs.z * 0.35f;
}
}
}
else if (m_enemyParts & Visibility::Body) {
@ -750,10 +761,10 @@ Vector Bot::getEnemyBodyOffset () {
spot = m_enemyOrigin;
}
else if (m_enemyParts & Visibility::Head) {
spot = m_enemyOrigin + getCustomHeight (distance);
spot = headOrigin (m_enemy, distance);
}
}
auto idealSpot = m_enemyOrigin;
auto idealSpot = spot;
if (m_difficulty < Difficulty::Hard && isEnemyInSight (idealSpot)) {
spot = idealSpot + ((spot - idealSpot) * 0.005f); // gradually adjust the aiming direction
@ -1079,7 +1090,7 @@ bool Bot::checkZoom (float distance) {
return zoomChange;
}
void Bot::selectWeapons (float distance, int, int id, int choosen) {
void Bot::handleWeapons (float distance, int, int id, int choosen) {
const auto tab = conf.getRawWeapons ();
// we want to fire weapon, don't reload now
@ -1249,7 +1260,7 @@ void Bot::fireWeapons () {
// if knife mode use knife only
if (isKnifeMode ()) {
selectWeapons (distance, selectIndex, selectId, choosenWeapon);
handleWeapons (distance, selectIndex, selectId, choosenWeapon);
return;
}
@ -1263,7 +1274,7 @@ void Bot::fireWeapons () {
&& !isGroupOfEnemies (pev->origin)
&& getCurrentTaskId () != Task::Camp) {
selectWeapons (distance, selectIndex, selectId, choosenWeapon);
handleWeapons (distance, selectIndex, selectId, choosenWeapon);
return;
}
@ -1316,7 +1327,7 @@ void Bot::fireWeapons () {
}
selectId = Weapon::Knife; // no available ammo, use knife!
}
selectWeapons (distance, selectIndex, selectId, choosenWeapon);
handleWeapons (distance, selectIndex, selectId, choosenWeapon);
}
bool Bot::isWeaponBadAtDistance (int weaponIndex, float distance) {

View file

@ -648,14 +648,19 @@ void Bot::camp_ () {
auto pathLength = m_lastPredictLength;
auto predictNode = m_lastPredictIndex;
if (isNodeValidForPredict (predictNode) && pathLength > 1) {
if (isNodeValidForPredict (predictNode)
&& pathLength > 1
&& vistab.visible (predictNode, m_currentNodeIndex)) {
m_lookAtSafe = graph[predictNode].origin + pev->view_ofs;
}
else {
pathLength = 0;
predictNode = findAimingNode (m_lastEnemyOrigin, pathLength);
if (isNodeValidForPredict (predictNode) && pathLength > 1) {
if (isNodeValidForPredict (predictNode) && pathLength > 1
&& vistab.visible ( predictNode, m_currentNodeIndex)) {
m_lookAtSafe = graph[predictNode].origin + pev->view_ofs;
}
}

View file

@ -441,12 +441,12 @@ void Bot::setAimDirection () {
// don't switch view right away after loosing focus with current enemy
if ((m_shootTime + rg (0.75f, 1.25f) > game.time ()
|| m_seeEnemyTime + 1.5f > game.time ())
|| m_seeEnemyTime + rg (1.0f, 1.25f) > game.time ())
&& m_forgetLastVictimTimer.elapsed ()
&& !m_lastEnemyOrigin.empty ()
&& util.isAlive (m_lastEnemy)
&& game.isNullEntity (m_enemy)) {
&& util.isPlayer (m_lastEnemy)
&& !util.isPlayer (m_enemy)) {
flags |= AimFlags::LastEnemy;
}