diff --git a/cfg/addons/yapb/conf/custom.cfg b/cfg/addons/yapb/conf/custom.cfg index 6ad83ae..89fc9ef 100644 --- a/cfg/addons/yapb/conf/custom.cfg +++ b/cfg/addons/yapb/conf/custom.cfg @@ -6,6 +6,8 @@ ; ; Custom configuration file, allow to change some hardcoded stuff in bot code. ; +; NOTE: All changes to this file takes effect only on server restart. +; ; ; Custom name for C4 model, for servers that replacing C4 model with it's own. @@ -28,3 +30,23 @@ AMXParachuteCvar = sv_parachute ; CustomCSDMSpawnPoint = view_spawn +; +; Primary cvar for detection if CSDM mod is activated in game. +; +CSDMDetectCvar = csdm_active + +; +; Primary cvar to detect if bot is running on Zombie Mod. +; +ZMDetectCvar = zp_delay + +; +; For Zombie Mod, the cvars that deals with time before any game mode starts. +; +ZMDelayCvar = zp_delay + +; +; For Zombie Mod, determines the team on which infected players are on. +; Valid values: T, CT. +; +ZMInfectedTeam = T diff --git a/inc/engine.h b/inc/engine.h index 878ef10..1398541 100644 --- a/inc/engine.h +++ b/inc/engine.h @@ -47,7 +47,8 @@ CR_DECLARE_SCOPED_ENUM (GameFlags, HasFakePings = cr::bit (10), // on that game version we can fake bots pings HasBotVoice = cr::bit (11), // on that game version we can use chatter AnniversaryHL25 = cr::bit (12), // half-life 25th anniversary engine - Xash3DLegacy = cr::bit (13) // old xash3d-branch + Xash3DLegacy = cr::bit (13), // old xash3d-branch + ZombieMod = cr::bit (14) // zombie mod is active ) // defines map type diff --git a/inc/manager.h b/inc/manager.h index 2ff470f..abcde90 100644 --- a/inc/manager.h +++ b/inc/manager.h @@ -122,6 +122,7 @@ public: void setLastWinner (int winner); void checkBotModel (edict_t *ent, char *infobuffer); void checkNeedsToBeKicked (); + void refreshCreatureStatus (); bool isTeamStacked (int team); bool kickRandom (bool decQuota = true, Team fromTeam = Team::Unassigned); diff --git a/inc/yapb.h b/inc/yapb.h index e27d9c9..c6bd94d 100644 --- a/inc/yapb.h +++ b/inc/yapb.h @@ -306,6 +306,7 @@ private: bool m_moveToC4 {}; // ct is moving to bomb bool m_needToSendWelcomeChat {}; // bot needs to greet people on server? bool m_isCreature {}; // bot is not a player, but something else ? zombie ? + bool m_isOnInfectedTeam {}; // bot is zombie (this assumes bot is a creature) bool m_defuseNotified {}; // bot is notified about bomb defusion bool m_jumpSequence {}; // next path link will be jump link bool m_checkFall {}; // check bot fall @@ -500,7 +501,7 @@ private: void selectWeaponByIndex (int index); void syncUpdatePredictedIndex (); void updatePredictedIndex (); - void refreshModelName (char *infobuffer); + void refreshCreatureStatus (char *infobuffer); void updateRightRef (); void completeTask (); diff --git a/src/botlib.cpp b/src/botlib.cpp index 54563e5..5032380 100644 --- a/src/botlib.cpp +++ b/src/botlib.cpp @@ -3244,7 +3244,7 @@ void Bot::logic () { } void Bot::spawned () { - if (game.is (GameFlags::CSDM)) { + if (game.is (GameFlags::CSDM | GameFlags::ZombieMod)) { newRound (); clearTasks (); } @@ -4089,7 +4089,27 @@ float Bot::getShiftSpeed () { return pev->maxspeed * 0.4f; } -void Bot::refreshModelName (char *infobuffer) { +void Bot::refreshCreatureStatus (char *infobuffer) { + // if bot is on infected team, assume he is a creature + if (game.is (GameFlags::ZombieMod)) { + static StringRef zmInfectedTeam (conf.fetchCustom ("ZMInfectedTeam")); + + // by default infected team is terrorists + Team infectedTeam = Team::Terrorist; + + if (zmInfectedTeam == "CT") { + infectedTeam = Team::CT; + } + + // if bot is on infected team, and zombie mode is active, assume bot is a creature/zombie + m_isOnInfectedTeam = game.getRealTeam (ent ()) == infectedTeam; + + // do not process next if already infected + if (m_isOnInfectedTeam) { + return; + } + } + if (infobuffer == nullptr) { infobuffer = engfuncs.pfnGetInfoKeyBuffer (ent ()); } @@ -4115,5 +4135,5 @@ bool Bot::isCreature () { constexpr auto modelMaskZombie = (('o' << 8) + 'z'); constexpr auto modelMaskChicken = (('h' << 8) + 'c'); - return m_modelMask == modelMaskZombie || m_modelMask == modelMaskChicken; + return m_isOnInfectedTeam || m_modelMask == modelMaskZombie || m_modelMask == modelMaskChicken; } diff --git a/src/config.cpp b/src/config.cpp index 8bc93ad..87b84b1 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -661,6 +661,10 @@ void BotConfig::loadCustomConfig () { m_custom["C4ModelName"] = "c4.mdl"; m_custom["AMXParachuteCvar"] = "sv_parachute"; m_custom["CustomCSDMSpawnPoint"] = "view_spawn"; + m_custom["CSDMDetectCvar"] = "csdm_active"; + m_custom["ZMDetectCvar"] = "zp_delay"; + m_custom["ZMDelayCvar"] = "zp_delay"; + m_custom["ZMInfectedTeam"] = "T"; }; setDefaults (); diff --git a/src/engine.cpp b/src/engine.cpp index 2f72752..ea9fb0b 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -951,7 +951,11 @@ void Game::applyGameModes () { return; } - static ConVarRef csdm_active ("csdm_active"); + static StringRef csdmActiveCvarName = conf.fetchCustom ("CSDMDetectCvar"); + static StringRef zmActiveCvarName = conf.fetchCustom ("ZMDetectCvar"); + static StringRef zmDelayCvarName = conf.fetchCustom ("ZMDelayCvar"); + + static ConVarRef csdm_active (csdmActiveCvarName); static ConVarRef csdm_version ("csdm_version"); static ConVarRef redm_active ("redm_active"); static ConVarRef mp_freeforall ("mp_freeforall"); @@ -976,12 +980,21 @@ void Game::applyGameModes () { } } - // some little support for zombie plague - static ConVarRef zp_delay ("zp_delay"); + // does zombie mod is in use + static ConVarRef zm_active (zmActiveCvarName); - // update our ignore timer if zp_elay exists - if (zp_delay.exists () && zp_delay.value () > 0.0f) { - cv_ignore_enemies_after_spawn_time.set (zp_delay.value () + 3.0f); + // do a some little support for zombie plague + if (zm_active.exists ()) { + static ConVarRef zm_delay (zmDelayCvarName); + + // update our ignore timer if zp_delay exists + if (zm_delay.exists () && zm_delay.value () > 0.0f) { + cv_ignore_enemies_after_spawn_time.set (zm_delay.value () + 3.5f); + } + m_gameFlags |= GameFlags::ZombieMod; + } + else { + m_gameFlags &= ~GameFlags::ZombieMod; } } @@ -1033,6 +1046,9 @@ void Game::slowFrame () { // kick failed bots bots.checkNeedsToBeKicked (); + // refresh bot infection (creature) status + bots.refreshCreatureStatus (); + // update next update time m_oneSecondFrame = nextUpdate + time (); } diff --git a/src/manager.cpp b/src/manager.cpp index af7a605..5d2f38f 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -814,7 +814,7 @@ void BotManager::setLastWinner (int winner) { void BotManager::checkBotModel (edict_t *ent, char *infobuffer) { for (const auto &bot : bots) { if (bot->ent () == ent) { - bot->refreshModelName (infobuffer); + bot->refreshCreatureStatus (infobuffer); break; } } @@ -829,6 +829,18 @@ void BotManager::checkNeedsToBeKicked () { } } +void BotManager::refreshCreatureStatus () { + if (!game.is (GameFlags::ZombieMod)) { + return; + } + + for (const auto &bot : bots) { + if (bot->m_isAlive) { + bot->refreshCreatureStatus (nullptr); + } + } +} + void BotManager::setWeaponMode (int selection) { // this function sets bots weapon mode @@ -1370,7 +1382,7 @@ void BotManager::handleDeath (edict_t *killer, edict_t *victim) { } } - // mark bot as "spawned", and reset it to new-round state when it dead (for csdm only) + // mark bot as "spawned", and reset it to new-round state when it dead (for csdm/zombie only) if (victimBot != nullptr) { victimBot->spawned (); } @@ -1519,7 +1531,7 @@ void Bot::newRound () { for (auto &timer : m_chatterTimes) { timer = kMaxChatterRepeatInterval; } - refreshModelName (nullptr); + refreshCreatureStatus (nullptr); m_isReloading = false; m_reloadState = Reload::None;