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
This commit is contained in:
jeefo 2025-02-05 21:28:29 +03:00
commit ecb1f20303
No known key found for this signature in database
GPG key ID: D696786B81B667C8
12 changed files with 79 additions and 106 deletions

View file

@ -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
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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);
}
}
}

View file

@ -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 <float> (), cv_rotate_stay_max.as <float> ());
@ -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;

View file

@ -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 ()) {

View file

@ -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 <short> (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) {

View file

@ -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);
}
}