fix: bad maxspeed after respawn with csdm (ref #482)

fix: free for all mode has no friends or foes
chat: disable dead chat on csdm
This commit is contained in:
jeefo 2023-09-14 16:48:36 +03:00
commit 948b441541
No known key found for this signature in database
GPG key ID: 927BCA0779BEA8ED
11 changed files with 119 additions and 64 deletions

View file

@ -398,6 +398,39 @@ public:
} }
}; };
// reference some game/mod cvars for access
class ConVarRef final : public NonCopyable {
private:
cvar_t *ptr_ {};
String name_ {};
bool checked_ {};
public:
ConVarRef (StringRef name) : name_ (name) {}
~ConVarRef () = default;
public:
bool exists () {
if (checked_ && !ptr_) {
return false;
}
checked_ = true;
ptr_ = engfuncs.pfnCVarGetPointer (name_.chars ());
return ptr_ != nullptr;
}
template <typename U = float> U value () {
return exists () ? static_cast <U> (ptr_->value) : static_cast <U> (0);
}
void set (StringRef value) {
if (exists ()) {
engfuncs.pfnCvar_DirectSet (ptr_, value.chars ());
}
}
};
// simplify access for console variables // simplify access for console variables
class ConVar final : public NonCopyable { class ConVar final : public NonCopyable {
public: public:

View file

@ -655,7 +655,7 @@ public:
int m_ammo[MAX_AMMO_SLOTS] {}; // total ammo amounts int m_ammo[MAX_AMMO_SLOTS] {}; // total ammo amounts
bool m_isVIP {}; // bot is vip? bool m_isVIP {}; // bot is vip?
bool m_notKilled {}; // has the player been killed or has he just respawned bool m_isAlive {}; // has the player been killed or has he just respawned
bool m_notStarted {}; // team/class not chosen yet bool m_notStarted {}; // team/class not chosen yet
bool m_ignoreBuyDelay {}; // when reaching buyzone in the middle of the round don't do pauses bool m_ignoreBuyDelay {}; // when reaching buyzone in the middle of the round don't do pauses
bool m_inBombZone {}; // bot in the bomb zone or not bool m_inBombZone {}; // bot in the bomb zone or not

View file

@ -54,7 +54,7 @@ void Bot::pushMsgQueue (int message) {
for (const auto &other : bots) { for (const auto &other : bots) {
if (other->pev != pev) { if (other->pev != pev) {
if (m_notKilled == other->m_notKilled) { if (m_isAlive == other->m_isAlive) {
other->m_sayTextBuffer.entityIndex = entityIndex; other->m_sayTextBuffer.entityIndex = entityIndex;
other->m_sayTextBuffer.sayText = m_chatBuffer; other->m_sayTextBuffer.sayText = m_chatBuffer;
} }
@ -574,7 +574,7 @@ void Bot::updatePickups () {
} }
else { else {
for (const auto &other : bots) { for (const auto &other : bots) {
if (other->m_notKilled) { if (other->m_isAlive) {
for (const auto &hostage : other->m_hostages) { for (const auto &hostage : other->m_hostages) {
if (hostage == ent) { if (hostage == ent) {
allowPickup = false; allowPickup = false;
@ -677,7 +677,7 @@ void Bot::updatePickups () {
if (!game.isNullEntity (pickupItem)) { if (!game.isNullEntity (pickupItem)) {
for (const auto &other : bots) { for (const auto &other : bots) {
if (other.get () != this && other->m_notKilled && other->m_pickupItem == pickupItem) { if (other.get () != this && other->m_isAlive && other->m_pickupItem == pickupItem) {
m_pickupItem = nullptr; m_pickupItem = nullptr;
m_pickupType = Pickup::None; m_pickupType = Pickup::None;
@ -831,7 +831,7 @@ void Bot::instantChatter (int type) {
const auto &playbackSound = conf.pickRandomFromChatterBank (type); const auto &playbackSound = conf.pickRandomFromChatterBank (type);
const auto &painSound = conf.pickRandomFromChatterBank (Chatter::DiePain); const auto &painSound = conf.pickRandomFromChatterBank (Chatter::DiePain);
if (m_notKilled) { if (m_isAlive) {
showChatterIcon (true); showChatterIcon (true);
} }
MessageWriter msg; MessageWriter msg;
@ -852,7 +852,7 @@ void Bot::instantChatter (int type) {
client.iconTimestamp[ownIndex] = game.time () + painSound.duration; client.iconTimestamp[ownIndex] = game.time () + painSound.duration;
writeChatterSound (painSound); writeChatterSound (painSound);
} }
else if (m_notKilled) { else if (m_isAlive) {
client.iconTimestamp[ownIndex] = game.time () + playbackSound.duration; client.iconTimestamp[ownIndex] = game.time () + playbackSound.duration;
writeChatterSound (playbackSound); writeChatterSound (playbackSound);
} }
@ -1561,7 +1561,7 @@ void Bot::updateEmotions () {
void Bot::overrideConditions () { void Bot::overrideConditions () {
// check if we need to escape from bomb // check if we need to escape from bomb
if (game.mapIs (MapFlags::Demolition) && bots.isBombPlanted () && m_notKilled && getCurrentTaskId () != Task::EscapeFromBomb && getCurrentTaskId () != Task::Camp && isOutOfBombTimer ()) { if (game.mapIs (MapFlags::Demolition) && bots.isBombPlanted () && m_isAlive && getCurrentTaskId () != Task::EscapeFromBomb && getCurrentTaskId () != Task::Camp && isOutOfBombTimer ()) {
completeTask (); // complete current task completeTask (); // complete current task
// then start escape from bomb immediate // then start escape from bomb immediate
@ -2211,7 +2211,7 @@ void Bot::checkRadioQueue () {
// check if no more followers are allowed // check if no more followers are allowed
for (const auto &bot : bots) { for (const auto &bot : bots) {
if (bot->m_notKilled) { if (bot->m_isAlive) {
if (bot->m_targetEntity == m_radioEntity) { if (bot->m_targetEntity == m_radioEntity) {
++numFollowers; ++numFollowers;
} }
@ -2240,7 +2240,7 @@ void Bot::checkRadioQueue () {
auto bot = bots[i]; auto bot = bots[i];
if (bot != nullptr) { if (bot != nullptr) {
if (bot->m_notKilled) { if (bot->m_isAlive) {
if (bot->m_targetEntity == m_radioEntity) { if (bot->m_targetEntity == m_radioEntity) {
bot->m_targetEntity = nullptr; bot->m_targetEntity = nullptr;
numFollowers--; numFollowers--;
@ -2672,10 +2672,10 @@ void Bot::tryHeadTowardRadioMessage () {
} }
void Bot::checkParachute () { void Bot::checkParachute () {
static auto parachute = engfuncs.pfnCVarGetPointer (conf.fetchCustom ("AMXParachuteCvar").chars ()); static ConVarRef parachute (conf.fetchCustom ("AMXParachuteCvar").chars ());
// if no cvar or it's not enabled do not bother // if no cvar or it's not enabled do not bother
if (parachute && parachute->value > 0.0f) { if (parachute.exists () && parachute.value () > 0.0f) {
if (isOnLadder () || pev->velocity.z > -50.0f || isOnFloor ()) { if (isOnLadder () || pev->velocity.z > -50.0f || isOnFloor ()) {
m_fallDownTime = 0.0f; m_fallDownTime = 0.0f;
} }
@ -2696,7 +2696,7 @@ void Bot::frame () {
if (m_updateTime <= game.time ()) { if (m_updateTime <= game.time ()) {
update (); update ();
} }
else if (m_notKilled) { else if (m_isAlive) {
updateLookAngles (); updateLookAngles ();
} }
@ -2704,7 +2704,7 @@ void Bot::frame () {
return; return;
} }
if (bots.isBombPlanted () && m_team == Team::CT && m_notKilled) { if (bots.isBombPlanted () && m_team == Team::CT && m_isAlive) {
const Vector &bombPosition = graph.getBombOrigin (); const Vector &bombPosition = graph.getBombOrigin ();
if (!m_hasProgressBar && getCurrentTaskId () != Task::EscapeFromBomb && pev->origin.distanceSq (bombPosition) < cr::sqrf (1540.0f) && !isBombDefusing (bombPosition)) { if (!m_hasProgressBar && getCurrentTaskId () != Task::EscapeFromBomb && pev->origin.distanceSq (bombPosition) < cr::sqrf (1540.0f) && !isBombDefusing (bombPosition)) {
@ -2746,9 +2746,10 @@ void Bot::update () {
kick (); kick ();
return; return;
} }
const auto tid = getCurrentTaskId ();
m_canChooseAimDirection = true; m_canChooseAimDirection = true;
m_notKilled = util.isAlive (ent ()); m_isAlive = util.isAlive (ent ());
m_team = game.getTeam (ent ()); m_team = game.getTeam (ent ());
m_healthValue = cr::clamp (pev->health, 0.0f, 100.0f); m_healthValue = cr::clamp (pev->health, 0.0f, 100.0f);
@ -2767,11 +2768,19 @@ void Bot::update () {
// is bot movement enabled // is bot movement enabled
bool botMovement = false; bool botMovement = false;
// for some unknown reason some bots have speed of 1.0 after respawn on csdm
if (game.is (GameFlags::CSDM) && cr::fequal (pev->maxspeed, 1.0f) && tid == Task::Normal) {
static ConVarRef sv_maxspeed ("sv_maxspeed");
// reset max speed to max value, thus allowing bot movement
pev->maxspeed = sv_maxspeed.value ();
}
// if the bot hasn't selected stuff to start the game yet, go do that... // if the bot hasn't selected stuff to start the game yet, go do that...
if (m_notStarted) { if (m_notStarted) {
updateTeamJoin (); // select team & class updateTeamJoin (); // select team & class
} }
else if (!m_notKilled) { else if (!m_isAlive) {
// we got a teamkiller? vote him away... // we got a teamkiller? vote him away...
if (m_voteKickIndex != m_lastVoteKick && cv_tkpunish.bool_ ()) { if (m_voteKickIndex != m_lastVoteKick && cv_tkpunish.bool_ ()) {
issueCommand ("vote %d", m_voteKickIndex); issueCommand ("vote %d", m_voteKickIndex);
@ -2793,7 +2802,7 @@ void Bot::update () {
m_voteMap = 0; m_voteMap = 0;
} }
} }
else if (m_buyingFinished && !(pev->maxspeed < 10.0f && getCurrentTaskId () != Task::PlantBomb && getCurrentTaskId () != Task::DefuseBomb) && !cv_freeze_bots.bool_ () && !graph.hasChanged ()) { else if (m_buyingFinished && !(pev->maxspeed < 10.0f && tid != Task::PlantBomb && tid != Task::DefuseBomb) && !cv_freeze_bots.bool_ () && !graph.hasChanged ()) {
botMovement = true; botMovement = true;
} }
checkMsgQueue (); checkMsgQueue ();
@ -2825,7 +2834,7 @@ void Bot::logicDuringFreezetime () {
Array <Bot *> teammates; Array <Bot *> teammates;
for (const auto &bot : bots) { for (const auto &bot : bots) {
if (bot->m_notKilled && bot->m_team == m_team && seesEntity (bot->pev->origin) && bot.get () != this) { if (bot->m_isAlive && bot->m_team == m_team && seesEntity (bot->pev->origin) && bot.get () != this) {
teammates.push (bot.get ()); teammates.push (bot.get ());
} }
} }
@ -3060,7 +3069,7 @@ void Bot::logic () {
checkParachute (); checkParachute ();
// display some debugging thingy to host entity // display some debugging thingy to host entity
if (!game.isDedicated () && cv_debug.int_ () >= 1) { if (cv_debug.int_ () >= 1) {
showDebugOverlay (); showDebugOverlay ();
} }
@ -3073,6 +3082,7 @@ void Bot::logic () {
void Bot::spawned () { void Bot::spawned () {
if (game.is (GameFlags::CSDM)) { if (game.is (GameFlags::CSDM)) {
newRound (); newRound ();
clearTasks ();
} }
} }
@ -3208,15 +3218,15 @@ void Bot::showDebugOverlay () {
// green = destination origin // green = destination origin
// blue = ideal angles // blue = ideal angles
// red = view angles // red = view angles
const auto lifeTime = 1; constexpr auto kArrowLifeTime = 1;
game.drawLine (overlayEntity, getEyesPos (), m_destOrigin, 10, 0, { 0, 255, 0 }, 250, 5, lifeTime, DrawLine::Arrow); game.drawLine (overlayEntity, getEyesPos (), m_destOrigin, 10, 0, { 0, 255, 0 }, 250, 5, kArrowLifeTime, DrawLine::Arrow);
game.drawLine (overlayEntity, getEyesPos () - Vector (0.0f, 0.0f, 16.0f), getEyesPos () + m_idealAngles.forward () * 300.0f, 10, 0, { 0, 0, 255 }, 250, 5, lifeTime, DrawLine::Arrow); game.drawLine (overlayEntity, getEyesPos () - Vector (0.0f, 0.0f, 16.0f), getEyesPos () + m_idealAngles.forward () * 300.0f, 10, 0, { 0, 0, 255 }, 250, 5, kArrowLifeTime, DrawLine::Arrow);
game.drawLine (overlayEntity, getEyesPos () - Vector (0.0f, 0.0f, 32.0f), getEyesPos () + pev->v_angle.forward () * 300.0f, 10, 0, { 255, 0, 0 }, 250, 5, lifeTime, DrawLine::Arrow); game.drawLine (overlayEntity, getEyesPos () - Vector (0.0f, 0.0f, 32.0f), getEyesPos () + pev->v_angle.forward () * 300.0f, 10, 0, { 255, 0, 0 }, 250, 5, kArrowLifeTime, DrawLine::Arrow);
// now draw line from source to destination // now draw line from source to destination
for (size_t i = 0; i < m_pathWalk.length () && i + 1 < m_pathWalk.length (); ++i) { for (size_t i = 0; i < m_pathWalk.length () && i + 1 < m_pathWalk.length (); ++i) {
game.drawLine (overlayEntity, graph[m_pathWalk.at (i)].origin, graph[m_pathWalk.at (i + 1)].origin, 15, 0, { 255, 100, 55 }, 200, 5, lifeTime, DrawLine::Arrow); game.drawLine (overlayEntity, graph[m_pathWalk.at (i)].origin, graph[m_pathWalk.at (i + 1)].origin, 15, 0, { 255, 100, 55 }, 200, 5, kArrowLifeTime, DrawLine::Arrow);
} }
} }
@ -3250,7 +3260,9 @@ void Bot::takeDamage (edict_t *inflictor, int damage, int armor, int bits) {
} }
if (util.isPlayer (inflictor) || (cv_attack_monsters.bool_ () && util.isMonster (inflictor))) { if (util.isPlayer (inflictor) || (cv_attack_monsters.bool_ () && util.isMonster (inflictor))) {
if (!util.isMonster (inflictor) && cv_tkpunish.bool_ () && game.getTeam (inflictor) == m_team && !util.isFakeClient (inflictor)) { const auto inflictorTeam = game.getTeam (inflictor);
if (!util.isMonster (inflictor) && cv_tkpunish.bool_ () && inflictorTeam == m_team && !util.isFakeClient (inflictor)) {
// alright, die you team killer!!! // alright, die you team killer!!!
m_actualReactionTime = 0.0f; m_actualReactionTime = 0.0f;
m_seeEnemyTime = game.time (); m_seeEnemyTime = game.time ();
@ -3281,7 +3293,7 @@ void Bot::takeDamage (edict_t *inflictor, int damage, int armor, int bits) {
} }
clearTask (Task::Camp); clearTask (Task::Camp);
if (game.isNullEntity (m_enemy) && m_team != game.getTeam (inflictor)) { if (game.isNullEntity (m_enemy) && m_team != inflictorTeam) {
m_lastEnemy = inflictor; m_lastEnemy = inflictor;
m_lastEnemyOrigin = inflictor->v.origin; m_lastEnemyOrigin = inflictor->v.origin;
@ -3504,9 +3516,11 @@ void Bot::debugMsgInternal (StringRef str) {
else if (level != 3) { else if (level != 3) {
playMessage = true; playMessage = true;
} }
if (playMessage && level > 3) { if (playMessage && level > 3) {
logger.message (printBuf.chars ()); logger.message (printBuf.chars ());
} }
if (playMessage) { if (playMessage) {
ctrl.msg (printBuf.chars ()); ctrl.msg (printBuf.chars ());
sendToChat (printBuf, false); sendToChat (printBuf, false);
@ -3810,7 +3824,7 @@ bool Bot::isBombDefusing (const Vector &bombOrigin) {
auto bot = bots[client.ent]; auto bot = bots[client.ent];
const auto bombDistanceSq = client.origin.distanceSq (bombOrigin); const auto bombDistanceSq = client.origin.distanceSq (bombOrigin);
if (bot && !bot->m_notKilled) { if (bot && !bot->m_isAlive) {
if (m_team != bot->m_team || bot->getCurrentTaskId () == Task::EscapeFromBomb) { if (m_team != bot->m_team || bot->getCurrentTaskId () == Task::EscapeFromBomb) {
continue; // skip other mess continue; // skip other mess
} }

View file

@ -318,7 +318,7 @@ bool Bot::isReplyingToChat () {
void Bot::checkForChat () { void Bot::checkForChat () {
// say a text every now and then // say a text every now and then
if (m_notKilled || !cv_chat.bool_ ()) { if (m_isAlive || !cv_chat.bool_ () || game.is (GameFlags::CSDM)) {
return; return;
} }

View file

@ -17,6 +17,10 @@ ConVar mp_friendlyfire ("mp_friendlyfire", nullptr, Var::GameRef);
ConVar sv_gravity ("sv_gravity", nullptr, Var::GameRef); ConVar sv_gravity ("sv_gravity", nullptr, Var::GameRef);
int Bot::numFriendsNear (const Vector &origin, const float radius) { int Bot::numFriendsNear (const Vector &origin, const float radius) {
if (game.is (GameFlags::FreeForAll)) {
return 0; // no friends on free for all mode
}
int count = 0; int count = 0;
const float radiusSq = cr::sqrf (radius); const float radiusSq = cr::sqrf (radius);
@ -33,6 +37,10 @@ int Bot::numFriendsNear (const Vector &origin, const float radius) {
} }
int Bot::numEnemiesNear (const Vector &origin, const float radius) { int Bot::numEnemiesNear (const Vector &origin, const float radius) {
if (game.is (GameFlags::FreeForAll)) {
return 0; // no enemies on free for all mode
}
int count = 0; int count = 0;
const float radiusSq = cr::sqrf (radius); const float radiusSq = cr::sqrf (radius);
@ -372,7 +380,7 @@ bool Bot::lookupEnemies () {
// now alarm all teammates who see this bot & don't have an actual enemy of the bots enemy should simulate human players seeing a teammate firing // now alarm all teammates who see this bot & don't have an actual enemy of the bots enemy should simulate human players seeing a teammate firing
for (const auto &other : bots) { for (const auto &other : bots) {
if (!other->m_notKilled || other->m_team != m_team || other.get () == this) { if (!other->m_isAlive || other->m_team != m_team || other.get () == this) {
continue; continue;
} }

View file

@ -640,11 +640,11 @@ void Game::checkCvarsBounds () {
// special case for xash3d, by default engine is not calling startframe if no players on server, but our quota management and bot adding // special case for xash3d, by default engine is not calling startframe if no players on server, but our quota management and bot adding
// mechanism assumes that starframe is called even if no players on server, so, set the xash3d's sv_forcesimulating cvar to 1 in case it's not // mechanism assumes that starframe is called even if no players on server, so, set the xash3d's sv_forcesimulating cvar to 1 in case it's not
if (is (GameFlags::Xash3D)) { if (is (GameFlags::Xash3D)) {
static cvar_t *sv_forcesimulating = engfuncs.pfnCVarGetPointer ("sv_forcesimulating"); static ConVarRef sv_forcesimulating ("sv_forcesimulating");
if (sv_forcesimulating && !cr::fequal (sv_forcesimulating->value, 1.0f)) { if (sv_forcesimulating.exists () && !cr::fequal (sv_forcesimulating.value (), 1.0f)) {
game.print ("Force-enable Xash3D sv_forcesimulating cvar."); game.print ("Force-enable Xash3D sv_forcesimulating cvar.");
engfuncs.pfnCVarSetFloat ("sv_forcesimulating", 1.0f); sv_forcesimulating.set ("1.0");
} }
} }
} }
@ -892,12 +892,13 @@ void Game::applyGameModes () {
return; return;
} }
static auto dmActive = engfuncs.pfnCVarGetPointer ("csdm_active"); static ConVarRef csdm_active ("csdm_active");
static auto freeForAll = engfuncs.pfnCVarGetPointer ("mp_freeforall"); static ConVarRef redm_active ("redm_active");
static ConVarRef mp_freeforall ("mp_freeforall");
// csdm is only with amxx and metamod // csdm is only with amxx and metamod
if (dmActive) { if (csdm_active.exists () || redm_active.exists ()) {
if (dmActive->value > 0.0f) { if (csdm_active.value () > 0.0f || redm_active.value () > 0.0f) {
m_gameFlags |= GameFlags::CSDM; m_gameFlags |= GameFlags::CSDM;
} }
else if (is (GameFlags::CSDM)) { else if (is (GameFlags::CSDM)) {
@ -906,12 +907,12 @@ void Game::applyGameModes () {
} }
// but this can be provided by regamedll // but this can be provided by regamedll
if (freeForAll) { if (mp_freeforall.exists ()) {
if (freeForAll->value > 0.0f) { if (mp_freeforall.value () > 0.0f) {
m_gameFlags |= GameFlags::FreeForAll; m_gameFlags |= (GameFlags::FreeForAll | GameFlags::CSDM);
} }
else if (is (GameFlags::FreeForAll)) { else if (is (GameFlags::FreeForAll)) {
m_gameFlags &= ~GameFlags::FreeForAll; m_gameFlags &= ~(GameFlags::FreeForAll | GameFlags::CSDM);
} }
} }
} }

View file

@ -114,7 +114,7 @@ void BotManager::destroyKillerEntity () {
void BotManager::touchKillerEntity (Bot *bot) { void BotManager::touchKillerEntity (Bot *bot) {
// bot is already dead. // bot is already dead.
if (!bot->m_notKilled) { if (!bot->m_isAlive) {
return; return;
} }
@ -282,7 +282,7 @@ Bot *BotManager::findAliveBot () {
// this function finds one bot, alive bot :) // this function finds one bot, alive bot :)
for (const auto &bot : m_bots) { for (const auto &bot : m_bots) {
if (bot->m_notKilled) { if (bot->m_isAlive) {
return bot.get (); return bot.get ();
} }
} }
@ -490,7 +490,7 @@ void BotManager::maintainAutoKill () {
} }
for (const auto &bot : m_bots) { for (const auto &bot : m_bots) {
if (bot->m_notKilled) { if (bot->m_isAlive) {
++aliveBots; ++aliveBots;
// do not interrupt assassination scenario, if vip is a bot // do not interrupt assassination scenario, if vip is a bot
@ -685,7 +685,7 @@ bool BotManager::kickRandom (bool decQuota, Team fromTeam) {
// first try to kick the bot that is currently dead // first try to kick the bot that is currently dead
for (const auto &bot : m_bots) { for (const auto &bot : m_bots) {
if (!bot->m_notKilled && belongsTeam (bot.get ())) // is this slot used? if (!bot->m_isAlive && belongsTeam (bot.get ())) // is this slot used?
{ {
updateQuota (); updateQuota ();
bot->kick (); bot->kick ();
@ -824,7 +824,7 @@ void BotManager::listBots () {
}; };
for (const auto &bot : bots) { for (const auto &bot : bots) {
ctrl.msg ("[%-3.1d]\t%-19.16s\t%-10.12s\t%-3.4s\t%-3.1d\t%-3.1d\t%-3.4s\t%-3.0f secs", bot->index (), bot->pev->netname.chars (), bot->m_personality == Personality::Rusher ? "rusher" : bot->m_personality == Personality::Normal ? "normal" : "careful", botTeam (bot->m_team), bot->m_difficulty, static_cast <int> (bot->pev->frags), bot->m_notKilled ? "yes" : "no", cv_rotate_bots.bool_ () ? bot->m_stayTime - game.time () : 0.0f); ctrl.msg ("[%-3.1d]\t%-19.16s\t%-10.12s\t%-3.4s\t%-3.1d\t%-3.1d\t%-3.4s\t%-3.0f secs", bot->index (), bot->pev->netname.chars (), bot->m_personality == Personality::Rusher ? "rusher" : bot->m_personality == Personality::Normal ? "normal" : "careful", botTeam (bot->m_team), bot->m_difficulty, static_cast <int> (bot->pev->frags), bot->m_isAlive ? "yes" : "no", cv_rotate_bots.bool_ () ? bot->m_stayTime - game.time () : 0.0f);
} }
ctrl.msg ("%d bots", m_bots.length ()); ctrl.msg ("%d bots", m_bots.length ());
} }
@ -887,7 +887,7 @@ Bot *BotManager::findHighestFragBot (int team) {
// search bots in this team // search bots in this team
for (const auto &bot : bots) { for (const auto &bot : bots) {
if (bot->m_notKilled && bot->m_team == team) { if (bot->m_isAlive && bot->m_team == team) {
if (bot->pev->frags > bestScore) { if (bot->pev->frags > bestScore) {
bestIndex = bot->index (); bestIndex = bot->index ();
bestScore = bot->pev->frags; bestScore = bot->pev->frags;
@ -1055,7 +1055,7 @@ Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int skin) {
m_sayTextBuffer.chatDelay = rg.get (3.8f, 10.0f); m_sayTextBuffer.chatDelay = rg.get (3.8f, 10.0f);
m_sayTextBuffer.chatProbability = rg.get (10, 100); m_sayTextBuffer.chatProbability = rg.get (10, 100);
m_notKilled = false; m_isAlive = false;
m_weaponBurstMode = BurstMode::Off; m_weaponBurstMode = BurstMode::Off;
m_difficulty = cr::clamp (static_cast <Difficulty> (difficulty), Difficulty::Noob, Difficulty::Expert); m_difficulty = cr::clamp (static_cast <Difficulty> (difficulty), Difficulty::Noob, Difficulty::Expert);
@ -1244,7 +1244,7 @@ void BotManager::handleDeath (edict_t *killer, edict_t *victim) {
if (cv_radio_mode.int_ () == 2) { if (cv_radio_mode.int_ () == 2) {
// need to send congrats on well placed shot // need to send congrats on well placed shot
for (const auto &notify : bots) { for (const auto &notify : bots) {
if (notify->m_notKilled && killerTeam == notify->m_team && killerTeam != victimTeam && killer != notify->ent () && notify->seesEntity (victim->v.origin)) { if (notify->m_isAlive && killerTeam == notify->m_team && killerTeam != victimTeam && killer != notify->ent () && notify->seesEntity (victim->v.origin)) {
if (!(killer->v.flags & FL_FAKECLIENT)) { if (!(killer->v.flags & FL_FAKECLIENT)) {
notify->pushChatterMessage (Chatter::NiceShotCommander); notify->pushChatterMessage (Chatter::NiceShotCommander);
} }
@ -1260,7 +1260,7 @@ void BotManager::handleDeath (edict_t *killer, edict_t *victim) {
// notice nearby to victim teammates, that attacker is near // notice nearby to victim teammates, that attacker is near
for (const auto &notify : bots) { for (const auto &notify : bots) {
if (notify->m_seeEnemyTime + 2.0f < game.time () && notify->m_notKilled && notify->m_team == victimTeam && game.isNullEntity (notify->m_enemy) && killerTeam != victimTeam && util.isVisible (killer->v.origin, notify->ent ())) { if (notify->m_seeEnemyTime + 2.0f < game.time () && notify->m_isAlive && notify->m_team == victimTeam && game.isNullEntity (notify->m_enemy) && killerTeam != victimTeam && util.isVisible (killer->v.origin, notify->ent ())) {
notify->m_actualReactionTime = 0.0f; notify->m_actualReactionTime = 0.0f;
notify->m_seeEnemyTime = game.time (); notify->m_seeEnemyTime = game.time ();
notify->m_enemy = killer; notify->m_enemy = killer;
@ -1298,7 +1298,7 @@ void BotManager::handleDeath (edict_t *killer, edict_t *victim) {
} }
} }
} }
victimBot->m_notKilled = false; victimBot->m_isAlive = false;
} }
} }
} }
@ -1449,7 +1449,7 @@ void Bot::newRound () {
m_lastEquipTime = 0.0f; m_lastEquipTime = 0.0f;
// if bot died, clear all weapon stuff and force buying again // if bot died, clear all weapon stuff and force buying again
if (!m_notKilled) { if (!m_isAlive) {
plat.bzero (&m_ammoInClip, sizeof (m_ammoInClip)); plat.bzero (&m_ammoInClip, sizeof (m_ammoInClip));
plat.bzero (&m_ammo, sizeof (m_ammo)); plat.bzero (&m_ammo, sizeof (m_ammo));
@ -1774,7 +1774,7 @@ void BotManager::notifyBombDefuse () {
for (const auto &bot : bots) { for (const auto &bot : bots) {
const auto task = bot->getCurrentTaskId (); const auto task = bot->getCurrentTaskId ();
if (!bot->m_defuseNotified && bot->m_notKilled && task != Task::MoveToPosition && task != Task::DefuseBomb && task != Task::EscapeFromBomb) { if (!bot->m_defuseNotified && bot->m_isAlive && task != Task::MoveToPosition && task != Task::DefuseBomb && task != Task::EscapeFromBomb) {
if (bot->m_team == Team::Terrorist && bot->pev->origin.distanceSq (bombPos) < cr::sqrf (384.0f)) { if (bot->m_team == Team::Terrorist && bot->pev->origin.distanceSq (bombPos) < cr::sqrf (384.0f)) {
bot->clearSearchNodes (); bot->clearSearchNodes ();
@ -1878,7 +1878,7 @@ void BotManager::selectLeaders (int team, bool reset) {
else if (team == Team::Terrorist && !m_leaderChoosen[Team::Terrorist]) { else if (team == Team::Terrorist && !m_leaderChoosen[Team::Terrorist]) {
auto bot = bots.findHighestFragBot (team); auto bot = bots.findHighestFragBot (team);
if (bot != nullptr && bot->m_notKilled) { if (bot != nullptr && bot->m_isAlive) {
bot->m_isLeader = true; bot->m_isLeader = true;
if (rg.chance (45)) { if (rg.chance (45)) {

View file

@ -57,7 +57,7 @@ void MessageDispatcher::netMsgTextMsg () {
bots.setBombPlanted (true); bots.setBombPlanted (true);
for (const auto &notify : bots) { for (const auto &notify : bots) {
if (notify->m_notKilled) { if (notify->m_isAlive) {
notify->clearSearchNodes (); notify->clearSearchNodes ();
// clear only camp tasks // clear only camp tasks

View file

@ -70,7 +70,7 @@ int Bot::findBestGoal () {
// do not stole from bots (ignore humans, fuck them) // do not stole from bots (ignore humans, fuck them)
for (const auto &other : bots) { for (const auto &other : bots) {
if (!other->m_notKilled) { if (!other->m_isAlive) {
continue; continue;
} }
@ -246,8 +246,7 @@ int Bot::findGoalPost (int tactic, IntArray *defensive, IntArray *offensive) {
if (tactic == GoalTactic::Defensive && !(*defensive).empty ()) { // careful goal if (tactic == GoalTactic::Defensive && !(*defensive).empty ()) { // careful goal
postprocessGoals (*defensive, goalChoices); postprocessGoals (*defensive, goalChoices);
} }
else if (tactic == GoalTactic::Camp && !graph.m_campPoints.empty ()) // camp node goal else if (tactic == GoalTactic::Camp && !graph.m_campPoints.empty ()) { // camp node goal
{
// pickup sniper points if possible for sniping bots // pickup sniper points if possible for sniping bots
if (!graph.m_sniperPoints.empty () && usesSniper ()) { if (!graph.m_sniperPoints.empty () && usesSniper ()) {
postprocessGoals (graph.m_sniperPoints, goalChoices); postprocessGoals (graph.m_sniperPoints, goalChoices);
@ -1303,7 +1302,7 @@ bool Bot::updateLiftHandling () {
// if some bot is following a bot going into lift - he should take the same lift to go // if some bot is following a bot going into lift - he should take the same lift to go
for (const auto &bot : bots) { for (const auto &bot : bots) {
if (!bot->m_notKilled || bot->m_team != m_team || bot->m_targetEntity != ent () || bot->getCurrentTaskId () != Task::FollowUser) { if (!bot->m_isAlive || bot->m_team != m_team || bot->m_targetEntity != ent () || bot->getCurrentTaskId () != Task::FollowUser) {
continue; continue;
} }
@ -1335,7 +1334,7 @@ bool Bot::updateLiftHandling () {
bool needWaitForTeammate = false; bool needWaitForTeammate = false;
for (const auto &bot : bots) { for (const auto &bot : bots) {
if (!bot->m_notKilled || bot->m_team != m_team || bot->m_targetEntity != ent () || bot->getCurrentTaskId () != Task::FollowUser || bot->m_liftEntity != m_liftEntity) { if (!bot->m_isAlive || bot->m_team != m_team || bot->m_targetEntity != ent () || bot->getCurrentTaskId () != Task::FollowUser || bot->m_liftEntity != m_liftEntity) {
continue; continue;
} }
@ -2352,7 +2351,7 @@ bool Bot::advanceMovement () {
// get ladder nodes used by other (first moving) bots // get ladder nodes used by other (first moving) bots
for (const auto &other : bots) { for (const auto &other : bots) {
// if another bot uses this ladder, wait 3 secs // if another bot uses this ladder, wait 3 secs
if (other.get () != this && other->m_notKilled && other->m_currentNodeIndex == destIndex) { if (other.get () != this && other->m_isAlive && other->m_currentNodeIndex == destIndex) {
startTask (Task::Pause, TaskPri::Pause, kInvalidNodeIndex, game.time () + 3.0f, false); startTask (Task::Pause, TaskPri::Pause, kInvalidNodeIndex, game.time () + 3.0f, false);
return true; return true;
} }
@ -3058,7 +3057,7 @@ bool Bot::isOccupiedNode (int index, bool needZeroVelocity) {
} }
auto bot = bots[client.ent]; auto bot = bots[client.ent];
if (bot == nullptr || bot == this || !bot->m_notKilled) { if (bot == nullptr || bot == this || !bot->m_isAlive) {
continue; continue;
} }
return bot->m_currentNodeIndex == index; return bot->m_currentNodeIndex == index;

View file

@ -89,7 +89,7 @@ void BotPractice::update () {
void BotPractice::syncUpdate () { void BotPractice::syncUpdate () {
// this function called after each end of the round to update knowledge about most dangerous nodes for each team. // this function called after each end of the round to update knowledge about most dangerous nodes for each team.
auto graphLength = graph.length (); const auto graphLength = graph.length ();
// no nodes, no practice used or nodes edited or being edited? // no nodes, no practice used or nodes edited or being edited?
if (!graphLength || graph.hasChanged () || !vistab.isReady ()) { if (!graphLength || graph.hasChanged () || !vistab.isReady ()) {

View file

@ -240,7 +240,7 @@ void Bot::normal_ () {
// make sure everyone else will not ask next few moments // make sure everyone else will not ask next few moments
for (const auto &bot : bots) { for (const auto &bot : bots) {
if (bot->m_notKilled) { if (bot->m_isAlive) {
bot->m_askCheckTime = game.time () + rg.get (5.0f, 30.0f); bot->m_askCheckTime = game.time () + rg.get (5.0f, 30.0f);
} }
} }
@ -817,7 +817,7 @@ void Bot::defuseBomb_ () {
if (bombPos.empty ()) { if (bombPos.empty ()) {
// fix for stupid behavior of CT's when bot is defused // fix for stupid behavior of CT's when bot is defused
for (const auto &bot : bots) { for (const auto &bot : bots) {
if (bot->m_team == m_team && bot->m_notKilled) { if (bot->m_team == m_team && bot->m_isAlive) {
auto defendPoint = graph.getFarest (bot->pev->origin); auto defendPoint = graph.getFarest (bot->pev->origin);
startTask (Task::Camp, TaskPri::Camp, kInvalidNodeIndex, game.time () + rg.get (30.0f, 60.0f), true); // push camp task on to stack startTask (Task::Camp, TaskPri::Camp, kInvalidNodeIndex, game.time () + rg.get (30.0f, 60.0f), true); // push camp task on to stack
@ -1583,7 +1583,7 @@ void Bot::pickupItem_ () {
// check if hostage is with a bot // check if hostage is with a bot
for (const auto &other : bots) { for (const auto &other : bots) {
if (other->m_notKilled) { if (other->m_isAlive) {
for (const auto &hostage : other->m_hostages) { for (const auto &hostage : other->m_hostages) {
if (hostage == ent) { if (hostage == ent) {
return EntitySearchResult::Continue; return EntitySearchResult::Continue;