/* <36b22a> ../cstrike/dlls/bot/cs_bot_manager.cpp:111 */ void CCSBotManager::__MAKE_VHOOK(RestartRound)(void) { // extend CBotManager::RestartRound(); SetLooseBomb(NULL); m_isBombPlanted = false; m_bombDefuser = NULL; m_earliestBombPlantTimestamp = gpGlobals->time + RANDOM_FLOAT(10, 30); IMPLEMENT_ARRAY(m_editCmd) = EDIT_NONE; ResetRadioMessageTimestamps(); m_lastSeenEnemyTimestamp = -9999.9f; m_roundStartTimestamp = gpGlobals->time + CVAR_GET_FLOAT("mp_freezetime"); // randomly decide if defensive team wants to "rush" as a whole const float defenseRushChance = 33.3f; // 25.0f; m_isDefenseRushing = (RANDOM_FLOAT(0, 100) <= defenseRushChance) ? true : false; TheBotPhrases->OnRoundRestart(); m_isRoundOver = false; m_isRespawnStarted = false; m_canRespawn = true; }
/* <36a3b6> ../cstrike/dlls/bot/cs_bot_manager.cpp:331 */ void CCSBotManager::__MAKE_VHOOK(ServerActivate)(void) { DestroyNavigationMap(); IMPLEMENT_ARRAY(m_isMapDataLoaded) = false; m_zoneCount = 0; m_gameScenario = SCENARIO_DEATHMATCH; ValidateMapData(); RestartRound(); IMPLEMENT_ARRAY(m_isLearningMap) = false; IMPLEMENT_ARRAY(m_isAnalysisRequested) = false; m_bServerActive = true; AddServerCommands(); TheBotPhrases->m_placeCount = 0; }
/* <36b780> ../cstrike/dlls/bot/cs_bot_manager.cpp:1109 */ void CCSBotManager::ValidateMapData(void) { if (IMPLEMENT_ARRAY(m_isMapDataLoaded) || !UTIL_IsGame("czero")) { return; } IMPLEMENT_ARRAY(m_isMapDataLoaded) = true; // TODO: Reverse me if (LoadNavigationMap()) { CONSOLE_ECHO("Failed to load navigation map.\n"); return; } CONSOLE_ECHO("Navigation map loaded.\n"); m_zoneCount = 0; m_gameScenario = SCENARIO_DEATHMATCH; // Search all entities in the map and set the game type and // store all zones (bomb target, etc). CBaseEntity *entity = NULL; int i; for (i = 1; i < gpGlobals->maxEntities; i++) { entity = CBaseEntity::Instance(INDEXENT(i)); if (entity == NULL) continue; bool found = false; bool isLegacy = false; if (FClassnameIs(entity->pev, "func_bomb_target")) { found = true; isLegacy = false; m_gameScenario = SCENARIO_DEFUSE_BOMB; } else if (FClassnameIs(entity->pev, "info_bomb_target")) { found = true; isLegacy = true; m_gameScenario = SCENARIO_DEFUSE_BOMB; } else if (FClassnameIs(entity->pev, "func_hostage_rescue")) { found = true; isLegacy = false; m_gameScenario = SCENARIO_RESCUE_HOSTAGES; } else if (FClassnameIs(entity->pev, "info_hostage_rescue")) { found = true; isLegacy = true; m_gameScenario = SCENARIO_RESCUE_HOSTAGES; } else if (FClassnameIs(entity->pev, "hostage_entity")) { // some very old maps (ie: cs_assault) use info_player_start // as rescue zones, so set the scenario if there are hostages // in the map m_gameScenario = SCENARIO_RESCUE_HOSTAGES; } else if (FClassnameIs(entity->pev, "func_vip_safetyzone")) { found = true; isLegacy = false; m_gameScenario = SCENARIO_ESCORT_VIP; } if (found) { if (m_zoneCount < MAX_ZONES) { if (isLegacy) m_zone[ m_zoneCount ].m_center = entity->pev->origin; else m_zone[ m_zoneCount ].m_center = (entity->pev->absmax + entity->pev->absmin) / 2.0f; m_zone[ m_zoneCount ].m_isLegacy = isLegacy; m_zone[ m_zoneCount ].m_index = m_zoneCount; m_zone[ m_zoneCount ].m_entity = entity; ++m_zoneCount; } else CONSOLE_ECHO("Warning: Too many zones, some will be ignored.\n"); } } // If there are no zones and the scenario is hostage rescue, // use the info_player_start entities as rescue zones. if (m_zoneCount == 0 && m_gameScenario == SCENARIO_RESCUE_HOSTAGES) { entity = NULL; while ((entity = UTIL_FindEntityByClassname(entity, "info_player_start")) != NULL) { if (FNullEnt(entity->edict())) break; if (m_zoneCount < MAX_ZONES) { m_zone[ m_zoneCount ].m_center = entity->pev->origin; m_zone[ m_zoneCount ].m_isLegacy = true; m_zone[ m_zoneCount ].m_index = m_zoneCount; m_zone[ m_zoneCount ].m_entity = entity; ++m_zoneCount; } else CONSOLE_ECHO("Warning: Too many zones, some will be ignored.\n"); } } // Collect nav areas that overlap each zone for (i = 0; i < m_zoneCount; i++) { Zone *zone = &m_zone[i]; if (zone->m_isLegacy) { const float legacyRange = 256.0f; zone->m_extent.lo.x = zone->m_center.x - legacyRange; zone->m_extent.lo.y = zone->m_center.y - legacyRange; zone->m_extent.lo.z = zone->m_center.z - legacyRange; zone->m_extent.hi.x = zone->m_center.x + legacyRange; zone->m_extent.hi.y = zone->m_center.y + legacyRange; zone->m_extent.hi.z = zone->m_center.z + legacyRange; } else { zone->m_extent.lo = zone->m_entity->pev->absmin; zone->m_extent.hi = zone->m_entity->pev->absmax; } // ensure Z overlap const float zFudge = 50.0f; zone->m_areaCount = 0; zone->m_extent.lo.z -= zFudge; zone->m_extent.hi.z += zFudge; // build a list of nav areas that overlap this zone for (NavAreaList::iterator iter = TheNavAreaList.begin(); iter != TheNavAreaList.end(); ++iter) { CNavArea *area = (*iter); const Extent *areaExtent = area->GetExtent(); if (areaExtent->hi.x >= zone->m_extent.lo.x && areaExtent->lo.x <= zone->m_extent.hi.x && areaExtent->hi.y >= zone->m_extent.lo.y && areaExtent->lo.y <= zone->m_extent.hi.y && areaExtent->hi.z >= zone->m_extent.lo.z && areaExtent->lo.z <= zone->m_extent.hi.z) { // area overlaps zone zone->m_area[ zone->m_areaCount++ ] = area; if (zone->m_areaCount == MAX_ZONE_NAV_AREAS) { break; } } } } }
/* <36c3c2> ../cstrike/dlls/bot/cs_bot_manager.cpp:903 */ NOBODY bool CCSBotManager::BotAddCommand(BotProfileTeamType team, bool isFromConsole) { if (IMPLEMENT_ARRAY(m_isLearningMap) || ENG_CHECK_PARM("-nobots", NULL)) return false; const BotProfile *profile = NULL; if (!isFromConsole || CMD_ARGC() < 2) { if (team == BOT_TEAM_ANY) { // if team not specified, check cv_bot_join_team cvar for preference if (!Q_stricmp(cv_bot_join_team.string, "T")) team = BOT_TEAM_T; else if (!Q_stricmp(cv_bot_join_team.string, "CT")) team = BOT_TEAM_CT; else { TeamName defaultTeam = SelectDefaultTeam(); if (defaultTeam == TERRORIST) team = BOT_TEAM_T; else if (defaultTeam == CT) team = BOT_TEAM_CT; } } // try to add a bot by name profile = TheBotProfiles->GetRandomProfile(GetDifficultyLevel(), team); if (profile == NULL) { CONSOLE_ECHO("All bot profiles at this difficulty level are in use.\n"); return true; } } else { // in career, ignore humans bool ignoreHumans = false; CHalfLifeMultiplay *mp = g_pGameRules; if (mp && mp->IsCareer()) ignoreHumans = true; if (UTIL_IsNameTaken(CMD_ARGV(1), ignoreHumans)) { CONSOLE_ECHO("Error - %s is already in the game.\n", CMD_ARGV(1)); return true; } profile = TheBotProfiles->GetProfile(CMD_ARGV(1), team); if (profile == NULL) { CONSOLE_ECHO("Error - no profile for '%s' exists.\n", CMD_ARGV(1)); return true; } } // create the bot if (CCSBotManager::AddBot(profile, team)) // TODO: Reverse me { if (isFromConsole) { // increase the bot quota to account for manually added bot CVAR_SET_FLOAT("bot_quota", cv_bot_quota.value + 1); } } return true; }
/* <4ee669> ../game_shared/bot/nav_file.cpp:379 */ NOBODY void CNavArea::Load(SteamFile *file, unsigned int version) { // load ID file->Read(&m_id, sizeof(unsigned int)); // update nextID to avoid collisions if (m_id >= IMPLEMENT_ARRAY(m_nextID)) IMPLEMENT_ARRAY(m_nextID) = m_id + 1; // load attribute flags file->Read(&m_attributeFlags, sizeof(unsigned char)); // load extent of area file->Read(&m_extent, 6 * sizeof(float)); m_center.x = (m_extent.lo.x + m_extent.hi.x) / 2.0f; m_center.y = (m_extent.lo.y + m_extent.hi.y) / 2.0f; m_center.z = (m_extent.lo.z + m_extent.hi.z) / 2.0f; // load heights of implicit corners file->Read(&m_neZ, sizeof(float)); file->Read(&m_swZ, sizeof(float)); // load connections (IDs) to adjacent areas // in the enum order NORTH, EAST, SOUTH, WEST for (int d = 0; d < NUM_DIRECTIONS; d++) { // load number of connections for this direction unsigned int count; file->Read(&count, sizeof(unsigned int)); for (unsigned int i = 0; i<count; ++i) { NavConnect connect; file->Read(&connect.id, sizeof(unsigned int)); m_connect[d].push_back(connect); } } // // Load hiding spots // // load number of hiding spots unsigned char hidingSpotCount; file->Read(&hidingSpotCount, sizeof(unsigned char)); if (version == 1) { // load simple vector array Vector pos; for (int h = 0; h < hidingSpotCount; ++h) { file->Read(&pos, 3 * sizeof(float)); // create new hiding spot and put on master list HidingSpot *spot = new HidingSpot(&pos, HidingSpot::IN_COVER); m_hidingSpotList.push_back(spot); } } else { // load HidingSpot objects for this area for (int h=0; h<hidingSpotCount; ++h) { // create new hiding spot and put on master list HidingSpot *spot = new HidingSpot; spot->Load(file, version); m_hidingSpotList.push_back(spot); } } // // Load number of approach areas // file->Read(&m_approachCount, sizeof(unsigned char)); // load approach area info (IDs) unsigned char type; for (int a = 0; a < m_approachCount; ++a) { file->Read(&m_approach[a].here.id, sizeof(unsigned int)); file->Read(&m_approach[a].prev.id, sizeof(unsigned int)); file->Read(&type, sizeof(unsigned char) ); m_approach[a].prevToHereHow = (NavTraverseType)type; file->Read(&m_approach[a].next.id, sizeof(unsigned int)); file->Read(&type, sizeof(unsigned char)); m_approach[a].hereToNextHow = (NavTraverseType)type; } // // Load encounter paths for this area // unsigned int count; file->Read(&count, sizeof(unsigned int)); if (version < 3) { // old data, read and discard for (unsigned int e = 0; e < count; ++e) { SpotEncounter encounter; file->Read(&encounter.from.id, sizeof(unsigned int)); file->Read(&encounter.to.id, sizeof(unsigned int)); file->Read(&encounter.path.from.x, 3 * sizeof(float)); file->Read(&encounter.path.to.x, 3 * sizeof(float)); // read list of spots along this path unsigned char spotCount; file->Read(&spotCount, sizeof(unsigned char)); for (int s = 0; s < spotCount; ++s) { Vector pos; file->Read(&pos, 3 * sizeof(float)); file->Read(&pos, sizeof(float)); } } return; } for (unsigned int e = 0; e<count; ++e) { SpotEncounter encounter; file->Read(&encounter.from.id, sizeof(unsigned int)); unsigned char dir; file->Read(&dir, sizeof(unsigned char)); encounter.fromDir = static_cast<NavDirType>(dir); file->Read(&encounter.to.id, sizeof(unsigned int)); file->Read(&dir, sizeof(unsigned char)); encounter.toDir = static_cast<NavDirType>(dir); // read list of spots along this path unsigned char spotCount; file->Read(&spotCount, sizeof(unsigned char)); SpotOrder order; for (int s = 0; s < spotCount; ++s) { file->Read(&order.id, sizeof(unsigned int)); unsigned char t; file->Read(&t, sizeof(unsigned char)); order.t = (float)t / 255.0f; encounter.spotList.push_back(order); } m_spotEncounterList.push_back(encounter); } if (version < 5) return; // // Load Place data // PlaceDirectory::EntryType entry; file->Read(&entry, sizeof(entry)); // convert entry to actual Place SetPlace(placeDirectory.EntryToPlace(entry)); }