//----------------------------------------------------------------------------- // Purpose: Called when an entity stops touching us. // Input : pOther - The entity that was touching us. //----------------------------------------------------------------------------- void CTriggerWateryDeath::EndTouch( CBaseEntity *pOther ) { if ( IsTouching( pOther ) ) { EHANDLE hOther; hOther = pOther; // Remove the time from our list int iIndex = m_hTouchingEntities.Find( hOther ); if ( iIndex != m_hTouchingEntities.InvalidIndex() ) { m_flEntityKillTimes.Remove( iIndex ); } } #ifdef HL2_DLL if ( pOther->IsPlayer() ) { for (int i = 0; i < m_hLeeches.Count(); i++ ) { CWateryDeathLeech *pLeech = dynamic_cast<CWateryDeathLeech*>( m_hLeeches[i].Get() ); if ( pLeech ) { pLeech->m_iFadeState = -1; } } if ( m_hLeeches.Count() > 0 ) m_hLeeches.Purge(); CHL2_Player *pHL2Player = dynamic_cast<CHL2_Player*>( pOther ); if ( pHL2Player ) { //Adrian: Hi, you might be wondering why I'm doing this, yes? // Well, EndTouch is called not only when the player leaves // the trigger, but also on level shutdown. We can't let the // soundpatch fade the sound out since we'll hit a nasty assert // cause it'll try to fade out a sound using an entity that might // be gone since we're shutting down the server. if ( !(pHL2Player->GetFlags() & FL_DONTTOUCH ) ) pHL2Player->StopWaterDeathSounds(); } } #endif BaseClass::EndTouch( pOther ); }
//------------------------------------------------------------------------------ // Purpose : //------------------------------------------------------------------------------ void CNPC_CraneDriver::Spawn( void ) { BaseClass::Spawn(); CapabilitiesClear(); CapabilitiesAdd( bits_CAP_INNATE_RANGE_ATTACK1 ); m_flDistTooFar = 2048.0; SetDistLook( 2048 ); m_PreviouslyPickedUpObjects.Purge(); m_hPickupTarget = NULL; m_bForcedPickup = false; m_bForcedDropoff = false; }
// Reset the whole system (level change, etc.) void CSoundControllerImp::SystemReset( void ) { for ( int i = m_soundList.Count()-1; i >=0; i-- ) { CSoundPatch *pNode = m_soundList[i]; // shutdown all active sounds pNode->Shutdown(); } // clear the list m_soundList.Purge(); // clear the command queue m_commandList.RemoveAll(); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void Decal_Shutdown( void ) { for ( int index = g_DecalDictionary.FirstInorder(); index != g_DecalDictionary.InvalidIndex(); index = g_DecalDictionary.NextInorder(index) ) { IMaterial *mat = g_DecalDictionary[index].material; if ( mat ) { GL_UnloadMaterial( mat ); } #ifdef _DEBUG delete[] g_DecalDictionary[index].m_pDebugName; #endif } g_DecalLookup.Purge(); g_DecalDictionary.RemoveAll(); }
//----------------------------------------------------------------------------- // Purpose: Generate a list of file matching mask //----------------------------------------------------------------------------- int CScriptLib::FindFiles( char* pFileMask, bool bRecurse, CUtlVector<fileList_t> &fileList ) { char dirPath[MAX_PATH]; char pattern[MAX_PATH]; char extension[MAX_PATH]; // get path only strcpy( dirPath, pFileMask ); V_StripFilename( dirPath ); // get pattern only V_FileBase( pFileMask, pattern, sizeof( pattern ) ); V_ExtractFileExtension( pFileMask, extension, sizeof( extension ) ); if ( extension[0] ) { strcat( pattern, "." ); strcat( pattern, extension ); } if ( !bRecurse ) { GetFileList( dirPath, pattern, fileList ); } else { // recurse and get the tree CUtlVector< fileList_t > tempList; CUtlVector< CUtlString > dirList; RecurseFileTree_r( dirPath, 0, dirList ); for ( int i=0; i<dirList.Count(); i++ ) { // iterate each directory found tempList.Purge(); tempList.EnsureCapacity( dirList.Count() ); GetFileList( dirList[i].String(), pattern, tempList ); int start = fileList.AddMultipleToTail( tempList.Count() ); for ( int j=0; j<tempList.Count(); j++ ) { fileList[start+j] = tempList[j]; } } } return fileList.Count(); }
//================================================================================ //================================================================================ void CefBasePanel::OnThink() { VPROF_BUDGET( __FUNCTION__, VPROF_BUDGETGROUP_CEF ); // Hay comandos que deben ejecutarse if ( g_QueueCommands.Count() > 0 ) { for ( int it = 0; it < g_QueueCommands.Count(); ++it ) { const char *pCommand = g_QueueCommands[it]; engine->ExecuteClientCmd( pCommand ); DevMsg( "[OnThink] engine.command: %s\n", pCommand ); } g_QueueCommands.Purge(); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void Decal_Shutdown( void ) { g_DecalLookup.Purge(); int c = g_DecalDictionary.Count(); int decal; for ( decal = 0; decal < c; decal++ ) { IMaterial *mat = g_DecalDictionary[ decal ].material; if ( mat ) { GL_UnloadMaterial( mat ); } } g_DecalDictionary.Purge(); }
bool CVRadDLL::Serialize() { if( !g_pIncremental ) return false; if( g_LastGoodLightData.Count() > 0 ) { pdlightdata->CopyArray( g_LastGoodLightData.Base(), g_LastGoodLightData.Count() ); if( g_pIncremental->Serialize() ) { // Delete this so it doesn't keep re-saving it. g_LastGoodLightData.Purge(); return true; } } return false; }
void EatTextModeKeyPresses() { if ( !g_bTextMode ) return; static bool bFirstRun = true; if ( bFirstRun ) { bFirstRun = false; MoveConsoleWindowToFront(); } char ch; while ( (ch = NextGetch()) != -1 ) { if ( ch == 8 ) { // Backspace.. if ( g_TextModeLine.Count() ) { g_TextModeLine.Remove( g_TextModeLine.Count() - 1 ); } } else if ( ch == '\r' ) { // Finish the line. if ( g_TextModeLine.Count() ) { g_TextModeLine.AddMultipleToTail( 2, "\n" ); Cbuf_AddText( g_TextModeLine.Base() ); g_TextModeLine.Purge(); } printf( "\n" ); } else { g_TextModeLine.AddToTail( ch ); } printf( "%c", ch ); } }
//----------------------------------------------------------------------------- // ExcludePathsDlg_SaveChanges // //----------------------------------------------------------------------------- void ExcludePathsDlg_SaveChanges( HWND hWnd ) { g_ExcludePaths.Purge(); HWND hWndTree = GetDlgItem( hWnd, IDC_PATHS_TREE ); ExcludePathsDlg_BuildExcludeList_r( hWndTree, TreeView_GetRoot( hWndTree ), 0, "" ); char szPath[MAX_PATH]; V_ComposeFileName( g_localPath, EXCLUDEPATHS_FILE, szPath, sizeof( szPath ) ); if ( !g_ExcludePaths.Count() ) { // no exclude paths unlink( szPath ); } else { FILE *fp = fopen( szPath, "wt" ); if ( !fp ) { Sys_MessageBox( "Error", "Could not open '%s' for writing\n", szPath ); return; } fprintf( fp, "// Auto-Generated by VXConsole - DO NOT MODIFY!\n" ); for ( int i = 0; i < g_ExcludePaths.Count(); i++ ) { // strip expected root path const char *pPath = g_ExcludePaths[i].String(); pPath += strlen( ROOT_NAME ); if ( !pPath[0] ) { // special code for root fprintf( fp, "*\n" ); break; } fprintf( fp, "\"\\%s\"\n", pPath ); } fclose( fp ); } }
void V_SplitString2( const char *pString, const char **pSeparators, int nSeparators, CUtlVector<char*> &outStrings ) { outStrings.Purge(); const char *pCurPos = pString; while ( 1 ) { int iFirstSeparator = -1; const char *pFirstSeparator = 0; for ( int i=0; i < nSeparators; i++ ) { const char *pTest = V_stristr( pCurPos, pSeparators[i] ); if ( pTest && (!pFirstSeparator || pTest < pFirstSeparator) ) { iFirstSeparator = i; pFirstSeparator = pTest; } } if ( pFirstSeparator ) { // Split on this separator and continue on. int separatorLen = strlen( pSeparators[iFirstSeparator] ); if ( pFirstSeparator > pCurPos ) { outStrings.AddToTail( AllocString( pCurPos, pFirstSeparator-pCurPos ) ); } pCurPos = pFirstSeparator + separatorLen; } else { // Copy the rest of the string if ( strlen( pCurPos ) ) { outStrings.AddToTail( AllocString( pCurPos, -1 ) ); } return; } } }
//----------------------------------------------------------------------------- // ExcludePathsDlg_Setup // //----------------------------------------------------------------------------- void ExcludePathsDlg_Setup( HWND hWnd ) { TreeView_SetBkColor( GetDlgItem( hWnd, IDC_PATHS_TREE ), g_backgroundColor ); CheckDlgButton( hWnd, IDC_PATHS_LINKGAMEDIRS, g_bLinkGameDirs ? BST_CHECKED : BST_UNCHECKED ); // read the exisiting exclude paths g_ExcludePaths.Purge(); char szFilename[MAX_PATH]; V_ComposeFileName( g_localPath, EXCLUDEPATHS_FILE, szFilename, sizeof( szFilename ) ); if ( Sys_Exists( szFilename ) ) { Sys_LoadScriptFile( szFilename ); while ( 1 ) { char *pToken = Sys_GetToken( true ); if ( !pToken || !pToken[0] ) { break; } Sys_StripQuotesFromToken( pToken ); if ( !stricmp( pToken, "*" ) ) { pToken = ""; } else if ( pToken[0] == '\\' ) { pToken++; } char szPath[MAX_PATH]; V_ComposeFileName( ROOT_NAME, pToken, szPath, sizeof( szPath ) ); V_FixSlashes( szPath ); g_ExcludePaths.AddToTail( szPath ); } } }
//----------------------------------------------------------------------------- // Purpose: Get list of files from current path that match pattern //----------------------------------------------------------------------------- int CScriptLib::GetFileList( const char* pDirPath, const char* pPattern, CUtlVector< fileList_t > &fileList ) { char sourcePath[MAX_PATH]; char fullPath[MAX_PATH]; bool bFindDirs; fileList.Purge(); strcpy( sourcePath, pDirPath ); int len = (int)strlen( sourcePath ); if ( !len ) { strcpy( sourcePath, ".\\" ); } else if ( sourcePath[len-1] != '\\' ) { sourcePath[len] = '\\'; sourcePath[len+1] = '\0'; } strcpy( fullPath, sourcePath ); if ( pPattern[0] == '\\' && pPattern[1] == '\0' ) { // find directories only bFindDirs = true; strcat( fullPath, "*" ); } else { // find files, use provided pattern bFindDirs = false; strcat( fullPath, pPattern ); } #ifdef WIN32 struct _finddata_t findData; intptr_t h = _findfirst( fullPath, &findData ); if ( h == -1 ) { return 0; } do { // dos attribute complexities i.e. _A_NORMAL is 0 if ( bFindDirs ) { // skip non dirs if ( !( findData.attrib & _A_SUBDIR ) ) continue; } else { // skip dirs if ( findData.attrib & _A_SUBDIR ) continue; } if ( !stricmp( findData.name, "." ) ) continue; if ( !stricmp( findData.name, ".." ) ) continue; char fileName[MAX_PATH]; strcpy( fileName, sourcePath ); strcat( fileName, findData.name ); int j = fileList.AddToTail(); fileList[j].fileName.Set( fileName ); fileList[j].timeWrite = findData.time_write; } while ( !_findnext( h, &findData ) ); _findclose( h ); #elif defined(POSIX) FIND_DATA findData; Q_FixSlashes( fullPath ); void *h = FindFirstFile( fullPath, &findData ); if ( (int)h == -1 ) { return 0; } do { // dos attribute complexities i.e. _A_NORMAL is 0 if ( bFindDirs ) { // skip non dirs if ( !( findData.dwFileAttributes & S_IFDIR ) ) continue; } else { // skip dirs if ( findData.dwFileAttributes & S_IFDIR ) continue; } if ( !stricmp( findData.cFileName, "." ) ) continue; if ( !stricmp( findData.cFileName, ".." ) ) continue; char fileName[MAX_PATH]; strcpy( fileName, sourcePath ); strcat( fileName, findData.cFileName ); int j = fileList.AddToTail(); fileList[j].fileName.Set( fileName ); struct stat statbuf; if ( stat( fileName, &statbuf ) ) #ifdef OSX fileList[j].timeWrite = statbuf.st_mtimespec.tv_sec; #else fileList[j].timeWrite = statbuf.st_mtime; #endif else fileList[j].timeWrite = 0; }
void C_SceneEntity::WipeQueuedEvents() { m_QueuedEvents.Purge(); }
void CNotifyList::LevelShutdownPreEntity( void ) { gEntList.RemoveListenerEntity( this ); m_notifyList.Purge(); }
void VMPITracker_End() { g_WorkUnits.Purge(); Graphical_End(); }
void EmitDispLMAlphaAndNeighbors() { int i; Msg( "Finding displacement neighbors...\n" ); // Build the CCoreDispInfos. CUtlVector<dface_t*> faces; // Create the core dispinfos and init them for use as CDispUtilsHelpers. for ( int iDisp = 0; iDisp < nummapdispinfo; ++iDisp ) { CCoreDispInfo *pDisp = new CCoreDispInfo; if ( !pDisp ) { g_CoreDispInfos.Purge(); return; } int nIndex = g_CoreDispInfos.AddToTail(); pDisp->SetListIndex( nIndex ); g_CoreDispInfos[nIndex] = pDisp; } for ( i=0; i < nummapdispinfo; i++ ) { g_CoreDispInfos[i]->SetDispUtilsHelperInfo( g_CoreDispInfos.Base(), nummapdispinfo ); } faces.SetSize( nummapdispinfo ); for( i = 0; i < numfaces; i++ ) { dface_t *pFace = &dfaces[i]; if( pFace->dispinfo == -1 ) continue; mapdispinfo_t *pMapDisp = &mapdispinfo[pFace->dispinfo]; // Set the displacement's face index. ddispinfo_t *pDisp = &g_dispinfo[pFace->dispinfo]; pDisp->m_iMapFace = i; // Get a CCoreDispInfo. All we need is the triangles and lightmap texture coordinates. CCoreDispInfo *pCoreDispInfo = g_CoreDispInfos[pFace->dispinfo]; DispMapToCoreDispInfo( pMapDisp, pCoreDispInfo, pFace ); faces[pFace->dispinfo] = pFace; } // Generate and export neighbor data. ExportNeighborData( g_CoreDispInfos.Base(), g_dispinfo.Base(), nummapdispinfo ); // Generate and export the active vert lists. ExportAllowedVertLists( g_CoreDispInfos.Base(), g_dispinfo.Base(), nummapdispinfo ); // Now that we know which vertices are actually going to be around, snap the ones that won't // be around onto the slightly-reduced mesh. This is so the engine's ray test code and // overlay code works right. SnapRemainingVertsToSurface( g_CoreDispInfos.Base(), g_dispinfo.Base(), nummapdispinfo ); Msg( "Finding lightmap sample positions...\n" ); for ( i=0; i < nummapdispinfo; i++ ) { dface_t *pFace = faces[i]; ddispinfo_t *pDisp = &g_dispinfo[pFace->dispinfo]; CCoreDispInfo *pCoreDispInfo = g_CoreDispInfos[i]; pDisp->m_iLightmapSamplePositionStart = g_DispLightmapSamplePositions.Count(); CalculateLightmapSamplePositions( pCoreDispInfo, pFace, g_DispLightmapSamplePositions ); } StartPacifier( "Displacement Alpha : "); // Build lightmap alphas. int dispCount = 0; // How many we've processed. for( i = 0; i < nummapdispinfo; i++ ) { dface_t *pFace = faces[i]; Assert( pFace->dispinfo == i ); mapdispinfo_t *pMapDisp = &mapdispinfo[pFace->dispinfo]; ddispinfo_t *pDisp = &g_dispinfo[pFace->dispinfo]; CCoreDispInfo *pCoreDispInfo = g_CoreDispInfos[i]; // Allocate space for the alpha values. pDisp->m_iLightmapAlphaStart = 0; // not used anymore ++dispCount; } EndPacifier(); }
//----------------------------------------------------------------------------- // Purpose: Get list of files from current path that match pattern //----------------------------------------------------------------------------- int CScriptLib::GetFileList( const char* pDirPath, const char* pPattern, CUtlVector< fileList_t > &fileList ) { char sourcePath[MAX_PATH]; char fullPath[MAX_PATH]; bool bFindDirs; fileList.Purge(); strcpy( sourcePath, pDirPath ); int len = (int)strlen( sourcePath ); if ( !len ) { strcpy( sourcePath, ".\\" ); } else if ( sourcePath[len-1] != '\\' ) { sourcePath[len] = '\\'; sourcePath[len+1] = '\0'; } strcpy( fullPath, sourcePath ); if ( pPattern[0] == '\\' && pPattern[1] == '\0' ) { // find directories only bFindDirs = true; strcat( fullPath, "*" ); } else { // find files, use provided pattern bFindDirs = false; strcat( fullPath, pPattern ); } struct _finddata_t findData; intptr_t h = _findfirst( fullPath, &findData ); if ( h == -1 ) { return 0; } do { // dos attribute complexities i.e. _A_NORMAL is 0 if ( bFindDirs ) { // skip non dirs if ( !( findData.attrib & _A_SUBDIR ) ) continue; } else { // skip dirs if ( findData.attrib & _A_SUBDIR ) continue; } if ( !stricmp( findData.name, "." ) ) continue; if ( !stricmp( findData.name, ".." ) ) continue; char fileName[MAX_PATH]; strcpy( fileName, sourcePath ); strcat( fileName, findData.name ); int j = fileList.AddToTail(); fileList[j].fileName.Set( fileName ); fileList[j].timeWrite = findData.time_write; } while ( !_findnext( h, &findData ) ); _findclose( h ); return fileList.Count(); }
void HandlePacket_LOOKING_FOR_WORKERS( bf_read &buf, const CIPAddr &ipFrom ) { // If we're downloading files for a job request, don't process any more "looking for workers" packets. if ( g_Waiting_hProcess ) return; // This will be a nonzero-length string if patching. char versionString[512]; buf.ReadString( versionString, sizeof( versionString ) ); int iPort = buf.ReadShort(); int iPriority = buf.ReadShort(); // Make sure we don't run the same job more than once. if ( !CheckJobID( buf, g_CurJobID ) ) return; CUtlVector<char*> newArgv; GetArgsFromBuffer( buf, newArgv, &g_Waiting_bShowAppWindow ); bool bForcePatch = false; if ( buf.GetNumBytesLeft() >= 1 ) bForcePatch = (buf.ReadByte() != 0); int iDownloaderPort = iPort; if ( buf.GetNumBytesLeft() >= 2 ) iDownloaderPort = buf.ReadShort(); // Add these arguments after the executable filename to tell the program // that it's an MPI worker and who to connect to. char strDownloaderIP[128], strMainIP[128]; V_snprintf( strDownloaderIP, sizeof( strDownloaderIP ), "%d.%d.%d.%d:%d", ipFrom.ip[0], ipFrom.ip[1], ipFrom.ip[2], ipFrom.ip[3], iDownloaderPort ); V_snprintf( strMainIP, sizeof( strMainIP ), "%d.%d.%d.%d:%d", ipFrom.ip[0], ipFrom.ip[1], ipFrom.ip[2], ipFrom.ip[3], iPort ); // (-mpi is already on the command line of whoever ran the app). // AppendArg( commandLine, sizeof( commandLine ), "-mpi" ); newArgv.InsertAfter( 0, CopyString( "-mpi_worker" ) ); newArgv.InsertAfter( 1, CopyString( strDownloaderIP ) ); // If the version string is set, then this is a patch. bool bPatching = false; if ( versionString[0] != 0 ) { bPatching = true; // Check that we haven't applied this patch version yet. This case usually happens right after we've applied a patch // and we're restarting. The vmpi_transfer master is still pinging us telling us to patch, but we don't want to // reapply this patch. if ( atof( versionString ) <= atof( g_VersionString ) && !bForcePatch ) { newArgv.PurgeAndDeleteElements(); return; } // Ok, it's a new version. Get rid of whatever was running before. KillRunningProcess( "Starting a patch..", true ); } // If there's already a job running, only interrupt it if this new one has a higher priority. if ( WaitForProcessToExit() ) { if ( iPriority > g_CurJobPriority ) { KillRunningProcess( "Interrupted by a higher priority process", true ); } else { // This means we're already running a job with equal to or greater priority than // the one that has been requested. We're going to ignore this request. newArgv.PurgeAndDeleteElements(); return; } } // Responses go here. g_CurRespondAddr = ipFrom; // Also look for -mpi_ShowAppWindow in the args to the service. if ( !g_Waiting_bShowAppWindow && FindArg( __argc, __argv, "-mpi_ShowAppWindow" ) ) g_Waiting_bShowAppWindow = true; // Copy all the files from the master and put them in our cache dir to run with. char cacheDir[MAX_PATH]; if ( StartDownloadingAppFiles( newArgv, cacheDir, sizeof( cacheDir ), g_Waiting_bShowAppWindow, &g_Waiting_hProcess, bPatching ) ) { // After it's downloaded, we want it to switch to the main connection port. if ( newArgv.Count() >= 3 && V_stricmp( newArgv[2], strDownloaderIP ) == 0 ) { delete newArgv[2]; newArgv[2] = CopyString( strMainIP ); } g_Waiting_StartTime = Plat_FloatTime(); g_Waiting_Argv.PurgeAndDeleteElements(); g_Waiting_Argv = newArgv; g_Waiting_Priority = iPriority; g_Waiting_bPatching = bPatching; newArgv.Purge(); } else { newArgv.PurgeAndDeleteElements(); } // Remember that we tried to run this job so we don't try to run it again. AddJobMemory( g_CurJobID ); SendStateToServicesBrowsers(); }
//----------------------------------------------------------------------------- // Purpose: // Input : *pTask - //----------------------------------------------------------------------------- void CNPC_CraneDriver::StartTask( const Task_t *pTask ) { switch( pTask->iTask ) { case TASK_WAIT_FOR_MOVEMENT: break; case TASK_CRANE_GET_POSITION_OVER_ENEMY: { if ( !GetEnemy() ) { TaskFail(FAIL_NO_ROUTE); return; } SetDesiredPosition( GetEnemy()->GetAbsOrigin() ); TaskComplete(); } break; case TASK_CRANE_GET_POSITION_OVER_OBJECT: { if ( !m_hPickupTarget ) { TaskFail("No object to pickup!"); return; } SetDesiredPosition( m_hPickupTarget->GetAbsOrigin() ); TaskComplete(); } break; case TASK_CRANE_GET_POSITION_OVER_LASTPOSITION: { SetDesiredPosition( m_vecLastPosition ); TaskComplete(); } break; case TASK_CRANE_TURN_MAGNET_OFF: { // If we picked up something, and we were being forced to pick something up, fire our output if ( m_hCrane->GetTotalMassOnCrane() > 0 && m_bForcedDropoff ) { // Are we supposed to pause first? if ( m_flReleasePause ) { m_flReleaseAt = gpGlobals->curtime + m_flReleasePause; m_OnPausingBeforeDrop.FireOutput( this, this ); return; } m_OnDroppedObject.FireOutput( this, this ); } m_hCrane->TurnMagnetOff(); TaskComplete(); } break; case TASK_END_FORCED_DROP: { m_bForcedDropoff = false; TaskComplete(); } break; case TASK_CRANE_FIND_OBJECT_TO_PICKUP: { Vector2D vecOrigin2D( m_hCrane->GetAbsOrigin().x, m_hCrane->GetAbsOrigin().y ); // Find a large physics object within our reach to pickup float flLargestMass = 0; CBaseEntity *pLargestEntity = NULL; CBaseEntity *pList[1024]; Vector delta( m_flDistTooFar, m_flDistTooFar, m_flDistTooFar*2 ); int count = UTIL_EntitiesInBox( pList, 1024, m_hCrane->GetAbsOrigin() - delta, m_hCrane->GetAbsOrigin() + delta, 0 ); for ( int i = 0; i < count; i++ ) { if ( !pList[i] ) continue; // Ignore the crane & the magnet if ( pList[i] == m_hCrane || pList[i] == m_hCrane->GetMagnet() ) continue; if ( m_PreviouslyPickedUpObjects.Find( pList[i] ) != m_PreviouslyPickedUpObjects.InvalidIndex() ) continue; // Get the VPhysics object IPhysicsObject *pPhysics = pList[i]->VPhysicsGetObject(); if ( pPhysics && pList[i]->GetMoveType() == MOVETYPE_VPHYSICS ) { float flMass = pPhysics->GetMass(); if ( flMass > flLargestMass && (flMass < MAXIMUM_CRANE_PICKUP_MASS) && (flMass > MINIMUM_CRANE_PICKUP_MASS) ) { // Biggest one we've found so far // Now make sure it's within our reach // Do our distance check in 2D Vector2D vecOrigin2D( m_hCrane->GetAbsOrigin().x, m_hCrane->GetAbsOrigin().y ); Vector2D vecEnemy2D( pList[i]->GetAbsOrigin().x, pList[i]->GetAbsOrigin().y ); float flDist = (vecOrigin2D - vecEnemy2D).Length(); // Maximum & Minimum size of the crane's reach if ( flDist > MAX_CRANE_FLAT_REACH ) continue; if ( flDist < MIN_CRANE_FLAT_REACH ) continue; flLargestMass = flMass; pLargestEntity = pList[i]; } } } // If we didn't find anything new, clear our list of targets if ( !pLargestEntity ) { m_PreviouslyPickedUpObjects.Purge(); } if ( !pLargestEntity ) { TaskFail("Couldn't find anything to pick up!"); return; } m_hPickupTarget = pLargestEntity; TaskComplete(); } break; case TASK_CRANE_DROP_MAGNET: { // Drop the magnet, but only end the task once the magnet's back up m_pVehicleInterface->NPC_SecondaryFire(); // Don't check to see if drop's finished until this time is up. // This is necessary because the crane won't start dropping this // frame, and our cranedriver will think it's finished immediately. m_flDropWait = gpGlobals->curtime + 0.5; } break; default: BaseClass::StartTask( pTask ); break; } }
//----------------------------------------------------------------------------- // Purpose: A CPointTemplate has asked us to reconnect all the entity I/O links // inside it's templates. Go through the keys and add look for values // that match a name within the group's entity names. Append %d to any // found values, which will later be filled out by a unique identifier // whenever the template is instanced. //----------------------------------------------------------------------------- void Templates_ReconnectIOForGroup( CPointTemplate *pGroup ) { int iCount = pGroup->GetNumTemplates(); if ( !iCount ) return; // First assemble a list of the targetnames of all the templates in the group. // We need to store off the original names here, because we're going to change // them as we go along. CUtlVector< grouptemplate_t > GroupTemplates; int i; for ( i = 0; i < iCount; i++ ) { grouptemplate_t newGroupTemplate; newGroupTemplate.iIndex = pGroup->GetTemplateIndexForTemplate(i); newGroupTemplate.pMapDataParser = new CEntityMapData( g_Templates[ newGroupTemplate.iIndex ]->pszMapData, g_Templates[ newGroupTemplate.iIndex ]->iMapDataLength ); Assert( newGroupTemplate.pMapDataParser ); newGroupTemplate.pMapDataParser->ExtractValue( "targetname", newGroupTemplate.pszName ); newGroupTemplate.bChangeTargetname = false; GroupTemplates.AddToTail( newGroupTemplate ); } if (pGroup->AllowNameFixup()) { char keyName[MAPKEY_MAXLENGTH]; char value[MAPKEY_MAXLENGTH]; char valueclipped[MAPKEY_MAXLENGTH]; // Now go through all the entities in the group and parse their mapdata keyvalues. // We're looking for any values that match targetnames of any of the group entities. for ( i = 0; i < iCount; i++ ) { // We need to know what instance of each key we're changing. // Store a table of the count of the keys we've run into. CUtlDict< int, int > KeyInstanceCount; CEntityMapData *mapData = GroupTemplates[i].pMapDataParser; // Loop through our keys if ( !mapData->GetFirstKey(keyName, value) ) continue; do { // Ignore targetnames if ( !stricmp( keyName, "targetname" ) ) continue; // Add to the count for this int idx = KeyInstanceCount.Find( keyName ); if ( idx == KeyInstanceCount.InvalidIndex() ) { idx = KeyInstanceCount.Insert( keyName, 0 ); } KeyInstanceCount[idx]++; // Entity I/O values are stored as "Targetname,<data>", so we need to see if there's a ',' in the string char *sValue = value; // FIXME: This is very brittle. Any key with a , will not be found. char *s = strchr( value, ',' ); if ( s ) { // Grab just the targetname of the receiver Q_strncpy( valueclipped, value, (s - value+1) ); sValue = valueclipped; } // Loop through our group templates for ( int iTName = 0; iTName < iCount; iTName++ ) { char *pName = GroupTemplates[iTName].pszName; if ( stricmp( pName, sValue ) ) continue; if ( template_debug.GetInt() ) { Msg("Template Connection Found: Key %s (\"%s\") in entity named \"%s\"(%d) matches entity %d's targetname\n", keyName, sValue, GroupTemplates[i].pszName, i, iTName ); } char newvalue[MAPKEY_MAXLENGTH]; // Get the current key instance. (-1 because it's this one we're changing) int nKeyInstance = KeyInstanceCount[idx] - 1; // Add our IO value to the targetname // We need to append it if this isn't an Entity I/O value, or prepend it to the ',' if it is if ( s ) { Q_strncpy( newvalue, valueclipped, MAPKEY_MAXLENGTH ); Q_strncat( newvalue, ENTITYIO_FIXUP_STRING, sizeof(newvalue), COPY_ALL_CHARACTERS ); Q_strncat( newvalue, s, sizeof(newvalue), COPY_ALL_CHARACTERS ); mapData->SetValue( keyName, newvalue, nKeyInstance ); } else { Q_strncpy( newvalue, sValue, MAPKEY_MAXLENGTH ); Q_strncat( newvalue, ENTITYIO_FIXUP_STRING, sizeof(newvalue), COPY_ALL_CHARACTERS ); mapData->SetValue( keyName, newvalue, nKeyInstance ); } // Remember we changed this targetname GroupTemplates[iTName].bChangeTargetname = true; // Set both entity's flags telling them their template needs fixup when it's spawned g_Templates[ GroupTemplates[i].iIndex ]->bNeedsEntityIOFixup = true; g_Templates[ GroupTemplates[iTName].iIndex ]->bNeedsEntityIOFixup = true; } } while ( mapData->GetNextKey(keyName, value) ); } // Now change targetnames for all entities that need them changed for ( i = 0; i < iCount; i++ ) { char value[MAPKEY_MAXLENGTH]; if ( GroupTemplates[i].bChangeTargetname ) { CEntityMapData *mapData = GroupTemplates[i].pMapDataParser; mapData->ExtractValue( "targetname", value ); Q_strncat( value, ENTITYIO_FIXUP_STRING, sizeof(value), COPY_ALL_CHARACTERS ); mapData->SetValue( "targetname", value ); } } } // Delete our group parsers for ( i = 0; i < iCount; i++ ) { delete GroupTemplates[i].pMapDataParser; } GroupTemplates.Purge(); }
int CMySQLQuery::Execute( IMySQL *pDB ) { int ret = pDB->Execute( m_QueryText.Base() ); m_QueryText.Purge(); return ret; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void EndGroupingSounds() { g_aGroupedSounds.Purge(); SetImpactSoundRoute( NULL ); }
void FoundryHelpers_ClearEntityHighlightEffects() { g_EntityHighlightEffects.Purge(); }
//----------------------------------------------------------------------------- // Trace rays from each unique vertex, accumulating direct and indirect // sources at each ray termination. Use the winding data to distribute the unique vertexes // into the rendering layout. //----------------------------------------------------------------------------- void CVradStaticPropMgr::ComputeLighting( CStaticProp &prop, int iThread, int prop_index ) { Vector samplePosition; Vector sampleNormal; CUtlVector<colorVertex_t> colorVerts; CUtlVector<badVertex_t> badVerts; StaticPropDict_t &dict = m_StaticPropDict[prop.m_ModelIdx]; studiohdr_t *pStudioHdr = dict.m_pStudioHdr; OptimizedModel::FileHeader_t *pVtxHdr = (OptimizedModel::FileHeader_t *)dict.m_VtxBuf.Base(); if ( !pStudioHdr || !pVtxHdr ) { // must have model and its verts for lighting computation // game will fallback to fullbright return; } // for access to this model's vertexes SetCurrentModel( pStudioHdr ); for ( int bodyID = 0; bodyID < pStudioHdr->numbodyparts; ++bodyID ) { OptimizedModel::BodyPartHeader_t* pVtxBodyPart = pVtxHdr->pBodyPart( bodyID ); mstudiobodyparts_t *pBodyPart = pStudioHdr->pBodypart( bodyID ); for ( int modelID = 0; modelID < pBodyPart->nummodels; ++modelID ) { OptimizedModel::ModelHeader_t* pVtxModel = pVtxBodyPart->pModel( modelID ); mstudiomodel_t *pStudioModel = pBodyPart->pModel( modelID ); // light all unique vertexes colorVerts.EnsureCount( pStudioModel->numvertices ); memset( colorVerts.Base(), 0, colorVerts.Count() * sizeof(colorVertex_t) ); int numVertexes = 0; for ( int meshID = 0; meshID < pStudioModel->nummeshes; ++meshID ) { mstudiomesh_t *pStudioMesh = pStudioModel->pMesh( meshID ); const mstudio_meshvertexdata_t *vertData = pStudioMesh->GetVertexData(); for ( int vertexID = 0; vertexID < pStudioMesh->numvertices; ++vertexID ) { // transform position and normal into world coordinate system matrix3x4_t matrix; AngleMatrix( prop.m_Angles, prop.m_Origin, matrix ); VectorTransform( *vertData->Position( vertexID ), matrix, samplePosition ); AngleMatrix( prop.m_Angles, matrix ); VectorTransform( *vertData->Normal( vertexID ), matrix, sampleNormal ); if ( (! (prop.m_Flags & STATIC_PROP_NO_PER_VERTEX_LIGHTING ) ) && PositionInSolid( samplePosition ) ) { // vertex is in solid, add to the bad list, and recover later badVertex_t badVertex; badVertex.m_ColorVertex = numVertexes; badVertex.m_Position = samplePosition; badVertex.m_Normal = sampleNormal; badVerts.AddToTail( badVertex ); } else { Vector direct_pos=samplePosition; int skip_prop=-1; Vector directColor(0,0,0); if (prop.m_Flags & STATIC_PROP_NO_PER_VERTEX_LIGHTING ) { if (prop.m_bLightingOriginValid) VectorCopy( prop.m_LightingOrigin, direct_pos ); else VectorCopy( prop.m_Origin, direct_pos ); skip_prop = prop_index; } if ( prop.m_Flags & STATIC_PROP_NO_SELF_SHADOWING ) skip_prop = prop_index; ComputeDirectLightingAtPoint( direct_pos, sampleNormal, directColor, iThread, skip_prop ); Vector indirectColor(0,0,0); if (g_bShowStaticPropNormals) { directColor= sampleNormal; directColor += Vector(1.0,1.0,1.0); directColor *= 50.0; } else if (numbounce >= 1) ComputeIndirectLightingAtPoint( samplePosition, sampleNormal, indirectColor, iThread, true ); colorVerts[numVertexes].m_bValid = true; colorVerts[numVertexes].m_Position = samplePosition; VectorAdd( directColor, indirectColor, colorVerts[numVertexes].m_Color ); } numVertexes++; } } // color in the bad vertexes // when entire model has no lighting origin and no valid neighbors // must punt, leave black coloring if ( badVerts.Count() && ( prop.m_bLightingOriginValid || badVerts.Count() != numVertexes ) ) { for ( int nBadVertex = 0; nBadVertex < badVerts.Count(); nBadVertex++ ) { Vector bestPosition; if ( prop.m_bLightingOriginValid ) { // use the specified lighting origin VectorCopy( prop.m_LightingOrigin, bestPosition ); } else { // find the closest valid neighbor int best = 0; float closest = FLT_MAX; for ( int nColorVertex = 0; nColorVertex < numVertexes; nColorVertex++ ) { if ( !colorVerts[nColorVertex].m_bValid ) { // skip invalid neighbors continue; } Vector delta; VectorSubtract( colorVerts[nColorVertex].m_Position, badVerts[nBadVertex].m_Position, delta ); float distance = VectorLength( delta ); if ( distance < closest ) { closest = distance; best = nColorVertex; } } // use the best neighbor as the direction to crawl VectorCopy( colorVerts[best].m_Position, bestPosition ); } // crawl toward best position // sudivide to determine a closer valid point to the bad vertex, and re-light Vector midPosition; int numIterations = 20; while ( --numIterations > 0 ) { VectorAdd( bestPosition, badVerts[nBadVertex].m_Position, midPosition ); VectorScale( midPosition, 0.5f, midPosition ); if ( PositionInSolid( midPosition ) ) break; bestPosition = midPosition; } // re-light from better position Vector directColor; ComputeDirectLightingAtPoint( bestPosition, badVerts[nBadVertex].m_Normal, directColor, iThread ); Vector indirectColor; ComputeIndirectLightingAtPoint( bestPosition, badVerts[nBadVertex].m_Normal, indirectColor, iThread, true ); // save results, not changing valid status // to ensure this offset position is not considered as a viable candidate colorVerts[badVerts[nBadVertex].m_ColorVertex].m_Position = bestPosition; VectorAdd( directColor, indirectColor, colorVerts[badVerts[nBadVertex].m_ColorVertex].m_Color ); } } // discard bad verts badVerts.Purge(); // distribute the lighting results for ( int nLod = 0; nLod < pVtxHdr->numLODs; nLod++ ) { OptimizedModel::ModelLODHeader_t *pVtxLOD = pVtxModel->pLOD( nLod ); for ( int nMesh = 0; nMesh < pStudioModel->nummeshes; ++nMesh ) { mstudiomesh_t* pMesh = pStudioModel->pMesh( nMesh ); OptimizedModel::MeshHeader_t* pVtxMesh = pVtxLOD->pMesh( nMesh ); for ( int nGroup = 0; nGroup < pVtxMesh->numStripGroups; ++nGroup ) { OptimizedModel::StripGroupHeader_t* pStripGroup = pVtxMesh->pStripGroup( nGroup ); int nMeshIdx = prop.m_MeshData.AddToTail(); prop.m_MeshData[nMeshIdx].m_Verts.AddMultipleToTail( pStripGroup->numVerts ); prop.m_MeshData[nMeshIdx].m_nLod = nLod; for ( int nVertex = 0; nVertex < pStripGroup->numVerts; ++nVertex ) { int nIndex = pMesh->vertexoffset + pStripGroup->pVertex( nVertex )->origMeshVertID; Assert( nIndex < pStudioModel->numvertices ); prop.m_MeshData[nMeshIdx].m_Verts[nVertex] = colorVerts[nIndex].m_Color; } } } } } } }
void CConfigFile::Term() { m_Entries.Purge(); m_SSDatabase[0] = m_SSResourcePath[0] = m_SSBSPPath[0] = 0; }
void CHLSL_Image::CreateScreenshot( CNodeView *n, const char *filepath ) { Vector4D graphBounds; n->GetGraphBoundaries( graphBounds ); int vsize_x, vsize_y; n->GetSize( vsize_x, vsize_y ); const float zoomFactor = 1.0f / clamp( sedit_screenshot_zoom.GetFloat(), 0.01f, 100.0f ); float nodespace_width = graphBounds.z - graphBounds.x; float nodespace_height = graphBounds.w - graphBounds.y; float nodespace_width_pershot = vsize_x * zoomFactor; float nodespace_height_pershot = vsize_y * zoomFactor; int numshots_x = ceil( nodespace_width / nodespace_width_pershot ); int numshots_y = ceil( nodespace_height / nodespace_height_pershot ); Vector2D extraSpace; extraSpace.x = (nodespace_width_pershot*numshots_x) - nodespace_width; extraSpace.y = (nodespace_height_pershot*numshots_y) - nodespace_height; extraSpace *= 0.5f; n->vecScreenshotBounds.Init( graphBounds.x - extraSpace.x, graphBounds.y - extraSpace.y, graphBounds.z + extraSpace.x, graphBounds.w + extraSpace.y ); int tgapixels_x = numshots_x * vsize_x - numshots_x; int tgapixels_y = numshots_y * vsize_y - numshots_y; unsigned int targetSize = tgapixels_x * 3 * tgapixels_y; unsigned char *pTGA = ( unsigned char * )malloc( targetSize ); if ( !pTGA ) { Warning( "Not enough memory available (failed to malloc %u bytes).\n", targetSize ); } Vector2D pos_old = n->AccessViewPos(); float zoom_old = n->AccessViewZoom(); n->bRenderingScreenShot = true; n->AccessViewZoom() = zoomFactor; int vp_x, vp_y; vp_x = vp_y = 0; n->LocalToScreen( vp_x, vp_y ); int screen_sx, screen_sy; engine->GetScreenSize( screen_sx, screen_sy ); vp_x++; vp_y++; vsize_x--; vsize_y--; n->AccessViewPos().Init(); CViewSetup view2D; view2D.x = 0; view2D.y = 0; view2D.width = screen_sx; view2D.height = screen_sy; view2D.m_bRenderToSubrectOfLargerScreen = false; Frustum _fplanes; CMatRenderContextPtr pRenderContext( materials ); #ifdef SHADER_EDITOR_DLL_2006 render->Push2DView( view2D, 0, false, NULL, _fplanes ); #else render->Push2DView( view2D, 0, NULL, _fplanes ); #endif pRenderContext->PushRenderTargetAndViewport( NULL, view2D.x, view2D.y, view2D.width, view2D.height ); // bool bSuccess = TGAWriter::WriteDummyFileNoAlloc( filepath, tgapixels_x, tgapixels_y, IMAGE_FORMAT_RGBA8888 ); // Assert( bSuccess ); if ( pTGA ) { for ( int sX = 0; sX < numshots_x; sX ++ ) { for ( int sY = 0; sY < numshots_y; sY ++ ) { Vector2D basepos( graphBounds.x + nodespace_width_pershot * 0.5f, graphBounds.w - nodespace_height_pershot * 0.5f ); basepos.x += sX * nodespace_width_pershot; basepos.y -= sY * nodespace_height_pershot; basepos.x *= -1.0f; basepos += extraSpace; n->AccessViewPos() = basepos; pRenderContext->ClearColor4ub( 0, 0, 0, 0 ); pRenderContext->ClearBuffers( true, true ); vgui::ipanel()->PaintTraverse( n->GetVPanel(), true ); unsigned int sizeimg = vsize_x * 3 * vsize_y; unsigned char *pImage = ( unsigned char * )malloc( sizeimg ); if ( pImage ) { pRenderContext->ReadPixels( vp_x, vp_y, vsize_x, vsize_y, pImage, IMAGE_FORMAT_RGB888 ); for ( int pX = 0; pX < vsize_x; pX ++ ) { for ( int pY = 0; pY < vsize_y; pY ++ ) { int targetpixel = (sX * vsize_x + pX) * 3 + ( sY * vsize_y + pY ) * tgapixels_x * 3; int srcpixel = pX * 3 + pY * vsize_x * 3; Q_memcpy( &pTGA[targetpixel], &pImage[srcpixel], 3 ); } } #if 0 #if DEBUG bool bSuccess = #endif TGAWriter::WriteRectNoAlloc( pImage, filepath, sX * vsize_x, sY * vsize_y, vsize_x, vsize_y, 0, IMAGE_FORMAT_RGB888 ); #if DEBUG Assert( bSuccess ); #endif #endif free( pImage ); } else Warning( "Tiling error (failed to malloc %u bytes).\n", sizeimg ); } } } if ( pTGA ) { //unsigned int iMaxTGASize = 1024 + (tgapixels_x * tgapixels_y * 3); //void *pTGA_BUFFER = malloc( iMaxTGASize ); //if ( pTGA_BUFFER ) //{ // CUtlBuffer buffer( pTGA_BUFFER, iMaxTGASize ); // TGAWriter::WriteToBuffer( pTGA, buffer, tgapixels_x, tgapixels_y, IMAGE_FORMAT_RGB888, IMAGE_FORMAT_RGB888 ); // filesystem->AsyncWrite( filepath, buffer.Base(), buffer.TellPut(), true ); //} //else //{ // Warning( "Not enough memory available (failed to malloc %u bytes).\n", iMaxTGASize ); //} jpeg_compress_struct jInfo; ValveJpegErrorHandler_t jErr; jpeg_destination_mgr jDest; jInfo.err = jpeg_std_error( &jErr.m_Base ); jInfo.err->error_exit = &ValveJpegErrorHandler; jpeg_create_compress( &jInfo ); jInfo.dest = &jDest; jInfo.dest->init_destination = &jInit_destination; jInfo.dest->empty_output_buffer = &jEmpty_output_buffer; jInfo.dest->term_destination = &jTerm_destination; jInfo.image_width = tgapixels_x; jInfo.image_height = tgapixels_y; jInfo.input_components = 3; jInfo.in_color_space = JCS_RGB; jpeg_set_defaults( &jInfo ); jpeg_set_quality( &jInfo, clamp( sedit_screenshot_quali.GetInt(), 1, 100 ), FALSE ); jpeg_start_compress(&jInfo, TRUE); JSAMPROW row_pointer[1]; int row_stride; row_stride = jInfo.image_width * 3; while (jInfo.next_scanline < jInfo.image_height) { row_pointer[0] = &pTGA[jInfo.next_scanline * row_stride]; jpeg_write_scanlines(&jInfo, row_pointer, 1); } jpeg_finish_compress(&jInfo); jpeg_destroy_compress(&jInfo); void *pBUFFER = malloc( jOut.Count() ); Q_memcpy( pBUFFER, jOut.Base(), jOut.Count() ); filesystem->AsyncWrite( filepath, pBUFFER, jOut.Count(), true ); jOut.Purge(); free( pTGA ); } pRenderContext->PopRenderTargetAndViewport(); render->PopView( _fplanes ); n->bRenderingScreenShot = false; n->AccessViewPos() = pos_old; n->AccessViewZoom() = zoom_old; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CDarknessLightSourcesSystem::LevelInitPreEntity() { m_LightSources.Purge(); }
//----------------------------------------------------------------------------- // A Scene image file contains all the compiled .XCD //----------------------------------------------------------------------------- bool CSceneImage::CreateSceneImageFile( CUtlBuffer &targetBuffer, char const *pchModPath, bool bLittleEndian, bool bQuiet, ISceneCompileStatus *pStatus ) { CUtlVector<fileList_t> vcdFileList; CUtlSymbolTable vcdSymbolTable( 0, 32, true ); Msg( "\n" ); // get all the VCD files according to the seacrh paths char searchPaths[512]; g_pFullFileSystem->GetSearchPath( "GAME", false, searchPaths, sizeof( searchPaths ) ); char *pPath = strtok( searchPaths, ";" ); while ( pPath ) { int currentCount = vcdFileList.Count(); char szPath[MAX_PATH]; V_ComposeFileName( pPath, "scenes/*.vcd", szPath, sizeof( szPath ) ); scriptlib->FindFiles( szPath, true, vcdFileList ); Msg( "Scenes: Searching '%s' - Found %d scenes.\n", szPath, vcdFileList.Count() - currentCount ); pPath = strtok( NULL, ";" ); } if ( !vcdFileList.Count() ) { Msg( "Scenes: No Scene Files found!\n" ); return false; } // iterate and convert all the VCD files bool bGameIsTF = V_stristr( pchModPath, "\\tf" ) != NULL; for ( int i=0; i<vcdFileList.Count(); i++ ) { const char *pFilename = vcdFileList[i].fileName.String(); const char *pSceneName = V_stristr( pFilename, "scenes\\" ); if ( !pSceneName ) { continue; } if ( !bLittleEndian && bGameIsTF && V_stristr( pSceneName, "high\\" ) ) { continue; } // process files in order they would be found in search paths // i.e. skipping later processed files that match an earlier conversion UtlSymId_t symbol = vcdSymbolTable.Find( pSceneName ); if ( symbol == UTL_INVAL_SYMBOL ) { vcdSymbolTable.AddString( pSceneName ); pStatus->UpdateStatus( pFilename, bQuiet, i, vcdFileList.Count() ); if ( !CreateTargetFile_VCD( pFilename, "", false, bLittleEndian ) ) { Error( "CreateSceneImageFile: Failed on '%s' conversion!\n", pFilename ); } } } if ( !g_SceneFiles.Count() ) { // nothing to do return true; } Msg( "Scenes: Finalizing %d unique scenes.\n", g_SceneFiles.Count() ); // get the string pool CUtlVector< unsigned int > stringOffsets; CUtlBuffer stringPool; g_ChoreoStringPool.GetTableAndPool( stringOffsets, stringPool ); if ( !bQuiet ) { Msg( "Scenes: String Table: %d bytes\n", stringOffsets.Count() * sizeof( int ) ); Msg( "Scenes: String Pool: %d bytes\n", stringPool.TellMaxPut() ); } // first header, then lookup table, then string pool blob int stringPoolStart = sizeof( SceneImageHeader_t ) + stringOffsets.Count() * sizeof( int ); // then directory int sceneEntryStart = stringPoolStart + stringPool.TellMaxPut(); // then variable sized summaries int sceneSummaryStart = sceneEntryStart + g_SceneFiles.Count() * sizeof( SceneImageEntry_t ); // then variable sized compiled binary scene data int sceneDataStart = 0; // construct header SceneImageHeader_t imageHeader = { 0 }; imageHeader.nId = SCENE_IMAGE_ID; imageHeader.nVersion = SCENE_IMAGE_VERSION; imageHeader.nNumScenes = g_SceneFiles.Count(); imageHeader.nNumStrings = stringOffsets.Count(); imageHeader.nSceneEntryOffset = sceneEntryStart; if ( !bLittleEndian ) { imageHeader.nId = BigLong( imageHeader.nId ); imageHeader.nVersion = BigLong( imageHeader.nVersion ); imageHeader.nNumScenes = BigLong( imageHeader.nNumScenes ); imageHeader.nNumStrings = BigLong( imageHeader.nNumStrings ); imageHeader.nSceneEntryOffset = BigLong( imageHeader.nSceneEntryOffset ); } targetBuffer.Put( &imageHeader, sizeof( imageHeader ) ); // header is immediately followed by string table and pool for ( int i = 0; i < stringOffsets.Count(); i++ ) { unsigned int offset = stringPoolStart + stringOffsets[i]; if ( !bLittleEndian ) { offset = BigLong( offset ); } targetBuffer.PutInt( offset ); } Assert( stringPoolStart == targetBuffer.TellMaxPut() ); targetBuffer.Put( stringPool.Base(), stringPool.TellMaxPut() ); // construct directory CUtlSortVector< SceneImageEntry_t, CSceneImageEntryLessFunc > imageDirectory; imageDirectory.EnsureCapacity( g_SceneFiles.Count() ); // build directory // directory is linear sorted by filename checksum for later binary search for ( int i = 0; i < g_SceneFiles.Count(); i++ ) { SceneImageEntry_t imageEntry = { 0 }; // name needs to be normalized for determinstic later CRC name calc // calc crc based on scenes\anydir\anyscene.vcd char szCleanName[MAX_PATH]; V_strncpy( szCleanName, g_SceneFiles[i].fileName.String(), sizeof( szCleanName ) ); V_strlower( szCleanName ); V_FixSlashes( szCleanName ); char *pName = V_stristr( szCleanName, "scenes\\" ); if ( !pName ) { // must have scenes\ in filename Error( "CreateSceneImageFile: Unexpected lack of scenes prefix on %s\n", g_SceneFiles[i].fileName.String() ); } CRC32_t crcFilename = CRC32_ProcessSingleBuffer( pName, strlen( pName ) ); imageEntry.crcFilename = crcFilename; // temp store an index to its file, fixup later, necessary to access post sort imageEntry.nDataOffset = i; if ( imageDirectory.Find( imageEntry ) != imageDirectory.InvalidIndex() ) { // filename checksums must be unique or runtime binary search would be bogus Error( "CreateSceneImageFile: Unexpected filename checksum collision!\n" ); } imageDirectory.Insert( imageEntry ); } // determine sort order and start of data after dynamic summaries CUtlVector< int > writeOrder; writeOrder.EnsureCapacity( g_SceneFiles.Count() ); sceneDataStart = sceneSummaryStart; for ( int i = 0; i < imageDirectory.Count(); i++ ) { // reclaim offset, indicates write order of scene file int iScene = imageDirectory[i].nDataOffset; writeOrder.AddToTail( iScene ); // march past each variable sized summary to determine start of scene data int numSounds = g_SceneFiles[iScene].soundList.Count(); sceneDataStart += sizeof( SceneImageSummary_t ) + ( numSounds - 1 ) * sizeof( int ); } // finalize and write directory Assert( sceneEntryStart == targetBuffer.TellMaxPut() ); int nSummaryOffset = sceneSummaryStart; int nDataOffset = sceneDataStart; for ( int i = 0; i < imageDirectory.Count(); i++ ) { int iScene = writeOrder[i]; imageDirectory[i].nDataOffset = nDataOffset; imageDirectory[i].nDataLength = g_SceneFiles[iScene].compiledBuffer.TellMaxPut(); imageDirectory[i].nSceneSummaryOffset = nSummaryOffset; if ( !bLittleEndian ) { imageDirectory[i].crcFilename = BigLong( imageDirectory[i].crcFilename ); imageDirectory[i].nDataOffset = BigLong( imageDirectory[i].nDataOffset ); imageDirectory[i].nDataLength = BigLong( imageDirectory[i].nDataLength ); imageDirectory[i].nSceneSummaryOffset = BigLong( imageDirectory[i].nSceneSummaryOffset ); } targetBuffer.Put( &imageDirectory[i], sizeof( SceneImageEntry_t ) ); int numSounds = g_SceneFiles[iScene].soundList.Count(); nSummaryOffset += sizeof( SceneImageSummary_t ) + (numSounds - 1) * sizeof( int ); nDataOffset += g_SceneFiles[iScene].compiledBuffer.TellMaxPut(); } // finalize and write summaries Assert( sceneSummaryStart == targetBuffer.TellMaxPut() ); for ( int i = 0; i < imageDirectory.Count(); i++ ) { int iScene = writeOrder[i]; int msecs = g_SceneFiles[iScene].msecs; int soundCount = g_SceneFiles[iScene].soundList.Count(); if ( !bLittleEndian ) { msecs = BigLong( msecs ); soundCount = BigLong( soundCount ); } targetBuffer.PutInt( msecs ); targetBuffer.PutInt( soundCount ); for ( int j = 0; j < g_SceneFiles[iScene].soundList.Count(); j++ ) { int soundId = g_SceneFiles[iScene].soundList[j]; if ( !bLittleEndian ) { soundId = BigLong( soundId ); } targetBuffer.PutInt( soundId ); } } // finalize and write data Assert( sceneDataStart == targetBuffer.TellMaxPut() ); for ( int i = 0; i < imageDirectory.Count(); i++ ) { int iScene = writeOrder[i]; targetBuffer.Put( g_SceneFiles[iScene].compiledBuffer.Base(), g_SceneFiles[iScene].compiledBuffer.TellMaxPut() ); } if ( !bQuiet ) { Msg( "Scenes: Final size: %.2f MB\n", targetBuffer.TellMaxPut() / (1024.0f * 1024.0f ) ); } // cleanup g_SceneFiles.Purge(); return true; }