From ecb1f2030353723721663250f3bbcd5ffb87cdce Mon Sep 17 00:00:00 2001 From: jeefo Date: Wed, 5 Feb 2025 21:28:29 +0300 Subject: [PATCH] conf: get decal indices during config load combat: do not init hitbox aiming if disabled nav: reverted some last changes nav: fixed check fall on ladders chat: added %g keyword that is replaced with graph author --- inc/config.h | 11 +++------- inc/constant.h | 4 ++-- inc/support.h | 2 +- inc/yapb.h | 7 ++++--- src/botlib.cpp | 6 ++++-- src/chatlib.cpp | 8 +++++-- src/combat.cpp | 2 +- src/config.cpp | 23 ++++++++++++++++----- src/manager.cpp | 4 +--- src/navigate.cpp | 54 +++++++++++++++++------------------------------- src/support.cpp | 50 ++++++++++++-------------------------------- src/tasks.cpp | 14 ++++++------- 12 files changed, 79 insertions(+), 106 deletions(-) diff --git a/inc/config.h b/inc/config.h index c442268..494d6e7 100644 --- a/inc/config.h +++ b/inc/config.h @@ -48,7 +48,7 @@ private: SmallArray m_weapons {}; SmallArray m_weaponProps {}; - StringArray m_logos {}; + IntArray m_logosIndices {}; StringArray m_avatars {}; HashMap > m_language {}; @@ -244,13 +244,8 @@ public: } // get's random logo index - int32_t getRandomLogoIndex () const { - return static_cast (m_logos.index (m_logos.random ())); - } - - // get random name by index - StringRef getLogoName (int index) { - return m_logos[index]; + int32_t getRandomLogoDecalIndex () const { + return static_cast (m_logosIndices.random ()); } // get custom value diff --git a/inc/constant.h b/inc/constant.h index 108ca9d..210d7e7 100644 --- a/inc/constant.h +++ b/inc/constant.h @@ -439,12 +439,12 @@ constexpr auto kSprayDistanceX2 = kSprayDistance * 2; constexpr auto kMaxChatterRepeatInterval = 99.0f; constexpr auto kViewFrameUpdate = 1.0f / 25.0f; constexpr auto kGrenadeDamageRadius = 385.0f; -constexpr auto kMinMovedDistance = 2.0f; +constexpr auto kMinMovedDistance = 3.0f; constexpr auto kInfiniteDistanceLong = static_cast (kInfiniteDistance); constexpr auto kMaxWeapons = 32; constexpr auto kNumWeapons = 26; -constexpr auto kMaxCollideMoves = 3; +constexpr auto kMaxCollideMoves = 4; constexpr auto kGameMaxPlayers = 32; constexpr auto kGameTeamNum = 2; constexpr auto kInvalidNodeIndex = -1; diff --git a/inc/support.h b/inc/support.h index 461ab07..43a38d8 100644 --- a/inc/support.h +++ b/inc/support.h @@ -62,7 +62,7 @@ public: bool findNearestPlayer (void **holder, edict_t *to, float searchDistance = 4096.0, bool sameTeam = false, bool needBot = false, bool needAlive = false, bool needDrawn = false, bool needBotWithC4 = false); // tracing decals for bots spraying logos - void decalTrace (entvars_t *pev, TraceResult *trace, int logotypeIndex); + void decalTrace (TraceResult *trace, int decalIndex); // update stats on clients void updateClients (); diff --git a/inc/yapb.h b/inc/yapb.h index 1acc54a..d3cb5e4 100644 --- a/inc/yapb.h +++ b/inc/yapb.h @@ -53,6 +53,7 @@ struct WeaponInfo { int id {}; // the weapon id value StringRef name {}; // name of the weapon when selecting it StringRef model {}; // model name to separate cs weapons + StringRef alias {}; // alias name for weapon int price {}; // price when buying int minPrimaryAmmo {}; // minimum primary ammo int teamStandard {}; // used by team (number) (standard map) @@ -235,7 +236,6 @@ private: float m_prevTime {}; // time previously checked movement speed float m_heavyTimestamp {}; // is it time to execute heavy-weight functions float m_prevSpeed {}; // speed some frames before - float m_prevVelocity {}; // velocity some frames before float m_timeDoorOpen {}; // time to next door open check float m_timeHitDoor {}; // specific time after hitting the door float m_lastChatTime {}; // time bot last chatted @@ -315,7 +315,6 @@ private: PathWalk m_pathWalk {}; // pointer to current node from path Dodge m_dodgeStrafeDir {}; // direction to strafe - Dodge m_avoidAction {}; // player avoid action Fight m_fightStyle {}; // combat style to use CollisionState m_collisionState {}; // collision State FindPath m_pathType {}; // which pathfinder to use @@ -351,6 +350,7 @@ private: Vector m_breakableOrigin {}; // origin of breakable Vector m_rightRef {}; // right referential vector Vector m_checkFallPoint[2] {}; // check fall point + Vector m_prevVelocity {}; // velocity some frames before Array m_ignoredBreakable {}; // list of ignored breakables Array m_ignoredItems {}; // list of pointers to entity to ignore for pickup @@ -651,7 +651,7 @@ public: int m_voteKickIndex {}; // index of player to vote against int m_lastVoteKick {}; // last index int m_voteMap {}; // number of map to vote for - int m_logotypeIndex {}; // index for logotype + int m_logoDecalIndex {}; // index for logotype int m_buyState {}; // current count in buying int m_blindButton {}; // buttons bot press, when blind int m_radioOrder {}; // actual command @@ -930,6 +930,7 @@ extern ConVar cv_camping_time_min; extern ConVar cv_camping_time_max; extern ConVar cv_smoke_grenade_checks; extern ConVar cv_check_darkness; +extern ConVar cv_use_hitbox_enemy_targeting; extern ConVar mp_freezetime; extern ConVar mp_roundtime; diff --git a/src/botlib.cpp b/src/botlib.cpp index 85fa92d..9f83c57 100644 --- a/src/botlib.cpp +++ b/src/botlib.cpp @@ -180,6 +180,7 @@ void Bot::checkBreakablesAround () { || !cv_destroy_breakables_around || usesKnife () || usesSniper () + || isOnLadder () || rg.chance (25) || !game.hasBreakables () || m_seeEnemyTime + 4.0f > game.time () @@ -3161,7 +3162,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 (!game.is (GameFlags::Xash3D) && rg (1, 100) < 2 && cv_spraypaints) { + if (rg (1, 100) < 30 && cv_spraypaints) { startTask (Task::Spraypaint, TaskPri::Spraypaint, kInvalidNodeIndex, game.time () + 1.0f, false); } @@ -3397,7 +3398,8 @@ void Bot::logic () { // save the previous speed (for checking if stuck) m_prevSpeed = cr::abs (m_moveSpeed); - m_prevVelocity = cr::abs (pev->velocity.length2d ()); + m_prevVelocity = pev->velocity; + m_lastDamageType = -1; // reset damage } diff --git a/src/chatlib.cpp b/src/chatlib.cpp index d5753e3..926affe 100644 --- a/src/chatlib.cpp +++ b/src/chatlib.cpp @@ -235,12 +235,13 @@ void Bot::prepareChatMessage (StringRef message) { if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive) || client.ent == ent ()) { continue; } + const auto playerIndex = game.indexOfPlayer (client.ent); if (needsEnemy && m_team != client.team) { - return humanizedName (game.indexOfPlayer (client.ent)); + return humanizedName (playerIndex); } else if (!needsEnemy && m_team == client.team) { - return humanizedName (game.indexOfPlayer (client.ent)); + return humanizedName (playerIndex); } } return getHighfragPlayer (); @@ -290,6 +291,9 @@ void Bot::prepareChatMessage (StringRef message) { case 'e': m_chatBuffer.replace ("%e", getPlayerAlive (true)); break; + + case 'g': + m_chatBuffer.replace ("%g", graph.getAuthor ()); }; ++replaceCounter; } diff --git a/src/combat.cpp b/src/combat.cpp index b3e4dc3..45ed1d5 100644 --- a/src/combat.cpp +++ b/src/combat.cpp @@ -180,7 +180,7 @@ bool Bot::checkBodyParts (edict_t *target) { } // hitboxes requested ? - if (game.is (GameFlags::HasStudioModels) && cv_use_hitbox_enemy_targeting) { + if (game.is (GameFlags::HasStudioModels) && cv_use_hitbox_enemy_targeting && m_hitboxEnumerator) { return checkBodyPartsWithHitboxes (target); } return checkBodyPartsWithOffsets (target); diff --git a/src/config.cpp b/src/config.cpp index e5901a9..2c2f7bc 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -735,19 +735,32 @@ void BotConfig::loadLogosConfig () { String line {}; MemFile file {}; + auto addLogoIndex = [&] (StringRef logo) { + const auto index = engfuncs.pfnDecalIndex (logo.chars ()); + + if (index > 0) { + m_logosIndices.push (index); + } + }; + m_logosIndices.clear (); + // logos initialization if (openConfig ("logos", "Logos config file not found. Loading defaults.", &file)) { - m_logos.clear (); - while (file.getLine (line)) { if (isCommentLine (line)) { continue; } - m_logos.push (cr::move (line.trim ())); + addLogoIndex (line); } } - else { - m_logos = cr::move (String { "{biohaz;{graf003;{graf004;{graf005;{lambda06;{target;{hand1;{spit2;{bloodhand6;{foot_l;{foot_r" }.split (";")); + + // use defaults + if (m_logosIndices.empty ()) { + auto defaults = String { "{biohaz;{graf003;{graf004;{graf005;{lambda06;{target;{hand1;{spit2;{bloodhand6;{foot_l;{foot_r" }.split (";"); + + for (const auto &logo : defaults) { + addLogoIndex (logo); + } } } diff --git a/src/manager.cpp b/src/manager.cpp index bc2445b..8a4e865 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -1157,7 +1157,7 @@ Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int skin) { m_startAction = BotMsg::None; m_retryJoin = 0; m_moneyAmount = 0; - m_logotypeIndex = conf.getRandomLogoIndex (); + m_logoDecalIndex = conf.getRandomLogoDecalIndex (); if (cv_rotate_bots) { m_stayTime = game.time () + rg (cv_rotate_stay_min.as (), cv_rotate_stay_max.as ()); @@ -1496,7 +1496,6 @@ void Bot::newRound () { m_askCheckTime = rg (30.0f, 90.0f); m_minSpeed = 260.0f; m_prevSpeed = 0.0f; - m_prevVelocity = 0.0f; m_prevOrigin = Vector (kInfiniteDistance, kInfiniteDistance, kInfiniteDistance); m_prevTime = game.time (); m_lookUpdateTime = game.time (); @@ -1630,7 +1629,6 @@ void Bot::newRound () { m_zoomCheckTime = 0.0f; m_strafeSetTime = 0.0f; m_dodgeStrafeDir = Dodge::None; - m_avoidAction = Dodge::None; m_fightStyle = Fight::None; m_lastFightStyleCheck = 0.0f; diff --git a/src/navigate.cpp b/src/navigate.cpp index 3e4bc27..a0423e4 100644 --- a/src/navigate.cpp +++ b/src/navigate.cpp @@ -530,23 +530,8 @@ void Bot::doPlayerAvoidance (const Vector &normal) { // found somebody? if (game.isNullEntity (m_hindrance)) { - m_avoidAction = Dodge::None; return; } - else { - if (util.getConeDeviation (ent (), m_hindrance->v.origin) < 0.8f) { - return; - } - - if (m_avoidAction != Dodge::None) { - if (m_avoidAction == Dodge::Left) { - setStrafeSpeed (normal, pev->maxspeed); - } - else if (m_avoidAction == Dodge::Right) { - setStrafeSpeed (normal, -pev->maxspeed); - } - } - } const float interval = m_frameInterval * (!isDucking () && pev->velocity.lengthSq2d () > 0.0f ? 6.0f : 2.0f); // use our movement angles, try to predict where we should be next frame @@ -566,31 +551,20 @@ void Bot::doPlayerAvoidance (const Vector &normal) { const auto &dir = (pev->origin - m_hindrance->v.origin).normalize2d_apx (); // to start strafing, we have to first figure out if the target is on the left side or right side - if ((m_avoidAction == Dodge::None - && m_path->radius > 16.0f - && !isInNarrowPlace ()) - || m_moveSpeed < 0.0f) { - if ((dir | right.normalize2d_apx ()) > 0.0f) { - m_avoidAction = Dodge::Left; - - // start strafing - setStrafeSpeed (normal, pev->maxspeed); - } - else { - m_avoidAction = Dodge::Right; - - // start strafing - setStrafeSpeed (normal, -pev->maxspeed); - } + if ((dir | right.normalize2d_apx ()) > 0.0f) { + // start strafing + setStrafeSpeed (normal, pev->maxspeed); + } + else { + // start strafing + setStrafeSpeed (normal, -pev->maxspeed); } - m_navTimeset = game.time (); if (distanceSq < cr::sqrf (96.0f)) { if ((dir | forward.normalize2d_apx ()) < 0.0f) { m_moveSpeed = -pev->maxspeed; } } - ignoreCollision (); } } @@ -600,10 +574,12 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) { TraceResult tr {}; m_isStuck = false; + const auto tid = getCurrentTaskId (); + // standing still, no need to check? - if (m_lastCollTime < game.time () && getCurrentTaskId () != Task::Attack) { + if (m_lastCollTime < game.time () && tid != Task::Attack && tid != Task::Camp) { // didn't we move enough previously? - if (movedDistance < kMinMovedDistance && (m_prevSpeed > 20.0f || m_prevVelocity < m_moveSpeed / 2)) { + if (movedDistance < kMinMovedDistance && m_prevSpeed > 20.0f) { m_prevTime = game.time (); // then consider being stuck m_isStuck = true; @@ -881,6 +857,14 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) { } void Bot::checkFall () { + if (isPreviousLadder ()) { + return; + } + else if (graph.exists (m_currentNodeIndex)) { + if (graph[m_currentNodeIndex].flags & NodeFlag::Ladder) { + return; + } + } if (!m_checkFall) { if (isOnFloor ()) { diff --git a/src/support.cpp b/src/support.cpp index 815191d..9be099a 100644 --- a/src/support.cpp +++ b/src/support.cpp @@ -103,24 +103,13 @@ bool BotSupport::isVisible (const Vector &origin, edict_t *ent) { return true; } -void BotSupport::decalTrace (entvars_t *pev, TraceResult *trace, int logotypeIndex) { +void BotSupport::decalTrace (TraceResult *trace, int decalIndex) { // this function draw spraypaint depending on the tracing results. - if (cr::fequal (trace->flFraction, 1.0f)) { + if (cr::fequal (trace->flFraction, 1.0f) || decalIndex <= 0) { return; } - auto logo = conf.getLogoName (logotypeIndex); - int entityIndex = -1, message = TE_DECAL; - int decalIndex = engfuncs.pfnDecalIndex (logo.chars ()); - - if (decalIndex <= 0) { - decalIndex = engfuncs.pfnDecalIndex ("{lambda06"); - } - - if (decalIndex <= 0) { - return; - } if (!game.isNullEntity (trace->pHit)) { if (trace->pHit->v.solid == SOLID_BSP || trace->pHit->v.movetype == MOVETYPE_PUSHSTEP) { @@ -148,32 +137,19 @@ void BotSupport::decalTrace (entvars_t *pev, TraceResult *trace, int logotypeInd decalIndex -= 256; } } + MessageWriter msg {}; - if (logo.startsWith ("{")) { - MessageWriter (MSG_BROADCAST, SVC_TEMPENTITY) - .writeByte (TE_PLAYERDECAL) - .writeByte (game.indexOfEntity (pev->pContainingEntity)) - .writeCoord (trace->vecEndPos.x) - .writeCoord (trace->vecEndPos.y) - .writeCoord (trace->vecEndPos.z) - .writeShort (static_cast (game.indexOfEntity (trace->pHit))) - .writeByte (decalIndex); - } - else { - MessageWriter msg {}; - - msg.start (MSG_BROADCAST, SVC_TEMPENTITY) - .writeByte (message) - .writeCoord (trace->vecEndPos.x) - .writeCoord (trace->vecEndPos.y) - .writeCoord (trace->vecEndPos.z) - .writeByte (decalIndex); - - if (entityIndex) { - msg.writeShort (entityIndex); - } - msg.end (); + msg.start (MSG_BROADCAST, SVC_TEMPENTITY) + .writeByte (message) + .writeCoord (trace->vecEndPos.x) + .writeCoord (trace->vecEndPos.y) + .writeCoord (trace->vecEndPos.z) + .writeByte (decalIndex); + + if (entityIndex) { + msg.writeShort (entityIndex); } + msg.end (); } bool BotSupport::isPlayer (edict_t *ent) { diff --git a/src/tasks.cpp b/src/tasks.cpp index ab2a5cf..01e94ea 100644 --- a/src/tasks.cpp +++ b/src/tasks.cpp @@ -99,11 +99,10 @@ void Bot::normal_ () { // spray logo sometimes if allowed to do so if (!(m_states & (Sense::SeeingEnemy | Sense::SuspectEnemy)) && m_seeEnemyTime + 5.0f < game.time () - && !m_reloadState && m_timeLogoSpray < game.time () - && !game.is (GameFlags::Xash3D) + && m_reloadState == Reload::None + && m_timeLogoSpray < game.time () && cv_spraypaints - && rg.chance (50) - && m_moveSpeed > getShiftSpeed () + && m_moveSpeed >= getShiftSpeed () && game.isNullEntity (m_pickupItem)) { if (!(game.mapIs (MapFlags::Demolition) && bots.isBombPlanted () && m_team == Team::CT)) { @@ -316,7 +315,7 @@ void Bot::spraypaint_ () { m_aimFlags |= AimFlags::Entity; // bot didn't spray this round? - if (m_timeLogoSpray < game.time () && getTask ()->time > game.time ()) { + if (m_timeLogoSpray <= game.time () && getTask ()->time > game.time ()) { const auto &forward = pev->v_angle.forward (); Vector sprayOrigin = getEyesPos () + forward * 128.0f; @@ -331,11 +330,12 @@ void Bot::spraypaint_ () { if (getTask ()->time - 0.5f < game.time ()) { // emit spray can sound - engfuncs.pfnEmitSound (ent (), CHAN_VOICE, "player/sprayer.wav", 1.0f, ATTN_NORM, 0, 100); + engfuncs.pfnEmitSound (pev->pContainingEntity, CHAN_VOICE, "player/sprayer.wav", 1.0f, ATTN_NORM, 0, 100); + game.testLine (getEyesPos (), getEyesPos () + forward * 128.0f, TraceIgnore::Monsters, ent (), &tr); // paint the actual logo decal - util.decalTrace (pev, &tr, m_logotypeIndex); + util.decalTrace (&tr, m_logoDecalIndex); m_timeLogoSpray = game.time () + rg (60.0f, 90.0f); } }