diff --git a/include/core.h b/include/core.h index 745a516..966a79d 100644 --- a/include/core.h +++ b/include/core.h @@ -60,8 +60,10 @@ enum GameFlags GAME_MOBILITY = (1 << 4), // additional flag that bot is running on android (additional flag) GAME_OFFICIAL_CSBOT = (1 << 5), // additional flag that indicates official cs bots are in game GAME_METAMOD = (1 << 6), // game running under metamod - GAME_SUPPORT_SVC_PINGS = (1 << 7), // on that game version we can fake bots pings - GAME_SUPPORT_BOT_VOICE = (1 << 8) // on that game version we can use chatter + GAME_CSDM = (1 << 7), // csdm mod currently in use + GAME_CSDM_FFA = (1 << 8), // csdm mod with ffa mode + GAME_SUPPORT_SVC_PINGS = (1 << 9), // on that game version we can fake bots pings + GAME_SUPPORT_BOT_VOICE = (1 << 10) // on that game version we can use chatter }; // bot menu ids @@ -123,6 +125,12 @@ enum Personality PERSONALITY_CAREFUL }; +// bot difficulties +enum Difficulty +{ + +}; + // collision states enum CollisionState { @@ -423,15 +431,15 @@ enum WaypointDownloadError }; // game start messages for counter-strike... -enum GameStartMessage +enum GameMessage { - GSM_IDLE = 1, - GSM_TEAM_SELECT = 2, - GSM_CLASS_SELECT = 3, - GSM_BUY_STUFF = 100, - GSM_RADIO = 200, - GSM_SAY = 10000, - GSM_SAY_TEAM = 10001 + GAME_MSG_NONE = 1, + GAME_MSG_TEAM_SELECT = 2, + GAME_MSG_CLASS_SELECT = 3, + GAME_MSG_PURCHASE = 100, + GAME_MSG_RADIO = 200, + GAME_MSG_SAY_CMD = 10000, + GAME_MSG_SAY_TEAM_MSG = 10001 }; // sensing states @@ -1531,7 +1539,6 @@ extern const char *FormatBuffer (const char *format, ...); // very global convars extern ConVar yb_jasonmode; extern ConVar yb_communication_type; -extern ConVar yb_csdm_mode; extern ConVar yb_ignore_enemies; #include diff --git a/include/corelib.h b/include/corelib.h index 57dfddf..2a9cb3c 100644 --- a/include/corelib.h +++ b/include/corelib.h @@ -55,13 +55,14 @@ static inline int A_stricmp (const char *str1, const char *str2, int length = -1 int iter = 0; if (length == -1) - length = strlen (str2); + length = strlen (str1); for (; iter < length; iter++) { if ((str1[iter] | 32) != (str2[iter] | 32)) break; } + if (iter != length) return 1; diff --git a/source/basecode.cpp b/source/basecode.cpp index 681e22f..9faae37 100644 --- a/source/basecode.cpp +++ b/source/basecode.cpp @@ -49,7 +49,7 @@ void Bot::PushMessageQueue (int message) { // this function put a message into the bot message queue - if (message == GSM_SAY) + if (message == GAME_MSG_SAY_CMD) { // notify other bots of the spoken text otherwise, bots won't respond to other bots (network messages aren't sent from bots) int entityIndex = GetIndex (); @@ -108,11 +108,13 @@ bool Bot::ItemIsVisible (const Vector &destination, const char *itemName) // check if line of sight to object is not blocked (i.e. visible) if (tr.flFraction != 1.0f) { + auto classname = STRING (tr.pHit->v.classname); + // check for standard items - if (strcmp (STRING (tr.pHit->v.classname), itemName) == 0) + if (strcmp (classname, itemName) == 0) return true; - if (tr.flFraction > 0.98f && (yb_csdm_mode.GetBool () && strncmp (STRING (tr.pHit->v.classname), "csdmw_", 6) == 0)) + if (tr.flFraction > 0.98f && ((g_gameFlags & GAME_CSDM) && strncmp (classname, "csdmw_", 6) == 0)) return true; return false; @@ -1061,7 +1063,7 @@ void Bot::RadioMessage (int message) m_forceRadio = false; m_radioSelect = message; - PushMessageQueue (GSM_RADIO); + PushMessageQueue (GAME_MSG_RADIO); } void Bot::ChatterMessage (int message) @@ -1085,7 +1087,7 @@ void Bot::ChatterMessage (int message) return; m_radioSelect = message; - PushMessageQueue (GSM_RADIO); + PushMessageQueue (GAME_MSG_RADIO); } void Bot::CheckMessageQueue (void) @@ -1100,22 +1102,22 @@ void Bot::CheckMessageQueue (void) int state = GetMessageQueue (); // nothing to do? - if (state == GSM_IDLE || (state == GSM_RADIO && yb_csdm_mode.GetInt () == 2)) + if (state == GAME_MSG_NONE || (state == GAME_MSG_RADIO && (g_gameFlags & GAME_CSDM_FFA))) return; switch (state) { - case GSM_BUY_STUFF: // general buy message + case GAME_MSG_PURCHASE: // general buy message // buy weapon if (m_nextBuyTime > engine.Time ()) { // keep sending message - PushMessageQueue (GSM_BUY_STUFF); + PushMessageQueue (GAME_MSG_PURCHASE); return; } - if (!m_inBuyZone || yb_csdm_mode.GetBool ()) + if (!m_inBuyZone || (g_gameFlags & GAME_CSDM)) { m_buyPending = true; m_buyingFinished = true; @@ -1164,12 +1166,12 @@ void Bot::CheckMessageQueue (void) return; } - PushMessageQueue (GSM_IDLE); + PushMessageQueue (GAME_MSG_NONE); PurchaseWeapons (); break; - case GSM_RADIO: // general radio message issued + case GAME_MSG_RADIO: // general radio message issued // if last bot radio command (global) happened just a second ago, delay response if (g_lastRadioTime[m_team] + 1.0f < engine.Time ()) { @@ -1294,16 +1296,16 @@ void Bot::CheckMessageQueue (void) g_lastRadioTime[m_team] = engine.Time (); // store last radio usage } else - PushMessageQueue (GSM_RADIO); + PushMessageQueue (GAME_MSG_RADIO); break; // team independent saytext - case GSM_SAY: + case GAME_MSG_SAY_CMD: SayText (m_tempStrings); break; // team dependent saytext - case GSM_SAY_TEAM: + case GAME_MSG_SAY_TEAM_MSG: TeamSayText (m_tempStrings); break; @@ -1773,7 +1775,7 @@ void Bot::PurchaseWeapons (void) } m_buyState++; - PushMessageQueue (GSM_BUY_STUFF); + PushMessageQueue (GAME_MSG_PURCHASE); } TaskItem *MaxDesire (TaskItem *first, TaskItem *second) @@ -2987,7 +2989,7 @@ void Bot::PeriodicThink (void) if (!sayBufferExists) { PrepareChatMessage (pickedPhrase); - PushMessageQueue (GSM_SAY); + PushMessageQueue (GAME_MSG_SAY_CMD); // add to ignore list m_sayTextBuffer.lastUsedSentences.Push (pickedPhrase); @@ -3060,7 +3062,7 @@ void Bot::RunTask_Normal (void) } // reached waypoint is a camp waypoint - if ((m_currentPath->flags & FLAG_CAMP) && !yb_csdm_mode.GetBool () && yb_camping_allowed.GetBool ()) + if ((m_currentPath->flags & FLAG_CAMP) && !(g_gameFlags & GAME_CSDM) && yb_camping_allowed.GetBool ()) { // check if bot has got a primary weapon and hasn't camped before if (HasPrimaryWeapon () && m_timeCamping + 10.0f < engine.Time () && !HasHostage ()) @@ -5286,7 +5288,7 @@ void Bot::GetDamage (edict_t *inflictor, int damage, int armor, int bits) m_seeEnemyTime = engine.Time (); } - if (!yb_csdm_mode.GetBool ()) + if (!(g_gameFlags & GAME_CSDM)) CollectExperienceData (inflictor, armor + damage); } } @@ -5488,7 +5490,7 @@ void Bot::ChatMessage (int type, bool isTeamSay) return; PrepareChatMessage (const_cast (pickedPhrase)); - PushMessageQueue (isTeamSay ? GSM_SAY_TEAM : GSM_SAY); + PushMessageQueue (isTeamSay ? GAME_MSG_SAY_TEAM_MSG : GAME_MSG_SAY_CMD); } void Bot::DiscardWeaponForUser (edict_t *user, bool discardC4) @@ -5521,7 +5523,7 @@ void Bot::DiscardWeaponForUser (edict_t *user, bool discardC4) m_buyingFinished = false; m_buyState = BUYSTATE_PRIMARY_WEAPON; - PushMessageQueue (GSM_BUY_STUFF); + PushMessageQueue (GAME_MSG_PURCHASE); m_nextBuyTime = engine.Time (); } } @@ -5899,7 +5901,7 @@ void Bot::ReactOnSound (void) } edict_t *player = nullptr; - if (hearEnemyIndex >= 0 && g_clients[hearEnemyIndex].team != m_team && yb_csdm_mode.GetInt () != 2) + if (hearEnemyIndex >= 0 && g_clients[hearEnemyIndex].team != m_team && !(g_gameFlags & GAME_CSDM_FFA)) player = g_clients[hearEnemyIndex].ent; // did the bot hear someone ? @@ -5995,7 +5997,7 @@ void Bot::EquipInBuyzone (int buyState) m_buyState = buyState; // push buy message - PushMessageQueue (GSM_BUY_STUFF); + PushMessageQueue (GAME_MSG_PURCHASE); m_nextBuyTime = engine.Time (); m_lastEquipTime = engine.Time (); diff --git a/source/chatlib.cpp b/source/chatlib.cpp index f7adc2f..4ba2a1c 100644 --- a/source/chatlib.cpp +++ b/source/chatlib.cpp @@ -416,7 +416,7 @@ bool Bot::RepliesToPlayer (void) if (Random.Int (1, 100) < m_sayTextBuffer.chatProbability + Random.Int (2, 10) && ParseChat (reinterpret_cast (&text))) { PrepareChatMessage (text); - PushMessageQueue (GSM_SAY); + PushMessageQueue (GAME_MSG_SAY_CMD); m_sayTextBuffer.entityIndex = -1; m_sayTextBuffer.sayText[0] = 0x0; diff --git a/source/combat.cpp b/source/combat.cpp index 92133db..bcab996 100644 --- a/source/combat.cpp +++ b/source/combat.cpp @@ -11,7 +11,6 @@ ConVar yb_shoots_thru_walls ("yb_shoots_thru_walls", "2"); ConVar yb_ignore_enemies ("yb_ignore_enemies", "0"); -ConVar yb_csdm_mode ("yb_csdm_mode", "0"); ConVar yb_check_enemy_rendering ("yb_check_enemy_rendering", "0"); ConVar mp_friendlyfire ("mp_friendlyfire", nullptr, VT_NOREGISTER); @@ -559,7 +558,7 @@ float Bot::GetZOffset (float distance) bool Bot::IsFriendInLineOfFire (float distance) { // bot can't hurt teammates, if friendly fire is not enabled... - if (!mp_friendlyfire.GetBool () || yb_csdm_mode.GetInt () > 0) + if (!mp_friendlyfire.GetBool () || (g_gameFlags & GAME_CSDM)) return false; MakeVectors (pev->v_angle); @@ -1470,7 +1469,7 @@ void Bot::AttachToUser (void) void Bot::CommandTeam (void) { // prevent spamming - if (m_timeTeamOrder > engine.Time () + 2 || yb_csdm_mode.GetInt () == 2 || yb_communication_type.GetInt () == 0) + if (m_timeTeamOrder > engine.Time () + 2.0f || (g_gameFlags & GAME_CSDM_FFA) || !yb_communication_type.GetInt ()) return; bool memberNear = false; diff --git a/source/engine.cpp b/source/engine.cpp index 8fb07ba..89389c7 100644 --- a/source/engine.cpp +++ b/source/engine.cpp @@ -631,12 +631,12 @@ void Engine::ProcessMessageCapture (void *ptr) switch (intVal) { case VMS_TEAM: - bot->m_startAction = GSM_TEAM_SELECT; + bot->m_startAction = GAME_MSG_TEAM_SELECT; break; case VMS_TF: case VMS_CT: - bot->m_startAction = GSM_CLASS_SELECT; + bot->m_startAction = GAME_MSG_CLASS_SELECT; break; } } @@ -649,21 +649,21 @@ void Engine::ProcessMessageCapture (void *ptr) break; if (strcmp (strVal, "#Team_Select") == 0) // team select menu? - bot->m_startAction = GSM_TEAM_SELECT; + bot->m_startAction = GAME_MSG_TEAM_SELECT; else if (strcmp (strVal, "#Team_Select_Spect") == 0) // team select menu? - bot->m_startAction = GSM_TEAM_SELECT; + bot->m_startAction = GAME_MSG_TEAM_SELECT; else if (strcmp (strVal, "#IG_Team_Select_Spect") == 0) // team select menu? - bot->m_startAction = GSM_TEAM_SELECT; + bot->m_startAction = GAME_MSG_TEAM_SELECT; else if (strcmp (strVal, "#IG_Team_Select") == 0) // team select menu? - bot->m_startAction = GSM_TEAM_SELECT; + bot->m_startAction = GAME_MSG_TEAM_SELECT; else if (strcmp (strVal, "#IG_VIP_Team_Select") == 0) // team select menu? - bot->m_startAction = GSM_TEAM_SELECT; + bot->m_startAction = GAME_MSG_TEAM_SELECT; else if (strcmp (strVal, "#IG_VIP_Team_Select_Spect") == 0) // team select menu? - bot->m_startAction = GSM_TEAM_SELECT; + bot->m_startAction = GAME_MSG_TEAM_SELECT; else if (strcmp (strVal, "#Terrorist_Select") == 0) // T model select? - bot->m_startAction = GSM_CLASS_SELECT; + bot->m_startAction = GAME_MSG_CLASS_SELECT; else if (strcmp (strVal, "#CT_Select") == 0) // CT model select menu? - bot->m_startAction = GSM_CLASS_SELECT; + bot->m_startAction = GAME_MSG_CLASS_SELECT; break; @@ -1043,7 +1043,7 @@ void Engine::ProcessMessageCapture (void *ptr) else client.team2 = SPECTATOR; - if (yb_csdm_mode.GetInt () == 2) + if (g_gameFlags & GAME_CSDM_FFA) client.team = playerIndex; else client.team = client.team2; diff --git a/source/interface.cpp b/source/interface.cpp index a707cd6..9864dce 100644 --- a/source/interface.cpp +++ b/source/interface.cpp @@ -12,7 +12,6 @@ // console vars ConVar yb_password ("yb_password", "", VT_PASSWORD); ConVar yb_password_key ("yb_password_key", "_ybpw"); - ConVar yb_language ("yb_language", "en"); ConVar yb_version ("yb_version", PRODUCT_VERSION, VT_READONLY); @@ -1513,7 +1512,6 @@ void ClientCommand (edict_t *ent) case 4: bots.KillAll (); - DisplayMenuToClient (ent, BOT_MENU_MAIN); break; case 10: @@ -2262,17 +2260,25 @@ void StartFrame (void) if (g_gameFlags & GAME_METAMOD) { - static cvar_t *csdm_active; - static cvar_t *mp_freeforall; + static auto dmActive = g_engfuncs.pfnCVarGetPointer ("csdm_active"); + static auto freeForAll = g_engfuncs.pfnCVarGetPointer ("mp_freeforall"); - if (csdm_active == nullptr) - csdm_active = CVAR_GET_POINTER ("csdm_active"); + if (dmActive && freeForAll) + { + if (dmActive->value > 0.0f) + { + g_gameFlags |= GAME_CSDM; - if (mp_freeforall == nullptr) - mp_freeforall = CVAR_GET_POINTER ("mp_freeforall"); + if (freeForAll->value > 0.0f) + g_gameFlags |= GAME_CSDM_FFA; + else if (g_gameFlags & GAME_CSDM_FFA) + g_gameFlags &= ~GAME_CSDM_FFA; + } + else if (g_gameFlags & GAME_CSDM) + g_gameFlags &= ~GAME_CSDM; - if (csdm_active != nullptr && csdm_active->value > 0) - yb_csdm_mode.SetInt (mp_freeforall != nullptr && mp_freeforall->value > 0 ? 2 : 1); + engine.Printf ("CSDM = %s (FFA = %s)", g_gameFlags & GAME_CSDM ? "true" : "false", g_gameFlags & GAME_CSDM_FFA ? "true" : "false"); + } } g_timePerSecondUpdate = engine.Time () + 1.0f; } diff --git a/source/manager.cpp b/source/manager.cpp index 1859895..7ea451e 100644 --- a/source/manager.cpp +++ b/source/manager.cpp @@ -450,6 +450,9 @@ void BotManager::MaintainBotQuota (void) else if (callResult == BOT_RESULT_TEAM_STACKED) { engine.Printf ("Could not add bot to the game: Team is stacked (to disable this check, set mp_limitteams and mp_autoteambalance to zero and restart the round)"); + + m_creationTab.RemoveAll (); + yb_quota.SetInt (GetBotsNum ()); } m_maintainTime = engine.Time () + 0.20f; } @@ -478,9 +481,9 @@ void BotManager::MaintainBotQuota (void) // quota mode char mode = yb_quota_mode.GetString ()[0]; - if (mode == 'f') // fill + if (mode == 'f' || mode == 'F') // fill desiredCount = A_max (0, desiredCount - numHumans); - else if (mode == 'm') // match + else if (mode == 'm' || mode == 'M') // match desiredCount = A_max (0, yb_quota.GetInt () * numHumans); desiredCount = A_min (desiredCount, engine.MaxClients () - (numHumans + (yb_autovacate.GetBool () ? 1 : 0))); @@ -946,7 +949,7 @@ Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int member, c m_notStarted = true; // hasn't joined game yet m_forceRadio = false; - m_startAction = GSM_IDLE; + m_startAction = GAME_MSG_NONE; m_retryJoin = 0; m_moneyAmount = 0; m_logotypeIndex = Random.Int (0, 9); @@ -1030,7 +1033,9 @@ Bot::~Bot (void) { // this is bot destructor + EnableChatterIcon (false); ReleaseUsedName (); + DeleteSearchNodes (); ResetTasks (); } @@ -1096,13 +1101,12 @@ bool BotManager::IsTeamStacked (int team) { const Client &client = g_clients[i]; - if ((client.flags & CF_USED) && ((client.team == TERRORIST) || client.team == CT)) - teamCount[client.team]++; + if ((client.flags & CF_USED) && client.team2 != SPECTATOR) + teamCount[client.team2]++; } return teamCount[team] + 1 > teamCount[team == CT ? TERRORIST : CT] + teamLimit; } - void Bot::NewRound (void) { // this function initializes a bot after creation & at the start of each round @@ -1300,13 +1304,13 @@ void Bot::NewRound (void) // clear its message queue for (i = 0; i < 32; i++) - m_messageQueue[i] = GSM_IDLE; + m_messageQueue[i] = GAME_MSG_NONE; m_actMessageIndex = 0; m_pushMessageIndex = 0; // and put buying into its message queue - PushMessageQueue (GSM_BUY_STUFF); + PushMessageQueue (GAME_MSG_PURCHASE); PushTask (TASK_NORMAL, TASKPRI_NORMAL, -1, 0.0f, true); if (Random.Int (0, 100) < 50) @@ -1365,7 +1369,7 @@ void Bot::StartGame (void) m_notStarted = false; // if bot was unable to join team, and no menus popups, check for stacked team - if (m_startAction == GSM_IDLE && ++m_retryJoin > 2) + if (m_startAction == GAME_MSG_NONE && ++m_retryJoin > 2) { if (bots.IsTeamStacked (m_wantedTeam - 1)) { @@ -1379,9 +1383,9 @@ void Bot::StartGame (void) } // handle counter-strike stuff here... - if (m_startAction == GSM_TEAM_SELECT) + if (m_startAction == GAME_MSG_TEAM_SELECT) { - m_startAction = GSM_IDLE; // switch back to idle + m_startAction = GAME_MSG_NONE; // switch back to idle char teamJoin = yb_join_team.GetString ()[0]; @@ -1396,9 +1400,9 @@ void Bot::StartGame (void) // select the team the bot wishes to join... engine.IssueBotCommand (GetEntity (), "menuselect %d", m_wantedTeam); } - else if (m_startAction == GSM_CLASS_SELECT) + else if (m_startAction == GAME_MSG_CLASS_SELECT) { - m_startAction = GSM_IDLE; // switch back to idle + m_startAction = GAME_MSG_NONE; // switch back to idle // czero has additional models int maxChoice = (g_gameFlags & GAME_CZERO) ? 5 : 4;