fix: behavior with bomb, when ignoring objectives (ref #696)

This commit is contained in:
jeefo 2025-05-22 22:05:48 +03:00
commit 9cb8171030
No known key found for this signature in database
GPG key ID: D696786B81B667C8
5 changed files with 58 additions and 40 deletions

View file

@ -37,15 +37,11 @@ private:
float m_plantSearchUpdateTime {}; // time to update for searching planted bomb float m_plantSearchUpdateTime {}; // time to update for searching planted bomb
float m_lastChatTime {}; // global chat time timestamp float m_lastChatTime {}; // global chat time timestamp
float m_timeBombPlanted {}; // time the bomb were planted float m_timeBombPlanted {}; // time the bomb were planted
float m_lastRadioTime[kGameTeamNum] {}; // global radio time
int m_lastWinner {}; // the team who won previous round int m_lastWinner {}; // the team who won previous round
int m_lastDifficulty {}; // last bots difficulty int m_lastDifficulty {}; // last bots difficulty
int m_bombSayStatus {}; // some bot is issued whine about bomb int m_bombSayStatus {}; // some bot is issued whine about bomb
int m_lastRadio[kGameTeamNum] {}; // last radio message for team
bool m_leaderChoosen[kGameTeamNum] {}; // is team leader choose thees round
bool m_economicsGood[kGameTeamNum] {}; // is team able to buy anything
bool m_bombPlanted {}; // is bomb planted ? bool m_bombPlanted {}; // is bomb planted ?
bool m_botsCanPause {}; // bots can do a little pause ? bool m_botsCanPause {}; // bots can do a little pause ?
bool m_roundOver {}; // well, round is over> bool m_roundOver {}; // well, round is over>
@ -59,6 +55,7 @@ private:
SmallArray <UniqueBot> m_bots {}; // all available bots SmallArray <UniqueBot> m_bots {}; // all available bots
edict_t *m_killerEntity {}; // killer entity for bots edict_t *m_killerEntity {}; // killer entity for bots
BotTeamData m_teamData[kGameTeamNum] {}; // teams shared data
protected: protected:
BotCreateResult create (StringRef name, int difficulty, int personality, int team, int skin); BotCreateResult create (StringRef name, int difficulty, int personality, int team, int skin);
@ -149,7 +146,7 @@ public:
} }
bool checkTeamEco (int team) const { bool checkTeamEco (int team) const {
return m_economicsGood[team]; return m_teamData[team].positiveEco;
} }
int32_t getLastWinner () const { int32_t getLastWinner () const {
@ -219,23 +216,23 @@ public:
void setLastRadioTimestamp (const int team, const float timestamp) { void setLastRadioTimestamp (const int team, const float timestamp) {
if (team == Team::CT || team == Team::Terrorist) { if (team == Team::CT || team == Team::Terrorist) {
m_lastRadioTime[team] = timestamp; m_teamData[team].lastRadioTimestamp = timestamp;
} }
} }
float getLastRadioTimestamp (const int team) const { float getLastRadioTimestamp (const int team) const {
if (team == Team::CT || team == Team::Terrorist) { if (team == Team::CT || team == Team::Terrorist) {
return m_lastRadioTime[team]; return m_teamData[team].lastRadioTimestamp;
} }
return 0.0f; return 0.0f;
} }
void setLastRadio (const int team, const int radio) { void setLastRadio (const int team, const int radio) {
m_lastRadio[team] = radio; m_teamData[team].lastRadioSlot = radio;
} }
int getLastRadio (const int team) const { int getLastRadio (const int team) const {
return m_lastRadio[team]; return m_teamData[team].lastRadioSlot;
} }
void setLastChatTimestamp (const float timestamp) { void setLastChatTimestamp (const float timestamp) {

View file

@ -115,6 +115,14 @@ struct FrameDelay {
float time {}; float time {};
}; };
// shared team data for bot
struct BotTeamData {
bool leaderChoosen {}; // is team leader choose thees round
bool positiveEco {}; // is team able to buy anything
float lastRadioTimestamp {}; // global radio time
int32_t lastRadioSlot = { kInvalidRadioSlot }; // last radio message for team
};
// include bot graph stuff // include bot graph stuff
#include <graph.h> #include <graph.h>
#include <vision.h> #include <vision.h>

View file

@ -441,7 +441,7 @@ void Bot::updatePickups () {
allowPickup = true; allowPickup = true;
pickupType = Pickup::Hostage; pickupType = Pickup::Hostage;
} }
else if (isDemolitionMap && isWeaponBox && model == "backpack.mdl") { else if (isDemolitionMap && isWeaponBox && model == "backpack.mdl" && !cv_ignore_objectives) {
allowPickup = true; allowPickup = true;
pickupType = Pickup::DroppedC4; pickupType = Pickup::DroppedC4;
} }
@ -4375,7 +4375,16 @@ void Bot::donateC4ToHuman () {
const float radiusSq = cr::sqrf (1024.0f); const float radiusSq = cr::sqrf (1024.0f);
for (const auto &client : util.getClients ()) { for (const auto &client : util.getClients ()) {
if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive) || client.team != m_team || client.ent == ent ()) { if (!(client.flags & ClientFlags::Used)
|| !(client.flags & ClientFlags::Alive)
|| client.team != m_team
|| client.ent == ent ()) {
continue;
}
// skip the bots
if (bots[client.ent]) {
continue; continue;
} }

View file

@ -60,12 +60,11 @@ ConVar mp_freezetime ("mp_freezetime", nullptr, Var::GameRef, true, "0");
BotManager::BotManager () { BotManager::BotManager () {
// this is a bot manager class constructor // this is a bot manager class constructor
for (int i = 0; i < kGameTeamNum; ++i) { for (auto &td : m_teamData) {
m_leaderChoosen[i] = false; td.leaderChoosen = false;
m_economicsGood[i] = true; td.positiveEco = true;
td.lastRadioSlot = kInvalidRadioSlot;
m_lastRadioTime[i] = 0.0f; td.lastRadioTimestamp = 0.0f;
m_lastRadio[i] = kInvalidRadioSlot;
} }
reset (); reset ();
@ -1008,11 +1007,13 @@ void BotManager::updateTeamEconomics (int team, bool setTrue) {
// that have not enough money to buy primary (with economics), and if this result higher 80%, player is can't // that have not enough money to buy primary (with economics), and if this result higher 80%, player is can't
// buy primary weapons. // buy primary weapons.
auto &ecoStatus = m_teamData[team].positiveEco;
if (setTrue || !cv_economics_rounds) { if (setTrue || !cv_economics_rounds) {
m_economicsGood[team] = true; ecoStatus = true;
return; // don't check economics while economics disable return; // don't check economics while economics disable
} }
const int *econLimit = conf.getEconLimit (); const auto econLimit = conf.getEconLimit ();
int numPoorPlayers = 0; int numPoorPlayers = 0;
int numTeamPlayers = 0; int numTeamPlayers = 0;
@ -1026,19 +1027,19 @@ void BotManager::updateTeamEconomics (int team, bool setTrue) {
++numTeamPlayers; // update count of team ++numTeamPlayers; // update count of team
} }
} }
m_economicsGood[team] = true; ecoStatus = true;
if (numTeamPlayers <= 1) { if (numTeamPlayers <= 1) {
return; return;
} }
// if 80 percent of team have no enough money to purchase primary weapon // if 80 percent of team have no enough money to purchase primary weapon
if ((numTeamPlayers * 80) / 100 <= numPoorPlayers) { if ((numTeamPlayers * 80) / 100 <= numPoorPlayers) {
m_economicsGood[team] = false; ecoStatus = false;
} }
// winner must buy something! // winner must buy something!
if (m_lastWinner == team) { if (m_lastWinner == team) {
m_economicsGood[team] = true; ecoStatus = true;
} }
} }
@ -2057,21 +2058,24 @@ void BotManager::updateInterestingEntities () {
} }
void BotManager::selectLeaders (int team, bool reset) { void BotManager::selectLeaders (int team, bool reset) {
auto &leaderChoosen = m_teamData[team].leaderChoosen;
if (reset) { if (reset) {
m_leaderChoosen[team] = false; leaderChoosen = false;
return; return;
} }
if (m_leaderChoosen[team]) { if (leaderChoosen) {
return; return;
} }
auto &leaderChoosenT = m_teamData[Team::Terrorist].leaderChoosen;
auto &leaderChoosenCT = m_teamData[Team::CT].leaderChoosen;
if (game.mapIs (MapFlags::Assassination)) { if (game.mapIs (MapFlags::Assassination)) {
if (team == Team::CT && !m_leaderChoosen[Team::CT]) { if (team == Team::CT && !leaderChoosenCT) {
for (const auto &bot : m_bots) { for (const auto &bot : m_bots) {
if (bot->m_isVIP) { if (bot->m_isVIP) {
// vip bot is the leader bot->m_isLeader = true; // vip bot is the leader
bot->m_isLeader = true;
if (rg.chance (50)) { if (rg.chance (50)) {
bot->pushRadioMessage (Radio::FollowMe); bot->pushRadioMessage (Radio::FollowMe);
@ -2079,9 +2083,9 @@ void BotManager::selectLeaders (int team, bool reset) {
} }
} }
} }
m_leaderChoosen[Team::CT] = true; leaderChoosenCT = true;
} }
else if (team == Team::Terrorist && !m_leaderChoosen[Team::Terrorist]) { else if (team == Team::Terrorist && !leaderChoosenT) {
auto bot = bots.findHighestFragBot (team); auto bot = bots.findHighestFragBot (team);
if (bot != nullptr && bot->m_isAlive) { if (bot != nullptr && bot->m_isAlive) {
@ -2091,11 +2095,11 @@ void BotManager::selectLeaders (int team, bool reset) {
bot->pushRadioMessage (Radio::FollowMe); bot->pushRadioMessage (Radio::FollowMe);
} }
} }
m_leaderChoosen[Team::Terrorist] = true; leaderChoosenT = true;
} }
} }
else if (game.mapIs (MapFlags::Demolition)) { else if (game.mapIs (MapFlags::Demolition)) {
if (team == Team::Terrorist && !m_leaderChoosen[Team::Terrorist]) { if (team == Team::Terrorist && !leaderChoosenT) {
for (const auto &bot : m_bots) { for (const auto &bot : m_bots) {
if (bot->m_hasC4) { if (bot->m_hasC4) {
// bot carrying the bomb is the leader // bot carrying the bomb is the leader
@ -2113,9 +2117,9 @@ void BotManager::selectLeaders (int team, bool reset) {
} }
} }
} }
m_leaderChoosen[Team::Terrorist] = true; leaderChoosenT = true;
} }
else if (!m_leaderChoosen[Team::CT]) { else if (!leaderChoosenCT) {
if (auto bot = bots.findHighestFragBot (team)) { if (auto bot = bots.findHighestFragBot (team)) {
bot->m_isLeader = true; bot->m_isLeader = true;
@ -2123,31 +2127,31 @@ void BotManager::selectLeaders (int team, bool reset) {
bot->pushRadioMessage (Radio::FollowMe); bot->pushRadioMessage (Radio::FollowMe);
} }
} }
m_leaderChoosen[Team::CT] = true; leaderChoosenCT = true;
} }
} }
else if (game.mapIs (MapFlags::Escape | MapFlags::KnifeArena | MapFlags::FightYard)) { else if (game.mapIs (MapFlags::Escape | MapFlags::KnifeArena | MapFlags::FightYard)) {
auto bot = bots.findHighestFragBot (team); auto bot = bots.findHighestFragBot (team);
if (!m_leaderChoosen[team] && bot) { if (!leaderChoosen && bot) {
bot->m_isLeader = true; bot->m_isLeader = true;
if (rg.chance (30)) { if (rg.chance (30)) {
bot->pushRadioMessage (Radio::FollowMe); bot->pushRadioMessage (Radio::FollowMe);
} }
m_leaderChoosen[team] = true; leaderChoosen = true;
} }
} }
else { else {
auto bot = bots.findHighestFragBot (team); auto bot = bots.findHighestFragBot (team);
if (!m_leaderChoosen[team] && bot) { if (!leaderChoosen && bot) {
bot->m_isLeader = true; bot->m_isLeader = true;
if (rg.chance (team == Team::Terrorist ? 30 : 40)) { if (rg.chance (team == Team::Terrorist ? 30 : 40)) {
bot->pushRadioMessage (Radio::FollowMe); bot->pushRadioMessage (Radio::FollowMe);
} }
m_leaderChoosen[team] = true; leaderChoosen = true;
} }
} }
} }
@ -2162,7 +2166,7 @@ void BotManager::initRound () {
updateTeamEconomics (team); updateTeamEconomics (team);
selectLeaders (team, true); selectLeaders (team, true);
m_lastRadioTime[team] = 0.0f; m_teamData[team].lastRadioTimestamp = 0.0f;
} }
reset (); reset ();

View file

@ -199,7 +199,7 @@ int Bot::findBestGoal () {
int Bot::findBestGoalWhenBombAction () { int Bot::findBestGoalWhenBombAction () {
int result = kInvalidNodeIndex; int result = kInvalidNodeIndex;
if (!bots.isBombPlanted ()) { if (!bots.isBombPlanted () && !cv_ignore_objectives) {
game.searchEntities ("classname", "weaponbox", [&] (edict_t *ent) { game.searchEntities ("classname", "weaponbox", [&] (edict_t *ent) {
if (util.isModel (ent, "backpack.mdl")) { if (util.isModel (ent, "backpack.mdl")) {
result = graph.getNearest (game.getEntityOrigin (ent)); result = graph.getNearest (game.getEntityOrigin (ent));