Beispiel #1
0
void GameDLL_Version_f()
{
	if (Q_stricmp(CMD_ARGV(1), "version") != 0)
		return;

	// print version
	CONSOLE_ECHO("ReGameDLL build: " __TIME__ " " __DATE__ " (" APP_VERSION_STRD ")\n");
	CONSOLE_ECHO("ReGameDLL API version %i.%i\n", REGAMEDLL_API_VERSION_MAJOR, REGAMEDLL_API_VERSION_MINOR);
	CONSOLE_ECHO("Build from: " APP_COMMITS_URL APP_COMMIT_ID " " APP_COMMIT_AUTHOR "\n");
}
void CLocalNav::RequestNav(CHostage *pOwner)
{
	if (nodeval > 17 || tot_inqueue)
	{
		if (tot_inqueue >= MAX_HOSTAGES)
		{
			CONSOLE_ECHO("queue full\n");
			return;
		}

		int i = qptr;

		for (int j = 0; j < tot_inqueue; j++)
		{
			CHostage *pHostage = GetClassPtr((CHostage *)queue[i]->pev);

			if (pHostage == pOwner)
				return;

			if (++i == MAX_HOSTAGES)
				i = 0;
		}

		queue[i] = pOwner;
		tot_inqueue++;
	}
	else
		pOwner->NavReady();
}
Beispiel #3
0
/* <4f169d> ../game_shared/bot/nav_file.cpp:811 */
void LoadLocationFile(const char *filename)
{
	char locFilename[256];
	Q_strcpy(locFilename, filename);

	char *dot = Q_strchr(locFilename, '.');
	if (dot)
	{
		Q_strcpy(dot, ".loc");

		int locDataLength;
		char *locDataFile = (char *)LOAD_FILE_FOR_ME(const_cast<char *>(locFilename), &locDataLength);
		char *locData = locDataFile;

		if (locData)
		{
			CONSOLE_ECHO("Loading legacy 'location file' '%s'\n", locFilename);

			// read directory
			locData = MP_COM_Parse(locData);
			int dirSize = Q_atoi(MP_COM_GetToken());

			if (dirSize)
			{
				std::vector<unsigned int> directory;
				directory.reserve(dirSize);

				for (int i = 0; i < dirSize; ++i)
				{
					locData = MP_COM_Parse(locData);
					directory.push_back(TheBotPhrases->NameToID(MP_COM_GetToken()));
				}

				// read places for each nav area
				unsigned int areaID, locDirIndex;
				while (true)
				{
					locData = MP_COM_Parse(locData);
					if (locData == NULL)
						break;

					areaID = Q_atoi(MP_COM_GetToken());

					locData = MP_COM_Parse(locData);
					locDirIndex = Q_atoi(MP_COM_GetToken());

					CNavArea *area = TheNavAreaGrid.GetNavAreaByID(areaID);
					unsigned int place = (locDirIndex > 0) ? directory[locDirIndex - 1] : UNDEFINED_PLACE;

					if (area)
						area->SetPlace(place);
				}
			}

			FREE_FILE(locDataFile);
		}
	}
}
CLocalNav::CLocalNav(CHostage *pOwner)
{
	m_pOwner = pOwner;
	m_pTargetEnt = NULL;
	m_nodeArr = new node_index_t[MAX_NODES];

#ifdef _DEBUG
	CONSOLE_ECHO("Allocated m_nodeArr: %d nodes, %lu bytes\n", MAX_NODES, sizeof(node_index_t) * MAX_NODES);
#endif

	if (tot_hostages >= MAX_HOSTAGES)
	{
#ifdef _DEBUG
		CONSOLE_ECHO("queue full (creation)\n");
#endif
		return;
	}

	hostages[tot_hostages++] = pOwner;
}
/* <36b714> ../cstrike/dlls/bot/cs_bot_manager.cpp:464 */
void PrintAllEntities(void)
{
	for (int i = 1; i < gpGlobals->maxEntities; i++)
	{
		edict_t *edict = INDEXENT(i);

		if (!edict || FStringNull(edict->v.classname))
			continue;

		CONSOLE_ECHO("  %s\n", STRING(edict->v.classname));
	}
}
/* <3fd373> ../cstrike/dlls/bot/cs_gamestate.cpp:313 */
void CSGameState::UpdatePlantedBomb(const Vector *pos)
{
	CCSBotManager *ctrl = TheCSBots();
	const CCSBotManager::Zone *zone = ctrl->GetClosestZone(pos);

	if (zone == NULL)
	{
		CONSOLE_ECHO("ERROR: Bomb planted outside of a zone!\n");
		m_plantedBombsite = UNKNOWN;
	}
	else
	{
		m_plantedBombsite = zone->m_index;
	}

	m_plantedBombPos = *pos;
	m_isPlantedBombPosKnown = true;
	SetBombState(PLANTED);
}
int CLocalNav::PathClear(Vector &vecSource, Vector &vecDest, BOOL fNoMonsters, TraceResult &tr)
{
	TRACE_MONSTER_HULL(m_pOwner->edict(), vecSource, vecDest, fNoMonsters, m_pOwner->edict(), &tr);

	if (tr.fStartSolid)
		return 0;

	if (tr.flFraction == 1)
		return 1;

	if (tr.pHit == m_pTargetEnt)
	{
#ifdef _DEBUG
		CONSOLE_ECHO("target edict hit!\n");
#endif
		m_fTargetEntHit = TRUE;
		return 1;
	}

	return 0;
}
Beispiel #8
0
/* <4f09b8> ../game_shared/bot/nav_file.cpp:212 */
void CNavArea::Save(int fd, unsigned int version)
{
	// save ID
	Q_write(fd, &m_id, sizeof(unsigned int));

	// save attribute flags
	Q_write(fd, &m_attributeFlags, sizeof(unsigned char));

	// save extent of area
	Q_write(fd, &m_extent, 6 * sizeof(float));

	// save heights of implicit corners
	Q_write(fd, &m_neZ, sizeof(float));
	Q_write(fd, &m_swZ, sizeof(float));

	// save connections to adjacent areas
	// in the enum order NORTH, EAST, SOUTH, WEST
	for (int d = 0; d < NUM_DIRECTIONS; ++d)
	{
		// save number of connections for this direction
		unsigned int count = m_connect[d].size();
		Q_write(fd, &count, sizeof(unsigned int));

		NavConnectList::const_iterator iter;
		for (iter = m_connect[d].begin(); iter != m_connect[d].end(); ++iter)
		{
			NavConnect connect = *iter;
			Q_write(fd, &connect.area->m_id, sizeof(unsigned int));
		}
	}

	// Store hiding spots for this area
	unsigned char count;
	if (m_hidingSpotList.size() > 255)
	{
		count = 255;
		CONSOLE_ECHO("Warning: NavArea #%d: Truncated hiding spot list to 255\n", m_id);
	}
	else
	{
		count = m_hidingSpotList.size();
	}

	Q_write(fd, &count, sizeof(unsigned char));

	// store HidingSpot objects
	unsigned int saveCount = 0;
	for (HidingSpotList::iterator iter = m_hidingSpotList.begin(); iter != m_hidingSpotList.end(); ++iter)
	{
		HidingSpot *spot = *iter;

		spot->Save(fd, version);

		// overflow check
		if (++saveCount == count)
			break;
	}

	// Save the approach areas for this area
	// save number of approach areas
	Q_write(fd, &m_approachCount, sizeof(unsigned char));

	if (cv_bot_debug.value > 0.0f)
	{
		CONSOLE_ECHO("  m_approachCount = %d\n", m_approachCount);
	}

	// save approach area info
	unsigned char type;
	unsigned int zero = 0;
	for (int a = 0; a < m_approachCount; ++a)
	{
		if (m_approach[a].here.area)
			Q_write(fd, &m_approach[a].here.area->m_id, sizeof(unsigned int));
		else
			Q_write(fd, &zero, sizeof(unsigned int));

		if (m_approach[a].prev.area)
			Q_write(fd, &m_approach[a].prev.area->m_id, sizeof(unsigned int));
		else
			Q_write(fd, &zero, sizeof(unsigned int));

		type = (unsigned char)m_approach[a].prevToHereHow;
		Q_write(fd, &type, sizeof(unsigned char));

		if (m_approach[a].next.area)
			Q_write(fd, &m_approach[a].next.area->m_id, sizeof(unsigned int));
		else
			Q_write(fd, &zero, sizeof(unsigned int));

		type = (unsigned char)m_approach[a].hereToNextHow;
		Q_write(fd, &type, sizeof(unsigned char));
	}

	// Save encounter spots for this area
	{
		// save number of encounter paths for this area
		unsigned int count = m_spotEncounterList.size();
		Q_write(fd, &count, sizeof(unsigned int));

		if (cv_bot_debug.value > 0.0f)
			CONSOLE_ECHO("  m_spotEncounterList.size() = %d\n", count);

		SpotEncounter *e;
		for (SpotEncounterList::iterator iter = m_spotEncounterList.begin(); iter != m_spotEncounterList.end(); ++iter)
		{
			e = &(*iter);

			if (e->from.area)
				Q_write(fd, &e->from.area->m_id, sizeof(unsigned int));
			else
				Q_write(fd, &zero, sizeof(unsigned int));

			unsigned char dir = e->fromDir;
			Q_write(fd, &dir, sizeof(unsigned char));

			if (e->to.area)
				Q_write(fd, &e->to.area->m_id, sizeof(unsigned int));
			else
				Q_write(fd, &zero, sizeof(unsigned int));

			dir = e->toDir;
			Q_write(fd, &dir, sizeof(unsigned char));

			// write list of spots along this path
			unsigned char spotCount;
			if (e->spotList.size() > 255)
			{
				spotCount = 255;
				CONSOLE_ECHO("Warning: NavArea #%d: Truncated encounter spot list to 255\n", m_id);
			}
			else
			{
				spotCount = e->spotList.size();
			}
			Q_write(fd, &spotCount, sizeof(unsigned char));

			saveCount = 0;
			for (SpotOrderList::iterator oiter = e->spotList.begin(); oiter != e->spotList.end(); ++oiter)
			{
				SpotOrder *order = &(*oiter);

				// order->spot may be NULL if we've loaded a nav mesh that has been edited but not re-analyzed
				unsigned int id = (order->spot) ? order->spot->GetID() : 0;
				Q_write(fd, &id, sizeof(unsigned int));

				unsigned char t = 255 * order->t;
				Q_write(fd, &t, sizeof(unsigned char));

				// overflow check
				if (++saveCount == spotCount)
					break;
			}
		}
	}

	// store place dictionary entry
	PlaceDirectory::EntryType entry = placeDirectory.GetEntry(GetPlace());
	Q_write(fd, &entry, sizeof(entry));
}
/**
 * Load the bot profile database
 */
