//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CCSPlayerResource::UpdatePlayerData( void ) { int i; m_iPlayerC4 = 0; m_iPlayerVIP = 0; for ( i = 1; i <= gpGlobals->maxClients; i++ ) { CCSPlayer *pPlayer = (CCSPlayer*)UTIL_PlayerByIndex( i ); if ( pPlayer && pPlayer->IsConnected() ) { if ( pPlayer->IsVIP() ) { // we should only have one VIP Assert( m_iPlayerVIP == 0 ); m_iPlayerVIP = i; } if ( pPlayer->HasC4() ) { // we should only have one bomb m_iPlayerC4 = i; } } } CBaseEntity *c4 = NULL; if ( m_iPlayerC4 == 0 ) { // no player has C4, update C4 position if ( g_C4s.Count() > 0 ) { c4 = g_C4s[0]; m_vecC4 = c4->GetAbsOrigin(); } else { m_vecC4.Init(); } } //int numHostages = g_Hostages.Count(); for ( i = 0; i < MAX_HOSTAGES; i++ ) { /*if ( i >= numHostages ) { // engine->Con_NPrintf( i, "Dead" ); m_bHostageAlive.Set( i, false ); m_isHostageFollowingSomeone.Set( i, false ); continue; } // CHostage* pHostage = g_Hostages[i]; //m_bHostageAlive.Set( i, pHostage->IsRescuable() ); /*if ( pHostage->IsValid() ) { m_iHostageX.Set( i, (int) pHostage->GetAbsOrigin().x ); m_iHostageY.Set( i, (int) pHostage->GetAbsOrigin().y ); m_iHostageZ.Set( i, (int) pHostage->GetAbsOrigin().z ); m_iHostageEntityIDs.Set( i, pHostage->entindex() ); //m_isHostageFollowingSomeone.Set( i, pHostage->IsFollowingSomeone() ); // engine->Con_NPrintf( i, "ID:%d Pos:(%.0f,%.0f,%.0f)", pHostage->entindex(), pHostage->GetAbsOrigin().x, pHostage->GetAbsOrigin().y, pHostage->GetAbsOrigin().z ); } else { // engine->Con_NPrintf( i, "Invalid" ); }*/ } if( !m_foundGoalPositions ) { // We only need to update these once a map, but we need the client to know about them. CBaseEntity* ent = NULL; while ( ( ent = gEntList.FindEntityByClassname( ent, "func_bomb_target" ) ) != NULL ) { const Vector &pos = ent->WorldSpaceCenter(); CNavArea *area = TheNavMesh->GetNearestNavArea( pos, true ); const char *placeName = (area) ? TheNavMesh->PlaceToName( area->GetPlace() ) : NULL; if ( placeName == NULL ) { // The bomb site has no area or place name, so just choose A then B if ( m_bombsiteCenterA.Get().IsZero() ) { m_bombsiteCenterA = pos; } else { m_bombsiteCenterB = pos; } } else { // The bomb site has a place name, so choose accordingly if( FStrEq( placeName, "BombsiteA" ) ) { m_bombsiteCenterA = pos; } else { m_bombsiteCenterB = pos; } } m_foundGoalPositions = true; } int hostageRescue = 0; while ( (( ent = gEntList.FindEntityByClassname( ent, "func_hostage_rescue" ) ) != NULL) && (hostageRescue < MAX_HOSTAGE_RESCUES) ) { const Vector &pos = ent->WorldSpaceCenter(); m_hostageRescueX.Set( hostageRescue, (int) pos.x ); m_hostageRescueY.Set( hostageRescue, (int) pos.y ); m_hostageRescueZ.Set( hostageRescue, (int) pos.z ); hostageRescue++; m_foundGoalPositions = true; } } bool bombSpotted = false; if ( c4 ) { Spotter spotter( c4, m_vecC4, TEAM_CT ); ForEachPlayer( spotter ); if ( spotter.Spotted() ) { bombSpotted = true; } } for ( int i=0; i < MAX_PLAYERS+1; i++ ) { CCSPlayer *target = ToCSPlayer( UTIL_PlayerByIndex( i ) ); if ( !target || !target->IsAlive() ) { m_bPlayerSpotted.Set( i, 0 ); continue; } Spotter spotter( target, target->EyePosition(), (target->GetTeamNumber()==TEAM_CT) ? TEAM_TERRORIST : TEAM_CT ); ForEachPlayer( spotter ); if ( spotter.Spotted() ) { if ( target->HasC4() ) { bombSpotted = true; } m_bPlayerSpotted.Set( i, 1 ); } else { m_bPlayerSpotted.Set( i, 0 ); } } if ( bombSpotted ) { m_bBombSpotted = true; } else { m_bBombSpotted = false; } BaseClass::UpdatePlayerData(); }
/* <4f3e47> ../game_shared/bot/nav_file.cpp:702 */ bool SaveNavigationMap(const char *filename) { if (filename == NULL) return false; // Store the NAV file COM_FixSlashes(const_cast<char *>(filename)); #ifdef WIN32 int fd = _open(filename, _O_BINARY | _O_CREAT | _O_WRONLY, _S_IREAD | _S_IWRITE); #else int fd = creat(filename, S_IRUSR | S_IWUSR | S_IRGRP); #endif // WIN32 if (fd < 0) return false; // store "magic number" to help identify this kind of file unsigned int magic = NAV_MAGIC_NUMBER; Q_write(fd, &magic, sizeof(unsigned int)); // store version number of file // 1 = hiding spots as plain vector array // 2 = hiding spots as HidingSpot objects // 3 = Encounter spots use HidingSpot ID's instead of storing vector again // 4 = Includes size of source bsp file to verify nav data correlation // ---- Beta Release at V4 ----- // 5 = Added Place info unsigned int version = 5; Q_write(fd, &version, sizeof(unsigned int)); // get size of source bsp file and store it in the nav file // so we can test if the bsp changed since the nav file was made char *bspFilename = GetBspFilename(filename); if (bspFilename == NULL) return false; unsigned int bspSize = (unsigned int)GET_FILE_SIZE(bspFilename); CONSOLE_ECHO("Size of bsp file '%s' is %u bytes.\n", bspFilename, bspSize); Q_write(fd, &bspSize, sizeof(unsigned int)); // Build a directory of the Places in this map placeDirectory.Reset(); NavAreaList::iterator it; for (it = TheNavAreaList.begin(); it != TheNavAreaList.end(); ++it) { CNavArea *area = *it; Place place = area->GetPlace(); if (place) { placeDirectory.AddPlace(place); } } placeDirectory.Save(fd); // Store navigation areas // store number of areas unsigned int count = TheNavAreaList.size(); Q_write(fd, &count, sizeof(unsigned int)); // store each area for (it = TheNavAreaList.begin(); it != TheNavAreaList.end(); ++it) { CNavArea *area = *it; area->Save(fd, version); } Q_close(fd); #ifdef _WIN32 // output a simple Wavefront file to visualize the generated areas in 3DSMax FILE *fp = fopen("c:\\tmp\\nav.obj", "w"); if (fp) { for (NavAreaList::iterator iter = TheNavAreaList.begin(); iter != TheNavAreaList.end(); ++iter) { (*iter)->Save(fp); } fclose(fp); } #endif // _WIN32 return true; }
CBasePlayer *CCSBot::FindMostDangerousThreat() { // maximum number of simulataneously attendable threats enum { MAX_THREATS = 16 }; struct CloseInfo { CBasePlayer *enemy; float range; } threat[ MAX_THREATS ]; int threatCount = 0; m_bomber = NULL; m_closestVisibleFriend = NULL; float closeFriendRange = 99999999999.9f; m_closestVisibleHumanFriend = NULL; float closeHumanFriendRange = 99999999999.9f; int i; { for (i = 1; i <= gpGlobals->maxClients; ++i) { CBasePlayer *player = UTIL_PlayerByIndex(i); if (player == NULL) continue; if (FNullEnt(player->pev)) continue; // is it a player? if (!player->IsPlayer()) continue; // ignore self if (player->entindex() == entindex()) continue; // is it alive? if (!player->IsAlive()) continue; // is it an enemy? if (player->m_iTeam == m_iTeam) { TraceResult result; UTIL_TraceLine(GetEyePosition(), player->pev->origin, ignore_monsters, ignore_glass, edict(), &result); if (result.flFraction == 1.0f) { // update watch timestamp int idx = player->entindex() - 1; m_watchInfo[idx].timestamp = gpGlobals->time; m_watchInfo[idx].isEnemy = false; // keep track of our closest friend Vector to = pev->origin - player->pev->origin; float rangeSq = to.LengthSquared(); if (rangeSq < closeFriendRange) { m_closestVisibleFriend = player; closeFriendRange = rangeSq; } // keep track of our closest human friend if (!player->IsBot() && rangeSq < closeHumanFriendRange) { m_closestVisibleHumanFriend = player; closeHumanFriendRange = rangeSq; } } continue; } // check if this enemy is fully if (!IsVisible(player, CHECK_FOV)) continue; // update watch timestamp int idx = player->entindex() - 1; m_watchInfo[idx].timestamp = gpGlobals->time; m_watchInfo[idx].isEnemy = true; // note if we see the bomber if (player->IsBombGuy()) { m_bomber = player; } // keep track of all visible threats Vector d = pev->origin - player->pev->origin; float distSq = d.LengthSquared(); // maintain set of visible threats, sorted by increasing distance if (threatCount == 0) { threat[0].enemy = player; threat[0].range = distSq; threatCount = 1; } else { // find insertion point int j; for (j = 0; j < threatCount; ++j) { if (distSq < threat[j].range) break; } // shift lower half down a notch for (int k = threatCount - 1; k >= j; --k) threat[k + 1] = threat[k]; // insert threat into sorted list threat[j].enemy = player; threat[j].range = distSq; if (threatCount < MAX_THREATS) ++threatCount; } } } { // track the maximum enemy and friend counts we've seen recently int prevEnemies = m_nearbyEnemyCount; int prevFriends = m_nearbyFriendCount; m_nearbyEnemyCount = 0; m_nearbyFriendCount = 0; for (i = 0; i < MAX_CLIENTS; ++i) { if (m_watchInfo[i].timestamp <= 0.0f) continue; const float recentTime = 3.0f; if (gpGlobals->time - m_watchInfo[i].timestamp < recentTime) { if (m_watchInfo[i].isEnemy) ++m_nearbyEnemyCount; else ++m_nearbyFriendCount; } } // note when we saw this batch of enemies if (prevEnemies == 0 && m_nearbyEnemyCount > 0) { m_firstSawEnemyTimestamp = gpGlobals->time; } if (prevEnemies != m_nearbyEnemyCount || prevFriends != m_nearbyFriendCount) { PrintIfWatched("Nearby friends = %d, enemies = %d\n", m_nearbyFriendCount, m_nearbyEnemyCount); } } { // Track the place where we saw most of our enemies struct PlaceRank { unsigned int place; int count; }; static PlaceRank placeRank[ MAX_PLACES_PER_MAP ]; int locCount = 0; PlaceRank common; common.place = 0; common.count = 0; for (i = 0; i < threatCount; ++i) { // find the area the player/bot is standing on CNavArea *area; CCSBot *bot = dynamic_cast<CCSBot *>(threat[i].enemy); if (bot != NULL && bot->IsBot()) { area = bot->GetLastKnownArea(); } else { area = TheNavAreaGrid.GetNearestNavArea(&threat[i].enemy->pev->origin); } if (area == NULL) continue; unsigned int threatLoc = area->GetPlace(); if (!threatLoc) continue; // if place is already in set, increment count int j; for (j = 0; j < locCount; ++j) { if (placeRank[j].place == threatLoc) break; } if (j == locCount) { // new place if (locCount < MAX_PLACES_PER_MAP) { placeRank[ locCount ].place = threatLoc; placeRank[ locCount ].count = 1; if (common.count == 0) common = placeRank[locCount]; ++locCount; } } else { // others are in that place, increment ++placeRank[j].count; // keep track of the most common place if (placeRank[j].count > common.count) common = placeRank[j]; } } // remember most common place m_enemyPlace = common.place; } { if (threatCount == 0) return NULL; // otherwise, find the closest threat that without using shield int t; for (t = 0; t < threatCount; ++t) { if (!threat[t].enemy->IsProtectedByShield()) { return threat[t].enemy; } } } // return closest threat return threat[0].enemy; }