/* ====================== UI_ParseAnimationFile ====================== */ static qboolean UI_ParseAnimationFile( const char *filename, uiPlayerInfo_t *pi ) { char *text_p, *prev; int len; int i; char *token; float fps; int skip; char text[20000]; fileHandle_t f; animation_t *animations; animations = pi->animations; memset( animations, 0, sizeof( animation_t ) * MAX_ANIMATIONS ); pi->fixedlegs = qfalse; pi->fixedtorso = qfalse; // load the file len = trap_FS_FOpenFile( filename, &f, FS_READ ); if ( len <= 0 ) { return qfalse; } if ( len >= ( sizeof( text ) - 1 ) ) { Com_Printf( "File %s too long\n", filename ); trap_FS_FCloseFile( f ); return qfalse; } trap_FS_Read( text, len, f ); text[len] = 0; trap_FS_FCloseFile( f ); // parse the text text_p = text; skip = 0; // quite the compiler warning // read optional parameters while ( 1 ) { prev = text_p; // so we can unget token = COM_Parse( &text_p ); if ( !token[0] ) { break; } if ( !Q_stricmp( token, "footsteps" ) ) { token = COM_Parse( &text_p ); if ( !token[0] ) { break; } continue; } else if ( !Q_stricmp( token, "headoffset" ) ) { for ( i = 0 ; i < 3 ; i++ ) { token = COM_Parse( &text_p ); if ( !token[0] ) { break; } } continue; } else if ( !Q_stricmp( token, "sex" ) ) { token = COM_Parse( &text_p ); if ( !token[0] ) { break; } continue; } else if ( !Q_stricmp( token, "fixedlegs" ) ) { pi->fixedlegs = qtrue; continue; } else if ( !Q_stricmp( token, "fixedtorso" ) ) { pi->fixedtorso = qtrue; continue; } // if it is a number, start parsing animations if ( token[0] >= '0' && token[0] <= '9' ) { text_p = prev; // unget the token break; } Com_Printf( "unknown token '%s' in %s\n", token, filename ); } // read information for each frame for ( i = 0 ; i < MAX_ANIMATIONS ; i++ ) { token = COM_Parse( &text_p ); if ( !token[0] ) { if( i >= TORSO_GETFLAG && i <= TORSO_NEGATIVE ) { animations[i].firstFrame = animations[TORSO_GESTURE].firstFrame; animations[i].frameLerp = animations[TORSO_GESTURE].frameLerp; animations[i].initialLerp = animations[TORSO_GESTURE].initialLerp; animations[i].loopFrames = animations[TORSO_GESTURE].loopFrames; animations[i].numFrames = animations[TORSO_GESTURE].numFrames; animations[i].reversed = qfalse; animations[i].flipflop = qfalse; continue; } break; } animations[i].firstFrame = atoi( token ); // leg only frames are adjusted to not count the upper body only frames if ( i == LEGS_WALKCR ) { skip = animations[LEGS_WALKCR].firstFrame - animations[TORSO_GESTURE].firstFrame; } if ( i >= LEGS_WALKCR && i<TORSO_GETFLAG) { animations[i].firstFrame -= skip; } token = COM_Parse( &text_p ); if ( !token[0] ) { break; } animations[i].numFrames = atoi( token ); animations[i].reversed = qfalse; animations[i].flipflop = qfalse; // if numFrames is negative the animation is reversed if (animations[i].numFrames < 0) { animations[i].numFrames = -animations[i].numFrames; animations[i].reversed = qtrue; } token = COM_Parse( &text_p ); if ( !token[0] ) { break; } animations[i].loopFrames = atoi( token ); token = COM_Parse( &text_p ); if ( !token[0] ) { break; } fps = atof( token ); if ( fps == 0 ) { fps = 1; } animations[i].frameLerp = 1000 / fps; animations[i].initialLerp = 1000 / fps; } if ( i != MAX_ANIMATIONS ) { Com_Printf( "Error parsing animation file: %s\n", filename ); return qfalse; } return qtrue; }
void G_LogWeaponOutput(void) { #ifdef LOGGING_WEAPONS int i,j,curwp; float pershot; fileHandle_t weaponfile; char string[1024]; int totalpickups[WP_NUM_WEAPONS]; int totaltime[WP_NUM_WEAPONS]; int totaldeaths[WP_NUM_WEAPONS]; int totaldamageMOD[MOD_MAX]; int totalkillsMOD[MOD_MAX]; int totaldamage[WP_NUM_WEAPONS]; int totalkills[WP_NUM_WEAPONS]; int totalshots[WP_NUM_WEAPONS]; int percharacter[WP_NUM_WEAPONS]; char info[MAX_INFO_STRING]; char mapname[MAX_QPATH]; char *nameptr, *unknownname="<Unknown>"; if (!g_statLog.integer) { return; } G_LogPrintf( LOG_WEAPON_STATS, "*****************************Weapon Log:\n" ); memset(totalpickups, 0, sizeof(totalpickups)); memset(totaltime, 0, sizeof(totaltime)); memset(totaldeaths, 0, sizeof(totaldeaths)); memset(totaldamageMOD, 0, sizeof(totaldamageMOD)); memset(totalkillsMOD, 0, sizeof(totalkillsMOD)); memset(totaldamage, 0, sizeof(totaldamage)); memset(totalkills, 0, sizeof(totalkills)); memset(totalshots, 0, sizeof(totalshots)); for (i=0; i<MAX_CLIENTS; i++) { if (G_WeaponLogClientTouch[i]) { // Ignore any entity/clients we don't care about! for (j=0;j<WP_NUM_WEAPONS;j++) { totalpickups[j] += G_WeaponLogPickups[i][j]; totaltime[j] += G_WeaponLogTime[i][j]; totaldeaths[j] += G_WeaponLogDeaths[i][j]; totalshots[j] += G_WeaponLogFired[i][j]; } for (j=0;j<MOD_MAX;j++) { totaldamageMOD[j] += G_WeaponLogDamage[i][j]; totalkillsMOD[j] += G_WeaponLogKills[i][j]; } } } // Now total the weapon data from the MOD data. for (j=0; j<MOD_MAX; j++) { if (j <= MOD_SENTRY) { curwp = weaponFromMOD[j]; totaldamage[curwp] += totaldamageMOD[j]; totalkills[curwp] += totalkillsMOD[j]; } } G_LogPrintf( LOG_WEAPON_STATS, "****Data by Weapon:\n" ); for (j=0; j<WP_NUM_WEAPONS; j++) { G_LogPrintf( LOG_WEAPON_STATS, "%15s: Pickups: %4d, Time: %5d, Deaths: %5d\n", weaponNameFromIndex[j], totalpickups[j], (int)(totaltime[j]/1000), totaldeaths[j]); } G_LogPrintf( LOG_WEAPON_STATS, "****Combat Data by Weapon:\n" ); for (j=0; j<WP_NUM_WEAPONS; j++) { if (totalshots[j] > 0) { pershot = (float)(totaldamage[j])/(float)(totalshots[j]); } else { pershot = 0; } G_LogPrintf( LOG_WEAPON_STATS, "%15s: Damage: %6d, Kills: %5d, Dmg per Shot: %f\n", weaponNameFromIndex[j], totaldamage[j], totalkills[j], pershot); } G_LogPrintf( LOG_WEAPON_STATS, "****Combat Data By Damage Type:\n" ); for (j=0; j<MOD_MAX; j++) { G_LogPrintf( LOG_WEAPON_STATS, "%25s: Damage: %6d, Kills: %5d\n", modNames[j], totaldamageMOD[j], totalkillsMOD[j]); } G_LogPrintf( LOG_WEAPON_STATS, "\n"); // Write the whole weapon statistic log out to a file. trap_FS_FOpenFile( g_statLogFile.string, &weaponfile, FS_APPEND ); if (!weaponfile) { //failed to open file, let's not crash, shall we? return; } // Write out the level name trap_GetServerinfo(info, sizeof(info)); Q_strncpyz(mapname, Info_ValueForKey( info, "mapname" ), sizeof(mapname)); Com_sprintf(string, sizeof(string), "\n\n\nLevel:\t%s\n\n\n", mapname); trap_FS_Write( string, strlen( string ), weaponfile); // Combat data per character // Start with Pickups per character Com_sprintf(string, sizeof(string), "Weapon Pickups per Player:\n\n"); trap_FS_Write( string, strlen( string ), weaponfile); Com_sprintf(string, sizeof(string), "Player"); trap_FS_Write(string, strlen(string), weaponfile); for (j=0; j<WP_NUM_WEAPONS; j++) { Com_sprintf(string, sizeof(string), "\t%s", weaponNameFromIndex[j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n"); trap_FS_Write(string, strlen(string), weaponfile); // Cycle through each player, give their name and the number of times they picked up each weapon. for (i=0; i<MAX_CLIENTS; i++) { if (G_WeaponLogClientTouch[i]) { // Ignore any entity/clients we don't care about! if ( g_entities[i].client ) { nameptr = g_entities[i].client->pers.netname; } else { nameptr = unknownname; } trap_FS_Write(nameptr, strlen(nameptr), weaponfile); for (j=0;j<WP_NUM_WEAPONS;j++) { Com_sprintf(string, sizeof(string), "\t%d", G_WeaponLogPickups[i][j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n"); trap_FS_Write(string, strlen(string), weaponfile); } } // Sum up the totals. Com_sprintf(string, sizeof(string), "\n***TOTAL:"); trap_FS_Write(string, strlen(string), weaponfile); for (j=0;j<WP_NUM_WEAPONS;j++) { Com_sprintf(string, sizeof(string), "\t%d", totalpickups[j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n\n\n"); trap_FS_Write(string, strlen(string), weaponfile); // Weapon fires per character Com_sprintf(string, sizeof(string), "Weapon Shots per Player:\n\n"); trap_FS_Write( string, strlen( string ), weaponfile); Com_sprintf(string, sizeof(string), "Player"); trap_FS_Write(string, strlen(string), weaponfile); for (j=0; j<WP_NUM_WEAPONS; j++) { Com_sprintf(string, sizeof(string), "\t%s", weaponNameFromIndex[j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n"); trap_FS_Write(string, strlen(string), weaponfile); // Cycle through each player, give their name and the number of times they picked up each weapon. for (i=0; i<MAX_CLIENTS; i++) { if (G_WeaponLogClientTouch[i]) { // Ignore any entity/clients we don't care about! if ( g_entities[i].client ) { nameptr = g_entities[i].client->pers.netname; } else { nameptr = unknownname; } trap_FS_Write(nameptr, strlen(nameptr), weaponfile); for (j=0;j<WP_NUM_WEAPONS;j++) { Com_sprintf(string, sizeof(string), "\t%d", G_WeaponLogFired[i][j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n"); trap_FS_Write(string, strlen(string), weaponfile); } } // Sum up the totals. Com_sprintf(string, sizeof(string), "\n***TOTAL:"); trap_FS_Write(string, strlen(string), weaponfile); for (j=0;j<WP_NUM_WEAPONS;j++) { Com_sprintf(string, sizeof(string), "\t%d", totalshots[j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n\n\n"); trap_FS_Write(string, strlen(string), weaponfile); // Weapon time per character Com_sprintf(string, sizeof(string), "Weapon Use Time per Player:\n\n"); trap_FS_Write( string, strlen( string ), weaponfile); Com_sprintf(string, sizeof(string), "Player"); trap_FS_Write(string, strlen(string), weaponfile); for (j=0; j<WP_NUM_WEAPONS; j++) { Com_sprintf(string, sizeof(string), "\t%s", weaponNameFromIndex[j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n"); trap_FS_Write(string, strlen(string), weaponfile); // Cycle through each player, give their name and the number of times they picked up each weapon. for (i=0; i<MAX_CLIENTS; i++) { if (G_WeaponLogClientTouch[i]) { // Ignore any entity/clients we don't care about! if ( g_entities[i].client ) { nameptr = g_entities[i].client->pers.netname; } else { nameptr = unknownname; } trap_FS_Write(nameptr, strlen(nameptr), weaponfile); for (j=0;j<WP_NUM_WEAPONS;j++) { Com_sprintf(string, sizeof(string), "\t%d", G_WeaponLogTime[i][j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n"); trap_FS_Write(string, strlen(string), weaponfile); } } // Sum up the totals. Com_sprintf(string, sizeof(string), "\n***TOTAL:"); trap_FS_Write(string, strlen(string), weaponfile); for (j=0;j<WP_NUM_WEAPONS;j++) { Com_sprintf(string, sizeof(string), "\t%d", totaltime[j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n\n\n"); trap_FS_Write(string, strlen(string), weaponfile); // Weapon deaths per character Com_sprintf(string, sizeof(string), "Weapon Deaths per Player:\n\n"); trap_FS_Write( string, strlen( string ), weaponfile); Com_sprintf(string, sizeof(string), "Player"); trap_FS_Write(string, strlen(string), weaponfile); for (j=0; j<WP_NUM_WEAPONS; j++) { Com_sprintf(string, sizeof(string), "\t%s", weaponNameFromIndex[j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n"); trap_FS_Write(string, strlen(string), weaponfile); // Cycle through each player, give their name and the number of times they picked up each weapon. for (i=0; i<MAX_CLIENTS; i++) { if (G_WeaponLogClientTouch[i]) { // Ignore any entity/clients we don't care about! if ( g_entities[i].client ) { nameptr = g_entities[i].client->pers.netname; } else { nameptr = unknownname; } trap_FS_Write(nameptr, strlen(nameptr), weaponfile); for (j=0;j<WP_NUM_WEAPONS;j++) { Com_sprintf(string, sizeof(string), "\t%d", G_WeaponLogDeaths[i][j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n"); trap_FS_Write(string, strlen(string), weaponfile); } } // Sum up the totals. Com_sprintf(string, sizeof(string), "\n***TOTAL:"); trap_FS_Write(string, strlen(string), weaponfile); for (j=0;j<WP_NUM_WEAPONS;j++) { Com_sprintf(string, sizeof(string), "\t%d", totaldeaths[j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n\n\n"); trap_FS_Write(string, strlen(string), weaponfile); // Weapon damage per character Com_sprintf(string, sizeof(string), "Weapon Damage per Player:\n\n"); trap_FS_Write( string, strlen( string ), weaponfile); Com_sprintf(string, sizeof(string), "Player"); trap_FS_Write(string, strlen(string), weaponfile); for (j=0; j<WP_NUM_WEAPONS; j++) { Com_sprintf(string, sizeof(string), "\t%s", weaponNameFromIndex[j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n"); trap_FS_Write(string, strlen(string), weaponfile); // Cycle through each player, give their name and the number of times they picked up each weapon. for (i=0; i<MAX_CLIENTS; i++) { if (G_WeaponLogClientTouch[i]) { // Ignore any entity/clients we don't care about! // We must grab the totals from the damage types for the player and map them to the weapons. memset(percharacter, 0, sizeof(percharacter)); for (j=0; j<MOD_MAX; j++) { if (j <= MOD_SENTRY) { curwp = weaponFromMOD[j]; percharacter[curwp] += G_WeaponLogDamage[i][j]; } } if ( g_entities[i].client ) { nameptr = g_entities[i].client->pers.netname; } else { nameptr = unknownname; } trap_FS_Write(nameptr, strlen(nameptr), weaponfile); for (j=0;j<WP_NUM_WEAPONS;j++) { Com_sprintf(string, sizeof(string), "\t%d", percharacter[j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n"); trap_FS_Write(string, strlen(string), weaponfile); } } // Sum up the totals. Com_sprintf(string, sizeof(string), "\n***TOTAL:"); trap_FS_Write(string, strlen(string), weaponfile); for (j=0;j<WP_NUM_WEAPONS;j++) { Com_sprintf(string, sizeof(string), "\t%d", totaldamage[j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n\n\n"); trap_FS_Write(string, strlen(string), weaponfile); // Weapon kills per character Com_sprintf(string, sizeof(string), "Weapon Kills per Player:\n\n"); trap_FS_Write( string, strlen( string ), weaponfile); Com_sprintf(string, sizeof(string), "Player"); trap_FS_Write(string, strlen(string), weaponfile); for (j=0; j<WP_NUM_WEAPONS; j++) { Com_sprintf(string, sizeof(string), "\t%s", weaponNameFromIndex[j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n"); trap_FS_Write(string, strlen(string), weaponfile); // Cycle through each player, give their name and the number of times they picked up each weapon. for (i=0; i<MAX_CLIENTS; i++) { if (G_WeaponLogClientTouch[i]) { // Ignore any entity/clients we don't care about! // We must grab the totals from the damage types for the player and map them to the weapons. memset(percharacter, 0, sizeof(percharacter)); for (j=0; j<MOD_MAX; j++) { if (j <= MOD_SENTRY) { curwp = weaponFromMOD[j]; percharacter[curwp] += G_WeaponLogKills[i][j]; } } if ( g_entities[i].client ) { nameptr = g_entities[i].client->pers.netname; } else { nameptr = unknownname; } trap_FS_Write(nameptr, strlen(nameptr), weaponfile); for (j=0;j<WP_NUM_WEAPONS;j++) { Com_sprintf(string, sizeof(string), "\t%d", percharacter[j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n"); trap_FS_Write(string, strlen(string), weaponfile); } } // Sum up the totals. Com_sprintf(string, sizeof(string), "\n***TOTAL:"); trap_FS_Write(string, strlen(string), weaponfile); for (j=0;j<WP_NUM_WEAPONS;j++) { Com_sprintf(string, sizeof(string), "\t%d", totalkills[j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n\n\n"); trap_FS_Write(string, strlen(string), weaponfile); // Damage type damage per character Com_sprintf(string, sizeof(string), "Typed Damage per Player:\n\n"); trap_FS_Write( string, strlen( string ), weaponfile); Com_sprintf(string, sizeof(string), "Player"); trap_FS_Write(string, strlen(string), weaponfile); for (j=0; j<MOD_MAX; j++) { Com_sprintf(string, sizeof(string), "\t%s", modNames[j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n"); trap_FS_Write(string, strlen(string), weaponfile); // Cycle through each player, give their name and the number of times they picked up each weapon. for (i=0; i<MAX_CLIENTS; i++) { if (G_WeaponLogClientTouch[i]) { // Ignore any entity/clients we don't care about! if ( g_entities[i].client ) { nameptr = g_entities[i].client->pers.netname; } else { nameptr = unknownname; } trap_FS_Write(nameptr, strlen(nameptr), weaponfile); for (j=0;j<MOD_MAX;j++) { Com_sprintf(string, sizeof(string), "\t%d", G_WeaponLogDamage[i][j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n"); trap_FS_Write(string, strlen(string), weaponfile); } } // Sum up the totals. Com_sprintf(string, sizeof(string), "\n***TOTAL:"); trap_FS_Write(string, strlen(string), weaponfile); for (j=0;j<MOD_MAX;j++) { Com_sprintf(string, sizeof(string), "\t%d", totaldamageMOD[j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n\n\n"); trap_FS_Write(string, strlen(string), weaponfile); // Damage type kills per character Com_sprintf(string, sizeof(string), "Damage-Typed Kills per Player:\n\n"); trap_FS_Write( string, strlen( string ), weaponfile); Com_sprintf(string, sizeof(string), "Player"); trap_FS_Write(string, strlen(string), weaponfile); for (j=0; j<MOD_MAX; j++) { Com_sprintf(string, sizeof(string), "\t%s", modNames[j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n"); trap_FS_Write(string, strlen(string), weaponfile); // Cycle through each player, give their name and the number of times they picked up each weapon. for (i=0; i<MAX_CLIENTS; i++) { if (G_WeaponLogClientTouch[i]) { // Ignore any entity/clients we don't care about! if ( g_entities[i].client ) { nameptr = g_entities[i].client->pers.netname; } else { nameptr = unknownname; } trap_FS_Write(nameptr, strlen(nameptr), weaponfile); for (j=0;j<MOD_MAX;j++) { Com_sprintf(string, sizeof(string), "\t%d", G_WeaponLogKills[i][j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n"); trap_FS_Write(string, strlen(string), weaponfile); } } // Sum up the totals. Com_sprintf(string, sizeof(string), "\n***TOTAL:"); trap_FS_Write(string, strlen(string), weaponfile); for (j=0;j<MOD_MAX;j++) { Com_sprintf(string, sizeof(string), "\t%d", totalkillsMOD[j]); trap_FS_Write(string, strlen(string), weaponfile); } Com_sprintf(string, sizeof(string), "\n\n\n"); trap_FS_Write(string, strlen(string), weaponfile); trap_FS_FCloseFile(weaponfile); #endif //LOGGING_WEAPONS }
static void CG_ServerCommand( void ) { const char *cmd; char text[MAX_SAY_TEXT]; cmd = CG_Argv( 0 ); if ( !cmd[0] ) { // server claimed the command return; } if ( !strcmp( cmd, "startCam" ) ) { CG_StartCamera( CG_Argv( 1 ), atoi( CG_Argv( 2 ) ) ); return; } if ( !strcmp( cmd, "stopCam" ) ) { CG_StopCamera(); return; } if ( !strcmp( cmd, "mvspd" ) ) { CG_RequestMoveSpeed( CG_Argv( 1 ) ); return; } if ( !strcmp( cmd, "dp" ) ) { // dynamite print (what a hack :( CG_CenterPrint( va( "%s %d %s", CG_translateString( "dynamitetimer" ), atoi( CG_Argv( 1 ) ), CG_translateString( "seconds" ) ), SCREEN_HEIGHT - ( SCREEN_HEIGHT * 0.25 ), SMALLCHAR_WIDTH ); return; } if ( !strcmp( cmd, "cp" ) ) { CG_CenterPrint( CG_Argv( 1 ), SCREEN_HEIGHT - ( SCREEN_HEIGHT * 0.25 ), SMALLCHAR_WIDTH ); return; } if ( !strcmp( cmd, "cs" ) ) { CG_ConfigStringModified(); return; } if ( !strcmp( cmd, "print" ) ) { CG_Printf( "%s", CG_Argv( 1 ) ); #ifdef MISSIONPACK cmd = CG_Argv( 1 ); // yes, this is obviously a hack, but so is the way we hear about // votes passing or failing if ( !Q_stricmpn( cmd, "vote failed", 11 ) || !Q_stricmpn( cmd, "team vote failed", 16 ) ) { trap_S_StartLocalSound( cgs.media.voteFailed, CHAN_ANNOUNCER ); } else if ( !Q_stricmpn( cmd, "vote passed", 11 ) || !Q_stricmpn( cmd, "team vote passed", 16 ) ) { trap_S_StartLocalSound( cgs.media.votePassed, CHAN_ANNOUNCER ); } #endif return; } if ( !strcmp( cmd, "chat" ) ) { if ( !cg_teamChatsOnly.integer ) { trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv( 1 ), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); CG_Printf( "%s\n", text ); } return; } if ( !strcmp( cmd, "tchat" ) ) { trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv( 1 ), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); CG_AddToTeamChat( text ); CG_Printf( "%s\n", text ); return; } // NERVE - SMF - limbo chat if ( !strcmp( cmd, "lchat" ) ) { trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv( 1 ), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); // CG_AddToLimboChat( text ); trap_UI_LimboChat( text ); CG_Printf( "%s\n", text ); return; } // -NERVE - SMF if ( !strcmp( cmd, "vchat" ) ) { // CG_VoiceChat( SAY_ALL ); return; } if ( !strcmp( cmd, "vtchat" ) ) { // CG_VoiceChat( SAY_TEAM ); return; } if ( !strcmp( cmd, "vtell" ) ) { // CG_VoiceChat( SAY_TELL ); return; } if ( !strcmp( cmd, "scores" ) ) { CG_ParseScores(); return; } if ( !strcmp( cmd, "tinfo" ) ) { CG_ParseTeamInfo(); return; } if ( !strcmp( cmd, "map_restart" ) ) { CG_MapRestart(); return; } if ( Q_stricmp( cmd, "remapShader" ) == 0 ) { if ( trap_Argc() == 4 ) { trap_R_RemapShader( CG_Argv( 1 ), CG_Argv( 2 ), CG_Argv( 3 ) ); } } // loaddeferred can be both a servercmd and a consolecmd if ( !strcmp( cmd, "loaddeferred" ) ) { // spelling fixed (SA) CG_LoadDeferredPlayers(); return; } // clientLevelShot is sent before taking a special screenshot for // the menu system during development if ( !strcmp( cmd, "clientLevelShot" ) ) { cg.levelShot = qtrue; return; } // NERVE - SMF if ( !Q_stricmp( cmd, "oid" ) ) { CG_ObjectivePrint( CG_Argv( 2 ), SMALLCHAR_WIDTH, atoi( CG_Argv( 1 ) ) ); return; } // -NERVE - SMF // // music // // loops \/ if ( !strcmp( cmd, "mu_start" ) ) { // has optional parameter for fade-up time int fadeTime = 0; // default to instant start Q_strncpyz( text, CG_Argv( 2 ), MAX_SAY_TEXT ); if ( text && strlen( text ) ) { fadeTime = atoi( text ); } trap_S_StartBackgroundTrack( CG_Argv( 1 ), CG_Argv( 1 ), fadeTime ); return; } // plays once then back to whatever the loop was \/ if ( !strcmp( cmd, "mu_play" ) ) { // has optional parameter for fade-up time int fadeTime = 0; // default to instant start Q_strncpyz( text, CG_Argv( 2 ), MAX_SAY_TEXT ); if ( text && strlen( text ) ) { fadeTime = atoi( text ); } trap_S_StartBackgroundTrack( CG_Argv( 1 ), "onetimeonly", fadeTime ); return; } if ( !strcmp( cmd, "mu_stop" ) ) { // has optional parameter for fade-down time int fadeTime = 0; // default to instant stop Q_strncpyz( text, CG_Argv( 1 ), MAX_SAY_TEXT ); if ( text && strlen( text ) ) { fadeTime = atoi( text ); } trap_S_FadeBackgroundTrack( 0.0f, fadeTime, 0 ); trap_S_StartBackgroundTrack( "", "", -2 ); // '-2' for 'queue looping track' (QUEUED_PLAY_LOOPED) return; } if ( !strcmp( cmd, "mu_fade" ) ) { trap_S_FadeBackgroundTrack( atof( CG_Argv( 1 ) ), atoi( CG_Argv( 2 ) ), 0 ); return; } if ( !strcmp( cmd, "snd_fade" ) ) { trap_S_FadeAllSound( atof( CG_Argv( 1 ) ), atoi( CG_Argv( 2 ) ) ); return; } if ( !strcmp( cmd, "rockandroll" ) ) { // map loaded, game is ready to begin. CG_Fade( 0, 0, 0, 255, cg.time, 0 ); // go black trap_UI_Popup( "pregame" ); // start pregame menu trap_Cvar_Set( "cg_norender", "1" ); // don't render the world until the player clicks in and the 'playerstart' func has been called (g_main in G_UpdateCvars() ~ilne 949) trap_S_FadeAllSound( 1.0f, 1000 ); // fade sound up return; } // ensure a file gets into a build (mainly for scripted music calls) if ( !strcmp( cmd, "addToBuild" ) ) { fileHandle_t f; if ( !cg_buildScript.integer ) { return; } // just open the file so it gets copied to the build dir //CG_FileTouchForBuild(CG_Argv(1)); trap_FS_FOpenFile( CG_Argv( 1 ), &f, FS_READ ); trap_FS_FCloseFile( f ); return; } CG_Printf( "Unknown client game command: %s\n", cmd ); }
int strap_FS_FOpenFile( const char *qpath, fileHandle_t *f, fsMode_t mode ) { return trap_FS_FOpenFile (qpath, f, mode); }
/* =============== CG_InitBuildables Initialises the animation db =============== */ void CG_InitBuildables( void ) { char filename[ MAX_QPATH ]; char soundfile[ MAX_QPATH ]; char *buildableName; char *modelFile; int i; int j; fileHandle_t f; memset( cg_buildables, 0, sizeof( cg_buildables ) ); //default sounds for( j = BANIM_NONE + 1; j < MAX_BUILDABLE_ANIMATIONS; j++ ) { strcpy( soundfile, cg_buildableSoundNames[ j - 1 ] ); Com_sprintf( filename, sizeof( filename ), "sound/buildables/alien/%s", soundfile ); defaultAlienSounds[ j ] = trap_S_RegisterSound( filename, qfalse ); Com_sprintf( filename, sizeof( filename ), "sound/buildables/human/%s", soundfile ); defaultHumanSounds[ j ] = trap_S_RegisterSound( filename, qfalse ); } cg.buildablesFraction = 0.0f; for( i = BA_NONE + 1; i < BA_NUM_BUILDABLES; i++ ) { buildableName = BG_Buildable( i )->name; //animation.cfg Com_sprintf( filename, sizeof( filename ), "models/buildables/%s/animation.cfg", buildableName ); if ( !CG_ParseBuildableAnimationFile( filename, i ) ) Com_Printf( S_COLOR_YELLOW "WARNING: failed to load animation file %s\n", filename ); //sound.cfg Com_sprintf( filename, sizeof( filename ), "sound/buildables/%s/sound.cfg", buildableName ); if ( !CG_ParseBuildableSoundFile( filename, i ) ) Com_Printf( S_COLOR_YELLOW "WARNING: failed to load sound file %s\n", filename ); //models for( j = 0; j <= 3; j++ ) { modelFile = BG_BuildableConfig( i )->models[ j ]; if( strlen( modelFile ) > 0 ) cg_buildables[ i ].models[ j ] = trap_R_RegisterModel( modelFile ); } //sounds for( j = BANIM_NONE + 1; j < MAX_BUILDABLE_ANIMATIONS; j++ ) { strcpy( soundfile, cg_buildableSoundNames[ j - 1 ] ); Com_sprintf( filename, sizeof( filename ), "sound/buildables/%s/%s", buildableName, soundfile ); if( cg_buildables[ i ].sounds[ j ].enabled ) { if( trap_FS_FOpenFile( filename, &f, FS_READ ) > 0 ) { //file exists so close it trap_FS_FCloseFile( f ); cg_buildables[ i ].sounds[ j ].sound = trap_S_RegisterSound( filename, qfalse ); } else { //file doesn't exist - use default if( BG_Buildable( i )->team == TEAM_ALIENS ) cg_buildables[ i ].sounds[ j ].sound = defaultAlienSounds[ j ]; else cg_buildables[ i ].sounds[ j ].sound = defaultHumanSounds[ j ]; } } } cg.buildablesFraction = (float)i / (float)( BA_NUM_BUILDABLES - 1 ); trap_UpdateScreen( ); } cgs.media.teslaZapTS = CG_RegisterTrailSystem( "models/buildables/tesla/zap" ); }
void BG_SiegeParseTeamFile(const char *filename) { fileHandle_t f; int len; char teamInfo[2048]; char parseBuf[1024]; char lookString[256]; int i = 1; qboolean success = qtrue; len = trap_FS_FOpenFile(filename, &f, FS_READ); if (!f || len >= 2048) { return; } trap_FS_Read(teamInfo, len, f); trap_FS_FCloseFile(f); teamInfo[len] = 0; if (BG_SiegeGetPairedValue(teamInfo, "name", parseBuf)) { strcpy(bgSiegeTeams[bgNumSiegeTeams].name, parseBuf); } else { Com_Error(ERR_DROP, "Siege team with no name definition"); } //I don't entirely like doing things this way but it's the easiest way. #ifdef CGAME if (BG_SiegeGetPairedValue(teamInfo, "FriendlyShader", parseBuf)) { bgSiegeTeams[bgNumSiegeTeams].friendlyShader = trap_R_RegisterShaderNoMip(parseBuf); } #else bgSiegeTeams[bgNumSiegeTeams].friendlyShader = 0; #endif bgSiegeTeams[bgNumSiegeTeams].numClasses = 0; if (BG_SiegeGetValueGroup(teamInfo, "Classes", teamInfo)) { while (success && i < MAX_SIEGE_CLASSES) { //keep checking for group values named class# up to MAX_SIEGE_CLASSES until we can't find one. strcpy(lookString, va("class%i", i)); success = BG_SiegeGetPairedValue(teamInfo, lookString, parseBuf); if (!success) { break; } bgSiegeTeams[bgNumSiegeTeams].classes[bgSiegeTeams[bgNumSiegeTeams].numClasses] = BG_SiegeFindClassByName(parseBuf); if (!bgSiegeTeams[bgNumSiegeTeams].classes[bgSiegeTeams[bgNumSiegeTeams].numClasses]) { Com_Error(ERR_DROP, "Invalid class specified: '%s'", parseBuf); } bgSiegeTeams[bgNumSiegeTeams].numClasses++; i++; } } if (!bgSiegeTeams[bgNumSiegeTeams].numClasses) { Com_Error(ERR_DROP, "Team defined with no allowable classes\n"); } //If we get here then it was a success, so increment the team number bgNumSiegeTeams++; }
void InitSagaMode(void) { vmCvar_t mapname; char levelname[512]; char goalreq[64]; char objectives[MAX_SAGA_INFO_SIZE]; int len = 0; fileHandle_t f; if (g_gametype.integer != GT_SAGA) { goto failure; } imperial_goals_completed = 0; rebel_goals_completed = 0; saga_round_over = 0; trap_Cvar_Register( &mapname, "mapname", "", CVAR_SERVERINFO | CVAR_ROM ); Com_sprintf(levelname, sizeof(levelname), "maps/%s.saga\0", mapname.string); if (!levelname[0]) { goto failure; } len = trap_FS_FOpenFile(levelname, &f, FS_READ); if (!f || len >= MAX_SAGA_INFO_SIZE) { goto failure; } trap_FS_Read(saga_info, len, f); saga_valid = 1; if (GetValueGroup(saga_info, "Rebel", objectives)) { if (GetPairedValue(objectives, "RequiredObjectives", goalreq)) { rebel_goals_required = atoi(goalreq); } if (GetPairedValue(objectives, "attackers", goalreq)) { rebel_attackers = atoi(goalreq); } } if (GetValueGroup(saga_info, "Imperial", objectives)) { if (GetPairedValue(objectives, "RequiredObjectives", goalreq)) { imperial_goals_required = atoi(goalreq); } if (GetPairedValue(objectives, "attackers", goalreq)) { imperial_attackers = atoi(goalreq); } } return; failure: saga_valid = 0; }
/* ================= UI_ForceConfigHandle ================= */ void UI_ForceConfigHandle( int oldindex, int newindex ) { fileHandle_t f; int len = 0; int i = 0; int c = 0; int iBuf = 0, forcePowerRank, currank; char fcfBuffer[8192]; char singleBuf[64]; char info[MAX_INFO_VALUE]; int forceTeam = 0; if (oldindex == 0) { //switching out from custom config, so first shove the current values into the custom storage i = 0; while (i < NUM_FORCE_POWERS) { gCustPowersRank[i] = uiForcePowersRank[i]; i++; } gCustRank = uiForceRank; gCustSide = uiForceSide; } if (newindex == 0) { //switching back to custom, shove the values back in from the custom storage i = 0; uiForceUsed = 0; gTouchedForce = qtrue; while (i < NUM_FORCE_POWERS) { uiForcePowersRank[i] = gCustPowersRank[i]; uiForceUsed += uiForcePowersRank[i]; i++; } uiForceRank = gCustRank; uiForceSide = gCustSide; UpdateForceUsed(); return; } //If we made it here, we want to load in a new config if (uiForceSide == FORCE_LIGHTSIDE) { //we should only be displaying lightside configs, so.. look in the light folder newindex += uiInfo.forceConfigLightIndexBegin; if (newindex >= uiInfo.forceConfigCount) { return; } len = trap_FS_FOpenFile(va("forcecfg/light/%s.fcf", uiInfo.forceConfigNames[newindex]), &f, FS_READ); } else { //else dark newindex += uiInfo.forceConfigDarkIndexBegin; if (newindex >= uiInfo.forceConfigCount || newindex > uiInfo.forceConfigLightIndexBegin) { //dark gets read in before light return; } len = trap_FS_FOpenFile(va("forcecfg/dark/%s.fcf", uiInfo.forceConfigNames[newindex]), &f, FS_READ); } if (len <= 0) { //This should not have happened. But, before we quit out, attempt searching the other light/dark folder for the file. if (uiForceSide == FORCE_LIGHTSIDE) { len = trap_FS_FOpenFile(va("forcecfg/dark/%s.fcf", uiInfo.forceConfigNames[newindex]), &f, FS_READ); } else { len = trap_FS_FOpenFile(va("forcecfg/light/%s.fcf", uiInfo.forceConfigNames[newindex]), &f, FS_READ); } if (len <= 0) { //still failure? Oh well. return; } } if (len >= 8192) { return; } trap_FS_Read(fcfBuffer, len, f); fcfBuffer[len] = 0; trap_FS_FCloseFile(f); i = 0; info[0] = '\0'; trap_GetConfigString(CS_SERVERINFO, info, sizeof(info)); if (atoi( Info_ValueForKey( info, "g_forceBasedTeams" ) )) { switch((int)(trap_Cvar_VariableValue("ui_myteam"))) { case TEAM_RED: forceTeam = FORCE_DARKSIDE; break; case TEAM_BLUE: forceTeam = FORCE_LIGHTSIDE; break; default: break; } } BG_LegalizedForcePowers(fcfBuffer, uiMaxRank, ui_freeSaber.integer, forceTeam, atoi( Info_ValueForKey( info, "g_gametype" )), 0); //legalize the config based on the max rank //now that we're done with the handle, it's time to parse our force data out of the string //we store strings in rank-side-xxxxxxxxx format (where the x's are individual force power levels) while (fcfBuffer[i] && fcfBuffer[i] != '-') { singleBuf[c] = fcfBuffer[i]; c++; i++; } singleBuf[c] = 0; c = 0; i++; iBuf = atoi(singleBuf); if (iBuf > uiMaxRank || iBuf < 0) { //this force config uses a rank level higher than our currently restricted level.. so we can't use it //FIXME: Print a message indicating this to the user return; } uiForceRank = iBuf; while (fcfBuffer[i] && fcfBuffer[i] != '-') { singleBuf[c] = fcfBuffer[i]; c++; i++; } singleBuf[c] = 0; c = 0; i++; uiForceSide = atoi(singleBuf); if (uiForceSide != FORCE_LIGHTSIDE && uiForceSide != FORCE_DARKSIDE) { uiForceSide = FORCE_LIGHTSIDE; return; } //clear out the existing powers while (c < NUM_FORCE_POWERS) { /* if (c==FP_LEVITATION) { uiForcePowersRank[c]=1; } else if (c==FP_SABER_OFFENSE && ui_freeSaber.integer) { uiForcePowersRank[c]=1; } else if (c==FP_SABER_DEFENSE && ui_freeSaber.integer) { uiForcePowersRank[c]=1; } else { uiForcePowersRank[c] = 0; } */ //rww - don't need to do these checks. Just trust whatever the saber config says. uiForcePowersRank[c] = 0; c++; } uiForceUsed = 0; uiForceAvailable = forceMasteryPoints[uiForceRank]; gTouchedForce = qtrue; for (c=0;fcfBuffer[i]&&c<NUM_FORCE_POWERS;c++,i++) { singleBuf[0] = fcfBuffer[i]; singleBuf[1] = 0; iBuf = atoi(singleBuf); // So, that means that Force Power "c" wants to be set to rank "iBuf". if (iBuf < 0) { iBuf = 0; } forcePowerRank = iBuf; if (forcePowerRank > FORCE_LEVEL_3 || forcePowerRank < 0) { //err.. not correct continue; // skip this power } if (uiForcePowerDarkLight[c] && uiForcePowerDarkLight[c] != uiForceSide) { //Apparently the user has crafted a force config that has powers that don't fit with the config's side. continue; // skip this power } // Accrue cost for each assigned rank for this power. for (currank=FORCE_LEVEL_1;currank<=forcePowerRank;currank++) { if (bgForcePowerCost[c][currank] > uiForceAvailable) { // Break out, we can't afford any more power. break; } // Pay for this rank of this power. uiForceUsed += bgForcePowerCost[c][currank]; uiForceAvailable -= bgForcePowerCost[c][currank]; uiForcePowersRank[c]++; } } if (uiForcePowersRank[FP_LEVITATION] < 1) { uiForcePowersRank[FP_LEVITATION]=1; } if (uiForcePowersRank[FP_SABER_OFFENSE] < 1 && ui_freeSaber.integer) { uiForcePowersRank[FP_SABER_OFFENSE]=1; } if (uiForcePowersRank[FP_SABER_DEFENSE] < 1 && ui_freeSaber.integer) { uiForcePowersRank[FP_SABER_DEFENSE]=1; } UpdateForceUsed(); }
void UI_SaveForceTemplate() { char *selectedName = UI_Cvar_VariableString("ui_SaveFCF"); char fcfString[512]; char forceStringValue[4]; fileHandle_t f; int strPlace = 0; int forcePlace = 0; int i = 0; qboolean foundFeederItem = qfalse; if (!selectedName || !selectedName[0]) { Com_Printf("You did not provide a name for the template.\n"); return; } if (uiForceSide == FORCE_LIGHTSIDE) { //write it into the light side folder trap_FS_FOpenFile(va("forcecfg/light/%s.fcf", selectedName), &f, FS_WRITE); } else { //if it isn't light it must be dark trap_FS_FOpenFile(va("forcecfg/dark/%s.fcf", selectedName), &f, FS_WRITE); } if (!f) { Com_Printf("There was an error writing the template file (read-only?).\n"); return; } Com_sprintf(fcfString, sizeof(fcfString), "%i-%i-", uiForceRank, uiForceSide); strPlace = strlen(fcfString); while (forcePlace < NUM_FORCE_POWERS) { Com_sprintf(forceStringValue, sizeof(forceStringValue), "%i", uiForcePowersRank[forcePlace]); //Just use the force digit even if multiple digits. Shouldn't be longer than 1. fcfString[strPlace] = forceStringValue[0]; strPlace++; forcePlace++; } fcfString[strPlace] = '\n'; fcfString[strPlace+1] = 0; trap_FS_Write(fcfString, strlen(fcfString), f); trap_FS_FCloseFile(f); Com_Printf("Template saved as \"%s\".\n", selectedName); //Now, update the FCF list UI_LoadForceConfig_List(); //Then, scroll through and select the template for the file we just saved while (i < uiInfo.forceConfigCount) { if (!Q_stricmp(uiInfo.forceConfigNames[i], selectedName)) { if ((uiForceSide == FORCE_LIGHTSIDE && uiInfo.forceConfigSide[i]) || (uiForceSide == FORCE_DARKSIDE && !uiInfo.forceConfigSide[i])) { Menu_SetFeederSelection(NULL, FEEDER_FORCECFG, UI_TranslateFCFIndex(i), NULL); foundFeederItem = qtrue; } } i++; } //Else, go back to 0 if (!foundFeederItem) { Menu_SetFeederSelection(NULL, FEEDER_FORCECFG, 0, NULL); } }
/* =============== G_MapExists Check if a map exists =============== */ qboolean G_MapExists( char *name ) { return trap_FS_FOpenFile( va( "maps/%s.bsp", name ), NULL, FS_READ ); }
/* ============ G_InitGame ============ */ void G_InitGame( int levelTime, int randomSeed, int restart ) { int i; G_Printf ("------- Game Initialization -------\n"); G_Printf ("gamename: %s\n", GAMEVERSION); G_Printf ("gamedate: %s\n", __DATE__); srand( randomSeed ); G_RegisterCvars(); G_ProcessIPBans(); G_InitMemory(); // set some level globals memset( &level, 0, sizeof( level ) ); level.time = levelTime; level.startTime = levelTime; level.snd_fry = G_SoundIndex("sound/player/fry.wav"); // FIXME standing in lava / slime if ( g_gametype.integer != GT_SINGLE_PLAYER && g_logfile.string[0] ) { if ( g_logfileSync.integer ) { trap_FS_FOpenFile( g_logfile.string, &level.logFile, FS_APPEND_SYNC ); } else { trap_FS_FOpenFile( g_logfile.string, &level.logFile, FS_APPEND ); } if ( !level.logFile ) { G_Printf( "WARNING: Couldn't open logfile: %s\n", g_logfile.string ); } else { char serverinfo[MAX_INFO_STRING]; trap_GetServerinfo( serverinfo, sizeof( serverinfo ) ); G_LogPrintf("------------------------------------------------------------\n" ); G_LogPrintf("InitGame: %s\n", serverinfo ); } } else { G_Printf( "Not logging to disk.\n" ); } G_InitWorldSession(); // initialize all entities for this game memset( g_entities, 0, MAX_GENTITIES * sizeof(g_entities[0]) ); level.gentities = g_entities; // initialize all clients for this game level.maxclients = g_maxclients.integer; memset( g_clients, 0, MAX_CLIENTS * sizeof(g_clients[0]) ); level.clients = g_clients; // set client fields on player ents for ( i=0 ; i<level.maxclients ; i++ ) { g_entities[i].client = level.clients + i; } // always leave room for the max number of clients, // even if they aren't all used, so numbers inside that // range are NEVER anything but clients level.num_entities = MAX_CLIENTS; for ( i=0 ; i<MAX_CLIENTS ; i++ ) { g_entities[i].classname = "clientslot"; } // let the server system know where the entites are trap_LocateGameData( level.gentities, level.num_entities, sizeof( gentity_t ), &level.clients[0].ps, sizeof( level.clients[0] ) ); // reserve some spots for dead player bodies InitBodyQue(); ClearRegisteredItems(); // parse the key/value pairs and spawn gentities G_SpawnEntitiesFromString(); // general initialization G_FindTeams(); // make sure we have flags for CTF, etc if( g_gametype.integer >= GT_TEAM ) { G_CheckTeamItems(); } SaveRegisteredItems(); G_Printf ("-----------------------------------\n"); if( g_gametype.integer == GT_SINGLE_PLAYER || trap_Cvar_VariableIntegerValue( "com_buildScript" ) ) { G_ModelIndex( SP_PODIUM_MODEL ); } if ( trap_Cvar_VariableIntegerValue( "bot_enable" ) ) { BotAISetup( restart ); BotAILoadMap( restart ); G_InitBots( restart ); } G_RemapTeamShaders(); }
/* =============== G_ParseMapRotationFile Load the map rotations from a map rotation file =============== */ static qboolean G_ParseMapRotationFile( const char *fileName ) { char *text_p; int i, j, k; int len; char *token; char text[ 20000 ]; char mrName[ MAX_QPATH ]; qboolean mrNameSet = qfalse; fileHandle_t f; // load the file len = trap_FS_FOpenFile( fileName, &f, FS_READ ); if( len < 0 ) return qfalse; if( len == 0 || len >= sizeof( text ) - 1 ) { trap_FS_FCloseFile( f ); G_Printf( S_COLOR_RED "ERROR: map rotation file %s is %s\n", fileName, len == 0 ? "empty" : "too long" ); return qfalse; } trap_FS_Read( text, len, f ); text[ len ] = 0; trap_FS_FCloseFile( f ); // parse the text text_p = text; // read optional parameters while( 1 ) { token = COM_Parse( &text_p ); if( !token ) break; if( !Q_stricmp( token, "" ) ) break; if( !Q_stricmp( token, "{" ) ) { if( mrNameSet ) { //check for name space clashes for( i = 0; i < mapRotations.numRotations; i++ ) { if( !Q_stricmp( mapRotations.rotations[ i ].name, mrName ) ) { G_Printf( S_COLOR_RED "ERROR: a map rotation is already named %s\n", mrName ); return qfalse; } } Q_strncpyz( mapRotations.rotations[ mapRotations.numRotations ].name, mrName, MAX_QPATH ); if( !G_ParseMapRotation( &mapRotations.rotations[ mapRotations.numRotations ], &text_p ) ) { G_Printf( S_COLOR_RED "ERROR: %s: failed to parse map rotation %s\n", fileName, mrName ); return qfalse; } //start parsing map rotations again mrNameSet = qfalse; if( mapRotations.numRotations == MAX_MAP_ROTATIONS ) { G_Printf( S_COLOR_RED "ERROR: maximum number of map rotations (%d) reached\n", MAX_MAP_ROTATIONS ); return qfalse; } else mapRotations.numRotations++; continue; } else { G_Printf( S_COLOR_RED "ERROR: unamed map rotation\n" ); return qfalse; } } if( !mrNameSet ) { Q_strncpyz( mrName, token, sizeof( mrName ) ); mrNameSet = qtrue; } else { G_Printf( S_COLOR_RED "ERROR: map rotation already named\n" ); return qfalse; } } for( i = 0; i < mapRotations.numRotations; i++ ) { for( j = 0; j < mapRotations.rotations[ i ].numMaps; j++ ) { if( Q_stricmp( mapRotations.rotations[ i ].maps[ j ].name, "*VOTE*") != 0 && !G_MapExists( mapRotations.rotations[ i ].maps[ j ].name ) ) { G_Printf( S_COLOR_RED "ERROR: map \"%s\" doesn't exist\n", mapRotations.rotations[ i ].maps[ j ].name ); return qfalse; } for( k = 0; k < mapRotations.rotations[ i ].maps[ j ].numConditions; k++ ) { if( !G_MapExists( mapRotations.rotations[ i ].maps[ j ].conditions[ k ].dest ) && !G_RotationExists( mapRotations.rotations[ i ].maps[ j ].conditions[ k ].dest ) ) { G_Printf( S_COLOR_RED "ERROR: conditional destination \"%s\" doesn't exist\n", mapRotations.rotations[ i ].maps[ j ].conditions[ k ].dest ); return qfalse; } } } } return qtrue; }
/* ================== getCustomVote *Returns a custom vote. This will go beyond MAX_CUSTOM_VOTES. ================== */ t_customvote getCustomVote(char* votecommand) { t_customvote result; fileHandle_t file; char buffer[4*1024]; char *token,*pointer; char key[MAX_TOKEN_CHARS]; trap_FS_FOpenFile(g_votecustom.string,&file,FS_READ); if(!file) { memset(&result,0,sizeof(result)); return result; } memset(&buffer,0,sizeof(buffer)); trap_FS_Read(&buffer,sizeof(buffer),file); trap_FS_FCloseFile(file); pointer = buffer; while ( qtrue ) { token = COM_Parse( &pointer ); if ( !token[0] ) { break; } if ( strcmp( token, "{" ) ) { Com_Printf( "Missing { in votecustom.cfg\n" ); break; } memset(&result,0,sizeof(result)); while ( 1 ) { token = COM_ParseExt( &pointer, qtrue ); if ( !token[0] ) { Com_Printf( "Unexpected end of customvote.cfg\n" ); break; } if ( !strcmp( token, "}" ) ) { break; } Q_strncpyz( key, token, sizeof( key ) ); token = COM_ParseExt( &pointer, qfalse ); if ( !token[0] ) { Com_Printf("Invalid/missing argument to %s in customvote.cfg\n",key); } if(!Q_stricmp(key,"votecommand")) { Q_strncpyz(result.votename,token,sizeof(result.votename)); } else if(!Q_stricmp(key,"displayname")) { Q_strncpyz(result.displayname,token,sizeof(result.displayname)); } else if(!Q_stricmp(key,"command")) { Q_strncpyz(result.command,token,sizeof(result.command)); } else { Com_Printf("Unknown key in customvote.cfg: %s\n",key); } } if(!Q_stricmp(result.votename,votecommand)) { return result; } } //Nothing was found memset(&result,0,sizeof(result)); return result; }
/* =============== UI_DrawPlayer =============== */ void UI_DrawPlayer( float x, float y, float w, float h, uiPlayerInfo_t *pi, int time ) { refdef_t refdef; refEntity_t legs = {0}; refEntity_t torso = {0}; refEntity_t head = {0}; #ifdef TA_WEAPSYS refEntity_t gun[MAX_HANDS] = {{0}}; #else refEntity_t gun = {0}; #endif refEntity_t barrel = {0}; refEntity_t flash = {0}; vec3_t origin; int renderfx; vec3_t mins = {-16, -16, -24}; vec3_t maxs = {16, 16, 32}; float len; float xx; float xscale; float yscale; #ifdef TA_WEAPSYS int i; vec3_t angles; #ifdef TURTLEARENA // PLAYERS char *newTagNames[3] = { "tag_hand_primary", "tag_hand_secondary", NULL }; #endif char *originalTagNames[3] = { "tag_weapon", "tag_flag", NULL }; #endif if ( !pi->legsModel || !pi->torsoModel || !pi->headModel #ifdef TA_PLAYERSYS || !pi->playercfg.animations[0].numFrames ) { #else || !pi->animations[0].numFrames ) { #endif return; } dp_realtime = time; if ( pi->pendingWeapon != WP_NUM_WEAPONS && dp_realtime > pi->weaponTimer ) { pi->weapon = pi->pendingWeapon; pi->lastWeapon = pi->pendingWeapon; pi->pendingWeapon = WP_NUM_WEAPONS; pi->weaponTimer = 0; #ifndef TA_WEAPSYS_EX if( pi->currentWeapon != pi->weapon ) { trap_S_StartLocalSound( weaponChangeSound, CHAN_LOCAL ); } #endif } CG_AdjustFrom640( &x, &y, &w, &h ); y -= jumpHeight; memset( &refdef, 0, sizeof( refdef ) ); memset( &legs, 0, sizeof(legs) ); memset( &torso, 0, sizeof(torso) ); memset( &head, 0, sizeof(head) ); refdef.rdflags = RDF_NOWORLDMODEL; AxisClear( refdef.viewaxis ); refdef.x = x; refdef.y = y; refdef.width = w; refdef.height = h; if ( ui_stretch.integer ) { xscale = cgs.screenXScaleStretch; yscale = cgs.screenYScaleStretch; } else { xscale = cgs.screenXScale; yscale = cgs.screenYScale; } refdef.fov_x = (int)((float)refdef.width / xscale / 640.0f * 90.0f); xx = refdef.width / xscale / tan( refdef.fov_x / 360 * M_PI ); refdef.fov_y = atan2( refdef.height / yscale, xx ); refdef.fov_y *= ( 360 / M_PI ); // calculate distance so the player nearly fills the box len = 0.7 * ( maxs[2] - mins[2] ); origin[0] = len / tan( DEG2RAD(refdef.fov_x) * 0.5 ); origin[1] = 0.5 * ( mins[1] + maxs[1] ); origin[2] = -0.5 * ( mins[2] + maxs[2] ); refdef.time = dp_realtime; trap_R_ClearScene(); // get the rotation information UI_PlayerAngles( pi, legs.axis, torso.axis, head.axis ); // get the animation state (after rotation, to allow feet shuffle) UI_PlayerAnimation( pi, &legs.oldframe, &legs.frame, &legs.backlerp, &torso.oldframe, &torso.frame, &torso.backlerp ); renderfx = RF_LIGHTING_ORIGIN | RF_NOSHADOW; // // add the legs // legs.hModel = pi->legsModel; legs.customSkin = CG_AddSkinToFrame( &pi->modelSkin ); VectorCopy( origin, legs.origin ); VectorCopy( origin, legs.lightingOrigin ); legs.renderfx = renderfx; VectorCopy (legs.origin, legs.oldorigin); Byte4Copy( pi->c1RGBA, legs.shaderRGBA ); CG_AddRefEntityWithMinLight( &legs ); if (!legs.hModel) { return; } // // add the torso // torso.hModel = pi->torsoModel; if (!torso.hModel) { return; } torso.customSkin = legs.customSkin; VectorCopy( origin, torso.lightingOrigin ); UI_PositionRotatedEntityOnTag( &torso, &legs, pi->legsModel, NULL, "tag_torso"); torso.renderfx = renderfx; Byte4Copy( pi->c1RGBA, torso.shaderRGBA ); CG_AddRefEntityWithMinLight( &torso ); // // add the head // head.hModel = pi->headModel; if (!head.hModel) { return; } head.customSkin = legs.customSkin; VectorCopy( origin, head.lightingOrigin ); UI_PositionRotatedEntityOnTag( &head, &torso, pi->torsoModel, NULL, "tag_head"); head.renderfx = renderfx; Byte4Copy( pi->c1RGBA, head.shaderRGBA ); CG_AddRefEntityWithMinLight( &head ); // // add the gun // if ( pi->currentWeapon != WP_NONE ) { #ifdef TA_WEAPSYS // get hands from cent for (i = 0; i < MAX_HANDS; i++) { memset( &gun[i], 0, sizeof(gun[i]) ); gun[i].hModel = pi->weaponModel[i]; VectorCopy( origin, gun[i].lightingOrigin ); gun[i].renderfx = renderfx; Byte4Copy( pi->c1RGBA, gun[i].shaderRGBA ); if (!originalTagNames[i] #ifdef TURTLEARENA // PLAYERS || !newTagNames[i] #endif ) { break; } if (!gun[i].hModel) { continue; } if ( #ifdef TURTLEARENA // PLAYERS !UI_PositionEntityOnTag( &gun[i], &torso, pi->torsoModel, NULL, newTagNames[i]) && #endif !UI_PositionEntityOnTag( &gun[i], &torso, pi->torsoModel, NULL, originalTagNames[i])) { // Failed to find tag continue; } CG_AddRefEntityWithMinLight( &gun[i] ); } #else memset( &gun, 0, sizeof(gun) ); gun.hModel = pi->weaponModel; Byte4Copy( pi->c1RGBA, gun.shaderRGBA ); VectorCopy( origin, gun.lightingOrigin ); UI_PositionEntityOnTag( &gun, &torso, pi->torsoModel, NULL, "tag_weapon"); gun.renderfx = renderfx; CG_AddRefEntityWithMinLight( &gun ); #endif } // // add the spinning barrel // #ifdef TA_WEAPSYS for (i = 0; i < MAX_HANDS; i++) #else if ( pi->barrelModel ) #endif { #ifdef TA_WEAPSYS if (!pi->barrelModel[i]) continue; #else vec3_t angles; #endif memset( &barrel, 0, sizeof(barrel) ); VectorCopy( origin, barrel.lightingOrigin ); barrel.renderfx = renderfx; #ifdef TA_WEAPSYS barrel.hModel = pi->barrelModel[i]; VectorClear(angles); if (bg_weapongroupinfo[pi->realWeapon].weapon[i]->barrelSpin != BS_NONE) { if (i & 1) angles[bg_weapongroupinfo[pi->realWeapon].weapon[i]->barrelSpin] = 360-UI_MachinegunSpinAngle( pi ); else angles[bg_weapongroupinfo[pi->realWeapon].weapon[i]->barrelSpin] = UI_MachinegunSpinAngle( pi ); } #else barrel.hModel = pi->barrelModel; angles[YAW] = 0; angles[PITCH] = 0; angles[ROLL] = UI_MachinegunSpinAngle( pi ); #endif AnglesToAxis( angles, barrel.axis ); #ifdef TA_WEAPSYS UI_PositionRotatedEntityOnTag( &barrel, &gun[i], pi->weaponModel[i], NULL, "tag_barrel"); #else UI_PositionRotatedEntityOnTag( &barrel, &gun, pi->weaponModel, NULL, "tag_barrel"); #endif CG_AddRefEntityWithMinLight( &barrel ); } // // add muzzle flash // if ( dp_realtime <= pi->muzzleFlashTime ) { #ifdef TA_WEAPSYS vec3_t *flashDlightColor; for (i = 0; i < MAX_HANDS; i++) { memset( &flash, 0, sizeof(flash) ); flash.hModel = pi->flashModel[i]; flashDlightColor = &pi->flashDlightColor[i]; Byte4Copy( pi->c1RGBA, flash.shaderRGBA ); if (!flash.hModel) continue; VectorCopy( origin, flash.lightingOrigin ); UI_PositionEntityOnTag( &flash, &gun[i], pi->weaponModel[i], NULL, "tag_flash"); flash.renderfx = renderfx; trap_R_AddRefEntityToScene( &flash ); // make a dlight for the flash if ( *flashDlightColor[0] || *flashDlightColor[1] || *flashDlightColor[2] ) { trap_R_AddJuniorLightToScene( flash.origin, 200 + (rand()&31), 1.0f, *flashDlightColor[0], *flashDlightColor[1], *flashDlightColor[2] ); } } #else if ( pi->flashModel ) { memset( &flash, 0, sizeof(flash) ); flash.hModel = pi->flashModel; Byte4Copy( pi->c1RGBA, flash.shaderRGBA ); VectorCopy( origin, flash.lightingOrigin ); UI_PositionEntityOnTag( &flash, &gun, pi->weaponModel, NULL, "tag_flash"); flash.renderfx = renderfx; CG_AddRefEntityWithMinLight( &flash ); } // make a dlight for the flash if ( pi->flashDlightColor[0] || pi->flashDlightColor[1] || pi->flashDlightColor[2] ) { trap_R_AddJuniorLightToScene( flash.origin, 200 + (rand()&31), 1.0f, pi->flashDlightColor[0], pi->flashDlightColor[1], pi->flashDlightColor[2] ); } #endif } // // add the chat icon // if ( pi->chat ) { #ifdef TA_DATA // shaders UI_PlayerFloatSprite( pi, torso.origin, trap_R_RegisterShaderNoMip( "sprites/talkBalloon" ) ); #else UI_PlayerFloatSprite( pi, torso.origin, trap_R_RegisterShaderNoMip( "sprites/balloon3" ) ); #endif } // // add an accent light // origin[0] -= 100; // + = behind, - = in front origin[1] += 100; // + = left, - = right origin[2] += 100; // + = above, - = below trap_R_AddJuniorLightToScene( origin, 500, 1.0, 1.0, 1.0, 1.0 ); origin[0] -= 100; origin[1] -= 100; origin[2] -= 100; trap_R_AddJuniorLightToScene( origin, 500, 1.0, 1.0, 0.0, 0.0 ); trap_R_RenderScene( &refdef ); } /* ========================== UI_FileExists ========================== */ static qboolean UI_FileExists(const char *filename) { int len; len = trap_FS_FOpenFile( filename, NULL, FS_READ ); if (len>0) { return qtrue; } return qfalse; }
void InitSiegeMode(void) { vmCvar_t mapname; char levelname[512]; char teamIcon[128]; char goalreq[64]; char teams[2048]; static char objective[MAX_SIEGE_INFO_SIZE]; char objecStr[8192]; int len = 0; int i = 0; // int j = 0; int objectiveNumTeam1 = 0; int objectiveNumTeam2 = 0; fileHandle_t f; objective[0] = '\0'; if (level.gametype != GT_SIEGE) { goto failure; } //reset SiegeSetCompleteData(0); //get pers data in case it existed from last level if (g_siegeTeamSwitch.integer) { trap_SiegePersGet(&g_siegePersistant); if (g_siegePersistant.beatingTime) { trap_SetConfigstring(CS_SIEGE_TIMEOVERRIDE, va("%i", g_siegePersistant.lastTime)); } else { trap_SetConfigstring(CS_SIEGE_TIMEOVERRIDE, "0"); } } else { //hmm, ok, nothing. trap_SetConfigstring(CS_SIEGE_TIMEOVERRIDE, "0"); } imperial_goals_completed = 0; rebel_goals_completed = 0; trap_Cvar_Register( &mapname, "mapname", "", CVAR_SERVERINFO | CVAR_ROM ); Com_sprintf(levelname, sizeof(levelname), "maps/%s.siege\0", mapname.string); if ( !levelname[0] ) { goto failure; } len = trap_FS_FOpenFile(levelname, &f, FS_READ); if (!f || len >= MAX_SIEGE_INFO_SIZE) { goto failure; } trap_FS_Read(siege_info, len, f); trap_FS_FCloseFile(f); siege_valid = 1; //See if players should be specs or ingame preround if (BG_SiegeGetPairedValue(siege_info, "preround_state", teams)) { if (teams[0]) { g_preroundState = atoi(teams); } } if (BG_SiegeGetValueGroup(siege_info, "Teams", teams)) { if (g_siegeTeam1.string[0] && Q_stricmp(g_siegeTeam1.string, "none")) { //check for override strcpy(team1, g_siegeTeam1.string); } else { //otherwise use level default BG_SiegeGetPairedValue(teams, "team1", team1); } if (g_siegeTeam2.string[0] && Q_stricmp(g_siegeTeam2.string, "none")) { //check for override strcpy(team2, g_siegeTeam2.string); } else { //otherwise use level default BG_SiegeGetPairedValue(teams, "team2", team2); } } else { G_Error("Siege teams not defined"); } if (BG_SiegeGetValueGroup(siege_info, team2, gParseObjectives)) { if (BG_SiegeGetPairedValue(gParseObjectives, "TeamIcon", teamIcon)) { trap_Cvar_Set( "team2_icon", teamIcon); } if (BG_SiegeGetPairedValue(gParseObjectives, "RequiredObjectives", goalreq)) { rebel_goals_required = atoi(goalreq); } if (BG_SiegeGetPairedValue(gParseObjectives, "Timed", goalreq)) { rebel_time_limit = atoi(goalreq)*1000; if (g_siegeTeamSwitch.integer && g_siegePersistant.beatingTime) { gRebelCountdown = level.time + g_siegePersistant.lastTime; } else { gRebelCountdown = level.time + rebel_time_limit; } } if (BG_SiegeGetPairedValue(gParseObjectives, "attackers", goalreq)) { rebel_attackers = atoi(goalreq); } } if (BG_SiegeGetValueGroup(siege_info, team1, gParseObjectives)) { if (BG_SiegeGetPairedValue(gParseObjectives, "TeamIcon", teamIcon)) { trap_Cvar_Set( "team1_icon", teamIcon); } if (BG_SiegeGetPairedValue(gParseObjectives, "RequiredObjectives", goalreq)) { imperial_goals_required = atoi(goalreq); } if (BG_SiegeGetPairedValue(gParseObjectives, "Timed", goalreq)) { if (rebel_time_limit) { Com_Printf("Tried to set imperial time limit, but there's already a rebel time limit!\nOnly one team can have a time limit.\n"); } else { imperial_time_limit = atoi(goalreq)*1000; if (g_siegeTeamSwitch.integer && g_siegePersistant.beatingTime) { gImperialCountdown = level.time + g_siegePersistant.lastTime; } else { gImperialCountdown = level.time + imperial_time_limit; } } } if (BG_SiegeGetPairedValue(gParseObjectives, "attackers", goalreq)) { imperial_attackers = atoi(goalreq); } } //Load the player class types BG_SiegeLoadClasses(NULL); if (!bgNumSiegeClasses) { //We didn't find any?! G_Error("Couldn't find any player classes for Siege"); } /* //We could probably just see what teams are used on this level, //then see what classes are used by those teams, and then precache //all weapons for said classes. However, I'm just going to do them //all for now. while (i < bgNumSiegeClasses) { cl = &bgSiegeClasses[i]; j = 0; while (j < WP_NUM_WEAPONS) { if (cl->weapons & (1 << j)) { //we use this weapon so register it. RegisterItem(BG_FindItemForWeapon(j)); } j++; } i++; } */ //Ok, I'm adding inventory item precaching now, so I'm finally going to optimize this //to only do weapons/items for the current teams used on the level. //Now load the teams since we have class data. BG_SiegeLoadTeams(); if (!bgNumSiegeTeams) { //React same as with classes. G_Error("Couldn't find any player teams for Siege"); } //Get and set the team themes for each team. This will control which classes can be //used on each team. if (BG_SiegeGetValueGroup(siege_info, team1, gParseObjectives)) { if (BG_SiegeGetPairedValue(gParseObjectives, "UseTeam", goalreq)) { BG_SiegeSetTeamTheme(SIEGETEAM_TEAM1, goalreq); } //Now count up the objectives for this team. i = 1; strcpy(objecStr, va("Objective%i", i)); while (BG_SiegeGetValueGroup(gParseObjectives, objecStr, objective)) { objectiveNumTeam1++; i++; strcpy(objecStr, va("Objective%i", i)); } } if (BG_SiegeGetValueGroup(siege_info, team2, gParseObjectives)) { if (BG_SiegeGetPairedValue(gParseObjectives, "UseTeam", goalreq)) { BG_SiegeSetTeamTheme(SIEGETEAM_TEAM2, goalreq); } //Now count up the objectives for this team. i = 1; strcpy(objecStr, va("Objective%i", i)); while (BG_SiegeGetValueGroup(gParseObjectives, objecStr, objective)) { objectiveNumTeam2++; i++; strcpy(objecStr, va("Objective%i", i)); } } //Set the configstring to show status of all current objectives strcpy(gObjectiveCfgStr, "t1"); while (objectiveNumTeam1 > 0) { //mark them all as not completed since we just initialized Q_strcat(gObjectiveCfgStr, 1024, "-0"); objectiveNumTeam1--; } //Finished doing team 1's objectives, now do team 2's Q_strcat(gObjectiveCfgStr, 1024, "|t2"); while (objectiveNumTeam2 > 0) { Q_strcat(gObjectiveCfgStr, 1024, "-0"); objectiveNumTeam2--; } //And finally set the actual config string trap_SetConfigstring(CS_SIEGE_OBJECTIVES, gObjectiveCfgStr); //precache saber data for classes that use sabers on both teams BG_PrecacheSabersForSiegeTeam(SIEGETEAM_TEAM1); BG_PrecacheSabersForSiegeTeam(SIEGETEAM_TEAM2); G_SiegeRegisterWeaponsAndHoldables(SIEGETEAM_TEAM1); G_SiegeRegisterWeaponsAndHoldables(SIEGETEAM_TEAM2); return; failure: siege_valid = 0; }
void *decoder_ogg_load( const char *filename, snd_info_t *info ) { OggVorbis_File vorbisfile; int filenum, bitstream, bytes_read, bytes_read_total; char *buffer; ov_callbacks callbacks = { ovcb_read, ovcb_seek, ovcb_close, ovcb_tell }; trap_FS_FOpenFile( filename, &filenum, FS_READ|FS_NOSIZE ); if( !filenum ) return NULL; if( trap_FS_IsUrl( filename ) ) { callbacks.seek_func = NULL; callbacks.tell_func = NULL; } qov_open_callbacks( (void *) (qintptr) filenum, &vorbisfile, NULL, 0, callbacks ); if( callbacks.seek_func && !qov_seekable( &vorbisfile ) ) { Com_Printf( "Error unsupported .ogg file (not seekable): %s\n", filename ); qov_clear( &vorbisfile ); // Does FS_FCloseFile return NULL; } if( qov_streams( &vorbisfile ) != 1 ) { Com_Printf( "Error unsupported .ogg file (multiple logical bitstreams): %s\n", filename ); qov_clear( &vorbisfile ); // Does FS_FCloseFile return NULL; } if( !read_ogg_header( vorbisfile, info ) ) { Com_Printf( "Error reading .ogg file header: %s\n", filename ); qov_clear( &vorbisfile ); // Does FS_FCloseFile return NULL; } buffer = S_Malloc( info->size ); bytes_read_total = 0; do { #ifdef ENDIAN_BIG bytes_read = qov_read( &vorbisfile, buffer+bytes_read_total, info->size-bytes_read_total, 1, 2, 1, &bitstream ); #elif defined (ENDIAN_LITTLE) bytes_read = qov_read( &vorbisfile, buffer+bytes_read_total, info->size-bytes_read_total, 0, 2, 1, &bitstream ); #else #error "runtime endianess detection support missing" #endif bytes_read_total += bytes_read; } while( bytes_read > 0 && bytes_read_total < info->size ); qov_clear( &vorbisfile ); // Does FS_FCloseFile if( !bytes_read_total ) { Com_Printf( "Error reading .ogg file: %s\n", filename ); S_Free( buffer ); return NULL; } return buffer; }
void UI_SaberLoadParms( void ) { int len, totallen, saberExtFNLen, fileCnt, i; char *holdChar, *marker; char saberExtensionListBuf[2048]; // The list of file names read in fileHandle_t f; char buffer[MAX_MENUFILE]; //ui.Printf( "UI Parsing *.sab saber definitions\n" ); ui_saber_parms_parsed = qtrue; UI_CacheSaberGlowGraphics(); //set where to store the first one totallen = 0; marker = SaberParms; marker[0] = '\0'; //now load in the extra .npc extensions fileCnt = trap_FS_GetFileList("ext_data/sabers", ".sab", saberExtensionListBuf, sizeof(saberExtensionListBuf) ); holdChar = saberExtensionListBuf; for ( i = 0; i < fileCnt; i++, holdChar += saberExtFNLen + 1 ) { saberExtFNLen = strlen( holdChar ); len = trap_FS_FOpenFile( va( "ext_data/sabers/%s", holdChar), &f, FS_READ ); if (!f) { continue; } if ( len == -1 ) { Com_Printf( "UI_SaberLoadParms: error reading %s\n", holdChar ); } else { if (len > sizeof(buffer) ) { Com_Error( ERR_FATAL, "UI_SaberLoadParms: file %s too large to read (max=%d)", holdChar, sizeof(buffer) ); } trap_FS_Read( buffer, len, f ); trap_FS_FCloseFile( f ); buffer[len] = 0; if ( totallen && *(marker-1) == '}' ) {//don't let it end on a } because that should be a stand-alone token strcat( marker, " " ); totallen++; marker++; } len = COM_Compress( buffer ); if ( totallen + len >= MAX_SABER_DATA_SIZE ) { Com_Error( ERR_FATAL, "UI_SaberLoadParms: ran out of space before reading %s\n(you must make the .sab files smaller)", holdChar ); } strcat( marker, buffer ); totallen += len; marker += len; } } }
/* =============== G_ParseMapRotationFile Load the map rotations from a map rotation file =============== */ static bool G_ParseMapRotationFile( const char *fileName ) { char *text_p; int i; int len; char *token; char text[ 20000 ]; char mrName[ MAX_QPATH ]; bool mrNameSet = false; fileHandle_t f; // load the file len = trap_FS_FOpenFile( fileName, &f, FS_READ ); if( len <= 0 ) return false; if( len >= sizeof( text ) - 1 ) { G_Printf( S_COLOR_RED "ERROR: map rotation file %s too long\n", fileName ); return false; } trap_FS_Read( text, len, f ); text[ len ] = 0; trap_FS_FCloseFile( f ); // parse the text text_p = text; // read optional parameters while( 1 ) { token = COM_Parse( &text_p ); if( !token ) break; if( !Q_stricmp( token, "" ) ) break; if( !Q_stricmp( token, "{" ) ) { if( mrNameSet ) { //check for name space clashes for( i = 0; i < mapRotations.numRotations; i++ ) { if( !Q_stricmp( mapRotations.rotations[ i ].name, mrName ) ) { G_Printf( S_COLOR_RED "ERROR: a map rotation is already named %s\n", mrName ); return false; } } Q_strncpyz( mapRotations.rotations[ mapRotations.numRotations ].name, mrName, MAX_QPATH ); if( !G_ParseMapRotation( &mapRotations.rotations[ mapRotations.numRotations ], &text_p ) ) { G_Printf( S_COLOR_RED "ERROR: %s: failed to parse map rotation %s\n", fileName, mrName ); return false; } //start parsing particle systems again mrNameSet = false; if( mapRotations.numRotations == MAX_MAP_ROTATIONS ) { G_Printf( S_COLOR_RED "ERROR: maximum number of map rotations (%d) reached\n", MAX_MAP_ROTATIONS ); return false; } else mapRotations.numRotations++; continue; } else { G_Printf( S_COLOR_RED "ERROR: unamed map rotation\n" ); return false; } } if( !mrNameSet ) { Q_strncpyz( mrName, token, sizeof( mrName ) ); mrNameSet = true; } else { G_Printf( S_COLOR_RED "ERROR: map rotation already named\n" ); return false; } } return true; }
void BG_SiegeParseClassFile(const char *filename, siegeClassDesc_t *descBuffer) { fileHandle_t f; int len; int i; char classInfo[4096]; char parseBuf[4096]; len = trap_FS_FOpenFile(filename, &f, FS_READ); if (!f || len >= 4096) { return; } trap_FS_Read(classInfo, len, f); trap_FS_FCloseFile(f); classInfo[len] = 0; //first get the description if we have a buffer for it if (descBuffer) { if (!BG_SiegeGetPairedValue(classInfo, "description", descBuffer->desc)) { strcpy(descBuffer->desc, "DESCRIPTION UNAVAILABLE"); } //Hit this assert? Memory has already been trashed. Increase //SIEGE_CLASS_DESC_LEN. assert(strlen(descBuffer->desc) < SIEGE_CLASS_DESC_LEN); } BG_SiegeGetValueGroup(classInfo, "ClassInfo", classInfo); //Parse name if (BG_SiegeGetPairedValue(classInfo, "name", parseBuf)) { strcpy(bgSiegeClasses[bgNumSiegeClasses].name, parseBuf); } else { Com_Error(ERR_DROP, "Siege class without name entry"); } //Parse forced model if (BG_SiegeGetPairedValue(classInfo, "model", parseBuf)) { strcpy(bgSiegeClasses[bgNumSiegeClasses].forcedModel, parseBuf); } else { //It's ok if there isn't one, it's optional. bgSiegeClasses[bgNumSiegeClasses].forcedModel[0] = 0; } //Parse forced skin if (BG_SiegeGetPairedValue(classInfo, "skin", parseBuf)) { strcpy(bgSiegeClasses[bgNumSiegeClasses].forcedSkin, parseBuf); } else { //It's ok if there isn't one, it's optional. bgSiegeClasses[bgNumSiegeClasses].forcedSkin[0] = 0; } //Parse first saber if (BG_SiegeGetPairedValue(classInfo, "saber1", parseBuf)) { strcpy(bgSiegeClasses[bgNumSiegeClasses].saber1, parseBuf); } else { //It's ok if there isn't one, it's optional. bgSiegeClasses[bgNumSiegeClasses].saber1[0] = 0; } //Parse second saber if (BG_SiegeGetPairedValue(classInfo, "saber2", parseBuf)) { strcpy(bgSiegeClasses[bgNumSiegeClasses].saber2, parseBuf); } else { //It's ok if there isn't one, it's optional. bgSiegeClasses[bgNumSiegeClasses].saber2[0] = 0; } //Parse forced saber stance if (BG_SiegeGetPairedValue(classInfo, "saberstyle", parseBuf)) { bgSiegeClasses[bgNumSiegeClasses].saberStance = BG_SiegeTranslateGenericTable(parseBuf, StanceTable, qtrue); } else { //It's ok if there isn't one, it's optional. bgSiegeClasses[bgNumSiegeClasses].saberStance = 0; } //Parse forced saber color if (BG_SiegeGetPairedValue(classInfo, "sabercolor", parseBuf)) { bgSiegeClasses[bgNumSiegeClasses].forcedSaberColor = atoi(parseBuf); bgSiegeClasses[bgNumSiegeClasses].hasForcedSaberColor = qtrue; } else { //It's ok if there isn't one, it's optional. bgSiegeClasses[bgNumSiegeClasses].hasForcedSaberColor = qfalse; } //Parse forced saber2 color if (BG_SiegeGetPairedValue(classInfo, "saber2color", parseBuf)) { bgSiegeClasses[bgNumSiegeClasses].forcedSaber2Color = atoi(parseBuf); bgSiegeClasses[bgNumSiegeClasses].hasForcedSaber2Color = qtrue; } else { //It's ok if there isn't one, it's optional. bgSiegeClasses[bgNumSiegeClasses].hasForcedSaber2Color = qfalse; } //Parse weapons if (BG_SiegeGetPairedValue(classInfo, "weapons", parseBuf)) { bgSiegeClasses[bgNumSiegeClasses].weapons = BG_SiegeTranslateGenericTable(parseBuf, WPTable, qtrue); } else { Com_Error(ERR_DROP, "Siege class without weapons entry"); } if (!(bgSiegeClasses[bgNumSiegeClasses].weapons & (1 << WP_SABER))) { //make sure it has melee if there's no saber bgSiegeClasses[bgNumSiegeClasses].weapons |= (1 << WP_MELEE); //always give them this too if they are not a saber user } //Parse forcepowers if (BG_SiegeGetPairedValue(classInfo, "forcepowers", parseBuf)) { BG_SiegeTranslateForcePowers(parseBuf, &bgSiegeClasses[bgNumSiegeClasses]); } else { //fine, clear out the powers. i = 0; while (i < NUM_FORCE_POWERS) { bgSiegeClasses[bgNumSiegeClasses].forcePowerLevels[i] = 0; i++; } } //Parse classflags if (BG_SiegeGetPairedValue(classInfo, "classflags", parseBuf)) { bgSiegeClasses[bgNumSiegeClasses].classflags = BG_SiegeTranslateGenericTable(parseBuf, bgSiegeClassFlagNames, qtrue); } else { //fine, we'll 0 it. bgSiegeClasses[bgNumSiegeClasses].classflags = 0; } //Parse maxhealth if (BG_SiegeGetPairedValue(classInfo, "maxhealth", parseBuf)) { bgSiegeClasses[bgNumSiegeClasses].maxhealth = atoi(parseBuf); } else { //It's alright, just default to 100 then. bgSiegeClasses[bgNumSiegeClasses].maxhealth = 100; } //Parse starthealth if (BG_SiegeGetPairedValue(classInfo, "starthealth", parseBuf)) { bgSiegeClasses[bgNumSiegeClasses].starthealth = atoi(parseBuf); } else { //It's alright, just default to 100 then. bgSiegeClasses[bgNumSiegeClasses].starthealth = bgSiegeClasses[bgNumSiegeClasses].maxhealth; } //Parse startarmor if (BG_SiegeGetPairedValue(classInfo, "maxarmor", parseBuf)) { bgSiegeClasses[bgNumSiegeClasses].maxarmor = atoi(parseBuf); } else { //It's alright, just default to 0 then. bgSiegeClasses[bgNumSiegeClasses].maxarmor = 0; } //Parse startarmor if (BG_SiegeGetPairedValue(classInfo, "startarmor", parseBuf)) { bgSiegeClasses[bgNumSiegeClasses].startarmor = atoi(parseBuf); if (!bgSiegeClasses[bgNumSiegeClasses].maxarmor) { //if they didn't specify a damn max armor then use this. bgSiegeClasses[bgNumSiegeClasses].maxarmor = bgSiegeClasses[bgNumSiegeClasses].startarmor; } } else { //default to maxarmor. bgSiegeClasses[bgNumSiegeClasses].startarmor = bgSiegeClasses[bgNumSiegeClasses].maxarmor; } //Parse speed (this is a multiplier value) if (BG_SiegeGetPairedValue(classInfo, "speed", parseBuf)) { bgSiegeClasses[bgNumSiegeClasses].speed = atof(parseBuf); } else { //It's alright, just default to 1 then. bgSiegeClasses[bgNumSiegeClasses].speed = 1.0f; } //Parse shader for ui to use if (BG_SiegeGetPairedValue(classInfo, "uishader", parseBuf)) { #ifdef QAGAME bgSiegeClasses[bgNumSiegeClasses].uiPortraitShader = 0; memset(bgSiegeClasses[bgNumSiegeClasses].uiPortrait,0,sizeof(bgSiegeClasses[bgNumSiegeClasses].uiPortrait)); #elif defined CGAME bgSiegeClasses[bgNumSiegeClasses].uiPortraitShader = 0; memset(bgSiegeClasses[bgNumSiegeClasses].uiPortrait,0,sizeof(bgSiegeClasses[bgNumSiegeClasses].uiPortrait)); #else //ui bgSiegeClasses[bgNumSiegeClasses].uiPortraitShader = trap_R_RegisterShaderNoMip(parseBuf); memcpy(bgSiegeClasses[bgNumSiegeClasses].uiPortrait,parseBuf,sizeof(bgSiegeClasses[bgNumSiegeClasses].uiPortrait)); #endif } else { //I guess this is an essential.. we don't want to render bad shaders or anything. Com_Error(ERR_DROP, "Siege class without uishader entry"); } //Parse shader for ui to use if (BG_SiegeGetPairedValue(classInfo, "class_shader", parseBuf)) { #ifdef QAGAME bgSiegeClasses[bgNumSiegeClasses].classShader = 0; #else //cgame, ui bgSiegeClasses[bgNumSiegeClasses].classShader = trap_R_RegisterShaderNoMip(parseBuf); assert( bgSiegeClasses[bgNumSiegeClasses].classShader ); if ( !bgSiegeClasses[bgNumSiegeClasses].classShader ) { Com_Printf( "ERROR: could not find class_shader %s for class %s\n", parseBuf, bgSiegeClasses[bgNumSiegeClasses].name ); } // A very hacky way to determine class . . . else #endif { // Find the base player class based on the icon name - very bad, I know. int titleLength,i,arrayTitleLength; char *holdBuf; titleLength = strlen(parseBuf); for (i=0;i<SPC_MAX;i++) { // Back up arrayTitleLength = strlen(classTitles[i]); if (arrayTitleLength>titleLength) // Too long { break; } holdBuf = parseBuf + ( titleLength - arrayTitleLength); if (!strcmp(holdBuf,classTitles[i])) { bgSiegeClasses[bgNumSiegeClasses].playerClass = i; break; } } // In case the icon name doesn't match up if (i>=SPC_MAX) { bgSiegeClasses[bgNumSiegeClasses].playerClass = SPC_INFANTRY; } } } else { //No entry! Bad bad bad Com_Printf( "ERROR: no class_shader defined for class %s\n", bgSiegeClasses[bgNumSiegeClasses].name ); } //Parse holdable items to use if (BG_SiegeGetPairedValue(classInfo, "holdables", parseBuf)) { bgSiegeClasses[bgNumSiegeClasses].invenItems = BG_SiegeTranslateGenericTable(parseBuf, HoldableTable, qtrue); } else { //Just don't start out with any then. bgSiegeClasses[bgNumSiegeClasses].invenItems = 0; } //Parse powerups to use if (BG_SiegeGetPairedValue(classInfo, "powerups", parseBuf)) { bgSiegeClasses[bgNumSiegeClasses].powerups = BG_SiegeTranslateGenericTable(parseBuf, PowerupTable, qtrue); } else { //Just don't start out with any then. bgSiegeClasses[bgNumSiegeClasses].powerups = 0; } //A successful read. bgNumSiegeClasses++; }
/* * S_ReadPlaylistFile */ static bgTrack_t *S_ReadPlaylistFile( const char *filename, bool shuffle, bool loop ) { int filenum, length; char *tmpname = 0; size_t tmpname_size = 0; char *data, *line, *entry; playlistItem_t items[MAX_PLAYLIST_ITEMS]; int i, numItems = 0; length = trap_FS_FOpenFile( filename, &filenum, FS_READ ); if( length < 0 ) { return NULL; } // load the playlist into memory data = S_Malloc( length + 1 ); trap_FS_Read( data, length, filenum ); trap_FS_FCloseFile( filenum ); srand( time( NULL ) ); while( *data ) { size_t s; entry = data; // read the whole line for( line = data; *line != '\0' && *line != '\n'; line++ ) ; // continue reading from the next character, if possible data = ( *line == '\0' ? line : line + 1 ); *line = '\0'; // trim whitespaces, tabs, etc entry = Q_trim( entry ); // special M3U entry or comment if( !*entry || *entry == '#' ) { continue; } if( trap_FS_IsUrl( entry ) ) { items[numItems].track = S_AllocTrack( entry ); } else { // append the entry name to playlist path s = strlen( filename ) + 1 + strlen( entry ) + 1; if( s > tmpname_size ) { if( tmpname ) { S_Free( tmpname ); } tmpname_size = s; tmpname = S_Malloc( tmpname_size ); } Q_strncpyz( tmpname, filename, tmpname_size ); COM_StripFilename( tmpname ); Q_strncatz( tmpname, "/", tmpname_size ); Q_strncatz( tmpname, entry, tmpname_size ); COM_SanitizeFilePath( tmpname ); items[numItems].track = S_AllocTrack( tmpname ); } if( ++numItems == MAX_PLAYLIST_ITEMS ) { break; } } if( tmpname ) { S_Free( tmpname ); tmpname = NULL; } if( !numItems ) { return NULL; } // set the playing order for( i = 0; i < numItems; i++ ) items[i].order = ( shuffle ? ( rand() % numItems ) : i ); // sort the playlist R_SortPlaylistItems( numItems, items ); // link the playlist for( i = 1; i < numItems; i++ ) { items[i - 1].track->next = items[i].track; items[i].track->prev = items[i - 1].track; items[i].track->loop = loop; } items[numItems - 1].track->next = items[0].track; items[0].track->prev = items[numItems - 1].track; items[0].track->loop = loop; return items[0].track; }
void CG_LoadLocations(void) { fileHandle_t f; // handle of file on disk int fLen = trap_FS_FOpenFile(va("maps/%s_loc_override.dat", cgs.rawmapname), &f, FS_READ); // length of the file char fBuffer[MAX_BUFFER]; // buffer to read the file into char message[128] = "\0"; // location description char temp[128] = "\0"; // temporary buffer int x = 0; // x-coord of the location int y = 0; // y-coord of the location int z = 0; // z-coord of the location int p = 0; // current location in the file buffer int t = 0; // current location in the temp buffer if (fLen < 0) { // open the location .dat file that matches the map's name fLen = trap_FS_FOpenFile(va("maps/%s_loc.dat", cgs.rawmapname), &f, FS_READ); if (fLen < 0) { CG_Printf("^dLoadLocations: ^3Warning: ^9No location data found for map ^2%s^9.\n", cgs.rawmapname); return; } } if (fLen > MAX_BUFFER) { trap_FS_FCloseFile(f); CG_Error("Location file is too big, make it smaller (max = %i bytes)\n", MAX_BUFFER); } trap_FS_Read(&fBuffer, fLen, f); // read the file into the buffer fBuffer[fLen] = '\0'; // make sure it's null-terminated trap_FS_FCloseFile(f); // close the file, we're done with it CG_Printf("^dLoadLocations: ^9location data for map ^2%s ^9loaded\n", cgs.rawmapname); // start parsing! while (p < fLen) { // check for the beginning of a comment if (fBuffer[p++] == '/') { //check for single line comment if (fBuffer[p] == '/') { while (p < fLen && (fBuffer[p] != '\n' && fBuffer[p] != '\r')) { p++; } } // check for multiline comment else if (fBuffer[p] == '*') { while (p < fLen && (fBuffer[p] != '*' && fBuffer[p + 1] != '/')) { p++; } } } // parse the next line while (p < fLen && (fBuffer[p] != '\n' || fBuffer[p] != '\r')) { // grab the x-coord while (p < fLen && fBuffer[p] != ' ') { temp[t++] = fBuffer[p++]; } temp[t] = '\0'; x = atoi(temp); t = 0; memset(&temp, 0, sizeof(temp)); if (p > fLen) { break; } p++; // grab the y-coord while (p < fLen && fBuffer[p] != ' ') { temp[t++] = fBuffer[p++]; } temp[t] = '\0'; y = atoi(temp); t = 0; memset(&temp, 0, sizeof(temp)); if (p > fLen) { break; } p++; // grab the z-coord while (p < fLen && fBuffer[p] != ' ') { temp[t++] = fBuffer[p++]; } temp[t] = '\0'; z = atoi(temp); t = 0; memset(&temp, 0, sizeof(temp)); if (p > fLen) { break; } p++; // grab the description while (p < fLen && fBuffer[p] != '\n' && fBuffer[p] != '\r') { // ignore quotation marks if (fBuffer[p] != '\"') { temp[t++] = fBuffer[p++]; } else { p++; } } temp[t] = '\0'; t = 0; // if @, then keep the previous location name, otherwise, update message if (Q_stricmp(temp, "@")) { strcpy(message, temp); } if (p > fLen) { break; } if ((x != 0 || y != 0 || z != 0) && strlen(message) > 0) { location_t *loc = &cgs.location[cgs.numLocations]; loc->index = cgs.numLocations; strcpy(loc->message, message); loc->origin[0] = x; loc->origin[1] = y; loc->origin[2] = z; cgs.numLocations++; if (cgs.numLocations == MAX_C_LOCATIONS) { CG_Printf("^9Too many locations specifed.\n"); break; } } } } // ok we are succesfull CG_Printf("^2%i ^9locations loaded.\n", cgs.numLocations); cgs.locationsLoaded = qtrue; }
/* * S_BackgroundTrack_GetWavinfo */ static int S_BackgroundTrack_GetWavinfo( const char *name, wavinfo_t *info ) { short t; int samples, file; int iff_data, last_chunk; char chunkName[4]; last_chunk = 0; memset( info, 0, sizeof( wavinfo_t ) ); trap_FS_FOpenFile( name, &file, FS_READ ); if( !file ) { return 0; } // find "RIFF" chunk if( !S_BackgroundTrack_FindNextChunk( "RIFF", &last_chunk, file ) ) { //Com_Printf( "Missing RIFF chunk\n" ); return 0; } trap_FS_Read( chunkName, 4, file ); if( !strncmp( chunkName, "WAVE", 4 ) ) { Com_Printf( "Missing WAVE chunk\n" ); return 0; } // get "fmt " chunk iff_data = trap_FS_Tell( file ) + 4; last_chunk = iff_data; if( !S_BackgroundTrack_FindNextChunk( "fmt ", &last_chunk, file ) ) { Com_Printf( "Missing fmt chunk\n" ); return 0; } trap_FS_Read( chunkName, 4, file ); trap_FS_Read( &t, sizeof( t ), file ); if( LittleShort( t ) != 1 ) { Com_Printf( "Microsoft PCM format only\n" ); return 0; } trap_FS_Read( &t, sizeof( t ), file ); info->channels = LittleShort( t ); trap_FS_Read( &info->rate, sizeof( info->rate ), file ); info->rate = LittleLong( info->rate ); trap_FS_Seek( file, 4 + 2, FS_SEEK_CUR ); trap_FS_Read( &t, sizeof( t ), file ); info->width = LittleShort( t ) / 8; info->loopstart = 0; // find data chunk last_chunk = iff_data; if( !S_BackgroundTrack_FindNextChunk( "data", &last_chunk, file ) ) { Com_Printf( "Missing data chunk\n" ); return 0; } trap_FS_Read( &samples, sizeof( samples ), file ); info->samples = LittleLong( samples ) / info->width / info->channels; info->dataofs = trap_FS_Tell( file ); return file; }
/* ====================== CG_ParseBuildableAnimationFile Read a configuration file containing animation counts and rates models/buildables/hivemind/animation.cfg, etc ====================== */ static qboolean CG_ParseBuildableAnimationFile( const char *filename, buildable_t buildable ) { char *text_p; int len; int i; char *token; float fps; char text[ 20000 ]; fileHandle_t f; animation_t *animations; animations = cg_buildables[ buildable ].animations; // load the file len = trap_FS_FOpenFile( filename, &f, FS_READ ); if( len < 0 ) return qfalse; if( len == 0 || len >= sizeof( text ) - 1 ) { trap_FS_FCloseFile( f ); CG_Printf( "File %s is %s\n", filename, len == 0 ? "empty" : "too long" ); return qfalse; } trap_FS_Read( text, len, f ); text[ len ] = 0; trap_FS_FCloseFile( f ); // parse the text text_p = text; // read information for each frame for( i = BANIM_NONE + 1; i < MAX_BUILDABLE_ANIMATIONS; i++ ) { token = COM_Parse( &text_p ); if( !*token ) break; animations[ i ].firstFrame = atoi( token ); token = COM_Parse( &text_p ); if( !*token ) break; animations[ i ].numFrames = atoi( token ); animations[ i ].reversed = qfalse; animations[ i ].flipflop = qfalse; // if numFrames is negative the animation is reversed if( animations[ i ].numFrames < 0 ) { animations[ i ].numFrames = -animations[ i ].numFrames; animations[ i ].reversed = qtrue; } token = COM_Parse( &text_p ); if ( !*token ) break; animations[i].loopFrames = atoi( token ); token = COM_Parse( &text_p ); if( !*token ) break; fps = atof( token ); if( fps == 0 ) fps = 1; animations[ i ].frameLerp = 1000 / fps; animations[ i ].initialLerp = 1000 / fps; } if( i != MAX_BUILDABLE_ANIMATIONS ) { CG_Printf( "Error parsing animation file: %s\n", filename ); return qfalse; } return qtrue; }
/* ======================= UI_CalcPostGameStats ======================= */ static void UI_CalcPostGameStats() { char map[MAX_QPATH]; char fileName[MAX_QPATH]; char info[MAX_INFO_STRING]; fileHandle_t f; int size, game, time, adjustedTime; postGameInfo_t oldInfo; postGameInfo_t newInfo; qboolean newHigh = qfalse; trap_GetConfigString( CS_SERVERINFO, info, sizeof(info) ); Q_strncpyz( map, Info_ValueForKey( info, "mapname" ), sizeof(map) ); game = atoi(Info_ValueForKey(info, "g_gametype")); // compose file name Com_sprintf(fileName, MAX_QPATH, "games/%s_%i.game", map, game); // see if we have one already memset(&oldInfo, 0, sizeof(postGameInfo_t)); if (trap_FS_FOpenFile(fileName, &f, FS_READ) >= 0) { // if so load it size = 0; trap_FS_Read(&size, sizeof(int), f); if (size == sizeof(postGameInfo_t)) { trap_FS_Read(&oldInfo, sizeof(postGameInfo_t), f); } trap_FS_FCloseFile(f); } newInfo.accuracy = atoi(UI_Argv(3)); newInfo.impressives = atoi(UI_Argv(4)); newInfo.excellents = atoi(UI_Argv(5)); newInfo.defends = atoi(UI_Argv(6)); newInfo.assists = atoi(UI_Argv(7)); newInfo.gauntlets = atoi(UI_Argv(8)); newInfo.baseScore = atoi(UI_Argv(9)); newInfo.perfects = atoi(UI_Argv(10)); newInfo.redScore = atoi(UI_Argv(11)); newInfo.blueScore = atoi(UI_Argv(12)); time = atoi(UI_Argv(13)); newInfo.captures = atoi(UI_Argv(14)); newInfo.time = (time - trap_Cvar_VariableValue("ui_matchStartTime")) / 1000; adjustedTime = uiInfo.mapList[ui_currentMap.integer].timeToBeat[game]; if (newInfo.time < adjustedTime) { newInfo.timeBonus = (adjustedTime - newInfo.time) * 10; } else { newInfo.timeBonus = 0; } if (newInfo.redScore > newInfo.blueScore && newInfo.blueScore <= 0) { newInfo.shutoutBonus = 100; } else { newInfo.shutoutBonus = 0; } newInfo.skillBonus = trap_Cvar_VariableValue("g_spSkill"); if (newInfo.skillBonus <= 0) { newInfo.skillBonus = 1; } newInfo.score = newInfo.baseScore + newInfo.shutoutBonus + newInfo.timeBonus; newInfo.score *= newInfo.skillBonus; // see if the score is higher for this one newHigh = (qboolean)(newInfo.redScore > newInfo.blueScore && newInfo.score > oldInfo.score); if (newHigh) { // if so write out the new one uiInfo.newHighScoreTime = uiInfo.uiDC.realTime + 20000; if (trap_FS_FOpenFile(fileName, &f, FS_WRITE) >= 0) { size = sizeof(postGameInfo_t); trap_FS_Write(&size, sizeof(int), f); trap_FS_Write(&newInfo, sizeof(postGameInfo_t), f); trap_FS_FCloseFile(f); } } if (newInfo.time < oldInfo.time) { uiInfo.newBestTime = uiInfo.uiDC.realTime + 20000; } // put back all the ui overrides trap_Cvar_Set("capturelimit", UI_Cvar_VariableString("ui_saveCaptureLimit")); trap_Cvar_Set("fraglimit", UI_Cvar_VariableString("ui_saveFragLimit")); trap_Cvar_Set("duel_fraglimit", UI_Cvar_VariableString("ui_saveDuelLimit")); trap_Cvar_Set("cg_drawTimer", UI_Cvar_VariableString("ui_drawTimer")); trap_Cvar_Set("g_doWarmup", UI_Cvar_VariableString("ui_doWarmup")); trap_Cvar_Set("g_Warmup", UI_Cvar_VariableString("ui_Warmup")); trap_Cvar_Set("sv_pure", UI_Cvar_VariableString("ui_pure")); trap_Cvar_Set("g_friendlyFire", UI_Cvar_VariableString("ui_friendlyFire")); UI_SetBestScores(&newInfo, qtrue); UI_ShowPostGame(newHigh); }
void CG_LoadHolsterData (clientInfo_t *ci) {//adjusts the manual holster positional data based on the holster.cfg file associated with the model or simply //use the default values int i; fileHandle_t f; int fLen = 0; char fileBuffer[MAX_HOLSTER_INFO_SIZE]; char holsterTypeValue[MAX_QPATH]; char holsterTypeGroup[MAX_HOLSTER_INFO_SIZE]; char *s; vec3_t vectorData; InitHolsterData(ci); if ( !ci->skinName || !Q_stricmp( "default", ci->skinName ) ) {//try default holster.cfg first fLen = trap_FS_FOpenFile(va("models/players/%s/holster.cfg", ci->modelName), &f, FS_READ); if( !f ) {//no file, use kyle's then. fLen = trap_FS_FOpenFile("models/players/kyle/holster.cfg", &f, FS_READ); } } else {//use the holster.cfg associated with this skin fLen = trap_FS_FOpenFile(va("models/players/%s/holster_%s.cfg", ci->modelName, ci->skinName), &f, FS_READ); if ( !f ) {//fall back to default holster.cfg fLen = trap_FS_FOpenFile(va("models/players/%s/holster.cfg", ci->modelName), &f, FS_READ); } if( !f ) {//still no dice, use kyle's then. fLen = trap_FS_FOpenFile("models/players/kyle/holster.cfg", &f, FS_READ); } } if ( !f || !fLen ) {//couldn't open file or it was empty, just use the defaults return; } if( fLen >= MAX_HOLSTER_INFO_SIZE ) { CG_Printf("Error: holster.cfg for %s is over the holster.cfg filesize limit.\n", ci->modelName); trap_FS_FCloseFile( f ); return; } trap_FS_Read(fileBuffer, fLen, f); trap_FS_FCloseFile( f ); s = fileBuffer; //parse file while( (s = BG_GetNextValueGroup(s, holsterTypeGroup)) != NULL ) { if( !BG_SiegeGetPairedValue(holsterTypeGroup, "holsterType", holsterTypeValue) ) {//couldn't find holster type in group CG_Printf("Error: The holster.cfg for %s appears to be missing a holsterType in one of its define groups.\n", ci->modelName); continue; } i = GetIDForString(holsterTypeTable, holsterTypeValue); if( i == -1 ) {//bad holster type CG_Printf("Error: The holster.cfg for %s has a bad holsterType in one of the define groups.\n", ci->modelName); continue; } if( BG_SiegeGetPairedValue(holsterTypeGroup, "boneIndex", holsterTypeValue) ) {//have bone index data for this holster type, use it if(!Q_stricmp(holsterTypeValue, "disabled") ) {//disable the rendering of this holster type on this model ci->holsterData[i].boneIndex = HOLSTER_NONE; } else { ci->holsterData[i].boneIndex = GetIDForString(holsterBoneTable, holsterTypeValue); } } if( BG_SiegeGetPairedValue(holsterTypeGroup, "posOffset", holsterTypeValue) ) {//parsing positional offset data sscanf (holsterTypeValue, "%f, %f, %f", &vectorData[0], &vectorData[1], &vectorData[2]); VectorCopy(vectorData, ci->holsterData[i].posOffset); //&ci->holsterData[i].posOffset[0], &ci->holsterData[i].posOffset[1], //&ci->holsterData[i].posOffset[2]); } if( BG_SiegeGetPairedValue(holsterTypeGroup, "angOffset", holsterTypeValue) ) {//parsing angular offset sscanf (holsterTypeValue, "%f, %f, %f", &vectorData[0], &vectorData[1], &vectorData[2]); VectorCopy(vectorData, ci->holsterData[i].angOffset); } } #ifdef _DEBUG CG_Printf("Holstered Weapon Data Loaded for %s.\n", ci->modelName); #endif }
/* ====================== UI_ParseAnimationFile ====================== */ static qboolean UI_ParseAnimationFile( const char *filename, playerInfo_t *pi ) { char *text_p, *prev; int len; int i; char *token; float fps; int skip; char text[20000]; fileHandle_t f; token = NULL; i = 0; fps = 0; prev = 0; memset( pi->animations, 0, sizeof( animation_t ) * MAX_ANIMATIONS ); // load the file len = trap_FS_FOpenFile( filename, &f, FS_READ ); if ( len <= 0 ) { return qfalse; } if ( len >= ( sizeof( text ) - 1 ) ) { Com_Printf( "File %s too long\n", filename ); return qfalse; } trap_FS_Read( text, len, f ); text[len] = 0; trap_FS_FCloseFile( f ); // parse the text text_p = text; skip = 0; // quite the compiler warning // NERVE - SMF - new!!!! AnimParseAnimConfig( pi, filename, text ); return qtrue; // -NERVE - SMF - This does not work with wolf's new animation system /* // read optional parameters while ( 1 ) { prev = text_p; // so we can unget token = COM_Parse( &text_p ); if ( !token ) { break; } if ( !Q_stricmp( token, "footsteps" ) ) { token = COM_Parse( &text_p ); if ( !token ) { break; } continue; } else if ( !Q_stricmp( token, "headoffset" ) ) { for ( i = 0 ; i < 3 ; i++ ) { token = COM_Parse( &text_p ); if ( !token ) { break; } } continue; } else if ( !Q_stricmp( token, "sex" ) ) { token = COM_Parse( &text_p ); if ( !token ) { break; } continue; } // if it is a number, start parsing animations if ( token[0] >= '0' && token[0] <= '9' ) { text_p = prev; // unget the token break; } Com_Printf( "unknown token '%s' is %s\n", token, filename ); } // read information for each frame for ( i = 0 ; i < MAX_ANIMATIONS ; i++ ) { token = COM_Parse( &text_p ); if ( !token ) { break; } animations[i].firstFrame = atoi( token ); // leg only frames are adjusted to not count the upper body only frames if ( i == LEGS_WALKCR ) { skip = animations[LEGS_WALKCR].firstFrame - animations[TORSO_GESTURE].firstFrame; } if ( i >= LEGS_WALKCR ) { animations[i].firstFrame -= skip; } token = COM_Parse( &text_p ); if ( !token ) { break; } animations[i].numFrames = atoi( token ); token = COM_Parse( &text_p ); if ( !token ) { break; } animations[i].loopFrames = atoi( token ); token = COM_Parse( &text_p ); if ( !token ) { break; } fps = atof( token ); if ( fps == 0 ) { fps = 1; } animations[i].frameLerp = 1000 / fps; animations[i].initialLerp = 1000 / fps; } if ( i != MAX_ANIMATIONS ) { Com_Printf( "Error parsing animation file: %s", filename ); return qfalse; } return qtrue; */ }
static void G_AddBot( const char *name, int skill, const char *team, const char *spawnPoint, int playerClass, int playerWeapon, int characerIndex, const char *respawn, const char *scriptName, int rank, int skills[], qboolean pow ) { #define MAX_BOTNAMES 1024 int clientNum; char *botinfo; gentity_t *bot; char *key; char *s; char *botname; // char *model; char userinfo[MAX_INFO_STRING]; // get the botinfo from bots.txt // CHRUKER: b070 - Was 'wolfbot' but this must match in case botinfo = G_GetBotInfoByName( "Wolfbot" ); if ( !botinfo ) { G_Printf( S_COLOR_RED "Error: Bot '%s' not defined\n", name ); return; } // create the bot's userinfo userinfo[0] = '\0'; botname = Info_ValueForKey( botinfo, "funname" ); if( !botname[0] ) { botname = Info_ValueForKey( botinfo, "name" ); } Info_SetValueForKey( userinfo, "name", botname ); Info_SetValueForKey( userinfo, "rate", "25000" ); Info_SetValueForKey( userinfo, "snaps", "20" ); Info_SetValueForKey( userinfo, "skill", va("%i", skill) ); s = Info_ValueForKey(botinfo, "aifile"); if (!*s ) { trap_Printf( S_COLOR_RED "Error: bot has no aifile specified\n" ); return; } // have the server allocate a client slot clientNum = trap_BotAllocateClient( 0 ); // Arnout: 0 means no prefered clientslot if ( clientNum == -1 ) { G_Printf( S_COLOR_RED "Unable to add bot. All player slots are in use.\n" ); G_Printf( S_COLOR_RED "Start server with more 'open' slots (or check setting of sv_maxclients cvar).\n" ); return; } // initialize the bot settings if( !team || !*team ) { if( PickTeam(clientNum) == TEAM_AXIS) { team = "red"; } else { team = "blue"; } } Info_SetValueForKey( userinfo, "characterfile", Info_ValueForKey( botinfo, "aifile" ) ); //Info_SetValueForKey( userinfo, "skill", va( "%i", skill ) ); Info_SetValueForKey( userinfo, "team", team ); if( spawnPoint && spawnPoint[0] ) { Info_SetValueForKey( userinfo, "spawnPoint", spawnPoint ); } if (scriptName && scriptName[0]) { Info_SetValueForKey( userinfo, "scriptName", scriptName ); } /* if (playerClass > 0) { Info_SetValueForKey( userinfo, "pClass", va("%i", playerClass) ); } if (playerWeapon) { Info_SetValueForKey( userinfo, "pWeapon", va("%i", playerWeapon) ); }*/ // END Mad Doc - TDF key = "wolfbot"; if (!Q_stricmp( (char *)name, key )) { // read the botnames file, and pick a name that doesnt exist fileHandle_t f; int len, i, j, k; qboolean setname = qfalse; char botnames[8192], *pbotnames, *listbotnames[MAX_BOTNAMES], *token, *oldpbotnames; int lengthbotnames[MAX_BOTNAMES]; len = trap_FS_FOpenFile( "botfiles/botnames.txt", &f, FS_READ ); if (len >= 0) { if (len > sizeof(botnames)) { G_Error( "botfiles/botnames.txt is too big (max = %i)", (int)sizeof(botnames) ); } memset( botnames, 0, sizeof(botnames) ); trap_FS_Read( botnames, len, f ); pbotnames = botnames; // read them in i = 0; oldpbotnames = pbotnames; while ((token = COM_Parse( &pbotnames ))) { if (!token[0]) break; listbotnames[i] = strstr( oldpbotnames, token ); lengthbotnames[i] = strlen(token); listbotnames[i][lengthbotnames[i]] = 0; oldpbotnames = pbotnames; if (++i == MAX_BOTNAMES) break; } // if (i > 2) { j = rand() % (i-1); // start at a random spot inthe list for( k = j + 1; k != j; k++ ) { if( k == i ) { k = -1; // gets increased on next loop continue; } if (ClientFromName( listbotnames[k] ) == -1) { // found an unused name Info_SetValueForKey( userinfo, "name", listbotnames[k] ); setname = qtrue; break; } } } // trap_FS_FCloseFile( f ); } if (!setname) { Info_SetValueForKey( userinfo, "name", va("wolfbot_%i", clientNum+1) ); } } else { Info_SetValueForKey( userinfo, "name", name ); } // if a character was specified, put the index of that character filename in the CS_CHARACTERS table in the userinfo if( characerIndex != -1 ) { Info_SetValueForKey( userinfo, "ch", va( "%i", characerIndex ) ); } // if a rank was specified, use that /* if (rank != -1) { Info_SetValueForKey(userinfo, "rank", va("%i", rank)); }*/ // END Mad Doc - TDF bot = &g_entities[ clientNum ]; bot->r.svFlags |= SVF_BOT; if( pow ) { bot->r.svFlags |= SVF_POW; } bot->inuse = qtrue; bot->aiName = bot->client->pers.netname; // register the userinfo trap_SetUserinfo( clientNum, userinfo ); // have it connect to the game as a normal client if ((s = ClientConnect( clientNum, qtrue, qtrue ))) { G_Printf( S_COLOR_RED "Unable to add bot: %s\n", s ); return; } SetTeam( bot, (char *)team, qtrue, -1, -1, qfalse ); /* if( skills ) { int i; for( i = 0; i < SK_NUM_SKILLS; i++ ) { bot->client->sess.skill[i] = skills[i]; } }*/ return; }
/* ================= CG_ParseVoiceChats ================= */ int CG_ParseVoiceChats( const char *filename, voiceChatList_t *voiceChatList, int maxVoiceChats ) { int len, i; fileHandle_t f; char buf[MAX_VOICEFILESIZE]; char **p, *ptr; char *token; voiceChat_t *voiceChats; qboolean compress; sfxHandle_t sound; compress = qtrue; if (cg_buildScript.integer) { compress = qfalse; } len = trap_FS_FOpenFile( filename, &f, FS_READ ); if ( !f ) { trap_Print( va( S_COLOR_RED "voice chat file not found: %s\n", filename ) ); return qfalse; } if ( len >= MAX_VOICEFILESIZE ) { trap_Print( va( S_COLOR_RED "voice chat file too large: %s is %i, max allowed is %i\n", filename, len, MAX_VOICEFILESIZE ) ); trap_FS_FCloseFile( f ); return qfalse; } trap_FS_Read( buf, len, f ); buf[len] = 0; trap_FS_FCloseFile( f ); ptr = buf; p = &ptr; Com_sprintf(voiceChatList->name, sizeof(voiceChatList->name), "%s", filename); voiceChats = voiceChatList->voiceChats; for ( i = 0; i < maxVoiceChats; i++ ) { voiceChats[i].id[0] = 0; } token = COM_ParseExt(p, qtrue); if (!token[0]) { return qtrue; } if (!Q_stricmp(token, "female")) { voiceChatList->gender = GENDER_FEMALE; } else if (!Q_stricmp(token, "male")) { voiceChatList->gender = GENDER_MALE; } else if (!Q_stricmp(token, "neuter")) { voiceChatList->gender = GENDER_NEUTER; } else { trap_Print( va( S_COLOR_RED "expected gender not found in voice chat file: %s\n", filename ) ); return qfalse; } voiceChatList->numVoiceChats = 0; while ( 1 ) { token = COM_ParseExt(p, qtrue); if (!token[0]) { return qtrue; } Com_sprintf(voiceChats[voiceChatList->numVoiceChats].id, sizeof( voiceChats[voiceChatList->numVoiceChats].id ), "%s", token); token = COM_ParseExt(p, qtrue); if (Q_stricmp(token, "{")) { trap_Print( va( S_COLOR_RED "expected { found %s in voice chat file: %s\n", token, filename ) ); return qfalse; } voiceChats[voiceChatList->numVoiceChats].numSounds = 0; while(1) { token = COM_ParseExt(p, qtrue); if (!token[0]) { return qtrue; } if (!Q_stricmp(token, "}")) break; sound = trap_S_RegisterSound( token, compress ); voiceChats[voiceChatList->numVoiceChats].sounds[voiceChats[voiceChatList->numVoiceChats].numSounds] = sound; token = COM_ParseExt(p, qtrue); if (!token[0]) { return qtrue; } Com_sprintf(voiceChats[voiceChatList->numVoiceChats].chats[ voiceChats[voiceChatList->numVoiceChats].numSounds], MAX_CHATSIZE, "%s", token); if (sound) voiceChats[voiceChatList->numVoiceChats].numSounds++; if (voiceChats[voiceChatList->numVoiceChats].numSounds >= MAX_VOICESOUNDS) break; } voiceChatList->numVoiceChats++; if (voiceChatList->numVoiceChats >= maxVoiceChats) return qtrue; } return qtrue; }
void BotUtilizePersonality(bot_state_t *bs) { fileHandle_t f; int len, rlen; int failed; int i; //char buf[131072]; char *readbuf, *group; len = trap_FS_FOpenFile(bs->settings.personalityfile, &f, FS_READ); failed = 0; if (!f) { G_Printf(S_COLOR_RED "Error: Specified personality not found\n"); return; } char *buf = (char *)B_TempAlloc(len + 1); trap_FS_Read(buf, len, f); buf[len] = 0; readbuf = (char *)B_TempAlloc(1024); group = (char *)B_TempAlloc(len); if (!GetValueGroup(buf, "GeneralBotInfo", group)) { G_Printf(S_COLOR_RED "Personality file contains no GeneralBotInfo group\n"); failed = 1; //set failed so we know to set everything to default values } if (!failed && GetPairedValue(group, "reflex", readbuf)) { bs->skills.reflex = atoi(readbuf); } else { bs->skills.reflex = 100; //default } if (!failed && GetPairedValue(group, "accuracy", readbuf)) { bs->skills.accuracy = atof(readbuf); } else { bs->skills.accuracy = 10; //default } if (!failed && GetPairedValue(group, "turnspeed", readbuf)) { bs->skills.turnspeed = atof(readbuf); } else { bs->skills.turnspeed = 0.01f; //default } if (!failed && GetPairedValue(group, "turnspeed_combat", readbuf)) { bs->skills.turnspeed_combat = atof(readbuf); } else { bs->skills.turnspeed_combat = 0.05f; //default } if (!failed && GetPairedValue(group, "maxturn", readbuf)) { bs->skills.maxturn = atof(readbuf); } else { bs->skills.maxturn = 360; //default } if (!failed && GetPairedValue(group, "perfectaim", readbuf)) { bs->skills.perfectaim = atoi(readbuf); } else { bs->skills.perfectaim = 0; //default } /* if (!failed && GetPairedValue(group, "chatability", readbuf)) { bs->canChat = atoi(readbuf); } else { bs->canChat = 0; //default } if (!failed && GetPairedValue(group, "chatfrequency", readbuf)) { bs->chatFrequency = atoi(readbuf); } else { bs->chatFrequency = 5; //default } */ if (!failed && GetPairedValue(group, "hatelevel", readbuf)) { bs->loved_death_thresh = atoi(readbuf); } else { bs->loved_death_thresh = 3; //default } if (!failed && GetPairedValue(group, "camper", readbuf)) { bs->isCamper = atoi(readbuf); } else { bs->isCamper = 0; //default } if (!failed && GetPairedValue(group, "saberspecialist", readbuf)) { bs->saberSpecialist = atoi(readbuf); } else { bs->saberSpecialist = 0; //default } if (!failed && GetPairedValue(group, "forceinfo", readbuf)) { Com_sprintf(bs->forceinfo, sizeof(bs->forceinfo), "%s\0", readbuf); } else { Com_sprintf(bs->forceinfo, sizeof(bs->forceinfo), "%s\0", DEFAULT_FORCEPOWERS); } i = 0; /* while (i < MAX_CHAT_BUFFER_SIZE) { //clear out the chat buffer for this bot gBotChatBuffer[bs->client][i] = '\0'; i++; } if (bs->canChat) { if (!ReadChatGroups(bs, buf)) { bs->canChat = 0; } } */ if (GetValueGroup(buf, "BotWeaponWeights", group)) { if (GetPairedValue(group, "WP_STUN_BATON", readbuf)) { bs->botWeaponWeights[WP_STUN_BATON] = atoi(readbuf); bs->botWeaponWeights[WP_MELEE] = bs->botWeaponWeights[WP_STUN_BATON]; } if (GetPairedValue(group, "WP_SABER", readbuf)) { bs->botWeaponWeights[WP_SABER] = atoi(readbuf); } if (GetPairedValue(group, "WP_BRYAR_PISTOL", readbuf)) { bs->botWeaponWeights[WP_BRYAR_PISTOL] = atoi(readbuf); } if (GetPairedValue(group, "WP_BLASTER", readbuf)) { bs->botWeaponWeights[WP_BLASTER] = atoi(readbuf); } if (GetPairedValue(group, "WP_DISRUPTOR", readbuf)) { bs->botWeaponWeights[WP_DISRUPTOR] = atoi(readbuf); } if (GetPairedValue(group, "WP_BOWCASTER", readbuf)) { bs->botWeaponWeights[WP_BOWCASTER] = atoi(readbuf); } if (GetPairedValue(group, "WP_REPEATER", readbuf)) { bs->botWeaponWeights[WP_REPEATER] = atoi(readbuf); } if (GetPairedValue(group, "WP_DEMP2", readbuf)) { bs->botWeaponWeights[WP_DEMP2] = atoi(readbuf); } if (GetPairedValue(group, "WP_FLECHETTE", readbuf)) { bs->botWeaponWeights[WP_FLECHETTE] = atoi(readbuf); } if (GetPairedValue(group, "WP_ROCKET_LAUNCHER", readbuf)) { bs->botWeaponWeights[WP_ROCKET_LAUNCHER] = atoi(readbuf); } if (GetPairedValue(group, "WP_THERMAL", readbuf)) { bs->botWeaponWeights[WP_THERMAL] = atoi(readbuf); } if (GetPairedValue(group, "WP_TRIP_MINE", readbuf)) { bs->botWeaponWeights[WP_TRIP_MINE] = atoi(readbuf); } if (GetPairedValue(group, "WP_DET_PACK", readbuf)) { bs->botWeaponWeights[WP_DET_PACK] = atoi(readbuf); } } bs->lovednum = 0; if (GetValueGroup(buf, "EmotionalAttachments", group)) { ParseEmotionalAttachments(bs, group); } B_TempFree(len + 1); //buf B_TempFree(1024); //readbuf B_TempFree(len); //group trap_FS_FCloseFile(f); }
//=========================================================================== // Routine : AOTCTC_Holocron_Loadpositions // Description : Loads holocron positions from .hpf file on disk void AOTCTC_Holocron_Loadpositions( void ) {// Does each online player's data. char *s, *t; int len; fileHandle_t f; char *buf; //[DynamicMemoryTweaks] char loadPath[MAX_QPATH]; //[/DynamicMemoryTweaks] int statnum = 0; float stats[50*3]; // 1 extra. int holocron_number = 0; //[RawMapName] //vmCvar_t mapname; //[/RawMapName] G_Printf("^5Loading holocron position table..."); //[RawMapName] //loadPath = (char *)B_TempAlloc(1024*4); //trap_Cvar_Register( &mapname, "mapname", "", CVAR_SERVERINFO | CVAR_ROM ); //Com_sprintf(loadPath, 1024*4, "holocron_positions/%s.hpf\0", mapname.string); Com_sprintf(loadPath, sizeof(loadPath), "holocron_positions/%s.hpf", level.rawmapname); //[/RawMapName] len = trap_FS_FOpenFile( loadPath, &f, FS_READ ); if ( !f ) { G_Printf(" ^3FAILED!!!\n"); G_Printf("^5No file exists! (^3%s^5)\n", loadPath); return; } if ( !len ) { //empty file G_Printf(" ^3FAILED!!!\n"); G_Printf("^5Empty file!\n"); trap_FS_FCloseFile( f ); return; } if ( (buf = BG_TempAlloc(len+1)) == 0 ) {//alloc memory for buffer G_Printf(" ^3FAILED!!!\n"); G_Printf("^5Unable to allocate buffer.\n"); return; } trap_FS_Read( buf, len, f ); trap_FS_FCloseFile( f ); for (t = s = buf; *t; /* */ ) { s = strchr(s, ' '); if (!s) break; while (*s == ' ') *s++ = 0; if (*t) { if (statnum == 0) { number_of_holocronpositions = atoi(t); if (number_of_holocronpositions <= 18) { G_Printf(" ^3FAILED!!!\n"); G_Printf("^5You need at least 18 holocron points!\n"); return; } } stats[statnum] = (float)atof(t); statnum++; } t = s; } statnum = 1; while (holocron_number < number_of_holocronpositions) { int reference = 0; while (reference <= 2) { holocrons[holocron_number].origin[reference] = stats[statnum]; statnum++; reference++; } holocron_number++; } BG_TempFree(len+1); G_Printf(" ^3Completed OK.\n"); G_Printf("^5Total Holocron Positions: ^7%i^5.\n", number_of_holocronpositions); holocrons_loaded = qtrue; }