void BotProfileManager::Init( const char *filename, unsigned int *checksum )
{
    FileHandle_t file = filesystem->Open( filename, "r" );

    if (!file)
    {
        if ( true ) // UTIL_IsGame( "czero" ) )
        {
            CONSOLE_ECHO( "WARNING: Cannot access bot profile database '%s'\n", filename );
        }
        return;
    }

    int dataLength = filesystem->Size( filename );
    char *dataPointer = new char[ dataLength ];
    int dataReadLength = filesystem->Read( dataPointer, dataLength, file );
    filesystem->Close( file );
    if ( dataReadLength > 0 )
    {
        // NULL-terminate based on the length read in, since Read() can transform \r\n to \n and
        // return fewer bytes than we were expecting.
        dataPointer[ dataReadLength - 1 ] = 0;
    }

    const char *dataFile = dataPointer;

    // compute simple checksum
    if (checksum)
    {
        *checksum = 0; // ComputeSimpleChecksum( (const unsigned char *)dataPointer, dataLength );
    }

    BotProfile defaultProfile;

    //
    // Parse the BotProfile.db into BotProfile instances
    //
    while( true )
    {
        dataFile = SharedParse( dataFile );
        if (!dataFile)
            break;

        char *token = SharedGetToken();

        bool isDefault = (!stricmp( token, "Default" ));
        bool isTemplate = (!stricmp( token, "Template" ));
        bool isCustomSkin = (!stricmp( token, "Skin" ));

        if ( isCustomSkin )
        {
            const int BufLen = 64;
            char skinName[BufLen];

            // get skin name
            dataFile = SharedParse( dataFile );
            if (!dataFile)
            {
                CONSOLE_ECHO( "Error parsing %s - expected skin name\n", filename );
                delete [] dataPointer;
                return;
            }
            token = SharedGetToken();
            Q_snprintf( skinName, sizeof( skinName ), "%s", token );

            // get attribute name
            dataFile = SharedParse( dataFile );
            if (!dataFile)
            {
                CONSOLE_ECHO( "Error parsing %s - expected 'Model'\n", filename );
                delete [] dataPointer;
                return;
            }
            token = SharedGetToken();
            if (stricmp( "Model", token ))
            {
                CONSOLE_ECHO( "Error parsing %s - expected 'Model'\n", filename );
                delete [] dataPointer;
                return;
            }

            // eat '='
            dataFile = SharedParse( dataFile );
            if (!dataFile)
            {
                CONSOLE_ECHO( "Error parsing %s - expected '='\n", filename );
                delete [] dataPointer;
                return;
            }
            token = SharedGetToken();
            if (strcmp( "=", token ))
            {
                CONSOLE_ECHO( "Error parsing %s - expected '='\n", filename );
                delete [] dataPointer;
                return;
            }

            // get attribute value
            dataFile = SharedParse( dataFile );
            if (!dataFile)
            {
                CONSOLE_ECHO( "Error parsing %s - expected attribute value\n", filename );
                delete [] dataPointer;
                return;
            }
            token = SharedGetToken();

            const char *decoratedName = GetDecoratedSkinName( skinName, filename );
            bool skinExists = GetCustomSkinIndex( decoratedName ) > 0;
            if ( m_nextSkin < NumCustomSkins && !skinExists )
            {
                // decorate the name
                m_skins[ m_nextSkin ] = CloneString( decoratedName );

                // construct the model filename
                m_skinModelnames[ m_nextSkin ] = CloneString( token );
                m_skinFilenames[ m_nextSkin ] = new char[ strlen(token)*2 + strlen("models/player//.mdl") + 1 ];
                Q_snprintf( m_skinFilenames[ m_nextSkin ], sizeof( m_skinFilenames[ m_nextSkin ] ), "models/player/%s/%s.mdl", token, token );
                ++m_nextSkin;
            }

            // eat 'End'
            dataFile = SharedParse( dataFile );
            if (!dataFile)
            {
                CONSOLE_ECHO( "Error parsing %s - expected 'End'\n", filename );
                delete [] dataPointer;
                return;
            }
            token = SharedGetToken();
            if (strcmp( "End", token ))
            {
                CONSOLE_ECHO( "Error parsing %s - expected 'End'\n", filename );
                delete [] dataPointer;
                return;
            }

            continue; // it's just a custom skin - no need to do inheritance on a bot profile, etc.
        }

        // encountered a new profile
        BotProfile *profile;

        if (isDefault)
        {
            profile = &defaultProfile;
        }
        else
        {
            profile = new BotProfile;

            // always inherit from Default
            *profile = defaultProfile;
        }

        // do inheritance in order of appearance
        if (!isTemplate && !isDefault)
        {
            const BotProfile *inherit = NULL;

            // template names are separated by "+"
            while(true)
            {
                char *c = strchr( token, '+' );
                if (c)
                    *c = '\000';

                // find the given template name
                FOR_EACH_LL( m_templateList, it )
                {
                    BotProfile *profile = m_templateList[ it ];
                    if (!stricmp( profile->GetName(), token ))
                    {
                        inherit = profile;
                        break;
                    }
                }

                if (inherit == NULL)
                {
                    CONSOLE_ECHO( "Error parsing '%s' - invalid template reference '%s'\n", filename, token );
                    delete [] dataPointer;
                    return;
                }

                // inherit the data
                profile->Inherit( inherit, &defaultProfile );

                if (c == NULL)
                    break;

                token = c+1;
            }
        }


        // get name of this profile
        if (!isDefault)
        {
            dataFile = SharedParse( dataFile );
            if (!dataFile)
            {
                CONSOLE_ECHO( "Error parsing '%s' - expected name\n", filename );
                delete [] dataPointer;
                return;
            }
            profile->m_name = CloneString( SharedGetToken() );

            /**
             * HACK HACK
             * Until we have a generalized means of storing bot preferences, we're going to hardcode the bot's
             * preference towards silencers based on his name.
             */
            if ( profile->m_name[0] % 2 )
            {
                profile->m_prefersSilencer = true;
            }
        }

        // read attributes for this profile
        bool isFirstWeaponPref = true;
        while( true )
        {
            // get next token
            dataFile = SharedParse( dataFile );
            if (!dataFile)
            {
                CONSOLE_ECHO( "Error parsing %s - expected 'End'\n", filename );
                delete [] dataPointer;
                return;
            }
            token = SharedGetToken();

            // check for End delimiter
            if (!stricmp( token, "End" ))
                break;

            // found attribute name - keep it
            char attributeName[64];
            strcpy( attributeName, token );

            // eat '='
            dataFile = SharedParse( dataFile );
            if (!dataFile)
            {
                CONSOLE_ECHO( "Error parsing %s - expected '='\n", filename );
                delete [] dataPointer;
                return;
            }

            token = SharedGetToken();
            if (strcmp( "=", token ))
            {
                CONSOLE_ECHO( "Error parsing %s - expected '='\n", filename );
                delete [] dataPointer;
                return;
            }

            // get attribute value
            dataFile = SharedParse( dataFile );
            if (!dataFile)
            {
                CONSOLE_ECHO( "Error parsing %s - expected attribute value\n", filename );
                delete [] dataPointer;
                return;
            }
            token = SharedGetToken();

            // store value in appropriate attribute
            if (!stricmp( "Aggression", attributeName ))
            {
                profile->m_aggression = (float)atof(token) / 100.0f;
            }
            else if (!stricmp( "Skill", attributeName ))
            {
                profile->m_skill = (float)atof(token) / 100.0f;
            }
            else if (!stricmp( "Skin", attributeName ))
            {
                profile->m_skin = atoi(token);
                if ( profile->m_skin == 0 )
                {
                    // atoi() failed - try to look up a custom skin by name
                    profile->m_skin = GetCustomSkinIndex( token, filename );
                }
            }
            else if (!stricmp( "Teamwork", attributeName ))
            {
                profile->m_teamwork = (float)atof(token) / 100.0f;
            }
            else if (!stricmp( "Cost", attributeName ))
            {
                profile->m_cost = atoi(token);
            }
            else if (!stricmp( "VoicePitch", attributeName ))
            {
                profile->m_voicePitch = atoi(token);
            }
            else if (!stricmp( "VoiceBank", attributeName ))
            {
                profile->m_voiceBank = FindVoiceBankIndex( token );
            }
            else if (!stricmp( "WeaponPreference", attributeName ))
            {
                // weapon preferences override parent prefs
                if (isFirstWeaponPref)
                {
                    isFirstWeaponPref = false;
                    profile->m_weaponPreferenceCount = 0;
                }

                if (!stricmp( token, "none" ))
                {
                    profile->m_weaponPreferenceCount = 0;
                }
                else
                {
                    if (profile->m_weaponPreferenceCount < BotProfile::MAX_WEAPON_PREFS)
                    {
                        profile->m_weaponPreference[ profile->m_weaponPreferenceCount++ ] = AliasToWeaponID( token );
                    }
                }
            }
            else if (!stricmp( "ReactionTime", attributeName ))
            {
                profile->m_reactionTime = (float)atof(token);

#ifndef GAMEUI_EXPORTS
                // subtract off latency due to "think" update rate.
                // In GameUI, we don't really care.
                //profile->m_reactionTime -= g_BotUpdateInterval;
#endif

            }
            else if (!stricmp( "AttackDelay", attributeName ))
            {
                profile->m_attackDelay = (float)atof(token);
            }
            else if (!stricmp( "Difficulty", attributeName ))
            {
                // override inheritance
                profile->m_difficultyFlags = 0;

                // parse bit flags
                while(true)
                {
                    char *c = strchr( token, '+' );
                    if (c)
                        *c = '\000';

                    for( int i=0; i<NUM_DIFFICULTY_LEVELS; ++i )
                        if (!stricmp( BotDifficultyName[i], token ))
                            profile->m_difficultyFlags |= (1 << i);

                    if (c == NULL)
                        break;

                    token = c+1;
                }
            }
            else if (!stricmp( "Team", attributeName ))
            {
                if ( !stricmp( token, "T" ) )
                {
                    profile->m_teams = TEAM_TERRORIST;
                }
                else if ( !stricmp( token, "CT" ) )
                {
                    profile->m_teams = TEAM_CT;
                }
                else
                {
                    profile->m_teams = TEAM_UNASSIGNED;
                }
            }
            else
            {
                CONSOLE_ECHO( "Error parsing %s - unknown attribute '%s'\n", filename, attributeName );
            }
        }

        if (!isDefault)
        {
            if (isTemplate)
            {
                // add to template list
                m_templateList.AddToTail( profile );
            }
            else
            {
                // add profile to the master list
                m_profileList.AddToTail( profile );
            }
        }
    }
Beispiel #10
0
/* <4f19c7> ../game_shared/bot/nav_file.cpp:947 */
NavErrorType LoadNavigationMap()
{
	// since the navigation map is destroyed on map change,
	// if it exists it has already been loaded for this map
	if (!TheNavAreaList.empty())
		return NAV_OK;

	// nav filename is derived from map filename
	char filename[256];
	Q_sprintf(filename, "maps\\%s.nav", STRING(gpGlobals->mapname));

	// free previous navigation map data
	DestroyNavigationMap();
	placeDirectory.Reset();

	IMPL_CLASS(CNavArea, m_nextID) = 1;

	SteamFile navFile(filename);

	if (!navFile.IsValid())
		return NAV_CANT_ACCESS_FILE;

	// check magic number
	bool result;
	unsigned int magic;
	result = navFile.Read(&magic, sizeof(unsigned int));
	if (!result || magic != NAV_MAGIC_NUMBER)
	{
		CONSOLE_ECHO("ERROR: Invalid navigation file '%s'.\n", filename);
		return NAV_INVALID_FILE;
	}

	// read file version number
	unsigned int version;
	result = navFile.Read(&version, sizeof(unsigned int));
	if (!result || version > 5)
	{
		CONSOLE_ECHO("ERROR: Unknown navigation file version.\n");
		return NAV_BAD_FILE_VERSION;
	}

	if (version >= 4)
	{
		// get size of source bsp file and verify that the bsp hasn't changed
		unsigned int saveBspSize;
		navFile.Read(&saveBspSize, sizeof(unsigned int));

		// verify size
		char *bspFilename = GetBspFilename(filename);
		if (bspFilename == NULL)
			return NAV_INVALID_FILE;

		unsigned int bspSize = (unsigned int)GET_FILE_SIZE(bspFilename);

		if (bspSize != saveBspSize)
		{
			// this nav file is out of date for this bsp file
			char *msg = "*** WARNING ***\nThe AI navigation data is from a different version of this map.\nThe CPU players will likely not perform well.\n";
			HintMessageToAllPlayers(msg);
			CONSOLE_ECHO("\n-----------------\n");
			CONSOLE_ECHO(msg);
			CONSOLE_ECHO("-----------------\n\n");
		}
	}

	// load Place directory
	if (version >= 5)
	{
		placeDirectory.Load(&navFile);
	}

	// get number of areas
	unsigned int count;
	result = navFile.Read(&count, sizeof(unsigned int));

	Extent extent;
	extent.lo.x = 9999999999.9f;
	extent.lo.y = 9999999999.9f;
	extent.hi.x = -9999999999.9f;
	extent.hi.y = -9999999999.9f;

	// load the areas and compute total extent
	for (unsigned int i = 0; i < count; ++i)
	{
		CNavArea *area = new CNavArea;
		area->Load(&navFile, version);
		TheNavAreaList.push_back(area);

		const Extent *areaExtent = area->GetExtent();

		// check validity of nav area
		if (areaExtent->lo.x >= areaExtent->hi.x || areaExtent->lo.y >= areaExtent->hi.y)
			CONSOLE_ECHO("WARNING: Degenerate Navigation Area #%d at ( %g, %g, %g )\n",
				area->GetID(), area->m_center.x, area->m_center.y, area->m_center.z);

		if (areaExtent->lo.x < extent.lo.x)
			extent.lo.x = areaExtent->lo.x;

		if (areaExtent->lo.y < extent.lo.y)
			extent.lo.y = areaExtent->lo.y;

		if (areaExtent->hi.x > extent.hi.x)
			extent.hi.x = areaExtent->hi.x;

		if (areaExtent->hi.y > extent.hi.y)
			extent.hi.y = areaExtent->hi.y;
	}

	// add the areas to the grid
	TheNavAreaGrid.Initialize(extent.lo.x, extent.hi.x, extent.lo.y, extent.hi.y);

	NavAreaList::iterator iter;
	for (iter = TheNavAreaList.begin(); iter != TheNavAreaList.end(); ++iter)
		TheNavAreaGrid.AddNavArea(*iter);

	// allow areas to connect to each other, etc
	for (iter = TheNavAreaList.begin(); iter != TheNavAreaList.end(); ++iter)
	{
		CNavArea *area = *iter;
		area->PostLoad();
	}

	// load legacy location file (Places)
	if (version < 5)
	{
		LoadLocationFile(filename);
	}

	// Set up all the ladders
	BuildLadders();

	return NAV_OK;
}
/* <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;
}
/* <36ace2> ../cstrike/dlls/bot/cs_bot_manager.cpp:484 */
void CCSBotManager::__MAKE_VHOOK(ServerCommand)(const char *pcmd)
{
	if (!m_bServerActive || !UTIL_IsGame("czero"))
		return;

	char buffer[400];
	const char *msg = CMD_ARGV(1);

	if (FStrEq(pcmd, "bot_about"))
	{
		Q_sprintf(buffer, "\n--------------------------------------------------------------------------\nThe Official Counter-Strike Bot V%d.%02d\nCreated by Michael S. Booth\nWeb: www.turtlerockstudios.com\\csbot\nE-mail: [email protected]\n--------------------------------------------------------------------------\n\n", CSBOT_VERSION_MAJOR, CSBOT_VERSION_MINOR);
		CONSOLE_ECHO(buffer);
		HintMessageToAllPlayers(buffer);
	}
	else if (FStrEq(pcmd, "bot_add"))
	{
		BotAddCommand(BOT_TEAM_ANY);
	}
	else if (FStrEq(pcmd, "bot_add_t"))
	{
		BotAddCommand(BOT_TEAM_T);
	}
	else if (FStrEq(pcmd, "bot_add_ct"))
	{
		BotAddCommand(BOT_TEAM_CT);
	}
	else if (FStrEq(pcmd, "bot_kill"))
	{
		bool killThemAll;
		if (CMD_ARGC() == 1 || FStrEq(msg, "all"))
			killThemAll = true;
		else
			killThemAll = false;

		for (int iIndex = 1; iIndex <= gpGlobals->maxClients; iIndex++)
		{
			CBasePlayer *pPlayer = (CBasePlayer *)UTIL_PlayerByIndex(iIndex);

			if (pPlayer == NULL)
				continue;

			if (FNullEnt(pPlayer->pev))
				continue;

			const char *name = STRING(pPlayer->pev->netname);

			if (FStrEq(name, ""))
				continue;

			if (pPlayer->IsBot())
			{
				if (killThemAll || FStrEq(name, msg))
				{
					pPlayer->TakeDamage(pPlayer->pev, pPlayer->pev, 9999.9f, DMG_CRUSH);
				}
			}
		}
	}
	else if (FStrEq(pcmd, "bot_kick"))
	{
		bool kickThemAll;
		if (CMD_ARGC() == 1 || FStrEq(msg, "all"))
			kickThemAll = true;
		else
			kickThemAll = false;

		for (int iIndex = 1; iIndex <= gpGlobals->maxClients; iIndex++)
		{
			CBasePlayer *pPlayer = (CBasePlayer *)UTIL_PlayerByIndex(iIndex);

			if (pPlayer == NULL)
				continue;

			if (FNullEnt(pPlayer->pev))
				continue;

			const char *name = STRING(pPlayer->pev->netname);

			if (FStrEq(name, ""))
				continue;

			if (pPlayer->IsBot())
			{
				if (kickThemAll || FStrEq(name, msg))
				{
					SERVER_COMMAND(UTIL_VarArgs("kick \"%s\"\n", name));
					CVAR_SET_FLOAT("bot_quota", cv_bot_quota.value - 1);
				}
			}
		}

		if (kickThemAll || cv_bot_quota.value < 0.0f)
		{
			CVAR_SET_FLOAT("bot_quota", 0);
		}
	}
	else if (FStrEq(pcmd, "bot_knives_only"))
	{
		CVAR_SET_FLOAT("bot_allow_pistols", 0);
		CVAR_SET_FLOAT("bot_allow_shotguns", 0);
		CVAR_SET_FLOAT("bot_allow_sub_machine_guns", 0);
		CVAR_SET_FLOAT("bot_allow_rifles", 0);
		CVAR_SET_FLOAT("bot_allow_machine_guns", 0);
		CVAR_SET_FLOAT("bot_allow_grenades", 0);
		CVAR_SET_FLOAT("bot_allow_snipers", 0);
		CVAR_SET_FLOAT("bot_allow_shield", 0);
	}
	else if (FStrEq(pcmd, "bot_pistols_only"))
	{
		CVAR_SET_FLOAT("bot_allow_pistols", 1);
		CVAR_SET_FLOAT("bot_allow_shotguns", 0);
		CVAR_SET_FLOAT("bot_allow_sub_machine_guns", 0);
		CVAR_SET_FLOAT("bot_allow_rifles", 0);
		CVAR_SET_FLOAT("bot_allow_machine_guns", 0);
		CVAR_SET_FLOAT("bot_allow_grenades", 0);
		CVAR_SET_FLOAT("bot_allow_snipers", 0);
		CVAR_SET_FLOAT("bot_allow_shield", 0);
	}
	else if (FStrEq(pcmd, "bot_snipers_only"))
	{
		CVAR_SET_FLOAT("bot_allow_pistols", 1);
		CVAR_SET_FLOAT("bot_allow_shotguns", 0);
		CVAR_SET_FLOAT("bot_allow_sub_machine_guns", 0);
		CVAR_SET_FLOAT("bot_allow_rifles", 0);
		CVAR_SET_FLOAT("bot_allow_machine_guns", 0);
		CVAR_SET_FLOAT("bot_allow_grenades", 0);
		CVAR_SET_FLOAT("bot_allow_snipers", 1);
		CVAR_SET_FLOAT("bot_allow_shield", 0);
	}
	else if (FStrEq(pcmd, "bot_all_weapons"))
	{
		CVAR_SET_FLOAT("bot_allow_pistols", 1);
		CVAR_SET_FLOAT("bot_allow_shotguns", 1);
		CVAR_SET_FLOAT("bot_allow_sub_machine_guns", 1);
		CVAR_SET_FLOAT("bot_allow_rifles", 1);
		CVAR_SET_FLOAT("bot_allow_machine_guns", 1);
		CVAR_SET_FLOAT("bot_allow_grenades", 1);
		CVAR_SET_FLOAT("bot_allow_snipers", 1);
		CVAR_SET_FLOAT("bot_allow_shield", 1);
	}
	else if (FStrEq(pcmd, "entity_dump"))
	{
		PrintAllEntities();
	}
	else if (FStrEq(pcmd, "bot_nav_delete"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_DELETE;
	}
	else if (FStrEq(pcmd, "bot_nav_split"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_SPLIT;
	}
	else if (FStrEq(pcmd, "bot_nav_merge"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_MERGE;
	}
	else if (FStrEq(pcmd, "bot_nav_mark"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_MARK;
	}
	else if (FStrEq(pcmd, "bot_nav_begin_area"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_BEGIN_AREA;
	}
	else if (FStrEq(pcmd, "bot_nav_end_area"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_END_AREA;
	}
	else if (FStrEq(pcmd, "bot_nav_connect"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_CONNECT;
	}
	else if (FStrEq(pcmd, "bot_nav_disconnect"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_DISCONNECT;
	}
	else if (FStrEq(pcmd, "bot_nav_splice"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_SPLICE;
	}
	else if (FStrEq(pcmd, "bot_nav_crouch"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_ATTRIB_CROUCH;
	}
	else if (FStrEq(pcmd, "bot_nav_jump"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_ATTRIB_JUMP;
	}
	else if (FStrEq(pcmd, "bot_nav_precise"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_ATTRIB_PRECISE;
	}
	else if (FStrEq(pcmd, "bot_nav_no_jump"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_ATTRIB_NO_JUMP;
	}
	else if (FStrEq(pcmd, "bot_nav_analyze"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_isAnalysisRequested) = true;
	}
	else if (FStrEq(pcmd, "bot_nav_strip"))
	{
		StripNavigationAreas();// TODO: reverse me
	}
	else if (FStrEq(pcmd, "bot_nav_save"))
	{
		GET_GAME_DIR(buffer);
		buffer[ Q_strlen(buffer) ] = '\\';

		Q_strcat(buffer, CBotManager::GetNavMapFilename());

		if (SaveNavigationMap(buffer))// TODO: reverse me
			CONSOLE_ECHO("Navigation map '%s' saved.\n", buffer);
		else
			CONSOLE_ECHO("ERROR: Cannot save navigation map '%s'.\n", buffer);
	}
	else if (FStrEq(pcmd, "bot_nav_load"))
	{
		ValidateMapData();
	}
	else if (FStrEq(pcmd, "bot_nav_use_place"))
	{
		if (CMD_ARGC() == 1)
		{
			int i = 0;
			const BotPhraseList *placeList = TheBotPhrases->GetPlaceList();

			for (BotPhraseList::const_iterator iter = placeList->begin(); iter != placeList->end(); ++iter, i++)
			{
				if ((*iter)->GetID() == GetNavPlace())
					CONSOLE_ECHO("--> %-26s", (*iter)->GetName());
				else
					CONSOLE_ECHO("%-30s", (*iter)->GetName());

				if (!(i % 3))
					CONSOLE_ECHO("\n");
			}
			CONSOLE_ECHO("\n");
		}
		else
		{
			const BotPhraseList *placeList = TheBotPhrases->GetPlaceList();
			const BotPhrase *found = NULL;
			bool isAmbiguous = false;

			for (BotPhraseList::const_iterator iter = placeList->begin(); iter != placeList->end(); ++iter)
			{
				if (!Q_strnicmp((*iter)->GetName(), msg, Q_strlen(msg)))
				{
					if (!Q_strcmp((*iter)->GetName(), msg))
					{
						found = (*iter);
						break;
					}

					if (found != NULL)
						isAmbiguous = true;
					else
						found = (*iter);
				}
			}

			if (isAmbiguous)
			{
				CONSOLE_ECHO("Ambiguous\n");
				return;
			}

			if (found != NULL)
			{
				CONSOLE_ECHO("Current place set to '%s'\n", found->GetName());
				m_navPlace = found->GetID();
			}
		}
	}
	else if (FStrEq(pcmd, "bot_nav_toggle_place_mode"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_TOGGLE_PLACE_MODE;
	}
	else if (FStrEq(pcmd, "bot_nav_place_floodfill"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_PLACE_FLOODFILL;
	}
	else if (FStrEq(pcmd, "bot_nav_place_pick"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_PLACE_PICK;
	}
	else if (FStrEq(pcmd, "bot_nav_toggle_place_painting"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_TOGGLE_PLACE_PAINTING;
	}
	else if (FStrEq(pcmd, "bot_goto_mark"))
	{
		// tell the first bot we find to go to our marked area
		CNavArea *area = GetMarkedArea();// TODO: reverse me
		if (area != NULL)
		{
			CBaseEntity *pEntity = NULL;
			while ((pEntity = UTIL_FindEntityByClassname(pEntity, "player")) != NULL)
			{
				if (!pEntity->IsPlayer())
					continue;

				if ((pEntity->pev->flags & FL_DORMANT) == FL_DORMANT)
					continue;

				CBasePlayer *playerOrBot = GetClassPtr((CBasePlayer *)pEntity->pev);

				if (playerOrBot->IsBot())
				{
					CCSBot *bot = reinterpret_cast<CCSBot *>(playerOrBot);
					bot->MoveTo(&area->m_center, FASTEST_ROUTE);// TODO: reverse me
					return;
				}
			}
		}
	}
	else if (FStrEq(pcmd, "bot_memory_usage"))
	{
		CONSOLE_ECHO("Memory usage:\n");
		CONSOLE_ECHO("  %d bytes per bot\b", sizeof(CCSBot));
		CONSOLE_ECHO("  %d Navigation Areas @ %d bytes each = %d bytes\n",
			TheNavAreaGrid.GetNavAreaCount(),
			sizeof(CNavArea),
			TheNavAreaGrid.GetNavAreaCount() * sizeof(CNavArea));
		CONSOLE_ECHO("  %d Hiding Spots @ %d bytes each = %d bytes\n",
			TheHidingSpotList.size(),
			sizeof(HidingSpot),
			sizeof(HidingSpot) * TheHidingSpotList.size());

		unsigned int encounterMem = 0;
		for (NavAreaList::iterator iter = TheNavAreaList.begin(); iter != TheNavAreaList.end(); ++iter)
		{
			CNavArea *area = (*iter);

			for (SpotEncounterList::iterator siter = area->m_spotEncounterList.begin(); siter != area->m_spotEncounterList.end(); ++siter)
			{
				// TODO: Fix me, this is crashed in HOOK_GAMEDLL
				SpotEncounter se = (*siter);

				encounterMem += sizeof(SpotEncounter);
				encounterMem += sizeof(SpotOrder) * se.spotList.size();
			}
		}

		CONSOLE_ECHO("  Encounter Spot data = %d bytes\n", encounterMem);
	}
	else if (FStrEq(pcmd, "bot_nav_mark_unnamed"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_MARK_UNNAMED;
	}
	else if (FStrEq(pcmd, "bot_nav_warp"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_WARP_TO_MARK;
	}
	else if (FStrEq(pcmd, "bot_nav_corner_select"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_SELECT_CORNER;
	}
	else if (FStrEq(pcmd, "bot_nav_corner_raise"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_RAISE_CORNER;
	}
	else if (FStrEq(pcmd, "bot_nav_corner_lower"))
	{
		IMPLEMENT_ARRAY_CLASS(CCSBotManager, m_editCmd) = EDIT_LOWER_CORNER;
	}
	else if (FStrEq(pcmd, "bot_nav_check_consistency"))
	{
		if (CMD_ARGC() != 2)
		{
			CONSOLE_ECHO("usage: bot_nav_check_consistency <filename>\n");
			return;
		}

		SanityCheckNavigationMap(msg);// TODO: reverse me
	}
}
Beispiel #13
0
/* <43c197> ../cstrike/dlls/hostage/states/hostage_idle.cpp:23 */
void HostageIdleState::__MAKE_VHOOK(OnUpdate)(CHostageImprov *improv)
{
	if (!UTIL_ActivePlayersInGame())
		return;

	if (m_mustFlee || (improv->IsScared() && !improv->IsTerroristNearby() && m_moveState != Moving))
	{
		if (!m_mustFlee && improv->GetScareIntensity() == CHostageImprov::TERRIFIED)
			m_mustFlee = true;

		if ((improv->GetScareIntensity() == CHostageImprov::TERRIFIED || m_mustFlee) || (m_fleeTimer.IsElapsed() && improv->GetScareIntensity() > CHostageImprov::NERVOUS))
		{
			m_fleeTimer.Start(RANDOM_FLOAT(10, 20));

			const float fleeChance = 33.3f;
			const float terroristRecentTime = 5.0f;

			if (!m_mustFlee && improv->GetTimeSinceLastSawPlayer(TERRORIST) > terroristRecentTime && RANDOM_FLOAT(0, 100) < fleeChance)
				m_mustFlee = true;

			if (m_mustFlee)
			{
				m_mustFlee = false;

				const Vector *spot = FindNearbyRetreatSpot(NULL, &improv->GetFeet(), improv->GetLastKnownArea(), 500.0, TERRORIST, false);

				if (spot != NULL)
				{
					improv->MoveTo(*spot);
					improv->Run();

					m_moveState = Moving;

					if (improv->GetScareIntensity() == CHostageImprov::TERRIFIED)
					{
						improv->Frighten(CHostageImprov::SCARED);
					}

					return;
				}
			}
		}
	}

	if (m_moveState && improv->IsAtMoveGoal())
	{
		m_moveState = NotMoving;

		improv->Stop();
		improv->FaceOutwards();
		
		const float crouchChance = 33.3f;
		if (improv->IsScared() && !improv->IsAtHome() && RANDOM_FLOAT(0, 100) <= crouchChance)
		{
			improv->Crouch();
		}

		return;
	}

	if (m_moveState == Moving)
	{
		improv->Run();
		return;
	}

	if (!improv->IsAtMoveGoal(75.0f))
	{
		improv->Walk();
		m_moveState = Moving;
		return;
	}

	CBasePlayer *rescuer = improv->GetClosestVisiblePlayer(CT);
	CBasePlayer *captor = improv->GetClosestVisiblePlayer(TERRORIST);

	if (rescuer != NULL)
	{
		improv->LookAt(rescuer->EyePosition());
		improv->Stop();

		if (captor != NULL)
		{
			const float attentionRange = 700.0f;
			float rangeT = (improv->GetCentroid() - captor->pev->origin).Length();
			
			if (rangeT < attentionRange)
			{
				const float cosTolerance = 0.95f;
				if (improv->IsAnyPlayerLookingAtMe(TERRORIST, cosTolerance))
				{
					improv->LookAt(captor->EyePosition());
				}
				else
				{
					TraceResult result;
					UTIL_TraceLine(rescuer->pev->origin, captor->pev->origin, ignore_monsters, ignore_glass, captor->edict(), &result);

					if (result.flFraction != 1.0f && m_disagreeTimer.IsElapsed())
					{
						improv->Disagree();
						m_disagreeTimer.Start(RANDOM_FLOAT(2, 4));
					}
				}

				return;
			}
		}
		else if (!TheCSBots()->IsRoundOver() && m_askTimer.IsElapsed())
		{
			const float closeRange = 200.0f;
			if ((rescuer->pev->origin - improv->GetCentroid()).IsLengthLessThan(closeRange))
			{
				if (improv->IsPlayerLookingAtMe(rescuer, 0.99))
				{
					HostageChatterType say;
					if (improv->IsTerroristNearby())
						say = HOSTAGE_CHATTER_WARN_NEARBY;
					else
						say = HOSTAGE_CHATTER_PLEASE_RESCUE_ME;

					improv->Chatter(say, false);
					m_askTimer.Start(RANDOM_FLOAT(3, 10));
				}
			}
		}

		if (m_waveTimer.IsElapsed())
		{
			CHostage *hostage = improv->GetEntity();

			const float waveRange = 250.0f;
			if ((rescuer->pev->origin - hostage->pev->origin).IsLengthGreaterThan(waveRange))
			{
				improv->Stop();
				improv->Wave();

				improv->LookAt(rescuer->EyePosition());
				improv->Chatter(HOSTAGE_CHATTER_CALL_TO_RESCUER, false);

				m_moveState = NotMoving;
				m_waveTimer.Start(RANDOM_FLOAT(10, 20));
			}
		}
	}
	else if (captor != NULL)
	{
		improv->LookAt(captor->EyePosition());
		improv->Stop();

		const float closeRange = 200.0f;
		if ((captor->pev->origin - improv->GetCentroid()).IsLengthLessThan(closeRange) && improv->IsPlayerLookingAtMe(captor, 0.99))
		{
			if (!m_intimidatedTimer.HasStarted())
			{
				m_intimidatedTimer.Start();
			}

			if (!improv->IsScared())
			{
				improv->Frighten(CHostageImprov::NERVOUS);
			}

			const float minThreatenTime = 1.0f;
			if ((!m_intimidatedTimer.HasStarted() || m_intimidatedTimer.IsGreaterThen(minThreatenTime)) && m_pleadTimer.IsElapsed())
			{
				improv->Chatter(HOSTAGE_CHATTER_INTIMIDATED, true);
				m_pleadTimer.Start(RANDOM_FLOAT(10, 20));
			}

			if (!improv->IsAtHome())
			{
				improv->Chatter(HOSTAGE_CHATTER_RETREAT, true);
				improv->Retreat();
			}
		}
		else
		{
			m_intimidatedTimer.Invalidate();
		}
	}
	else
	{
		improv->ClearLookAt();

		const float pushbackRange = 60.0f;
		if (pushbackRange - improv->GetAggression() * 5.0f < TheCSBots()->GetElapsedRoundTime() && m_escapeTimer.IsElapsed())
		{
			const float stayHomeDuration = 5.0f;
			m_escapeTimer.Start(stayHomeDuration);

			float sightTimeT = improv->GetTimeSinceLastSawPlayer(TERRORIST);
			float sightTimeCT = improv->GetTimeSinceLastSawPlayer(CT);

			const float waitTime = 15.0f - improv->GetAggression() * 3.0f;

			if (sightTimeT > waitTime && sightTimeCT > waitTime)
			{
				if (improv->IsTerroristNearby())
				{
					if (cv_hostage_debug.value > 0.0f)
					{
						CONSOLE_ECHO("Hostage: I want to escape, but a T is nearby\n");
					}

					m_escapeTimer.Start(waitTime);
				}
				else
				{
					improv->Escape();

					if (cv_hostage_debug.value > 0.0f)
					{
						CONSOLE_ECHO("Hostage: I'm escaping!\n");
					}
				}
			}
		}
	}

}
Beispiel #14
0
void CHostageImprov::__MAKE_VHOOK(OnTouch)(CBaseEntity *other)
{
	const char *classname;
	Vector2D to;
	const float pushForce = 20.0f;

	classname = STRING(other->pev->classname);

	if (cv_hostage_debug.value != 0.0)
	{
		CONSOLE_ECHO("%5.1f: Hostage hit '%s'\n", gpGlobals->time, classname);
	}

	m_collisionTimer.Start();

	if (FStrEq(classname, "worldspawn"))
	{
		const float lookAheadRange = 30.0f;
		float ground;
		Vector normal = Vector(0, 0, 1);
		Vector alongFloor;
		TraceResult result;
		bool isStep = false;

		UTIL_MakeVectors(m_hostage->pev->angles);

		if (!GetSimpleGroundHeightWithFloor(&GetEyes(), &ground, &normal))
			return;

		if (cv_hostage_debug.value < 0.0)
		{
			UTIL_DrawBeamPoints(GetFeet() + normal * 50, GetFeet(), 2, 255, 255, 0);
		}

		alongFloor = CrossProduct(normal, gpGlobals->v_right);

		Vector pos = alongFloor * lookAheadRange;

		for (float_precision offset = 1.0f; offset <= 18.0f; offset += 3.0f)
		{
			Vector vecStart = GetFeet();
			vecStart.z += offset;

			UTIL_TraceLine(vecStart, vecStart + pos, ignore_monsters, dont_ignore_glass, m_hostage->pev->pContainingEntity, &result);

			if (result.flFraction < 1.0f && result.vecPlaneNormal.z < MaxUnitZSlope)
			{
				isStep = true;
				break;
			}
		}

		if (isStep)
		{
			float stepAheadGround = pos.z;
			Vector stepAheadNormal = Vector(0, 0, stepAheadGround);

			m_inhibitObstacleAvoidance.Start(0.5);

			for (float range = 1.0f; range <= 30.5f; range += 5.0f)
			{
				Vector stepAhead = GetFeet() + alongFloor * range;
				stepAhead.z = GetEyes().z;

				if (GetSimpleGroundHeightWithFloor(&stepAhead, &stepAheadGround, &stepAheadNormal))
				{
					float dz = stepAheadGround - GetFeet().z;

					if (dz > 0.0f && dz < 18.0f)
					{
						m_hostage->pev->origin.z = stepAheadGround + 3.0f;
						break;
					}
				}
			}
		}
		else if (!IsMoving() && !IsUsingLadder())
		{
			bool isSeam = false;
			const float checkSeamRange = 50.0f;
			Vector posBehind;

			posBehind = GetEyes() - alongFloor * checkSeamRange;
			UTIL_TraceLine(posBehind, posBehind - Vector(0, 0, 9999), ignore_monsters, dont_ignore_glass, m_hostage->pev->pContainingEntity, &result);

			if (result.flFraction < 1.0f && DotProduct(result.vecPlaneNormal, normal) < 1.0f)
			{
				isSeam = true;
			}
			else
			{
				Vector posAhead = GetEyes() + alongFloor * checkSeamRange;
				UTIL_TraceLine(posAhead, posAhead - Vector(0, 0, 9999), ignore_monsters, dont_ignore_glass, m_hostage->pev->pContainingEntity, &result);

				if (result.flFraction < 1.0f && DotProduct(result.vecPlaneNormal, normal) < 1.0f)
					isSeam = true;
			}

			if (isSeam)
			{
				if (cv_hostage_debug.value != 0.0)
				{
					CONSOLE_ECHO("Hostage stuck on seam.\n");
				}

				const float nudge = 3.0f;
				m_hostage->pev->origin.z += nudge;
			}
		}
	}
	else if (FStrEq(classname, "func_breakable"))
	{
		other->TakeDamage(m_hostage->pev, m_hostage->pev, 9999.9, DMG_BULLET);
	}
	else if (other->IsPlayer() || FClassnameIs(other->pev, "hostage_entity"))
	{
		to = (m_hostage->pev->origin - other->pev->origin).Make2D();
		to.NormalizeInPlace();

		m_vel.x += to.x * pushForce;
		m_vel.y += to.y * pushForce;
	}
}
Beispiel #15
0
void EXT_FUNC GameDLLInit()
{
	g_psv_gravity = CVAR_GET_POINTER("sv_gravity");
	g_psv_aim = CVAR_GET_POINTER("sv_aim");
	g_footsteps = CVAR_GET_POINTER("mp_footsteps");
	g_psv_accelerate = CVAR_GET_POINTER("sv_accelerate");
	g_psv_friction = CVAR_GET_POINTER("sv_friction");
	g_psv_stopspeed = CVAR_GET_POINTER("sv_stopspeed");

	CVAR_REGISTER(&displaysoundlist);
	CVAR_REGISTER(&timelimit);
	CVAR_REGISTER(&friendlyfire);
	CVAR_REGISTER(&flashlight);
	CVAR_REGISTER(&decalfrequency);
	CVAR_REGISTER(&allowmonsters);
	CVAR_REGISTER(&roundtime);
	CVAR_REGISTER(&buytime);
	CVAR_REGISTER(&freezetime);
	CVAR_REGISTER(&c4timer);
	CVAR_REGISTER(&ghostfrequency);
	CVAR_REGISTER(&autokick);
	CVAR_REGISTER(&autokick_timeout);
	CVAR_REGISTER(&restartround);
	CVAR_REGISTER(&sv_restart);
	CVAR_REGISTER(&limitteams);
	CVAR_REGISTER(&autoteambalance);
	CVAR_REGISTER(&tkpunish);
	CVAR_REGISTER(&hostagepenalty);
	CVAR_REGISTER(&mirrordamage);
	CVAR_REGISTER(&logmessages);
	CVAR_REGISTER(&forcecamera);
	CVAR_REGISTER(&forcechasecam);
	CVAR_REGISTER(&mapvoteratio);
	CVAR_REGISTER(&maxrounds);
	CVAR_REGISTER(&winlimit);
	CVAR_REGISTER(&windifference);
	CVAR_REGISTER(&fadetoblack);
	CVAR_REGISTER(&logdetail);
	CVAR_REGISTER(&startmoney);
	CVAR_REGISTER(&playerid);
	CVAR_REGISTER(&allow_spectators);
	CVAR_REGISTER(&mp_chattime);
	CVAR_REGISTER(&kick_percent);
	CVAR_REGISTER(&fragsleft);
	CVAR_REGISTER(&timeleft);
	CVAR_REGISTER(&humans_join_team);

// Remove unused cvars
#ifndef REGAMEDLL_FIXES

	CVAR_REGISTER(&sk_plr_9mm_bullet1);
	CVAR_REGISTER(&sk_plr_9mm_bullet2);
	CVAR_REGISTER(&sk_plr_9mm_bullet3);
	CVAR_REGISTER(&sk_plr_357_bullet1);
	CVAR_REGISTER(&sk_plr_357_bullet2);
	CVAR_REGISTER(&sk_plr_357_bullet3);
	CVAR_REGISTER(&sk_plr_9mmAR_bullet1);
	CVAR_REGISTER(&sk_plr_9mmAR_bullet2);
	CVAR_REGISTER(&sk_plr_9mmAR_bullet3);
	CVAR_REGISTER(&sk_plr_9mmAR_grenade1);
	CVAR_REGISTER(&sk_plr_9mmAR_grenade2);
	CVAR_REGISTER(&sk_plr_9mmAR_grenade3);
	CVAR_REGISTER(&sk_plr_buckshot1);
	CVAR_REGISTER(&sk_plr_buckshot2);
	CVAR_REGISTER(&sk_plr_buckshot3);
	CVAR_REGISTER(&sk_plr_rpg1);
	CVAR_REGISTER(&sk_plr_rpg2);
	CVAR_REGISTER(&sk_plr_rpg3);
	CVAR_REGISTER(&sk_12mm_bullet1);
	CVAR_REGISTER(&sk_12mm_bullet2);
	CVAR_REGISTER(&sk_12mm_bullet3);
	CVAR_REGISTER(&sk_9mmAR_bullet1);
	CVAR_REGISTER(&sk_9mmAR_bullet2);
	CVAR_REGISTER(&sk_9mmAR_bullet3);
	CVAR_REGISTER(&sk_9mm_bullet1);
	CVAR_REGISTER(&sk_9mm_bullet2);
	CVAR_REGISTER(&sk_9mm_bullet3);
	CVAR_REGISTER(&sk_suitcharger1);
	CVAR_REGISTER(&sk_suitcharger2);
	CVAR_REGISTER(&sk_suitcharger3);
	CVAR_REGISTER(&sk_battery1);
	CVAR_REGISTER(&sk_battery2);
	CVAR_REGISTER(&sk_battery3);
	CVAR_REGISTER(&sk_healthcharger1);
	CVAR_REGISTER(&sk_healthcharger2);
	CVAR_REGISTER(&sk_healthcharger3);
	CVAR_REGISTER(&sk_healthkit1);
	CVAR_REGISTER(&sk_healthkit2);
	CVAR_REGISTER(&sk_healthkit3);
	CVAR_REGISTER(&sk_scientist_heal1);
	CVAR_REGISTER(&sk_scientist_heal2);
	CVAR_REGISTER(&sk_scientist_heal3);

#endif // REGAMEDLL_FIXES

#ifdef REGAMEDLL_ADD

	ADD_SERVER_COMMAND("game", GameDLL_Version_f);
	ADD_SERVER_COMMAND("endround", GameDLL_EndRound_f);

	CVAR_REGISTER(&game_version);
	CVAR_REGISTER(&maxmoney);
	CVAR_REGISTER(&round_infinite);
	CVAR_REGISTER(&hegrenade_penetration);
	CVAR_REGISTER(&nadedrops);
	CVAR_REGISTER(&roundrespawn_time);
	CVAR_REGISTER(&auto_reload_weapons);
	CVAR_REGISTER(&refill_bpammo_weapons);

	// print version
	CONSOLE_ECHO("ReGameDLL build: " __TIME__ " " __DATE__ " (" APP_VERSION_STRD ")\n");
	CONSOLE_ECHO("ReGameDLL API version %i.%i\n", REGAMEDLL_API_VERSION_MAJOR, REGAMEDLL_API_VERSION_MINOR);

#endif // REGAMEDLL_ADD

	Bot_RegisterCvars();
	Tutor_RegisterCVars();
	Hostage_RegisterCVars();
}
Beispiel #16
0
/* <4f029e> ../game_shared/bot/nav_file.cpp:562 */
NavErrorType CNavArea::PostLoad()
{
	NavErrorType error = NAV_OK;

	// connect areas together
	for (int d = 0; d < NUM_DIRECTIONS; ++d)
	{
		NavConnectList::iterator iter;
		for (iter = m_connect[d].begin(); iter != m_connect[d].end(); ++iter)
		{
			NavConnect *connect = &(*iter);

			unsigned int id = connect->id;
			connect->area = TheNavAreaGrid.GetNavAreaByID(id);
			if (id && connect->area == NULL)
			{
				CONSOLE_ECHO("ERROR: Corrupt navigation data. Cannot connect Navigation Areas.\n");
				error = NAV_CORRUPT_DATA;
			}
		}
	}

	// resolve approach area IDs
	for (int a = 0; a < m_approachCount; ++a)
	{
		m_approach[a].here.area = TheNavAreaGrid.GetNavAreaByID(m_approach[a].here.id);
		if (m_approach[a].here.id && m_approach[a].here.area == NULL)
		{
			CONSOLE_ECHO("ERROR: Corrupt navigation data. Missing Approach Area (here).\n");
			error = NAV_CORRUPT_DATA;
		}

		m_approach[a].prev.area = TheNavAreaGrid.GetNavAreaByID(m_approach[a].prev.id);
		if (m_approach[a].prev.id && m_approach[a].prev.area == NULL)
		{
			CONSOLE_ECHO("ERROR: Corrupt navigation data. Missing Approach Area (prev).\n");
			error = NAV_CORRUPT_DATA;
		}

		m_approach[a].next.area = TheNavAreaGrid.GetNavAreaByID(m_approach[a].next.id);
		if (m_approach[a].next.id && m_approach[a].next.area == NULL)
		{
			CONSOLE_ECHO("ERROR: Corrupt navigation data. Missing Approach Area (next).\n");
			error = NAV_CORRUPT_DATA;
		}
	}

	// resolve spot encounter IDs
	SpotEncounter *e;
	for (SpotEncounterList::iterator iter = m_spotEncounterList.begin(); iter != m_spotEncounterList.end(); ++iter)
	{
		e = &(*iter);

		e->from.area = TheNavAreaGrid.GetNavAreaByID(e->from.id);
		if (e->from.area == NULL)
		{
			CONSOLE_ECHO("ERROR: Corrupt navigation data. Missing \"from\" Navigation Area for Encounter Spot.\n");
			error = NAV_CORRUPT_DATA;
		}

		e->to.area = TheNavAreaGrid.GetNavAreaByID(e->to.id);
		if (e->to.area == NULL)
		{
			CONSOLE_ECHO("ERROR: Corrupt navigation data. Missing \"to\" Navigation Area for Encounter Spot.\n");
			error = NAV_CORRUPT_DATA;
		}

		if (e->from.area && e->to.area)
		{
			// compute path
			float halfWidth;
			ComputePortal(e->to.area, e->toDir, &e->path.to, &halfWidth);
			ComputePortal(e->from.area, e->fromDir, &e->path.from, &halfWidth);

			const float eyeHeight = HalfHumanHeight;
			e->path.from.z = e->from.area->GetZ(&e->path.from) + eyeHeight;
			e->path.to.z = e->to.area->GetZ(&e->path.to) + eyeHeight;
		}

		// resolve HidingSpot IDs
		for (SpotOrderList::iterator oiter = e->spotList.begin(); oiter != e->spotList.end(); ++oiter)
		{
			SpotOrder *order = &(*oiter);

			order->spot = GetHidingSpotByID(order->id);
			if (order->spot == NULL)
			{
				CONSOLE_ECHO("ERROR: Corrupt navigation data. Missing Hiding Spot\n");
				error = NAV_CORRUPT_DATA;
			}
		}
	}

	// build overlap list
	// TODO: Optimize this
	for (NavAreaList::iterator oiter = TheNavAreaList.begin(); oiter != TheNavAreaList.end(); ++oiter)
	{
		CNavArea *area = *oiter;

		if (area == this)
			continue;

		if (IsOverlapping(area))
			m_overlapList.push_back(area);
	}

	return error;
}
Beispiel #17
0
/* <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;
}
/* <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;
				}
			}
		}
	}
}
Beispiel #19
0
/* <4f05c5> ../game_shared/bot/nav_file.cpp:876 */
void SanityCheckNavigationMap(const char *mapName)
{
	if (!mapName)
	{
		CONSOLE_ECHO("ERROR: navigation file not specified.\n");
		return;
	}

	// nav filename is derived from map filename
	const int BufLen = 4096;
	char bspFilename[BufLen];
	char navFilename[BufLen];

	Q_snprintf(bspFilename, BufLen, "maps\\%s.bsp", mapName);
	Q_snprintf(navFilename, BufLen, "maps\\%s.nav", mapName);

	SteamFile navFile(navFilename);

	if (!navFile.IsValid())
	{
		CONSOLE_ECHO("ERROR: navigation file %s does not exist.\n", navFilename);
		return;
	}

	// check magic number
	bool result;
	unsigned int magic;
	result = navFile.Read(&magic, sizeof(unsigned int));
	if (!result || magic != NAV_MAGIC_NUMBER)
	{
		CONSOLE_ECHO("ERROR: Invalid navigation file '%s'.\n", navFilename);
		return;
	}

	// read file version number
	unsigned int version;
	result = navFile.Read(&version, sizeof(unsigned int));
	if (!result || version > 5)
	{
		CONSOLE_ECHO("ERROR: Unknown version in navigation file %s.\n", navFilename);
		return;
	}

	if (version >= 4)
	{
		// get size of source bsp file and verify that the bsp hasn't changed
		unsigned int saveBspSize;
		navFile.Read(&saveBspSize, sizeof(unsigned int));

		// verify size
		if (bspFilename == NULL)
		{
			CONSOLE_ECHO("ERROR: No map corresponds to navigation file %s.\n", navFilename);
			return;
		}

		unsigned int bspSize = (unsigned int)GET_FILE_SIZE(bspFilename);

		if (bspSize != saveBspSize)
		{
			// this nav file is out of date for this bsp file
			CONSOLE_ECHO("ERROR: Out-of-date navigation data in navigation file %s.\n", navFilename);
			return;
		}
	}

	CONSOLE_ECHO("navigation file %s passes the sanity check.\n", navFilename);
}
//--------------------------------------------------------------------------------------------------------------
void BuyState::OnUpdate( CCSBot *me )
{
	char cmdBuffer[256];

	// wait for a Navigation Mesh
	if (!TheNavMesh->IsLoaded())
		return;

	// apparently we cant buy things in the first few seconds, so wait a bit
	if (m_isInitialDelay)
	{
		const float waitToBuyTime = 0.25f;
		if (gpGlobals->curtime - me->GetStateTimestamp() < waitToBuyTime)
			return;

		m_isInitialDelay = false;
	}

	// if we're done buying and still in the freeze period, wait
	if (m_doneBuying)
	{
		if (CSGameRules()->IsMultiplayer() && CSGameRules()->IsFreezePeriod())
		{
			// make sure we're locked and loaded
			me->EquipBestWeapon( MUST_EQUIP );
			me->Reload();
			me->ResetStuckMonitor();
			return;
		}

		me->Idle();
		return;
	}

	// If we're supposed to buy a specific weapon for debugging, do so and then bail
	const char *cheatWeaponString = bot_loadout.GetString();
	if ( cheatWeaponString && *cheatWeaponString )
	{
		CUtlVector<char*, CUtlMemory<char*> > loadout;
		Q_SplitString( cheatWeaponString, " ", loadout );
		for ( int i=0; i<loadout.Count(); ++i )
		{
			const char *item = loadout[i];
			if ( FStrEq( item, "vest" ) )
			{
				me->GiveNamedItem( "item_kevlar" );
			}
			else if ( FStrEq( item, "vesthelm" ) )
			{
				me->GiveNamedItem( "item_assaultsuit" );
			}
			else if ( FStrEq( item, "defuser" ) )
			{
				if ( me->GetTeamNumber() == TEAM_CT )
				{
					me->GiveDefuser();
				}
			}
			else if ( FStrEq( item, "nvgs" ) )
			{
				me->m_bHasNightVision = true;
			}
			else if ( FStrEq( item, "primammo" ) )
			{
				me->AttemptToBuyAmmo( 0 );
			}
			else if ( FStrEq( item, "secammo" ) )
			{
				me->AttemptToBuyAmmo( 1 );
			}
			else
			{
				me->GiveWeapon( item );
			}
		}
		m_doneBuying = true;
		return;
	}


	if (!me->IsInBuyZone())
	{
		m_doneBuying = true;
		CONSOLE_ECHO( "%s bot spawned outside of a buy zone (%d, %d, %d)\n",
						(me->GetTeamNumber() == TEAM_CT) ? "CT" : "Terrorist",
						(int)me->GetAbsOrigin().x,
						(int)me->GetAbsOrigin().y,
						(int)me->GetAbsOrigin().z );
		return;
	}

	// try to buy some weapons
	const float buyInterval = 0.02f;
	if (gpGlobals->curtime - me->GetStateTimestamp() > buyInterval)
	{
		me->m_stateTimestamp = gpGlobals->curtime;

		bool isPreferredAllDisallowed = true;

		// try to buy our preferred weapons first
		if (m_prefIndex < me->GetProfile()->GetWeaponPreferenceCount() && bot_randombuy.GetBool() == false )
		{
			// need to retry because sometimes first buy fails??
			const int maxPrefRetries = 2;
			if (m_prefRetries >= maxPrefRetries)
			{
				// try to buy next preferred weapon
				++m_prefIndex;
				m_prefRetries = 0;
				return;
			}

			int weaponPreference = me->GetProfile()->GetWeaponPreference( m_prefIndex );

			// don't buy it again if we still have one from last round
			char weaponPreferenceName[32];
			Q_snprintf( weaponPreferenceName, sizeof(weaponPreferenceName), "weapon_%s", me->GetProfile()->GetWeaponPreferenceAsString( m_prefIndex ) );
			if( me->Weapon_OwnsThisType(weaponPreferenceName) )//Prefs and buyalias use the short version, this uses the long
			{
				// done with buying preferred weapon
				m_prefIndex = 9999;
				return;
			}

			if (me->HasShield() && weaponPreference == WEAPON_SHIELDGUN)
			{
				// done with buying preferred weapon
				m_prefIndex = 9999;
				return;
			}

			const char *buyAlias = NULL;

			if (weaponPreference == WEAPON_SHIELDGUN)
			{
				if (TheCSBots()->AllowTacticalShield())
					buyAlias = "shield";
			}
			else
			{
				buyAlias = WeaponIDToAlias( weaponPreference );
				WeaponType type = GetWeaponType( buyAlias );
				switch( type )
				{
					case PISTOL:
						if (!TheCSBots()->AllowPistols())
							buyAlias = NULL;
						break;

					case SHOTGUN:
						if (!TheCSBots()->AllowShotguns())
							buyAlias = NULL;
						break;

					case SUB_MACHINE_GUN:
						if (!TheCSBots()->AllowSubMachineGuns())
							buyAlias = NULL;
						break;

					case RIFLE:
						if (!TheCSBots()->AllowRifles())
							buyAlias = NULL;
						break;

					case MACHINE_GUN:
						if (!TheCSBots()->AllowMachineGuns())
							buyAlias = NULL;
						break;

					case SNIPER_RIFLE:
						if (!TheCSBots()->AllowSnipers())
							buyAlias = NULL;
						break;
				}
			}

			if (buyAlias)
			{
				Q_snprintf( cmdBuffer, 256, "buy %s\n", buyAlias );

				CCommand args;
				args.Tokenize( cmdBuffer );
				me->ClientCommand( args );

				me->PrintIfWatched( "Tried to buy preferred weapon %s.\n", buyAlias );
				isPreferredAllDisallowed = false;
			}

			++m_prefRetries;

			// bail out so we dont waste money on other equipment
			// unless everything we prefer has been disallowed, then buy at random
			if (isPreferredAllDisallowed == false)
				return;
		}

		// if we have no preferred primary weapon (or everything we want is disallowed), buy at random
		if (!me->HasPrimaryWeapon() && (isPreferredAllDisallowed || !me->GetProfile()->HasPrimaryPreference()))
		{
			if (m_buyShield)
			{
				// buy a shield
				CCommand args;
				args.Tokenize( "buy shield" );
				me->ClientCommand( args );

				me->PrintIfWatched( "Tried to buy a shield.\n" );
			}
			else 
			{
				// build list of allowable weapons to buy
				BuyInfo *masterPrimary = (me->GetTeamNumber() == TEAM_TERRORIST) ? primaryWeaponBuyInfoT : primaryWeaponBuyInfoCT;
				BuyInfo *stockPrimary[ PRIMARY_WEAPON_BUY_COUNT ];
				int stockPrimaryCount = 0;

				// dont choose sniper rifles as often
				const float sniperRifleChance = 50.0f;
				bool wantSniper = (RandomFloat( 0, 100 ) < sniperRifleChance) ? true : false;

				if ( bot_randombuy.GetBool() )
				{
					wantSniper = true;
				}

				for( int i=0; i<PRIMARY_WEAPON_BUY_COUNT; ++i )
				{
					if ((masterPrimary[i].type == SHOTGUN && TheCSBots()->AllowShotguns()) ||
						(masterPrimary[i].type == SUB_MACHINE_GUN && TheCSBots()->AllowSubMachineGuns()) ||
						(masterPrimary[i].type == RIFLE && TheCSBots()->AllowRifles()) ||
						(masterPrimary[i].type == SNIPER_RIFLE && TheCSBots()->AllowSnipers() && wantSniper) ||
						(masterPrimary[i].type == MACHINE_GUN && TheCSBots()->AllowMachineGuns()))
					{
						stockPrimary[ stockPrimaryCount++ ] = &masterPrimary[i];
					}
				}
 
				if (stockPrimaryCount)
				{
					// buy primary weapon if we don't have one
					int which;

					// on hard difficulty levels, bots try to buy preferred weapons on the first pass
					if (m_retries == 0 && TheCSBots()->GetDifficultyLevel() >= BOT_HARD && bot_randombuy.GetBool() == false )
					{
						// count up available preferred weapons
						int prefCount = 0;
						for( which=0; which<stockPrimaryCount; ++which )
							if (stockPrimary[which]->preferred)
								++prefCount;

						if (prefCount)
						{
							int whichPref = RandomInt( 0, prefCount-1 );
							for( which=0; which<stockPrimaryCount; ++which )
								if (stockPrimary[which]->preferred && whichPref-- == 0)
									break;
						}
						else
						{
							// no preferred weapons available, just pick randomly
							which = RandomInt( 0, stockPrimaryCount-1 );
						}
					}
					else
					{
						which = RandomInt( 0, stockPrimaryCount-1 );
					}

					Q_snprintf( cmdBuffer, 256, "buy %s\n", stockPrimary[ which ]->buyAlias );

					CCommand args;
					args.Tokenize( cmdBuffer );
					me->ClientCommand( args );

					me->PrintIfWatched( "Tried to buy %s.\n", stockPrimary[ which ]->buyAlias );
				}
			}
		}


		//
		// If we now have a weapon, or have tried for too long, we're done
		//
		if (me->HasPrimaryWeapon() || m_retries++ > 5)
		{
			// primary ammo
			CCommand args;
			if (me->HasPrimaryWeapon())
			{
				args.Tokenize( "buy primammo" );
				me->ClientCommand( args );
			}

			// buy armor last, to make sure we bought a weapon first
			args.Tokenize( "buy vesthelm" );
			me->ClientCommand( args );
			args.Tokenize( "buy vest" );
			me->ClientCommand( args );

			// pistols - if we have no preferred pistol, buy at random
			if (TheCSBots()->AllowPistols() && !me->GetProfile()->HasPistolPreference())
			{
				if (m_buyPistol)
				{
					int which = RandomInt( 0, SECONDARY_WEAPON_BUY_COUNT-1 );
					
					const char *what = NULL;

					if (me->GetTeamNumber() == TEAM_TERRORIST)
						what = secondaryWeaponBuyInfoT[ which ].buyAlias;
					else
						what = secondaryWeaponBuyInfoCT[ which ].buyAlias;

					Q_snprintf( cmdBuffer, 256, "buy %s\n", what );
					args.Tokenize( cmdBuffer );
					me->ClientCommand( args );


					// only buy one pistol
					m_buyPistol = false;
				}

				// make sure we have enough pistol ammo
				args.Tokenize( "buy secammo" );
				me->ClientCommand( args );
			}

			// buy a grenade if we wish, and we don't already have one
			if (m_buyGrenade && !me->HasGrenade())
			{
				if (UTIL_IsTeamAllBots( me->GetTeamNumber() ))
				{
					// only allow Flashbangs if everyone on the team is a bot (dont want to blind our friendly humans)
					float rnd = RandomFloat( 0, 100 );

					if (rnd < 10)
					{
						args.Tokenize( "buy smokegrenade" );
						me->ClientCommand( args );	// smoke grenade
					}
					else if (rnd < 35)
					{
						args.Tokenize( "buy flashbang" );
						me->ClientCommand( args );	// flashbang
					}
					else
					{
						args.Tokenize( "buy hegrenade" );
						me->ClientCommand( args );	// he grenade
					}
				}
				else
				{
					if (RandomFloat( 0, 100 ) < 10)
					{
						args.Tokenize( "buy smokegrenade" );	// smoke grenade
						me->ClientCommand( args );
					}
					else
					{
						args.Tokenize( "buy hegrenade" );	// he grenade
						me->ClientCommand( args );
					}
				}
			}

			if (m_buyDefuseKit)
			{
				args.Tokenize( "buy defuser" );
				me->ClientCommand( args );
			}

			m_doneBuying = true;
		}
	}
}
Beispiel #21
0
// Load the bot profile database
void BotProfileManager::Init(const char *filename, unsigned int *checksum)
{
	static const char *BotDifficultyName[] = { "EASY", "NORMAL", "HARD", "EXPERT", nullptr };

	int dataLength;
	char *dataPointer = (char *)LOAD_FILE_FOR_ME(const_cast<char *>(filename), &dataLength);
	char *dataFile = dataPointer;

	if (!dataFile)
	{
		if (AreBotsAllowed())
		{
			CONSOLE_ECHO("WARNING: Cannot access bot profile database '%s'\n", filename);
		}

		return;
	}

	// compute simple checksum
	if (checksum)
	{
		*checksum = ComputeSimpleChecksum((const unsigned char *)dataPointer, dataLength);
	}

	// keep list of templates used for inheritance
	BotProfileList templateList;
	BotProfile defaultProfile;

	// Parse the BotProfile.db into BotProfile instances
	while (true)
	{
		dataFile = SharedParse(dataFile);
		if (!dataFile)
			break;

		char *token = SharedGetToken();

		bool isDefault = (!Q_stricmp(token, "Default"));
		bool isTemplate = (!Q_stricmp(token, "Template"));
		bool isCustomSkin = (!Q_stricmp(token, "Skin"));

		if (isCustomSkin)
		{
			const int BufLen = 64;
			char skinName[BufLen];

			// get skin name
			dataFile = SharedParse(dataFile);
			if (!dataFile)
			{
				CONSOLE_ECHO("Error parsing %s - expected skin name\n", filename);
				FREE_FILE(dataPointer);
				return;
			}

			token = SharedGetToken();
			Q_snprintf(skinName, BufLen, "%s", token);

			// get attribute name
			dataFile = SharedParse(dataFile);
			if (!dataFile)
			{
				CONSOLE_ECHO("Error parsing %s - expected 'Model'\n", filename);
				FREE_FILE(dataPointer);
				return;
			}

			token = SharedGetToken();
			if (Q_stricmp(token, "Model") != 0)
			{
				CONSOLE_ECHO("Error parsing %s - expected 'Model'\n", filename);
				FREE_FILE(dataPointer);
				return;
			}

			// eat '='
			dataFile = SharedParse(dataFile);
			if (!dataFile)
			{
				CONSOLE_ECHO("Error parsing %s - expected '='\n", filename);
				FREE_FILE(dataPointer);
				return;
			}

			token = SharedGetToken();
			if (Q_strcmp(token, "=") != 0)
			{
				CONSOLE_ECHO("Error parsing %s - expected '='\n", filename);
				FREE_FILE(dataPointer);
				return;
			}

			// get attribute value
			dataFile = SharedParse(dataFile);
			if (!dataFile)
			{
				CONSOLE_ECHO("Error parsing %s - expected attribute value\n", filename);
				FREE_FILE(dataPointer);
				return;
			}

			token = SharedGetToken();

			const char *decoratedName = GetDecoratedSkinName(skinName, filename);
			bool skinExists = GetCustomSkinIndex(decoratedName) > 0;
			if (m_nextSkin < NumCustomSkins && !skinExists)
			{
				// decorate the name
				m_skins[m_nextSkin] = CloneString(decoratedName);

				// construct the model filename
				m_skinModelnames[m_nextSkin] = CloneString(token);
				m_skinFilenames[m_nextSkin] = new char[Q_strlen(token) * 2 + Q_strlen("models/player//.mdl") + 1];
				Q_sprintf(m_skinFilenames[m_nextSkin], "models/player/%s/%s.mdl", token, token);
				m_nextSkin++;
			}

			// eat 'End'
			dataFile = SharedParse(dataFile);
			if (!dataFile)
			{
				CONSOLE_ECHO("Error parsing %s - expected 'End'\n", filename);
				FREE_FILE(dataPointer);
				return;
			}

			token = SharedGetToken();
			if (Q_strcmp(token, "End") != 0)
			{
				CONSOLE_ECHO("Error parsing %s - expected 'End'\n", filename);
				FREE_FILE(dataPointer);
				return;
			}

			// it's just a custom skin - no need to do inheritance on a bot profile, etc.
			continue;
		}

		// encountered a new profile
		BotProfile *profile;
		if (isDefault)
		{
			profile = &defaultProfile;
		}
		else
		{
			profile = new BotProfile;
			// always inherit from Default
			*profile = defaultProfile;
		}

		// do inheritance in order of appearance
		if (!isTemplate && !isDefault)
		{
			const BotProfile *inherit = nullptr;

			// template names are separated by "+"
			while (true)
			{
				char *c = Q_strchr(token, '+');
				if (c)
					*c = '\0';

				// find the given template name
				for (auto templates : templateList)
				{
					if (!Q_stricmp(templates->GetName(), token))
					{
						inherit = templates;
						break;
					}
				}

				if (!inherit)
				{
					CONSOLE_ECHO("Error parsing '%s' - invalid template reference '%s'\n", filename, token);
					FREE_FILE(dataPointer);
					return;
				}

				// inherit the data
				profile->Inherit(inherit, &defaultProfile);

				if (c == nullptr)
					break;

				token = c + 1;
			}
		}

		// get name of this profile
		if (!isDefault)
		{
			dataFile = SharedParse(dataFile);
			if (!dataFile)
			{
				CONSOLE_ECHO("Error parsing '%s' - expected name\n", filename);
				FREE_FILE(dataPointer);
				return;
			}

			profile->m_name = CloneString(SharedGetToken());

#ifdef REGAMEDLL_FIXES
			if (RANDOM_LONG(0, 2) == 2)
#else
			// HACK HACK
			// Until we have a generalized means of storing bot preferences, we're going to hardcode the bot's
			// preference towards silencers based on his name.
			if (profile->m_name[0] % 2)
#endif
			{
				profile->m_prefersSilencer = true;
			}
		}

		// read attributes for this profile
		bool isFirstWeaponPref = true;
		while (true)
		{
			// get next token
			dataFile = SharedParse(dataFile);
			if (!dataFile)
			{
				CONSOLE_ECHO("Error parsing %s - expected 'End'\n", filename);
				FREE_FILE(dataPointer);
				return;
			}

			token = SharedGetToken();

			// check for End delimiter
			if (!Q_stricmp(token, "End"))
				break;

			// found attribute name - keep it
			char attributeName[64];
			Q_strcpy(attributeName, token);

			// eat '='
			dataFile = SharedParse(dataFile);
			if (!dataFile)
			{
				CONSOLE_ECHO("Error parsing %s - expected '='\n", filename);
				FREE_FILE(dataPointer);
				return;
			}

			token = SharedGetToken();
			if (Q_strcmp(token, "=") != 0)
			{
				CONSOLE_ECHO("Error parsing %s - expected '='\n", filename);
				FREE_FILE(dataPointer);
				return;
			}

			// get attribute value
			dataFile = SharedParse(dataFile);
			if (!dataFile)
			{
				CONSOLE_ECHO("Error parsing %s - expected attribute value\n", filename);
				FREE_FILE(dataPointer);
				return;
			}

			token = SharedGetToken();

			// store value in appropriate attribute
			if (!Q_stricmp("Aggression", attributeName))
			{
				profile->m_aggression = Q_atof(token) / 100.0f;
			}
			else if (!Q_stricmp("Skill", attributeName))
			{
				profile->m_skill = Q_atof(token) / 100.0f;
			}
			else if (!Q_stricmp("Skin", attributeName))
			{
				profile->m_skin = Q_atoi(token);

				if (profile->m_skin == 0)
				{
					// Q_atoi() failed - try to look up a custom skin by name
					profile->m_skin = GetCustomSkinIndex(token, filename);
				}
			}
			else if (!Q_stricmp("Teamwork", attributeName))
			{
				profile->m_teamwork = Q_atof(token) / 100.0f;
			}
			else if (!Q_stricmp("Cost", attributeName))
			{
				profile->m_cost = Q_atoi(token);
			}
			else if (!Q_stricmp("VoicePitch", attributeName))
			{
				profile->m_voicePitch = Q_atoi(token);
			}
			else if (!Q_stricmp("VoiceBank", attributeName))
			{
				profile->m_voiceBank = FindVoiceBankIndex(token);
			}
			else if (!Q_stricmp("WeaponPreference", attributeName))
			{
				// weapon preferences override parent prefs
				if (isFirstWeaponPref)
				{
					isFirstWeaponPref = false;
					profile->m_weaponPreferenceCount = 0;
				}

				if (!Q_stricmp(token, "none"))
				{
					profile->m_weaponPreferenceCount = 0;
				}
				else
				{
					if (profile->m_weaponPreferenceCount < BotProfile::MAX_WEAPON_PREFS)
					{
						profile->m_weaponPreference[profile->m_weaponPreferenceCount++] = AliasToWeaponID(token);
					}
				}
			}
			else if (!Q_stricmp("ReactionTime", attributeName))
			{
				profile->m_reactionTime = Q_atof(token);

#ifndef GAMEUI_EXPORTS
				// subtract off latency due to "think" update rate.
				// In GameUI, we don't really care.
				profile->m_reactionTime -= g_flBotFullThinkInterval;
#endif

			}
			else if (!Q_stricmp("AttackDelay", attributeName))
			{
				profile->m_attackDelay = Q_atof(token);
			}
			else if (!Q_stricmp("Difficulty", attributeName))
			{
				// override inheritance
				profile->m_difficultyFlags = 0;

				// parse bit flags
				while (true)
				{
					char *c = Q_strchr(token, '+');
					if (c)
						*c = '\0';

					for (int i = 0; i < NUM_DIFFICULTY_LEVELS; i++)
					{
						if (!Q_stricmp(BotDifficultyName[i], token))
							profile->m_difficultyFlags |= (1<<i);
					}

					if (c == nullptr)
						break;

					token = c + 1;
				}
			}
			else if (!Q_stricmp("Team", attributeName))
			{
				if (!Q_stricmp(token, "T"))
				{
					profile->m_teams = BOT_TEAM_T;
				}
				else if (!Q_stricmp(token, "CT"))
				{
					profile->m_teams = BOT_TEAM_CT;
				}
				else
				{
					profile->m_teams = BOT_TEAM_ANY;
				}
			}
			else
			{
				CONSOLE_ECHO("Error parsing %s - unknown attribute '%s'\n", filename, attributeName);
			}
		}

		if (!isDefault)
		{
			if (isTemplate)
			{
				// add to template list
				templateList.push_back(profile);
			}
			else
			{
				// add profile to the master list
				m_profileList.push_back(profile);
			}
		}
	}

	FREE_FILE(dataPointer);

	// free the templates
	for (auto templates : templateList)
		delete templates;

	templateList.clear();
}
int CLocalNav::FindPath(Vector &vecStart, Vector &vecDest, float flTargetRadius, BOOL fNoMonsters)
{
	int nIndexBest;
	node_index_t *node;
	Vector vecNodeLoc;
	float flDistToDest;

#ifdef _DEBUG
	CONSOLE_ECHO("findpath: %f\n", gpGlobals->time);
#endif
	nIndexBest = FindDirectPath(vecStart, vecDest, flTargetRadius, fNoMonsters);

	if (nIndexBest != -1)
		return nIndexBest;

	m_vecStartingLoc = vecStart;
	m_nindexAvailableNode = 0;
	AddPathNodes(-1, fNoMonsters);

	vecNodeLoc = vecStart;
	nIndexBest = GetBestNode(vecNodeLoc, vecDest);

	while (nIndexBest != -1)
	{
		node = GetNode(nIndexBest);
		vecNodeLoc = node->vecLoc;
		node->fSearched = TRUE;
		flDistToDest = (vecDest - node->vecLoc).Length2D();

		if (flDistToDest <= flTargetRadius)
			break;

		if (flDistToDest <= HOSTAGE_STEPSIZE)
			break;

		if ((flDistToDest - flTargetRadius) > (MAX_NODES - m_nindexAvailableNode) * HOSTAGE_STEPSIZE || m_nindexAvailableNode == MAX_NODES)
		{
			nIndexBest = -1;
			break;
		}

		AddPathNodes(nIndexBest, fNoMonsters);
		nIndexBest = GetBestNode(vecNodeLoc, vecDest);
	}

	if (m_nindexAvailableNode <= 10)
		nodeval += 2;
	else if (m_nindexAvailableNode <= 20)
		nodeval += 4;
	else if (m_nindexAvailableNode <= 30)
		nodeval += 8;
	else if (m_nindexAvailableNode <= 40)
		nodeval += 13;
	else if (m_nindexAvailableNode <= 50)
		nodeval += 19;
	else if (m_nindexAvailableNode <= 60)
		nodeval += 26;
	else if (m_nindexAvailableNode <= 70)
		nodeval += 34;
	else if (m_nindexAvailableNode <= 80)
		nodeval += 43;
	else if (m_nindexAvailableNode <= 90)
		nodeval += 53;
	else if (m_nindexAvailableNode <= 100)
		nodeval += 64;
	else if (m_nindexAvailableNode <= 110)
		nodeval += 76;
	else if (m_nindexAvailableNode <= 120)
		nodeval += 89;
	else if (m_nindexAvailableNode <= 130)
		nodeval += 103;
	else if (m_nindexAvailableNode <= 140)
		nodeval += 118;
	else if (m_nindexAvailableNode <= 150)
		nodeval += 134;
	else if (m_nindexAvailableNode <= 160)
		nodeval += 151;
	else
		nodeval += 169;

	return nIndexBest;
}