static sboolean Music_ParseLeveldata(const char *psLevelName) { sboolean bReturn = qfalse; if (MusicData == NULL) { MusicData = new MusicData_t; } // already got this data? // if (MusicData->size() && !Q_stricmp(psLevelName,gsLevelNameForCompare.c_str())) { return qtrue; } MusicData->clear(); char sLevelName[MAX_QPATH]; Q_strncpyz(sLevelName,psLevelName,sizeof(sLevelName)); gsLevelNameForLoad = sLevelName; // harmless to init here even if we fail to parse dms.dat file gsLevelNameForCompare = sLevelName; // harmless to init here even if we fail to parse dms.dat file gsLevelNameForBossLoad = sLevelName; // harmless to init here even if we fail to parse dms.dat file char *pText = NULL; /*int iTotalBytesLoaded = */FS_ReadFile(sFILENAME_DMS, (void **)&pText ); if (pText) { char *psStrippedText = StripTrailingWhiteSpaceOnEveryLine(pText); CGenericParser2 Parser; char *psDataPtr = psStrippedText; // because ptr gets advanced, so we supply a clone that GP can alter if (Parser.Parse(&psDataPtr, true)) { CGPGroup *pFileGroup = Parser.GetBaseParseGroup(); if (pFileGroup) { CGPGroup *pgMusicFiles = pFileGroup->FindSubGroup(sKEY_MUSICFILES); if (pgMusicFiles) { CGPGroup *pgLevelMusic = pFileGroup->FindSubGroup(sKEY_LEVELMUSIC); if (pgLevelMusic) { CGPGroup *pgThisLevelMusic = NULL; // // check for new USE keyword... // int iSanityLimit = 0; sstring_t sSearchName(sLevelName); while (sSearchName.c_str()[0] && iSanityLimit < 10) { gsLevelNameForLoad = sSearchName; gsLevelNameForBossLoad = sSearchName; pgThisLevelMusic = pgLevelMusic->FindSubGroup(sSearchName.c_str()); if (pgThisLevelMusic) { CGPValue *pValue = pgThisLevelMusic->FindPair(sKEY_USES); if (pValue) { // re-search using the USE param... // sSearchName = pValue->GetTopValue(); iSanityLimit++; // Com_DPrintf("Using \"%s\"\n",sSearchName.c_str()); } else { // no new USE keyword found... // sSearchName = ""; } } else { // level entry not found... // break; } } // now go ahead and use the final music set we've decided on... // if (pgThisLevelMusic && iSanityLimit < 10) { // these are optional fields, so see which ones we find... // LPCSTR psName_Explore = NULL; LPCSTR psName_Action = NULL; LPCSTR psName_Boss = NULL; LPCSTR psName_Death = NULL; // LPCSTR psName_UseBoss = NULL; for (CGPValue *pValue = pgThisLevelMusic->GetPairs(); pValue; pValue = pValue->GetNext()) { LPCSTR psKey = pValue->GetName(); LPCSTR psValue = pValue->GetTopValue(); if (Q_stricmp(psValue,sKEY_PLACEHOLDER)) // ignore "placeholder" items { if (!Q_stricmp(psKey,sKEY_EXPLORE)) { psName_Explore = psValue; } else if (!Q_stricmp(psKey,sKEY_ACTION)) { psName_Action = psValue; } else if (!Q_stricmp(psKey,sKEY_USEBOSS)) { psName_UseBoss = psValue; } else if (!Q_stricmp(psKey,sKEY_BOSS)) { psName_Boss = psValue; } else if (!Q_stricmp(psKey,sKEY_DEATH)) { psName_Death = psValue; } } } bReturn = qtrue; // defualt to ON now, so I can turn it off if "useboss" fails if (psName_UseBoss) { CGPGroup *pgLevelMusicOfBoss = pgLevelMusic->FindSubGroup(psName_UseBoss); if (pgLevelMusicOfBoss) { CGPValue *pValueBoss = pgLevelMusicOfBoss->FindPair(sKEY_BOSS); if (pValueBoss) { psName_Boss = pValueBoss->GetTopValue(); gsLevelNameForBossLoad = psName_UseBoss; } else { MUSIC_PARSE_ERROR(va("'useboss' \"%s\" has no \"boss\" entry!\n",psName_UseBoss)); bReturn = qfalse; } } else { MUSIC_PARSE_ERROR(va("Unable to find 'useboss' entry \"%s\"\n",psName_UseBoss)); bReturn = qfalse; } } // done this way in case I want to conditionally pass any bools depending on music type... // if (bReturn && psName_Explore) { bReturn = Music_ParseMusic(Parser, MusicData, pgMusicFiles, psName_Explore, sKEY_EXPLORE, eBGRNDTRACK_EXPLORE); } if (bReturn && psName_Action) { bReturn = Music_ParseMusic(Parser, MusicData, pgMusicFiles, psName_Action, sKEY_ACTION, eBGRNDTRACK_ACTION); } if (bReturn && psName_Boss) { bReturn = Music_ParseMusic(Parser, MusicData, pgMusicFiles, psName_Boss, sKEY_BOSS, eBGRNDTRACK_BOSS); } if (bReturn /*&& psName_Death*/) // LAST MINUTE HACK!!, always force in some death music!!!! { //bReturn = Music_ParseMusic(Parser, MusicData, pgMusicFiles, psName_Death, sKEY_DEATH, eBGRNDTRACK_DEATH); MusicFile_t m; m.sFileNameBase = "death_music"; (*MusicData)[ sKEY_DEATH ] = m; } } else { MUSIC_PARSE_WARNING(va("Unable to find entry for \"%s\" in \"%s\"\n",sLevelName,sFILENAME_DMS)); } } else { MUSIC_PARSE_ERROR(va("Unable to find subgroup \"%s\"\n",sKEY_LEVELMUSIC)); } } else { MUSIC_PARSE_ERROR(va("Unable to find subgroup \"%s\"\n",sKEY_MUSICFILES)); } } else { MUSIC_PARSE_ERROR( "Error calling GP2.GetBaseParseGroup()\n" ); } } else { MUSIC_PARSE_ERROR( "Error using GP to parse file\n" ); } Z_Free(psStrippedText); FS_FreeFile( pText ); } else { MUSIC_PARSE_ERROR( "Unable to even read main file\n" ); // file name specified in error message } if (bReturn) { // sort exit points, and do some error checking... // for (MusicData_t::iterator itMusicData = MusicData->begin(); itMusicData != MusicData->end(); ++itMusicData) { LPCSTR psMusicStateType = (*itMusicData).first.c_str(); MusicFile_t &MusicFile = (*itMusicData).second; // kludge up an enum, only interested in boss or not at the moment, so... // MusicState_e eMusicState = !stricmp(psMusicStateType,"boss") ? eBGRNDTRACK_BOSS : !stricmp(psMusicStateType,"death") ? eBGRNDTRACK_DEATH : eBGRNDTRACK_EXPLORE; if (!MusicFile.MusicExitTimes.empty()) { sort(MusicFile.MusicExitTimes.begin(),MusicFile.MusicExitTimes.end()); } // check music exists... // LPCSTR psMusicFileName = Music_BuildFileName( MusicFile.sFileNameBase.c_str(), eMusicState ); if (!S_FileExists( psMusicFileName )) { MUSIC_PARSE_ERROR(va("Music file \"%s\" not found!\n",psMusicFileName)); return qfalse; // have to return, because music data destroyed now } // check all transition music pieces exist, and that entry points into new pieces after transitions also exist... // for (int iExitPoint=0; iExitPoint < MusicFile.MusicExitPoints.size(); iExitPoint++) { MusicExitPoint_t &MusicExitPoint = MusicFile.MusicExitPoints[ iExitPoint ]; LPCSTR psTransitionFileName = Music_BuildFileName( MusicExitPoint.sNextFile.c_str(), eMusicState ); if (!S_FileExists( psTransitionFileName )) { MUSIC_PARSE_ERROR(va("Transition file \"%s\" (entry \"%s\" ) not found!\n",psTransitionFileName, MusicExitPoint.sNextFile.c_str())); return qfalse; // have to return, because music data destroyed now } LPCSTR psNextMark = MusicExitPoint.sNextMark.c_str(); if (strlen(psNextMark)) // always NZ ptr { // then this must be "action" music under current rules... // assert( !strcmp(psMusicStateType, Music_BaseStateToString(eBGRNDTRACK_ACTION) ? Music_BaseStateToString(eBGRNDTRACK_ACTION):"") ); // // does this marker exist in the explore piece? // MusicData_t::iterator itExploreMusicData = MusicData->find( Music_BaseStateToString(eBGRNDTRACK_EXPLORE) ); if (itExploreMusicData != MusicData->end()) { MusicFile_t &MusicFile_Explore = (*itExploreMusicData).second; if (!MusicFile_Explore.MusicEntryTimes.count(psNextMark)) { MUSIC_PARSE_ERROR( va("Unable to find entry point \"%s\" in description for \"%s\"\n",psNextMark,MusicFile_Explore.sFileNameBase.c_str()) ); return qfalse; // have to return, because music data destroyed now } } else { MUSIC_PARSE_ERROR( va("Unable to find %s piece to match \"%s\"\n", Music_BaseStateToString(eBGRNDTRACK_EXPLORE), MusicFile.sFileNameBase.c_str() ) ); return qfalse; // have to return, because music data destroyed now } } } } } #ifdef _DEBUG /* // dump the whole thing out to prove it was read in ok... // if (bReturn) { for (MusicData_t::iterator itMusicData = MusicData->begin(); itMusicData != MusicData->end(); ++itMusicData) { LPCSTR psMusicState = (*itMusicData).first.c_str(); MusicFile_t &MusicFile = (*itMusicData).second; OutputDebugString(va("Music State: \"%s\", File: \"%s\"\n",psMusicState, MusicFile.sFileNameBase.c_str())); // entry times... // for (MusicEntryTimes_t::iterator itEntryTimes = MusicFile.MusicEntryTimes.begin(); itEntryTimes != MusicFile.MusicEntryTimes.end(); ++itEntryTimes) { LPCSTR psMarkerName = (*itEntryTimes).first.c_str(); float fEntryTime = (*itEntryTimes).second; OutputDebugString(va("Entry time for \"%s\": %f\n", psMarkerName, fEntryTime)); } // exit points... // for (int i=0; i<MusicFile.MusicExitPoints.size(); i++) { MusicExitPoint_t &MusicExitPoint = MusicFile.MusicExitPoints[i]; OutputDebugString(va("Exit point %d: sNextFile: \"%s\", sNextMark: \"%s\"\n",i,MusicExitPoint.sNextFile.c_str(),MusicExitPoint.sNextMark.c_str())); } // exit times... // for (i=0; i<MusicFile.MusicExitTimes.size(); i++) { MusicExitTime_t &MusicExitTime = MusicFile.MusicExitTimes[i]; OutputDebugString(va("Exit time %d: fTime: %f, iExitPoint: %d\n",i,MusicExitTime.fTime,MusicExitTime.iExitPoint)); } } } */ #endif return bReturn; }
static bool Music_ParseMusic( gsl::czstring filename, const CGenericParser2& Parser, MusicData_t* MusicData, const CGPGroup& pgMusicFiles, const gsl::cstring_view& psMusicName, const gsl::cstring_view& psMusicNameKey, MusicState_e eMusicState ) { bool bReturn = false; MusicFile_t MusicFile; const CGPGroup* pgMusicFile = pgMusicFiles.FindSubGroup( psMusicName ); if( pgMusicFile ) { // read subgroups... // bool bEntryFound = false; bool bExitFound = false; // // (read entry points first, so I can check exit points aren't too close in time) // const CGPGroup* pEntryGroup = pgMusicFile->FindSubGroup( sKEY_ENTRY ); if( pEntryGroup ) { // read entry points... // for( auto& prop : pEntryGroup->GetProperties() ) { //if (!strncmp(psKey,sKEY_MARKER,strlen(sKEY_MARKER))) // for now, assume anything is a marker MusicFile.MusicEntryTimes[ StringViewToSString( prop.GetName() ) ] = Q::svtoi( prop.GetTopValue() ); bEntryFound = true; } } for( auto& group : pgMusicFile->GetSubGroups() ) { auto& groupName = group.GetName(); if( groupName == sKEY_ENTRY ) { // skip entry points, I've already read them in above // } else if( groupName == sKEY_EXIT ) { int iThisExitPointIndex = MusicFile.MusicExitPoints.size(); // must eval this first, so unaffected by push_back etc // // read this set of exit points... // MusicExitPoint_t MusicExitPoint; for( auto& prop : group.GetProperties() ) { auto& key = prop.GetName(); auto& value = prop.GetTopValue(); if( key == sKEY_NEXTFILE ) { MusicExitPoint.sNextFile = StringViewToSString( value ); bExitFound = true; // harmless to keep setting } else if( key == sKEY_NEXTMARK ) { MusicExitPoint.sNextMark = StringViewToSString( value ); } else if( key == sKEY_TIME ) { MusicExitTime_t MusicExitTime; MusicExitTime.fTime = Q::svtof( value ); MusicExitTime.iExitPoint = iThisExitPointIndex; // new check, don't keep this this exit point if it's within 1.5 seconds either way of an entry point... // bool bTooCloseToEntryPoint = false; for( auto& item : MusicFile.MusicEntryTimes ) { float fThisEntryTime = item.second; if( Q_fabs( fThisEntryTime - MusicExitTime.fTime ) < 1.5f ) { // bTooCloseToEntryPoint = true; // not sure about this, ignore for now break; } } if( !bTooCloseToEntryPoint ) { MusicFile.MusicExitTimes.push_back( MusicExitTime ); } } } MusicFile.MusicExitPoints.push_back( MusicExitPoint ); int iNumExitPoints = MusicFile.MusicExitPoints.size(); // error checking... // switch( eMusicState ) { case eBGRNDTRACK_EXPLORE: if( iNumExitPoints > iMAX_EXPLORE_TRANSITIONS ) { Music_Parse_Error( filename, build_string( "\"", psMusicName, "\" has > ", iMAX_EXPLORE_TRANSITIONS, " ", psMusicNameKey, " transitions defined!\n" ) ); return false; } break; case eBGRNDTRACK_ACTION: if( iNumExitPoints > iMAX_ACTION_TRANSITIONS ) { Music_Parse_Error( filename, build_string( "\"", psMusicName, "\" has > ", iMAX_ACTION_TRANSITIONS, " ", psMusicNameKey, " transitions defined!\n" ) ); return false; } break; case eBGRNDTRACK_BOSS: case eBGRNDTRACK_DEATH: Music_Parse_Error( filename, build_string( "\"", psMusicName, "\" has ", psMusicNameKey, " transitions defined, this is not allowed!\n" ) ); return false; default: break; } } } // for now, assume everything was ok unless some obvious things are missing... // bReturn = true; // boss & death pieces can omit entry/exit stuff if( eMusicState != eBGRNDTRACK_BOSS && eMusicState != eBGRNDTRACK_DEATH ) { if( !bEntryFound ) { Music_Parse_Error( filename, build_string( "Unable to find subgroup \"", sKEY_ENTRY, "\" in group \"", psMusicName, "\"\n" ) ); bReturn = false; } if( !bExitFound ) { Music_Parse_Error( filename, build_string( "Unable to find subgroup \"", sKEY_EXIT, "\" in group \"", psMusicName, "\"\n" ) ); bReturn = false; } } } else { Music_Parse_Error( filename, build_string( "Unable to find musicfiles entry \"", psMusicName, "\"\n" ) ); } if( bReturn ) { MusicFile.sFileNameBase = StringViewToSString( psMusicName ); ( *MusicData )[ StringViewToSString( psMusicNameKey ) ] = MusicFile; } return bReturn; }
static sboolean Music_ParseMusic(CGenericParser2 &Parser, MusicData_t *MusicData, CGPGroup *pgMusicFiles, LPCSTR psMusicName, LPCSTR psMusicNameKey, MusicState_e eMusicState) { sboolean bReturn = qfalse; #ifdef _XBOX Z_SetNewDeleteTemporary(true); #endif MusicFile_t MusicFile; #ifdef _XBOX Z_SetNewDeleteTemporary(false); #endif CGPGroup *pgMusicFile = pgMusicFiles->FindSubGroup(psMusicName); if (pgMusicFile) { // read subgroups... // sboolean bEntryFound = qfalse; sboolean bExitFound = qfalse; // // (read entry points first, so I can check exit points aren't too close in time) // CGPGroup *pEntryGroup = pgMusicFile->FindSubGroup(sKEY_ENTRY); if (pEntryGroup) { // read entry points... // for (CGPValue *pValue = pEntryGroup->GetPairs(); pValue; pValue = pValue->GetNext()) { LPCSTR psKey = pValue->GetName(); LPCSTR psValue = pValue->GetTopValue(); //if (!strncmp(psKey,sKEY_MARKER,strlen(sKEY_MARKER))) // for now, assume anything is a marker { MusicFile.MusicEntryTimes[psKey] = atof(psValue); bEntryFound = qtrue; // harmless to keep setting } } } for (CGPGroup *pGroup = pgMusicFile->GetSubGroups(); pGroup; pGroup = pGroup->GetNext()) { LPCSTR psGroupName = pGroup->GetName(); if (!strcmp(psGroupName,sKEY_ENTRY)) { // skip entry points, I've already read them in above // } else if (!strcmp(psGroupName,sKEY_EXIT)) { int iThisExitPointIndex = MusicFile.MusicExitPoints.size(); // must eval this first, so unaffected by push_back etc // // read this set of exit points... // MusicExitPoint_t MusicExitPoint; for (CGPValue *pValue = pGroup->GetPairs(); pValue; pValue = pValue->GetNext()) { LPCSTR psKey = pValue->GetName(); LPCSTR psValue = pValue->GetTopValue(); if (!strcmp(psKey,sKEY_NEXTFILE)) { MusicExitPoint.sNextFile = psValue; bExitFound = qtrue; // harmless to keep setting } else if (!strcmp(psKey,sKEY_NEXTMARK)) { MusicExitPoint.sNextMark = psValue; } else if (!strncmp(psKey,sKEY_TIME,strlen(sKEY_TIME))) { MusicExitTime_t MusicExitTime; MusicExitTime.fTime = atof(psValue); MusicExitTime.iExitPoint= iThisExitPointIndex; // new check, don't keep this this exit point if it's within 1.5 seconds either way of an entry point... // sboolean bTooCloseToEntryPoint = qfalse; for (MusicEntryTimes_t::iterator itEntryTimes = MusicFile.MusicEntryTimes.begin(); itEntryTimes != MusicFile.MusicEntryTimes.end(); ++itEntryTimes) { float fThisEntryTime = (*itEntryTimes).second; if (Q_fabs(fThisEntryTime - MusicExitTime.fTime) < 1.5f) { // bTooCloseToEntryPoint = qtrue; // not sure about this, ignore for now break; } } if (!bTooCloseToEntryPoint) { #ifdef _XBOX Z_SetNewDeleteTemporary(true); #endif MusicFile.MusicExitTimes.push_back(MusicExitTime); #ifdef _XBOX Z_SetNewDeleteTemporary(false); #endif } } } #ifdef _XBOX Z_SetNewDeleteTemporary(true); #endif MusicFile.MusicExitPoints.push_back(MusicExitPoint); #ifdef _XBOX Z_SetNewDeleteTemporary(false); #endif int iNumExitPoints = MusicFile.MusicExitPoints.size(); // error checking... // switch (eMusicState) { case eBGRNDTRACK_EXPLORE: if (iNumExitPoints > iMAX_EXPLORE_TRANSITIONS) { MUSIC_PARSE_ERROR( va("\"%s\" has > %d %s transitions defined!\n",psMusicName,iMAX_EXPLORE_TRANSITIONS,psMusicNameKey) ); return qfalse; } break; case eBGRNDTRACK_ACTION: if (iNumExitPoints > iMAX_ACTION_TRANSITIONS) { MUSIC_PARSE_ERROR( va("\"%s\" has > %d %s transitions defined!\n",psMusicName,iMAX_ACTION_TRANSITIONS,psMusicNameKey) ); return qfalse; } break; case eBGRNDTRACK_BOSS: case eBGRNDTRACK_DEATH: MUSIC_PARSE_ERROR( va("\"%s\" has %s transitions defined, this is not allowed!\n",psMusicName,psMusicNameKey) ); break; } } } // for now, assume everything was ok unless some obvious things are missing... // bReturn = qtrue; if (eMusicState != eBGRNDTRACK_BOSS && eMusicState != eBGRNDTRACK_DEATH) // boss & death pieces can omit entry/exit stuff { if (!bEntryFound) { MUSIC_PARSE_ERROR(va("Unable to find subgroup \"%s\" in group \"%s\"\n",sKEY_ENTRY,psMusicName)); bReturn = qfalse; } if (!bExitFound) { MUSIC_PARSE_ERROR(va("Unable to find subgroup \"%s\" in group \"%s\"\n",sKEY_EXIT,psMusicName)); bReturn = qfalse; } } } else { MUSIC_PARSE_ERROR(va("Unable to find musicfiles entry \"%s\"\n",psMusicName)); } if (bReturn) { MusicFile.sFileNameBase = psMusicName; (*MusicData)[ psMusicNameKey ] = MusicFile; } return bReturn; }
// returns true if at least one set of skin data was read, else false... // static bool Skins_Read(LPCSTR psModelFilename) { LPCSTR psError = NULL; CWaitCursor; LPCSTR psSkinsPath = Skins_ModelNameToSkinPath(psModelFilename); // eg "models/characters/skins" if (psSkinsPath) { string strThisModelBaseName(String_ToLower(Filename_WithoutExt(Filename_WithoutPath(psModelFilename)))); char **ppsSkinFiles; int iSkinFiles; // scan for skin files... // ppsSkinFiles = //ri.FS_ListFiles( "shaders", ".shader", &iSkinFiles ); Sys_ListFiles( va("%s%s",gamedir,psSkinsPath),// const char *directory, ".g2skin", // const char *extension, NULL, // char *filter, &iSkinFiles,// int *numfiles, qfalse // qboolean wantsubs ); if ( !ppsSkinFiles || !iSkinFiles ) { CurrentSkins.clear(); CurrentSkinsSurfacePrefs.clear(); return false; } if ( iSkinFiles > MAX_SKIN_FILES ) { WarningBox(va("%d skin files found, capping to %d\n\n(tell me if this ever happens -Ste)", iSkinFiles, MAX_SKIN_FILES )); iSkinFiles = MAX_SKIN_FILES; } // load and parse skin files... // // for now, I just scan each file and if it's out of date then I invalidate it's model-prefs info... // extern bool GetFileTime(LPCSTR psFileName, FILETIME &ft); for (int i=0; i<iSkinFiles; i++) { bool bReParseThisFile = false; char sFileName[MAX_QPATH]; LPCSTR psFileName = ppsSkinFiles[i]; Com_sprintf( sFileName, sizeof( sFileName ), "%s/%s", psSkinsPath, psFileName ); psFileName = &sFileName[0]; // have a go at getting this time/date stamp if not already present... // if (!SkinFileTimeDates[psFileName].bValid) { FILETIME ft; if (GetFileTime(psFileName, ft)) { SkinFileTimeDates[psFileName].ft = ft; SkinFileTimeDates[psFileName].bValid = true; } } // now see if there's a valid time-stamp, and use it if so, else give up and re-scan all files... // if (SkinFileTimeDates[psFileName].bValid) { FILETIME ft; if (GetFileTime(psFileName, ft)) { LONG l = CompareFileTime( &SkinFileTimeDates[psFileName].ft, &ft); bReParseThisFile = (l<0); } else { bReParseThisFile = true; } } else { bReParseThisFile = true; } if (bReParseThisFile) { G2SkinModelPrefs[sFileName].clear(); } } if (1)//bReParseSkinFiles || !CurrentSkins.size()) { CurrentSkins.clear(); CurrentSkinsSurfacePrefs.clear(); char *buffers[MAX_SKIN_FILES]={0}; // long iTotalBytesLoaded = 0; for ( int i=0; i<iSkinFiles && !psError; i++ ) { char sFileName[MAX_QPATH]; string strThisSkinFile(ppsSkinFiles[i]); Com_sprintf( sFileName, sizeof( sFileName ), "%s/%s", psSkinsPath, strThisSkinFile.c_str() ); StatusMessage( va("Scanning skin %d/%d: \"%s\"...",i+1,iSkinFiles,sFileName)); //ri.Printf( PRINT_ALL, "...loading '%s'\n", sFileName ); bool _bDiskLoadOccured = false; // debug use only, but wtf? #define LOAD_SKIN_FILE \ /*iTotalBytesLoaded += */ ri.FS_ReadFile( sFileName, (void **)&buffers[i] ); \ if ( !buffers[i] ) \ { \ CurrentSkins.clear(); \ CurrentSkinsSurfacePrefs.clear(); \ \ ri.Error( ERR_DROP, "Couldn't load %s", sFileName );\ } \ _bDiskLoadOccured = true; // see if we should pay attention to the contents of this file... // CGPGroup *pFileGroup = NULL; CGPGroup *pParseGroup_Prefs = NULL; CGenericParser2 SkinParser; // bool bParseThisFile = false; // // if we have any information about this skin file as regards what models it refers to, use the info... // if (G2SkinModelPrefs[sFileName].size()) { map<string, int>::iterator it = G2SkinModelPrefs[sFileName].find( strThisModelBaseName ); if (it != G2SkinModelPrefs[sFileName].end()) { // this skin file contains this entry, so just check that we can setup the parse groups ok... // LOAD_SKIN_FILE; char *psDataPtr = buffers[i]; if (SkinParser.Parse(&psDataPtr, true)) { pFileGroup = SkinParser.GetBaseParseGroup(); if (pFileGroup) { pParseGroup_Prefs = pFileGroup->FindSubGroup(sSKINKEYWORD_PREFS);//, true); if (pParseGroup_Prefs) { bParseThisFile = true; } } } else { ErrorBox(va("{} - Brace mismatch error in file \"%s\"!",sFileName)); } } } else { // no size info for this file, so check it manually... // LOAD_SKIN_FILE; if (Skins_ParseThisFile(SkinParser, buffers[i], strThisModelBaseName, pFileGroup, pParseGroup_Prefs, sFileName, G2SkinModelPrefs) ) { bParseThisFile = true; } } if (bParseThisFile) { psError = Skins_Parse( strThisSkinFile, pFileGroup, pParseGroup_Prefs); if (psError) { ErrorBox(va("Skins_Read(): Error reading file \"%s\"!\n\n( Skins will be ignored for this model )\n\nError was:\n\n",sFileName,psError)); } } else { //OutputDebugString(va("Skipping parse of file \"%s\" %s\n",sFileName, _bDiskLoadOccured?"":"( and no load! )")); } } // // free loaded skin files... // for ( i=0; i<iSkinFiles; i++ ) { if (buffers[i]) { ri.FS_FreeFile( buffers[i] ); } } } StatusMessage(NULL); Sys_FreeFileList( ppsSkinFiles ); } else { CurrentSkins.clear(); CurrentSkinsSurfacePrefs.clear(); } if (psError) { return false; } return !!(CurrentSkins.size()); }