diff --git a/include/core.h b/include/core.h index fa1cc35..2ca004d 100644 --- a/include/core.h +++ b/include/core.h @@ -63,7 +63,7 @@ enum GameFlags GAME_CZERO = (1 << 2), // Counter-Strike: Condition Zero GAME_LEGACY = (1 << 3), // Counter-Strike 1.3-1.5 with/without Steam GAME_MOBILITY = (1 << 4), // additional flag that bot is running on android (additional flag) - GAME_OFFICIAL_CSBOT = (1 << 5) // additional flag that indicates offficial cs bots are ingame + GAME_OFFICIAL_CSBOT = (1 << 5) // additional flag that indicates official cs bots are in game }; // log levels @@ -74,7 +74,6 @@ enum LogLevel LL_ERROR = 3, // error log message LL_IGNORE = 4, // additional flag LL_FATAL = 5 // fatal error log message (terminate the game!) - }; // chat types id's @@ -284,6 +283,34 @@ enum Weapon #endif }; +// buy counts +enum BuyState +{ + BUYSTATE_PRIMARY_WEAPON = 0, + BUYSTATE_ARMOR_VESTHELM, + BUYSTATE_SECONDARY_WEAPON, + BUYSTATE_GRENADES, + BUYSTATE_DEFUSER, + BUYSTATE_AMMO, + BUYSTATE_FINISHED +}; + +// economics limits +enum EconomyLimit +{ + ECO_PRIMARY_GT = 0, + ECO_SMG_GT_CT, + ECO_SMG_GT_TE, + ECO_SHOTGUN_GT, + ECO_SHOTGUN_LT, + ECO_HEAVY_GT, + ECO_HEAVY_LT, + ECO_PROSTOCK_NORMAL, + ECO_PROSTOCK_RUSHER, + ECO_PROSTOCK_CAREFUL, + ECO_SHIELDGUN_GT +}; + // defines for pickup items enum PickupType { @@ -445,6 +472,14 @@ enum PathFlag PATHFLAG_JUMP = (1 << 0), // must jump for this connection }; +// enum pathfind search type +enum SearchPathType +{ + SEARCH_PATH_FASTEST = 0, + SEARCH_PATH_SAFEST_FASTER, + SEARCH_PATH_SAFEST +}; + // defines waypoint connection types enum PathConnection { @@ -752,7 +787,7 @@ private: PathNode *m_navNodeStart; // pointer to start of path finding nodes Path *m_currentPath; // pointer to the current path waypoint - unsigned char m_pathType; // which pathfinder to use + SearchPathType m_pathType; // which pathfinder to use unsigned char m_visibility; // visibility flags int m_currentWaypointIndex; // current waypoint index @@ -854,7 +889,7 @@ private: void PurchaseWeapons (void); bool IsMorePowerfulWeaponCanBeBought (void); - int PickBestFromRandom (int *random, int count); + int PickBestFromRandom (int *random, int count, int moneySave); bool CanDuckUnder (const Vector &normal); bool CanJumpUp (const Vector &normal); @@ -1018,7 +1053,7 @@ private: int GetAimingWaypoint (const Vector &to); void FindShortestPath (int srcIndex, int destIndex); - void FindPath (int srcIndex, int destIndex, unsigned char pathType = 0); + void FindPath (int srcIndex, int destIndex, SearchPathType pathType = SEARCH_PATH_FASTEST); void DebugMsg (const char *format, ...); void PeriodicThink (void); @@ -1153,7 +1188,7 @@ public: void DisplayDebugOverlay (void); void NewRound (void); - void EquipInBuyzone (int buyCount); + void EquipInBuyzone (int buyState); void PushMessageQueue (int message); void PrepareChatMessage (char *text); bool FindWaypoint (void); diff --git a/project/yapb.vcxproj b/project/yapb.vcxproj index 1b089e6..5d6b43f 100644 --- a/project/yapb.vcxproj +++ b/project/yapb.vcxproj @@ -49,6 +49,7 @@ {C232645A-3B99-48F4-A1F3-F20CF0A9568B} yapb 8.1 + 8.1 @@ -80,7 +81,7 @@ true true false - AllRules.ruleset + NativeRecommendedRules.ruleset .\release\ diff --git a/source/basecode.cpp b/source/basecode.cpp index 3fd24ad..1b827c9 100644 --- a/source/basecode.cpp +++ b/source/basecode.cpp @@ -1104,12 +1104,12 @@ void Bot::CheckMessageQueue (void) // if bot buying is off then no need to buy if (!yb_botbuy.GetBool ()) - m_buyState = 6; + m_buyState = BUYSTATE_FINISHED; // if fun-mode no need to buy if (yb_jasonmode.GetBool ()) { - m_buyState = 6; + m_buyState = BUYSTATE_FINISHED; SelectWeaponByName ("weapon_knife"); } @@ -1117,8 +1117,8 @@ void Bot::CheckMessageQueue (void) if (IsPlayerVIP (GetEntity ())) { m_isVIP = true; - m_buyState = 6; - m_pathType = 0; + m_buyState = BUYSTATE_FINISHED; + m_pathType = SEARCH_PATH_FASTEST; } // prevent terrorists from buying on es maps @@ -1128,13 +1128,13 @@ void Bot::CheckMessageQueue (void) // prevent teams from buying on fun maps if (g_mapType & (MAP_KA | MAP_FY)) { - m_buyState = 6; + m_buyState = BUYSTATE_FINISHED; if (g_mapType & MAP_KA) yb_jasonmode.SetInt (1); } - if (m_buyState > 5) + if (m_buyState > BUYSTATE_FINISHED - 1) { m_buyingFinished = true; return; @@ -1382,11 +1382,11 @@ bool Bot::IsMorePowerfulWeaponCanBeBought (void) return false; } -int Bot::PickBestFromRandom (int *random, int count) +int Bot::PickBestFromRandom(int *random, int count, int moneySave) { // this function taken from gina bot, it's picks best available weapon from random choice - float buyFactor = (m_moneyAmount - 3000.0f) / (16000.0f - 3000.0f) * 3.0f; + float buyFactor = (m_moneyAmount - static_cast (moneySave)) / (16000.0f - static_cast (moneySave)) * 3.0f; if (buyFactor < 1.0f) buyFactor = 1.0f; @@ -1410,15 +1410,16 @@ void Bot::PurchaseWeapons (void) bool isPistolMode = g_weaponSelect[25].teamStandard == -1 && g_weaponSelect[3].teamStandard == 2; bool teamEcoValid = bots.EconomicsValid (m_team); - // do this, because xash engine is not capable to run all the features goldsrc, but we have cs 1.6 on it, so buy table must be the same bool isOldGame = (g_gameFlags & GAME_LEGACY) && !(g_gameFlags & GAME_XASH); switch (m_buyState) { - case 0: // if no primary weapon and bot has some money, buy a primary weapon + case BUYSTATE_PRIMARY_WEAPON: // if no primary weapon and bot has some money, buy a primary weapon if ((!HasShield () && !HasPrimaryWeapon () && teamEcoValid) || (teamEcoValid && IsMorePowerfulWeaponCanBeBought ())) { + int moneySave = 0; + do { bool ignoreWeapon = false; @@ -1450,21 +1451,22 @@ void Bot::PurchaseWeapons (void) if (IsRestricted (selectedWeapon->id)) continue; - int economicsPrice = 0; + int *limit = g_botBuyEconomyTable; + int prostock = 0; - // filter out weapons with bot economics (thanks for idea to nicebot project) + // filter out weapons with bot economics switch (m_personality) { case PERSONALITY_RUSHER: - economicsPrice = g_botBuyEconomyTable[8]; + prostock = limit[ECO_PROSTOCK_RUSHER]; break; case PERSONALITY_CAREFUL: - economicsPrice = g_botBuyEconomyTable[7]; + prostock = limit[ECO_PROSTOCK_CAREFUL]; break; case PERSONALITY_NORMAL: - economicsPrice = g_botBuyEconomyTable[9]; + prostock = limit[ECO_PROSTOCK_NORMAL]; break; } @@ -1476,12 +1478,12 @@ void Bot::PurchaseWeapons (void) case WEAPON_UMP45: case WEAPON_P90: case WEAPON_MP5: - if (m_moneyAmount > g_botBuyEconomyTable[1] + economicsPrice) + if (m_moneyAmount > limit[ECO_SMG_GT_CT] + prostock) ignoreWeapon = true; break; } - if (selectedWeapon->id == WEAPON_SHIELD && m_moneyAmount > g_botBuyEconomyTable[10]) + if (selectedWeapon->id == WEAPON_SHIELD && m_moneyAmount > limit[ECO_SHIELDGUN_GT]) ignoreWeapon = true; } else if (m_team == TERRORIST) @@ -1493,7 +1495,7 @@ void Bot::PurchaseWeapons (void) case WEAPON_P90: case WEAPON_MP5: case WEAPON_SCOUT: - if (m_moneyAmount > g_botBuyEconomyTable[2] + economicsPrice) + if (m_moneyAmount > limit[ECO_SMG_GT_TE] + prostock) ignoreWeapon = true; break; } @@ -1503,8 +1505,12 @@ void Bot::PurchaseWeapons (void) { case WEAPON_XM1014: case WEAPON_M3: - if (m_moneyAmount < g_botBuyEconomyTable[3] || m_moneyAmount > g_botBuyEconomyTable[4]) + if (m_moneyAmount < limit[ECO_SHOTGUN_LT]) ignoreWeapon = true; + + if (m_moneyAmount >= limit[ECO_SHOTGUN_GT]) + ignoreWeapon = false; + break; } @@ -1514,15 +1520,20 @@ void Bot::PurchaseWeapons (void) case WEAPON_G3SG1: case WEAPON_AWP: case WEAPON_M249: - if (m_moneyAmount < g_botBuyEconomyTable[5] || m_moneyAmount > g_botBuyEconomyTable[6]) + if (m_moneyAmount < limit[ECO_HEAVY_LT]) ignoreWeapon = true; + + if (m_moneyAmount >= limit[ECO_HEAVY_GT]) + ignoreWeapon = false; + break; } if (ignoreWeapon && g_weaponSelect[25].teamStandard == 1 && yb_economics_rounds.GetBool ()) continue; - int moneySave = Random.Long (900, 1100); + // save money for grenade for example? + moneySave = Random.Long (300, 600); if (bots.GetLastWinner () == m_team) moneySave = 0; @@ -1539,7 +1550,7 @@ void Bot::PurchaseWeapons (void) // choose randomly from the best ones... if (foundWeapons > 1) - chosenWeapon = PickBestFromRandom (choices, foundWeapons); + chosenWeapon = PickBestFromRandom (choices, foundWeapons, moneySave); else chosenWeapon = choices[foundWeapons - 1]; @@ -1574,7 +1585,7 @@ void Bot::PurchaseWeapons (void) break; } - case 1: // if armor is damaged and bot has some money, buy some armor + case BUYSTATE_ARMOR_VESTHELM: // if armor is damaged and bot has some money, buy some armor if (pev->armorvalue < Random.Long (50, 80) && (isPistolMode || (teamEcoValid && HasPrimaryWeapon ()))) { // if bot is rich, buy kevlar + helmet, else buy a single kevlar @@ -1585,7 +1596,7 @@ void Bot::PurchaseWeapons (void) } break; - case 2: // if bot has still some money, buy a better secondary weapon + case BUYSTATE_SECONDARY_WEAPON: // if bot has still some money, buy a better secondary weapon if (isPistolMode || (HasPrimaryWeapon () && (pev->weapons & ((1 << WEAPON_USP) | (1 << WEAPON_GLOCK))) && m_moneyAmount > Random.Long (7500, 9000))) { do @@ -1627,7 +1638,7 @@ void Bot::PurchaseWeapons (void) // choose randomly from the best ones... if (foundWeapons > 1) - chosenWeapon = PickBestFromRandom (choices, foundWeapons); + chosenWeapon = PickBestFromRandom (choices, foundWeapons, Random.Long (100, 200)); else chosenWeapon = choices[foundWeapons - 1]; @@ -1654,7 +1665,7 @@ void Bot::PurchaseWeapons (void) } break; - case 3: // if bot has still some money, choose if bot should buy a grenade or not + case BUYSTATE_GRENADES: // if bot has still some money, choose if bot should buy a grenade or not if (Random.Long (1, 100) < g_grenadeBuyPrecent[0] && m_moneyAmount >= 400 && !IsRestricted (WEAPON_EXPLOSIVE)) { // buy a he grenade @@ -1677,7 +1688,7 @@ void Bot::PurchaseWeapons (void) } break; - case 4: // if bot is CT and we're on a bomb map, randomly buy the defuse kit + case BUYSTATE_DEFUSER: // if bot is CT and we're on a bomb map, randomly buy the defuse kit if ((g_mapType & MAP_DE) && m_team == CT && Random.Long (1, 100) < 80 && m_moneyAmount > 200 && !IsRestricted (WEAPON_DEFUSER)) { if (isOldGame) @@ -1687,7 +1698,7 @@ void Bot::PurchaseWeapons (void) } break; - case 5: // buy enough primary & secondary ammo (do not check for money here) + case BUYSTATE_AMMO: // buy enough primary & secondary ammo (do not check for money here) for (int i = 0; i <= 5; i++) FakeClientCommand (GetEntity (), "buyammo%d", Random.Long (1, 2)); // simulate human @@ -3245,7 +3256,7 @@ void Bot::RunTask_Normal (void) // do pathfinding if it's not the current waypoint if (destIndex != m_currentWaypointIndex) - FindPath (m_currentWaypointIndex, destIndex, ((g_bombPlanted && m_team == CT) || yb_debug_goal.GetInt () != -1) ? 0 : m_pathType); + FindPath (m_currentWaypointIndex, destIndex, ((g_bombPlanted && m_team == CT) || yb_debug_goal.GetInt () != -1) ? SEARCH_PATH_FASTEST : m_pathType); } else { @@ -3390,7 +3401,7 @@ void Bot::RunTask_SeekCover (void) TaskComplete (); m_prevGoalIndex = -1; - m_pathType = 0; + m_pathType = SEARCH_PATH_FASTEST; // start hide task PushTask (TASK_HIDE, TASKPRI_HIDE, -1, GetWorldTime () + Random.Float (5.0f, 15.0f), false); @@ -3458,7 +3469,7 @@ void Bot::RunTask_SeekCover (void) GetTask ()->data = destIndex; if (destIndex != m_currentWaypointIndex) - FindPath (m_currentWaypointIndex, destIndex, 0); + FindPath (m_currentWaypointIndex, destIndex, SEARCH_PATH_FASTEST); } } @@ -3785,7 +3796,7 @@ void Bot::RunTask_PlantBomb (void) TaskComplete (); // tell teammates to move over here... - if (GetNearbyFriendsNearPosition (pev->origin, 1200) != 0) + if (GetNearbyFriendsNearPosition (pev->origin, 1200.0f) != 0) RadioMessage (Radio_NeedBackup); DeleteSearchNodes (); @@ -4481,7 +4492,7 @@ void Bot::RunTask_PickupItem () if (HasShield ()) // If we have the shield... FakeClientCommand (GetEntity (), "drop"); // discard both shield and pistol } - EquipInBuyzone (0); + EquipInBuyzone (BUYSTATE_PRIMARY_WEAPON); } else { @@ -4493,7 +4504,7 @@ void Bot::RunTask_PickupItem () SelectWeaponbyNumber (weaponID); FakeClientCommand (GetEntity (), "drop"); } - EquipInBuyzone (0); + EquipInBuyzone (BUYSTATE_PRIMARY_WEAPON); } CheckSilencer (); // check the silencer } @@ -4988,9 +4999,6 @@ void Bot::BotAI (void) // save the previous speed (for checking if stuck) m_prevSpeed = fabsf (m_moveSpeed); m_lastDamageType = -1; // reset damage - - pev->angles.ClampAngles (); - pev->v_angle.ClampAngles (); } void Bot::DisplayDebugOverlay (void) @@ -5566,7 +5574,7 @@ void Bot::DiscardWeaponForUser (edict_t *user, bool discardC4) if (m_inBuyZone) { m_buyingFinished = false; - m_buyState = 0; + m_buyState = BUYSTATE_PRIMARY_WEAPON; PushMessageQueue (GSM_BUY_STUFF); m_nextBuyTime = GetWorldTime (); @@ -5750,7 +5758,7 @@ void Bot::MoveToVector (const Vector &to) if (to.IsZero ()) return; - FindPath (m_currentWaypointIndex, waypoints.FindNearest (to), 0); + FindPath (m_currentWaypointIndex, waypoints.FindNearest (to), SEARCH_PATH_FASTEST); } byte Bot::ThrottledMsec (void) @@ -6023,7 +6031,7 @@ bool Bot::IsShootableBreakable (edict_t *ent) return false; } -void Bot::EquipInBuyzone (int buyCount) +void Bot::EquipInBuyzone (int buyState) { // this function is gets called when bot enters a buyzone, to allow bot to buy some stuff @@ -6036,7 +6044,7 @@ void Bot::EquipInBuyzone (int buyCount) if (m_seeEnemyTime + 5.0f < GetWorldTime () && m_lastEquipTime + 15.0f < GetWorldTime () && m_inBuyZone && checkBuyTime && !g_bombPlanted && m_moneyAmount > g_botBuyEconomyTable[0]) { m_buyingFinished = false; - m_buyState = buyCount; + m_buyState = buyState; // push buy message PushMessageQueue (GSM_BUY_STUFF); diff --git a/source/manager.cpp b/source/manager.cpp index d7654ef..1679461 100644 --- a/source/manager.cpp +++ b/source/manager.cpp @@ -199,7 +199,6 @@ int BotManager::CreateBot (const String &name, int difficulty, int personality, CenterPrint ("Maximum players reached (%d/%d). Unable to create Bot.", GetMaxClients (), GetMaxClients ()); return 2; } - int index = IndexOfEntity (bot) - 1; InternalAssert (index >= 0 && index <= 32); // check index @@ -1079,15 +1078,15 @@ void Bot::NewRound (void) switch (m_personality) { case PERSONALITY_NORMAL: - m_pathType = Random.Long (0, 100) > 50 ? 1 : 2; + m_pathType = Random.Long (0, 100) > 50 ? SEARCH_PATH_SAFEST_FASTER : SEARCH_PATH_SAFEST; break; case PERSONALITY_RUSHER: - m_pathType = 0; + m_pathType = SEARCH_PATH_FASTEST; break; case PERSONALITY_CAREFUL: - m_pathType = 2; + m_pathType = SEARCH_PATH_SAFEST; break; } @@ -1190,7 +1189,7 @@ void Bot::NewRound (void) m_sayTextBuffer.entityIndex = -1; m_sayTextBuffer.sayText[0] = 0x0; - m_buyState = 0; + m_buyState = BUYSTATE_PRIMARY_WEAPON; m_lastEquipTime = 0.0f; if (!m_notKilled) // if bot died, clear all weapon stuff and force buying again diff --git a/source/navigate.cpp b/source/navigate.cpp index 679f38d..b2b3da0 100644 --- a/source/navigate.cpp +++ b/source/navigate.cpp @@ -1610,7 +1610,7 @@ float hfunctionNumberNodes (int index, int startIndex, int goalIndex) return hfunctionSquareDist (index, startIndex, goalIndex) / 128.0f * g_highestKills; } -void Bot::FindPath (int srcIndex, int destIndex, unsigned char pathType) +void Bot::FindPath(int srcIndex, int destIndex, SearchPathType pathType /*= SEARCH_PATH_FASTEST */) { // this function finds a path from srcIndex to destIndex @@ -1656,7 +1656,7 @@ void Bot::FindPath (int srcIndex, int destIndex, unsigned char pathType) switch (pathType) { - case 0: + case SEARCH_PATH_FASTEST: if ((g_mapType & MAP_CS) && HasHostage ()) { gcalc = gfunctionPathDistWithHostage; @@ -1669,7 +1669,7 @@ void Bot::FindPath (int srcIndex, int destIndex, unsigned char pathType) } break; - case 1: + case SEARCH_PATH_SAFEST_FASTER: if (m_team == TERRORIST) { gcalc = gfunctionKillsDistT; @@ -1687,7 +1687,7 @@ void Bot::FindPath (int srcIndex, int destIndex, unsigned char pathType) } break; - case 2: + case SEARCH_PATH_SAFEST: default: if (m_team == TERRORIST) { @@ -1719,6 +1719,12 @@ void Bot::FindPath (int srcIndex, int destIndex, unsigned char pathType) // remove the first node from the open list int currentIndex = openList.Pop (); + if (currentIndex < 0 || currentIndex > g_numWaypoints) + { + AddLogEntry (false, LL_FATAL, "openList.Pop () = %d. It's not possible to continue execution. Please obtain better waypoint."); + return; + } + // is the current node the goal node? if (currentIndex == destIndex) { diff --git a/source/netmsg.cpp b/source/netmsg.cpp index 72ae95f..c0d1b1f 100644 --- a/source/netmsg.cpp +++ b/source/netmsg.cpp @@ -232,7 +232,7 @@ void NetworkMsg::Execute (void *p) m_bot->m_inBuyZone = (enabled != 0); // try to equip in buyzone - m_bot->EquipInBuyzone (0); + m_bot->EquipInBuyzone (BUYSTATE_PRIMARY_WEAPON); } else if (strcmp (PTR_TO_STR (p), "vipsafety") == 0) m_bot->m_inVIPZone = (enabled != 0); diff --git a/source/support.cpp b/source/support.cpp index dc5de6a..988dde0 100644 --- a/source/support.cpp +++ b/source/support.cpp @@ -1220,7 +1220,7 @@ char *Localizer::TranslateInput (const char *input) { if (strcmp (string, m_langTab[i].original) == 0) { - strncpy (string, m_langTab[i].translated, 1023); + strncpy (string, m_langTab[i].translated, SIZEOF_CHAR (string)); if (ptr != input) strncat (string, ptr, 1024 - 1 - strlen (string)); diff --git a/source/waypoint.cpp b/source/waypoint.cpp index 00f075c..f930aa2 100644 --- a/source/waypoint.cpp +++ b/source/waypoint.cpp @@ -448,7 +448,7 @@ void Waypoint::Delete (void) int index = FindNearest (g_hostEntity->v.origin, 50.0f); - if (index == -1) + if (index < 0) return; Path *path = NULL; @@ -1271,7 +1271,7 @@ bool Waypoint::Reachable (Bot *bot, int index) float distance = (dest - src).GetLength (); - // check is destination is close to us enoguh + // check is destination is close to us enough if (distance >= 150.0f) return false; @@ -2570,7 +2570,7 @@ WaypointDownloadError WaypointDownloader::DoDownload (void) finished = true; // ugly, but whatever - if (buffer[recvPosition - 2] == '4' && buffer[recvPosition - 1] == '0' && buffer[recvPosition] == '4') + if (recvPosition > 2 && buffer[recvPosition - 2] == '4' && buffer[recvPosition - 1] == '0' && buffer[recvPosition] == '4') { FreeSocket (socketHandle); return WDE_NOTFOUND_ERROR;