/* ** GLimp_Init ** ** This is the platform specific OpenGL initialization function. It ** is responsible for loading OpenGL, initializing it, setting ** extensions, creating a window of the appropriate size, doing ** fullscreen manipulations, etc. Its overall responsibility is ** to make sure that a functional OpenGL subsystem is operating ** when it returns to the ref. */ void GLimp_Init( void ) { char buf[1024]; cvar_t *lastValidRenderer = ri.Cvar_Get( "r_lastValidRenderer", "(uninitialized)", CVAR_ARCHIVE ); cvar_t *cv; ri.Printf( PRINT_ALL, "Initializing OpenGL subsystem\n" ); // // check OS version to see if we can do fullscreen display changes // if ( !GLW_CheckOSVersion() ) { ri.Error( ERR_VID_FATAL, "GLimp_Init() - incorrect operating system\n" ); } // save off hInstance and wndproc cv = ri.Cvar_Get( "win_hinstance", "", 0 ); sscanf( cv->string, "%i", (int *)&g_wv.hInstance ); cv = ri.Cvar_Get( "win_wndproc", "", 0 ); sscanf( cv->string, "%i", (int *)&glw_state.wndproc ); r_allowSoftwareGL = ri.Cvar_Get( "r_allowSoftwareGL", "0", CVAR_LATCH ); r_maskMinidriver = ri.Cvar_Get( "r_maskMinidriver", "0", CVAR_LATCH ); // load appropriate DLL and initialize subsystem GLW_StartOpenGL(); // get our config strings Q_strncpyz( glConfig.vendor_string, qglGetString( GL_VENDOR ), sizeof( glConfig.vendor_string ) ); Q_strncpyz( glConfig.renderer_string, qglGetString( GL_RENDERER ), sizeof( glConfig.renderer_string ) ); Q_strncpyz( glConfig.version_string, qglGetString( GL_VERSION ), sizeof( glConfig.version_string ) ); Q_strncpyz( glConfig.extensions_string, qglGetString( GL_EXTENSIONS ), sizeof( glConfig.extensions_string ) ); // TTimo - safe check if ( strlen( qglGetString( GL_EXTENSIONS ) ) >= sizeof( glConfig.extensions_string ) ) { Com_Printf( S_COLOR_YELLOW "WARNNING: GL extensions string too long (%d), truncated to %d\n", strlen( qglGetString( GL_EXTENSIONS ) ), sizeof( glConfig.extensions_string ) ); } // // chipset specific configuration // Q_strncpyz( buf, glConfig.renderer_string, sizeof( buf ) ); Q_strlwr( buf ); // // NOTE: if changing cvars, do it within this block. This allows them // to be overridden when testing driver fixes, etc. but only sets // them to their default state when the hardware is first installed/run. // if ( Q_stricmp( lastValidRenderer->string, glConfig.renderer_string ) ) { glConfig.hardwareType = GLHW_GENERIC; ri.Cvar_Set( "r_textureMode", "GL_LINEAR_MIPMAP_NEAREST" ); // VOODOO GRAPHICS w/ 2MB if ( strstr( buf, "voodoo graphics/1 tmu/2 mb" ) ) { ri.Cvar_Set( "r_picmip", "2" ); ri.Cvar_Get( "r_picmip", "1", CVAR_ARCHIVE | CVAR_LATCH ); } else { //----(SA) FIXME: RETURN TO DEFAULT Another id build change for DK/DM ri.Cvar_Set( "r_picmip", "1" ); //----(SA) was "1" // JPW NERVE back to 1 //----(SA) if ( strstr( buf, "rage 128" ) || strstr( buf, "rage128" ) ) { ri.Cvar_Set( "r_finish", "0" ); } // Savage3D and Savage4 should always have trilinear enabled else if ( strstr( buf, "savage3d" ) || strstr( buf, "s3 savage4" ) ) { ri.Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" ); } } } // // this is where hardware specific workarounds that should be // detected/initialized every startup should go. // if ( strstr( buf, "banshee" ) || strstr( buf, "voodoo3" ) ) { glConfig.hardwareType = GLHW_3DFX_2D3D; } // VOODOO GRAPHICS w/ 2MB else if ( strstr( buf, "voodoo graphics/1 tmu/2 mb" ) ) { } else if ( strstr( buf, "glzicd" ) ) { } else if ( strstr( buf, "rage pro" ) /*|| strstr( buf, "Rage Pro")*/ || strstr( buf, "ragepro" ) ) { glConfig.hardwareType = GLHW_RAGEPRO; ri.Printf( PRINT_WARNING, "WARNING: Rage Pro hardware is unsupported. Rendering errors may occur.\n" ); } else if ( strstr( buf, "rage 128" ) ) { } else if ( strstr( buf, "permedia2" ) ) { glConfig.hardwareType = GLHW_PERMEDIA2; ri.Printf( PRINT_WARNING, "WARNING: Permedia hardware is unsupported. Rendering errors may occur.\n" ); } else if ( strstr( buf, "riva 128" ) ) { glConfig.hardwareType = GLHW_RIVA128; ri.Printf( PRINT_WARNING, "WARNING: Riva 128 hardware is unsupported. Rendering errors may occur.\n" ); } else if ( strstr( buf, "matrox" ) ) { } else if ( strstr( buf, "riva tnt " ) ) { } if ( strstr( buf, "geforce3" ) || strstr( buf, "geforce4 ti" ) || strstr( buf, "geforce fx 5600" ) || strstr( buf, "geforce fx 5800" ) || strstr( buf, "radeon 8500" ) || strstr( buf, "radeon 9000" ) || strstr( buf, "radeon 9500" ) || strstr( buf, "radeon 9600" ) || strstr( buf, "radeon 9700" ) || strstr( buf, "radeon 9800" ) || strstr( buf, "nv20" ) || strstr( buf, "nv30" ) ) { ri.Cvar_Set( "r_highQualityVideo", "1" ); } else { ri.Cvar_Set( "r_highQualityVideo", "0" ); } ri.Cvar_Set( "r_lastValidRenderer", glConfig.renderer_string ); GLW_InitExtensions(); WG_CheckHardwareGamma(); // initialise default lists GLW_GenDefaultLists(); }
/* ==================== RE_RegisterModel Loads in a model for the given name Zero will be returned if the model fails to load. An entry will be retained for failed models as an optimization to prevent disk rescanning if they are asked for again. ==================== */ qhandle_t RE_RegisterModel( const char *name ) { model_t *mod; unsigned *buffer; int bufferLen = 0; int lod; int ident; qboolean loaded; qhandle_t hModel; int numLoaded; if ( !name || !name[ 0 ] ) { ri.Printf( PRINT_ALL, "RE_RegisterModel: NULL name\n" ); return 0; } if ( strlen( name ) >= MAX_QPATH ) { Com_Printf( "Model name exceeds MAX_QPATH\n" ); return 0; } // search the currently loaded models for ( hModel = 1; hModel < tr.numModels; hModel++ ) { mod = tr.models[ hModel ]; if ( !strcmp( mod->name, name ) ) { if ( mod->type == MOD_BAD ) { return 0; } return hModel; } } // allocate a new model_t if ( ( mod = R_AllocModel() ) == NULL ) { ri.Printf( PRINT_WARNING, "RE_RegisterModel: R_AllocModel() failed for '%s'\n", name ); return 0; } // only set the name after the model has been successfully loaded Q_strncpyz( mod->name, name, sizeof( mod->name ) ); // make sure the render thread is stopped R_SyncRenderThread(); mod->numLods = 0; // load the files numLoaded = 0; #if defined( COMPAT_ET ) if ( strstr( name, ".mds" ) || strstr( name, ".mdm" ) || strstr( name, ".mdx" ) || strstr( name, ".md5mesh" ) || strstr( name, ".psk" ) ) #else if ( strstr( name, ".md5mesh" ) || strstr( name, ".psk" ) ) #endif { // try loading skeletal file loaded = qfalse; bufferLen = ri.FS_ReadFile( name, ( void ** ) &buffer ); if ( buffer ) { loadmodel = mod; ident = LittleLong( * ( unsigned * ) buffer ); #if defined( COMPAT_ET ) #if 0 if ( ident == MDS_IDENT ) { loaded = R_LoadMDS( mod, buffer, name ); } else #endif if ( ident == MDM_IDENT ) { loaded = R_LoadMDM( mod, buffer, name ); } else if ( ident == MDX_IDENT ) { loaded = R_LoadMDX( mod, buffer, name ); } #endif #if defined( USE_REFENTITY_ANIMATIONSYSTEM ) if ( !Q_stricmpn( ( const char * ) buffer, "MD5Version", 10 ) ) { loaded = R_LoadMD5( mod, buffer, bufferLen, name ); } else if ( !Q_stricmpn( ( const char * ) buffer, PSK_IDENTSTRING, PSK_IDENTLEN ) ) { loaded = R_LoadPSK( mod, buffer, bufferLen, name ); } #endif ri.FS_FreeFile( buffer ); } if ( loaded ) { // make sure the VBO glState entries are save R_BindNullVBO(); R_BindNullIBO(); return mod->index; } } for ( lod = MD3_MAX_LODS - 1; lod >= 0; lod-- ) { char filename[ 1024 ]; strcpy( filename, name ); if ( lod != 0 ) { char namebuf[ 80 ]; if ( strrchr( filename, '.' ) ) { *strrchr( filename, '.' ) = 0; } sprintf( namebuf, "_%d.md3", lod ); strcat( filename, namebuf ); } filename[ strlen( filename ) - 1 ] = '3'; // try MD3 first ri.FS_ReadFile( filename, ( void ** ) &buffer ); if ( !buffer ) { filename[ strlen( filename ) - 1 ] = 'c'; // try MDC second ri.FS_ReadFile( filename, ( void ** ) &buffer ); if ( !buffer ) { continue; } } loadmodel = mod; ident = LittleLong( * ( unsigned * ) buffer ); if ( ident == MD3_IDENT ) { loaded = R_LoadMD3( mod, lod, buffer, bufferLen, name ); ri.FS_FreeFile( buffer ); } #if defined( COMPAT_ET ) else if ( ident == MDC_IDENT ) { loaded = R_LoadMDC( mod, lod, buffer, bufferLen, name ); ri.FS_FreeFile( buffer ); } #endif else { ri.FS_FreeFile( buffer ); ri.Printf( PRINT_WARNING, "RE_RegisterModel: unknown fileid for %s\n", name ); goto fail; } if ( !loaded ) { if ( lod == 0 ) { goto fail; } else { break; } } else { // make sure the VBO glState entries are save R_BindNullVBO(); R_BindNullIBO(); mod->numLods++; numLoaded++; // if we have a valid model and are biased // so that we won't see any higher detail ones, // stop loading them // if ( lod <= r_lodbias->integer ) { // break; // } } } // make sure the VBO glState entries are save R_BindNullVBO(); R_BindNullIBO(); if ( numLoaded ) { // duplicate into higher lod spots that weren't // loaded, in case the user changes r_lodbias on the fly for ( lod--; lod >= 0; lod-- ) { mod->numLods++; mod->mdv[ lod ] = mod->mdv[ lod + 1 ]; } return mod->index; } #ifndef NDEBUG else { ri.Printf( PRINT_WARNING, "couldn't load '%s'\n", name ); } #endif fail: // we still keep the model_t around, so if the model name is asked for // again, we won't bother scanning the filesystem mod->type = MOD_BAD; // make sure the VBO glState entries are save R_BindNullVBO(); R_BindNullIBO(); return 0; }
static qboolean R_LoadMD5Anim( skelAnimation_t *skelAnim, void *buffer, int bufferSize, const char *name ) { int i, j; md5Animation_t *anim; md5Frame_t *frame; md5Channel_t *channel; char *token; int version; char *buf_p; buf_p = buffer; skelAnim->type = AT_MD5; skelAnim->md5 = anim = ri.Hunk_Alloc( sizeof( *anim ), h_low ); // skip MD5Version indent string COM_ParseExt2( &buf_p, qfalse ); // check version token = COM_ParseExt2( &buf_p, qfalse ); version = atoi( token ); if ( version != MD5_VERSION ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: '%s' has wrong version (%i should be %i)\n", name, version, MD5_VERSION ); return qfalse; } // skip commandline <arguments string> token = COM_ParseExt2( &buf_p, qtrue ); token = COM_ParseExt2( &buf_p, qtrue ); // parse numFrames <number> token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "numFrames" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected 'numFrames' found '%s' in model '%s'\n", token, name ); return qfalse; } token = COM_ParseExt2( &buf_p, qfalse ); anim->numFrames = atoi( token ); // parse numJoints <number> token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "numJoints" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected 'numJoints' found '%s' in model '%s'\n", token, name ); return qfalse; } token = COM_ParseExt2( &buf_p, qfalse ); anim->numChannels = atoi( token ); // parse frameRate <number> token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "frameRate" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected 'frameRate' found '%s' in model '%s'\n", token, name ); return qfalse; } token = COM_ParseExt2( &buf_p, qfalse ); anim->frameRate = atoi( token ); // parse numAnimatedComponents <number> token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "numAnimatedComponents" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected 'numAnimatedComponents' found '%s' in model '%s'\n", token, name ); return qfalse; } token = COM_ParseExt2( &buf_p, qfalse ); anim->numAnimatedComponents = atoi( token ); // parse hierarchy { token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "hierarchy" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected 'hierarchy' found '%s' in model '%s'\n", token, name ); return qfalse; } token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, "{" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected '{' found '%s' in model '%s'\n", token, name ); return qfalse; } // parse all the channels anim->channels = ri.Hunk_Alloc( sizeof( md5Channel_t ) * anim->numChannels, h_low ); for ( i = 0, channel = anim->channels; i < anim->numChannels; i++, channel++ ) { token = COM_ParseExt2( &buf_p, qtrue ); Q_strncpyz( channel->name, token, sizeof( channel->name ) ); //ri.Printf(PRINT_ALL, "RE_RegisterAnimation: '%s' has channel '%s'\n", name, channel->name); token = COM_ParseExt2( &buf_p, qfalse ); channel->parentIndex = atoi( token ); if ( channel->parentIndex >= anim->numChannels ) { ri.Error( ERR_DROP, "RE_RegisterAnimation: '%s' has channel '%s' with bad parent index %i while numBones is %i\n", name, channel->name, channel->parentIndex, anim->numChannels ); } token = COM_ParseExt2( &buf_p, qfalse ); channel->componentsBits = atoi( token ); token = COM_ParseExt2( &buf_p, qfalse ); channel->componentsOffset = atoi( token ); } // parse } token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "}" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected '}' found '%s' in model '%s'\n", token, name ); return qfalse; } // parse bounds { token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "bounds" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected 'bounds' found '%s' in model '%s'\n", token, name ); return qfalse; } token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, "{" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected '{' found '%s' in model '%s'\n", token, name ); return qfalse; } anim->frames = ri.Hunk_Alloc( sizeof( md5Frame_t ) * anim->numFrames, h_low ); for ( i = 0, frame = anim->frames; i < anim->numFrames; i++, frame++ ) { // skip ( token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "(" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected '(' found '%s' in model '%s'\n", token, name ); return qfalse; } for ( j = 0; j < 3; j++ ) { token = COM_ParseExt2( &buf_p, qfalse ); frame->bounds[ 0 ][ j ] = atof( token ); } // skip ) token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, ")" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected ')' found '%s' in model '%s'\n", token, name ); return qfalse; } // skip ( token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, "(" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected '(' found '%s' in model '%s'\n", token, name ); return qfalse; } for ( j = 0; j < 3; j++ ) { token = COM_ParseExt2( &buf_p, qfalse ); frame->bounds[ 1 ][ j ] = atof( token ); } // skip ) token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, ")" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected ')' found '%s' in model '%s'\n", token, name ); return qfalse; } } // parse } token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "}" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected '}' found '%s' in model '%s'\n", token, name ); return qfalse; } // parse baseframe { token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "baseframe" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected 'baseframe' found '%s' in model '%s'\n", token, name ); return qfalse; } token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, "{" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected '{' found '%s' in model '%s'\n", token, name ); return qfalse; } for ( i = 0, channel = anim->channels; i < anim->numChannels; i++, channel++ ) { // skip ( token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "(" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected '(' found '%s' in model '%s'\n", token, name ); return qfalse; } for ( j = 0; j < 3; j++ ) { token = COM_ParseExt2( &buf_p, qfalse ); channel->baseOrigin[ j ] = atof( token ); } // skip ) token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, ")" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected ')' found '%s' in model '%s'\n", token, name ); return qfalse; } // skip ( token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, "(" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected '(' found '%s' in model '%s'\n", token, name ); return qfalse; } for ( j = 0; j < 3; j++ ) { token = COM_ParseExt2( &buf_p, qfalse ); channel->baseQuat[ j ] = atof( token ); } QuatCalcW( channel->baseQuat ); // skip ) token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, ")" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected ')' found '%s' in model '%s'\n", token, name ); return qfalse; } } // parse } token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "}" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected '}' found '%s' in model '%s'\n", token, name ); return qfalse; } for ( i = 0, frame = anim->frames; i < anim->numFrames; i++, frame++ ) { // parse frame <number> { token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "frame" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected 'baseframe' found '%s' in model '%s'\n", token, name ); return qfalse; } token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, va( "%i", i ) ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected '%i' found '%s' in model '%s'\n", i, token, name ); return qfalse; } token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, "{" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected '{' found '%s' in model '%s'\n", token, name ); return qfalse; } frame->components = ri.Hunk_Alloc( sizeof( float ) * anim->numAnimatedComponents, h_low ); for ( j = 0; j < anim->numAnimatedComponents; j++ ) { token = COM_ParseExt2( &buf_p, qtrue ); frame->components[ j ] = atof( token ); } // parse } token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "}" ) ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: expected '}' found '%s' in model '%s'\n", token, name ); return qfalse; } } // everything went ok return qtrue; }
/* ============ Cmd_ArgsBuffer The interpreted versions use this because they can't have pointers returned to them ============ */ M_EXPORT void M_DECL Cmd_ArgsBuffer( char *buffer, int bufferLength ) { Q_strncpyz( buffer, Cmd_Args(), bufferLength ); }
/* ========================== UI_RegisterClientModelname ========================== */ qboolean UI_RegisterClientModelname( playerInfo_t *pi, const char *modelSkinName, const char *headModelSkinName, const char *teamName ) { char modelName[MAX_QPATH]; char skinName[MAX_QPATH]; char headModelName[MAX_QPATH]; char headSkinName[MAX_QPATH]; char filename[MAX_QPATH]; char *slash; pi->torsoModel = 0; pi->headModel = 0; if ( !modelSkinName[0] ) { return qfalse; } Q_strncpyz( modelName, modelSkinName, sizeof( modelName ) ); slash = strchr( modelName, '/' ); if ( !slash ) { // modelName did not include a skin name Q_strncpyz( skinName, "default", sizeof( skinName ) ); } else { Q_strncpyz( skinName, slash + 1, sizeof( skinName ) ); *slash = '\0'; } Q_strncpyz( headModelName, headModelSkinName, sizeof( headModelName ) ); slash = strchr( headModelName, '/' ); if ( !slash ) { // modelName did not include a skin name Q_strncpyz( headSkinName, "default", sizeof( skinName ) ); } else { Q_strncpyz( headSkinName, slash + 1, sizeof( skinName ) ); *slash = '\0'; } // load cmodels before models so filecache works Com_sprintf( filename, sizeof( filename ), "models/players/%s/lower.md3", modelName ); pi->legsModel = trap_R_RegisterModel( filename ); if ( !pi->legsModel ) { Com_sprintf( filename, sizeof( filename ), "models/players/characters/%s/lower.md3", modelName ); pi->legsModel = trap_R_RegisterModel( filename ); if ( !pi->legsModel ) { Com_Printf( "Failed to load model file %s\n", filename ); return qfalse; } } Com_sprintf( filename, sizeof( filename ), "models/players/%s/upper.md3", modelName ); pi->torsoModel = trap_R_RegisterModel( filename ); if ( !pi->torsoModel ) { Com_sprintf( filename, sizeof( filename ), "models/players/characters/%s/upper.md3", modelName ); pi->torsoModel = trap_R_RegisterModel( filename ); if ( !pi->torsoModel ) { Com_Printf( "Failed to load model file %s\n", filename ); return qfalse; } } if (headModelName[0] == '*' ) { Com_sprintf( filename, sizeof( filename ), "models/players/heads/%s/%s.md3", &headModelName[1], &headModelName[1] ); } else { Com_sprintf( filename, sizeof( filename ), "models/players/%s/head.md3", headModelName ); } pi->headModel = trap_R_RegisterModel( filename ); if ( !pi->headModel && headModelName[0] != '*') { Com_sprintf( filename, sizeof( filename ), "models/players/heads/%s/%s.md3", headModelName, headModelName ); pi->headModel = trap_R_RegisterModel( filename ); } if (!pi->headModel) { Com_Printf( "Failed to load model file %s\n", filename ); return qfalse; } // if any skins failed to load, fall back to default if ( !UI_RegisterClientSkin( pi, modelName, skinName, headModelName, headSkinName, teamName) ) { if ( !UI_RegisterClientSkin( pi, modelName, "default", headModelName, "default", teamName ) ) { Com_Printf( "Failed to load skin file: %s : %s\n", modelName, skinName ); return qfalse; } } // load the animations Com_sprintf( filename, sizeof( filename ), "models/players/%s/animation.cfg", modelName ); if ( !UI_ParseAnimationFile( filename, pi->animations ) ) { Com_sprintf( filename, sizeof( filename ), "models/players/characters/%s/animation.cfg", modelName ); if ( !UI_ParseAnimationFile( filename, pi->animations ) ) { Com_Printf( "Failed to load animation file %s\n", filename ); return qfalse; } } return qtrue; }
/* ============ Cmd_TokenizeString Parses the given string into command line tokens. The text is copied to a seperate buffer and 0 characters are inserted in the apropriate place, The argv array will point into this temporary buffer. ============ */ static void Cmd_TokenizeString2(const char *text_in, qboolean ignoreQuotes) { const char *text; char *textOut; // clear previous args cmd_argc = 0; if (!text_in) { return; } Q_strncpyz(cmd_cmd, text_in, sizeof(cmd_cmd)); text = text_in; textOut = cmd_tokenized; while (1) { if (cmd_argc == MAX_STRING_TOKENS) { return; // this is usually something malicious } while (1) { // skip whitespace while (*text && *text <= ' ') { text++; } if (!*text) { return; // all tokens parsed } // skip // comments if (text[0] == '/' && text[1] == '/') { // lets us put 'http://' in commandlines if (text == text_in || (text > text_in && text[-1] != ':')) { return; // all tokens parsed } } // skip /* */ comments if (text[0] == '/' && text[1] == '*') { while (*text && (text[0] != '*' || text[1] != '/')) { text++; } if (!*text) { return; // all tokens parsed } text += 2; } else { break; // we are ready to parse a token } } // handle quoted strings // NOTE: this doesn't handle \" escaping if (!ignoreQuotes && *text == '"') { cmd_argv[cmd_argc] = textOut; cmd_argc++; text++; while (*text && *text != '"') { *textOut++ = *text++; } *textOut++ = 0; if (!*text) { return; // all tokens parsed } text++; continue; } // regular token cmd_argv[cmd_argc] = textOut; cmd_argc++; // skip until whitespace, quote, or command while (*text > ' ') { if (!ignoreQuotes && text[0] == '"') { break; } if (text[0] == '/' && text[1] == '/') { // lets us put 'http://' in commandlines if (text == text_in || (text > text_in && text[-1] != ':')) { break; } } // skip /* */ comments if (text[0] == '/' && text[1] == '*') { break; } *textOut++ = *text++; } *textOut++ = 0; if (!*text) { return; // all tokens parsed } } }
/* ================= UI_SPPostgameMenu_f ================= */ void UI_SPPostgameMenu_f( void ) { int playerGameRank; int playerClientNum; int n; int oldFrags, newFrags; const char *arena; int awardValues[6]; char map[MAX_QPATH]; char info[MAX_INFO_STRING]; memset( &postgameMenuInfo, 0, sizeof(postgameMenuInfo) ); trap_GetConfigString( CS_SYSTEMINFO, info, sizeof(info) ); postgameMenuInfo.serverId = atoi( Info_ValueForKey( info, "sv_serverid" ) ); trap_GetConfigString( CS_SERVERINFO, info, sizeof(info) ); Q_strncpyz( map, Info_ValueForKey( info, "mapname" ), sizeof(map) ); arena = UI_GetArenaInfoByMap( map ); if ( !arena ) { return; } Q_strncpyz( arenainfo, arena, sizeof(arenainfo) ); postgameMenuInfo.level = atoi( Info_ValueForKey( arenainfo, "num" ) ); postgameMenuInfo.numClients = atoi( UI_Argv( 1 ) ); playerClientNum = atoi( UI_Argv( 2 ) ); playerGameRank = 8; // in case they ended game as a spectator if( postgameMenuInfo.numClients > MAX_SCOREBOARD_CLIENTS ) { postgameMenuInfo.numClients = MAX_SCOREBOARD_CLIENTS; } for( n = 0; n < postgameMenuInfo.numClients; n++ ) { postgameMenuInfo.clientNums[n] = atoi( UI_Argv( 8 + n * 3 + 1 ) ); postgameMenuInfo.ranks[n] = atoi( UI_Argv( 8 + n * 3 + 2 ) ); postgameMenuInfo.scores[n] = atoi( UI_Argv( 8 + n * 3 + 3 ) ); if( postgameMenuInfo.clientNums[n] == playerClientNum ) { playerGameRank = (postgameMenuInfo.ranks[n] & ~RANK_TIED_FLAG) + 1; } } UI_SetBestScore( postgameMenuInfo.level, playerGameRank ); // process award stats and prepare presentation data awardValues[AWARD_ACCURACY] = atoi( UI_Argv( 3 ) ); awardValues[AWARD_IMPRESSIVE] = atoi( UI_Argv( 4 ) ); awardValues[AWARD_EXCELLENT] = atoi( UI_Argv( 5 ) ); awardValues[AWARD_GAUNTLET] = atoi( UI_Argv( 6 ) ); awardValues[AWARD_FRAGS] = atoi( UI_Argv( 7 ) ); awardValues[AWARD_PERFECT] = atoi( UI_Argv( 8 ) ); postgameMenuInfo.numAwards = 0; if( awardValues[AWARD_ACCURACY] >= 50 ) { UI_LogAwardData( AWARD_ACCURACY, 1 ); postgameMenuInfo.awardsEarned[postgameMenuInfo.numAwards] = AWARD_ACCURACY; postgameMenuInfo.awardsLevels[postgameMenuInfo.numAwards] = awardValues[AWARD_ACCURACY]; postgameMenuInfo.numAwards++; } if( awardValues[AWARD_IMPRESSIVE] ) { UI_LogAwardData( AWARD_IMPRESSIVE, awardValues[AWARD_IMPRESSIVE] ); postgameMenuInfo.awardsEarned[postgameMenuInfo.numAwards] = AWARD_IMPRESSIVE; postgameMenuInfo.awardsLevels[postgameMenuInfo.numAwards] = awardValues[AWARD_IMPRESSIVE]; postgameMenuInfo.numAwards++; } if( awardValues[AWARD_EXCELLENT] ) { UI_LogAwardData( AWARD_EXCELLENT, awardValues[AWARD_EXCELLENT] ); postgameMenuInfo.awardsEarned[postgameMenuInfo.numAwards] = AWARD_EXCELLENT; postgameMenuInfo.awardsLevels[postgameMenuInfo.numAwards] = awardValues[AWARD_EXCELLENT]; postgameMenuInfo.numAwards++; } if( awardValues[AWARD_GAUNTLET] ) { UI_LogAwardData( AWARD_GAUNTLET, awardValues[AWARD_GAUNTLET] ); postgameMenuInfo.awardsEarned[postgameMenuInfo.numAwards] = AWARD_GAUNTLET; postgameMenuInfo.awardsLevels[postgameMenuInfo.numAwards] = awardValues[AWARD_GAUNTLET]; postgameMenuInfo.numAwards++; } oldFrags = UI_GetAwardLevel( AWARD_FRAGS ) / 100; UI_LogAwardData( AWARD_FRAGS, awardValues[AWARD_FRAGS] ); newFrags = UI_GetAwardLevel( AWARD_FRAGS ) / 100; if( newFrags > oldFrags ) { postgameMenuInfo.awardsEarned[postgameMenuInfo.numAwards] = AWARD_FRAGS; postgameMenuInfo.awardsLevels[postgameMenuInfo.numAwards] = newFrags * 100; postgameMenuInfo.numAwards++; } if( awardValues[AWARD_PERFECT] ) { UI_LogAwardData( AWARD_PERFECT, 1 ); postgameMenuInfo.awardsEarned[postgameMenuInfo.numAwards] = AWARD_PERFECT; postgameMenuInfo.awardsLevels[postgameMenuInfo.numAwards] = 1; postgameMenuInfo.numAwards++; } if ( playerGameRank == 1 ) { postgameMenuInfo.won = UI_TierCompleted( postgameMenuInfo.level ); } else { postgameMenuInfo.won = -1; } postgameMenuInfo.starttime = uis.realtime; postgameMenuInfo.scoreboardtime = uis.realtime; trap_Key_SetCatcher( KEYCATCH_UI ); uis.menusp = 0; UI_SPPostgameMenu_Init(); UI_PushMenu( &postgameMenuInfo.menu ); if ( playerGameRank == 1 ) { Menu_SetCursorToItem( &postgameMenuInfo.menu, &postgameMenuInfo.item_next ); } else { Menu_SetCursorToItem( &postgameMenuInfo.menu, &postgameMenuInfo.item_again ); } Prepname( 0 ); Prepname( 1 ); Prepname( 2 ); if ( playerGameRank != 1 ) { postgameMenuInfo.winnerSound = trap_S_RegisterSound( va( "sound/player/announce/%s_wins.wav", postgameMenuInfo.placeNames[0] ), qfalse ); trap_Cmd_ExecuteText( EXEC_APPEND, "music music/loss\n" ); } else { postgameMenuInfo.winnerSound = trap_S_RegisterSound( "sound/player/announce/youwin.wav", qfalse ); trap_Cmd_ExecuteText( EXEC_APPEND, "music music/win\n" ); } postgameMenuInfo.phase = 1; postgameMenuInfo.lastTier = UI_GetNumSPTiers(); if ( UI_GetSpecialArenaInfo( "final" ) ) { postgameMenuInfo.lastTier++; } trap_Cvar_Set( "cl_postgame", "1" ); }
/* ===================== Cvar_InfoStringBuffer ===================== */ void Cvar_InfoStringBuffer( int bit, char* buff, int buffsize ) { Q_strncpyz(buff,Cvar_InfoString(bit),buffsize); }
/* ==================== RE_RegisterModel Loads in a model for the given name Zero will be returned if the model fails to load. An entry will be retained for failed models as an optimization to prevent disk rescanning if they are asked for again. ==================== */ qhandle_t RE_RegisterModel( const char *name ) { model_t *mod; unsigned *buf; int lod; int ident; qboolean loaded; qhandle_t hModel; int numLoaded; if ( !name || !name[0] ) { CL_RefPrintf( PRINT_ALL, "RE_RegisterModel: NULL name\n" ); return 0; } if ( strlen( name ) >= MAX_QPATH ) { Com_Printf( "Model name exceeds MAX_QPATH\n" ); return 0; } // // search the currently loaded models // for ( hModel = 1 ; hModel < tr.numModels; hModel++ ) { mod = tr.models[hModel]; if ( !strcmp( mod->name, name ) ) { if( mod->type == MOD_BAD ) { return 0; } return hModel; } } // allocate a new model_t if ( ( mod = R_AllocModel() ) == NULL ) { CL_RefPrintf( PRINT_WARNING, "RE_RegisterModel: R_AllocModel() failed for '%s'\n", name); return 0; } // only set the name after the model has been successfully loaded Q_strncpyz( mod->name, name, sizeof( mod->name ) ); // make sure the render thread is stopped R_SyncRenderThread(); mod->numLods = 0; // // load the files // numLoaded = 0; for ( lod = MD3_MAX_LODS - 1 ; lod >= 0 ; lod-- ) { char filename[1024]; strcpy( filename, name ); if ( lod != 0 ) { char namebuf[80]; if ( strrchr( filename, '.' ) ) { *strrchr( filename, '.' ) = 0; } sprintf( namebuf, "_%d.md3", lod ); strcat( filename, namebuf ); } FS_ReadFile( filename, (void **)&buf ); if ( !buf ) { continue; } loadmodel = mod; ident = LittleLong(*(unsigned *)buf); if ( ident == MD4_IDENT ) { loaded = R_LoadMD4( mod, buf, name ); } else { if ( ident != MD3_IDENT ) { CL_RefPrintf (PRINT_WARNING,"RE_RegisterModel: unknown fileid for %s\n", name); goto fail; } loaded = R_LoadMD3( mod, lod, buf, name ); } FS_FreeFile (buf); if ( !loaded ) { if ( lod == 0 ) { goto fail; } else { break; } } else { mod->numLods++; numLoaded++; // if we have a valid model and are biased // so that we won't see any higher detail ones, // stop loading them // if ( lod <= r_lodbias->integer ) { // break; // } } } if ( numLoaded ) { // duplicate into higher lod spots that weren't // loaded, in case the user changes r_lodbias on the fly for ( lod-- ; lod >= 0 ; lod-- ) { mod->numLods++; mod->md3[lod] = mod->md3[lod+1]; } return mod->index; } #ifdef _DEBUG else { CL_RefPrintf (PRINT_WARNING,"RE_RegisterModel: couldn't load %s\n", name); } #endif fail: // we still keep the model_t around, so if the model name is asked for // again, we won't bother scanning the filesystem mod->type = MOD_BAD; return 0; }
void G_Say( gentity_t *ent, gentity_t *target, int mode, const char *chatText ) { int j; gentity_t *other; int color; char name[64]; // don't let text be too long for malicious reasons char text[MAX_SAY_TEXT]; char location[64]; if ( g_gametype.integer < GT_TEAM && mode == SAY_TEAM ) { mode = SAY_ALL; } /* LQ3A: Spectators can only talk to other spectators when muted. */ if ((ent->client->sess.sessionTeam == TEAM_SPECTATOR) && g_spectatorMute.integer) { mode = SAY_TEAM; } switch ( mode ) { default: case SAY_ALL: G_LogPrintf( "say: %s: %s\n", ent->client->pers.netname, chatText ); Com_sprintf (name, sizeof(name), "%s%c%c"EC": ", ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE ); color = COLOR_GREEN; break; case SAY_TEAM: G_LogPrintf( "sayteam: %s: %s\n", ent->client->pers.netname, chatText ); if (Team_GetLocationMsg(ent, location, sizeof(location))) Com_sprintf (name, sizeof(name), EC"(%s%c%c"EC") (%s)"EC": ", ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE, location); else Com_sprintf (name, sizeof(name), EC"(%s%c%c"EC")"EC": ", ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE ); color = COLOR_CYAN; break; case SAY_TELL: if (target && g_gametype.integer >= GT_TEAM && target->client->sess.sessionTeam == ent->client->sess.sessionTeam && Team_GetLocationMsg(ent, location, sizeof(location))) Com_sprintf (name, sizeof(name), EC"[%s%c%c"EC"] (%s)"EC": ", ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE, location ); else Com_sprintf (name, sizeof(name), EC"[%s%c%c"EC"]"EC": ", ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE ); color = COLOR_MAGENTA; break; } Q_strncpyz( text, chatText, sizeof(text) ); if ( target ) { G_SayTo( ent, target, mode, color, name, text ); return; } // echo the text to the console if ( g_dedicated.integer ) { G_Printf( "%s%s\n", name, text); } // send it to all the apropriate clients for (j = 0; j < level.maxclients; j++) { other = &g_entities[j]; G_SayTo( ent, other, mode, color, name, text ); } }
/* ================== Cmd_CallTeamVote_f ================== */ void Cmd_CallTeamVote_f( gentity_t *ent ) { int i, team, cs_offset; char arg1[MAX_STRING_TOKENS]; char arg2[MAX_STRING_TOKENS]; team = ent->client->sess.sessionTeam; if ( team == TEAM_RED ) cs_offset = 0; else if ( team == TEAM_BLUE ) cs_offset = 1; else return; if ( !g_allowVote.integer ) { trap_SendServerCommand( ent-g_entities, "print \"Voting not allowed here.\n\"" ); return; } if ( level.teamVoteTime[cs_offset] ) { trap_SendServerCommand( ent-g_entities, "print \"A team vote is already in progress.\n\"" ); return; } if ( ent->client->pers.teamVoteCount >= MAX_VOTE_COUNT ) { trap_SendServerCommand( ent-g_entities, "print \"You have called the maximum number of team votes.\n\"" ); return; } if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) { trap_SendServerCommand( ent-g_entities, "print \"Not allowed to call a vote as spectator.\n\"" ); return; } // make sure it is a valid command to vote on trap_Argv( 1, arg1, sizeof( arg1 ) ); arg2[0] = '\0'; for ( i = 2; i < trap_Argc(); i++ ) { if (i > 2) strcat(arg2, " "); trap_Argv( i, &arg2[strlen(arg2)], sizeof( arg2 ) - strlen(arg2) ); } if( strchr( arg1, ';' ) || strchr( arg2, ';' ) ) { trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string.\n\"" ); return; } if ( !Q_stricmp( arg1, "leader" ) ) { char netname[MAX_NETNAME], leader[MAX_NETNAME]; if ( !arg2[0] ) { i = ent->client->ps.clientNum; } else { // numeric values are just slot numbers for (i = 0; i < 3; i++) { if ( !arg2[i] || arg2[i] < '0' || arg2[i] > '9' ) break; } if ( i >= 3 || !arg2[i]) { i = atoi( arg2 ); if ( i < 0 || i >= level.maxclients ) { trap_SendServerCommand( ent-g_entities, va("print \"Bad client slot: %i\n\"", i) ); return; } if ( !g_entities[i].inuse ) { trap_SendServerCommand( ent-g_entities, va("print \"Client %i is not active\n\"", i) ); return; } } else { Q_strncpyz(leader, arg2, sizeof(leader)); Q_CleanStr(leader); for ( i = 0 ; i < level.maxclients ; i++ ) { if ( level.clients[i].pers.connected == CON_DISCONNECTED ) continue; if (level.clients[i].sess.sessionTeam != team) continue; Q_strncpyz(netname, level.clients[i].pers.netname, sizeof(netname)); Q_CleanStr(netname); if ( !Q_stricmp(netname, leader) ) { break; } } if ( i >= level.maxclients ) { trap_SendServerCommand( ent-g_entities, va("print \"%s is not a valid player on your team.\n\"", arg2) ); return; } } } Com_sprintf(arg2, sizeof(arg2), "%d", i); } else { trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string.\n\"" ); trap_SendServerCommand( ent-g_entities, "print \"Team vote commands are: leader <player>.\n\"" ); return; } Com_sprintf( level.teamVoteString[cs_offset], sizeof( level.teamVoteString[cs_offset] ), "%s %s", arg1, arg2 ); for ( i = 0 ; i < level.maxclients ; i++ ) { if ( level.clients[i].pers.connected == CON_DISCONNECTED ) continue; if (level.clients[i].sess.sessionTeam == team) trap_SendServerCommand( i, va("print \"%s called a team vote.\n\"", ent->client->pers.netname ) ); } // start the voting, the caller autoamtically votes yes level.teamVoteTime[cs_offset] = level.time; level.teamVoteYes[cs_offset] = 1; level.teamVoteNo[cs_offset] = 0; for ( i = 0 ; i < level.maxclients ; i++ ) { if (level.clients[i].sess.sessionTeam == team) level.clients[i].ps.eFlags &= ~EF_TEAMVOTED; } ent->client->ps.eFlags |= EF_TEAMVOTED; trap_SetConfigstring( CS_TEAMVOTE_TIME + cs_offset, va("%i", level.teamVoteTime[cs_offset] ) ); trap_SetConfigstring( CS_TEAMVOTE_STRING + cs_offset, level.teamVoteString[cs_offset] ); trap_SetConfigstring( CS_TEAMVOTE_YES + cs_offset, va("%i", level.teamVoteYes[cs_offset] ) ); trap_SetConfigstring( CS_TEAMVOTE_NO + cs_offset, va("%i", level.teamVoteNo[cs_offset] ) ); }
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_Open( filename, &f, FS_READ ); if (!f || len >= 4096) { return; } trap->FS_Read( classInfo, len, f ); trap->FS_Close( f ); classInfo[len] = 0; //first get the description if we have a buffer for it if (descBuffer) { if (!BG_SiegeGetPairedValue(classInfo, "description", descBuffer->desc)) { Q_strncpyz(descBuffer->desc, "DESCRIPTION UNAVAILABLE", sizeof(descBuffer->desc)); } //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)) { Q_strncpyz(bgSiegeClasses[bgNumSiegeClasses].name, parseBuf, sizeof(bgSiegeClasses[0].name)); } else { Com_Error(ERR_DROP, "Siege class without name entry"); } //Parse forced model if (BG_SiegeGetPairedValue(classInfo, "model", parseBuf)) { Q_strncpyz(bgSiegeClasses[bgNumSiegeClasses].forcedModel, parseBuf, sizeof(bgSiegeClasses[0].forcedModel)); } 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)) { Q_strncpyz(bgSiegeClasses[bgNumSiegeClasses].forcedSkin, parseBuf, sizeof(bgSiegeClasses[0].forcedSkin)); } 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)) { Q_strncpyz(bgSiegeClasses[bgNumSiegeClasses].saber1, parseBuf, sizeof(bgSiegeClasses[0].saber1)); } 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)) { Q_strncpyz(bgSiegeClasses[bgNumSiegeClasses].saber2, parseBuf, sizeof(bgSiegeClasses[0].saber2)); } 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 //bgSiegeClasses[bgNumSiegeClasses].weapons |= (1 << WP_BRYAR_PISTOL); } //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)) { #if defined(_GAME) 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)); #elif defined(_UI) //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 _GAME bgSiegeClasses[bgNumSiegeClasses].classShader = 0; #else //cgame, ui #if defined(_CGAME) bgSiegeClasses[bgNumSiegeClasses].classShader = trap->R_RegisterShaderNoMip(parseBuf); #elif defined(_UI) bgSiegeClasses[bgNumSiegeClasses].classShader = trap->R_RegisterShaderNoMip(parseBuf); #endif assert( bgSiegeClasses[bgNumSiegeClasses].classShader ); if ( !bgSiegeClasses[bgNumSiegeClasses].classShader ) { //Com_Error( ERR_DROP, "ERROR: could not find class_shader %s for class %s\n", parseBuf, bgSiegeClasses[bgNumSiegeClasses].name ); 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, 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_Error( ERR_DROP, "ERROR: no class_shader defined for class %s\n", bgSiegeClasses[bgNumSiegeClasses].name ); 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++; }
//====================================== //Class loading functions //====================================== void BG_SiegeTranslateForcePowers(char *buf, siegeClass_t *siegeClass) { char checkPower[1024]; char checkLevel[256]; int l = 0; int k = 0; int j = 0; int i = 0; int parsedLevel = 0; qboolean allPowers = qfalse; qboolean noPowers = qfalse; if (!Q_stricmp(buf, "FP_ALL")) { //this is a special case, just give us all the powers on level 3 allPowers = qtrue; } if (buf[0] == '0' && !buf[1]) { //no powers then noPowers = qtrue; } //First clear out the powers, or in the allPowers case, give us all level 3. while (i < NUM_FORCE_POWERS) { if (allPowers) { siegeClass->forcePowerLevels[i] = FORCE_LEVEL_3; } else { siegeClass->forcePowerLevels[i] = 0; } i++; } if (allPowers || noPowers) { //we're done now then. return; } i = 0; while (buf[i]) { //parse through the list which is seperated by |, and add all the weapons into a bitflag if (buf[i] != ' ' && buf[i] != '|') { j = 0; while (buf[i] && buf[i] != ' ' && buf[i] != '|' && buf[i] != ',') { checkPower[j] = buf[i]; j++; i++; } checkPower[j] = 0; if (buf[i] == ',') { //parse the power level i++; l = 0; while (buf[i] && buf[i] != ' ' && buf[i] != '|') { checkLevel[l] = buf[i]; l++; i++; } checkLevel[l] = 0; parsedLevel = atoi(checkLevel); //keep sane limits on the powers if (parsedLevel < 0) { parsedLevel = 0; } if (parsedLevel > FORCE_LEVEL_5) { parsedLevel = FORCE_LEVEL_5; } } else { //if it's not there, assume level 3 I guess. parsedLevel = 3; } if (checkPower[0]) { //Got the name, compare it against the weapon table strings. k = 0; if (!Q_stricmp(checkPower, "FP_JUMP")) { //haqery Q_strncpyz(checkPower, "FP_LEVITATION", sizeof(checkPower)); } while (FPTable[k].id != -1 && FPTable[k].name[0]) { if (!Q_stricmp(checkPower, FPTable[k].name)) { //found it, add the weapon into the weapons value siegeClass->forcePowerLevels[k] = parsedLevel; break; } k++; } } } if (!buf[i]) { break; } i++; } }
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_Open(filename, &f, FS_READ); if (!f || len >= 2048) { return; } trap->FS_Read( teamInfo, len, f ); trap->FS_Close( f ); teamInfo[len] = 0; if (BG_SiegeGetPairedValue(teamInfo, "name", parseBuf)) { Q_strncpyz(bgSiegeTeams[bgNumSiegeTeams].name, parseBuf, sizeof(bgSiegeTeams[0].name)); } 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. Q_strncpyz(lookString, va("class%i", i), sizeof(lookString)); 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_Printf( "Invalid class specified: '%s'\n", 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++; }
/** * @brief Recursively removes files matching a given pattern from homepath. * * Useful for removing incomplete downloads and other garbage. * Files listed in the com_cleanWhitelist cvar are protected from deletion. * Additionally, executable and configuration files are protected unless 'force' * argument is passed to this command. */ void Cmd_CleanHomepath_f(void) { int i, j, patternFiles = 0, delFiles = 0, totalFiles = 0; char path[MAX_OSPATH]; qboolean force = qfalse, pretend = qfalse; // *.so and *.dll are denied per default in FS_Remove but throw a Com_Error() -> game aborts const char whitelist[] = ".txt .cfg .dat .gm .way .so .dll"; if (Cmd_Argc() < 3) { // files in fs_homepath are downloaded again when required - but better print a warning for inexperienced users Com_Printf("usage: clean [force | pretend] [modname / all] [pattern 1] [pattern n]\n" "example: clean all *tmp */zzz* etmain/etkey\n" "Warning: This command deletes files in fs_homepath. If you are not sure how to use this command do not play with fire!\n"); return; } // if home- and basepath are same better don't start to clean ... if (FS_IsSamePath(Cvar_VariableString("fs_homepath"), Cvar_VariableString("fs_basepath"))) { Com_Printf("Invalid configuration to run clean cmd - 'fs_homepath' and 'fs_basepath' are equal.\n"); return; } // avoid unreferenced pk3 runtime issues (not on HD but still referenced in game) #ifndef DEDICATED if (cls.state != CA_DISCONNECTED) { Com_Printf("You are connected to a server - enter '/disconnect' to run '/clean'.\n"); return; } #else if (com_sv_running && com_sv_running->integer) { Com_Printf("Server is running - enter '/killserver' to run '/clean'.\n"); return; } #endif // DEDICATED Cvar_VariableStringBuffer("fs_homepath", path, sizeof(path)); // if there are any command options, they must be at the very beginning for (i = 1; i < Cmd_Argc(); i++) { if (!Q_stricmp(Cmd_Argv(i), "force") || !Q_stricmp(Cmd_Argv(i), "f")) { force = qtrue; continue; } if (!Q_stricmp(Cmd_Argv(i), "pretend") || !Q_stricmp(Cmd_Argv(i), "p")) { pretend = qtrue; continue; } break; } // if the first argument is "all" or "*", search the whole homepath if (Q_stricmp(Cmd_Argv(i), "all") && Q_stricmp(Cmd_Argv(i), "*")) { Q_strcat(path, sizeof(path), va("%c%s", PATH_SEP, Cmd_Argv(i))); // check if it points to a valid directory if (FS_OSStatFile(path) != 1) { Com_Printf("Cannot commence cleaning, because \"%s\" is not a valid directory under fs_homepath (%s)\n", Cmd_Argv(i), path); return; } } for (i++; i < Cmd_Argc(); i++) { char **pFiles = NULL; pFiles = Sys_ListFiles(path, NULL, Cmd_Argv(i), &patternFiles, qtrue); Com_Printf("Found %i files matching the pattern \"%s\" under %s\n", patternFiles, Cmd_Argv(i), path); for (j = 0; j < patternFiles; j++) { char *tokens; char tmp_whitelist[MAX_OSPATH]; qboolean whitelisted = qfalse; totalFiles++; Q_strncpyz(tmp_whitelist, (force ? Cvar_VariableString("com_cleanwhitelist") : va("%s %s", Cvar_VariableString("com_cleanwhitelist"), whitelist)), sizeof(tmp_whitelist)); // Check if this file is in the whitelist tokens = strtok(tmp_whitelist, " ,;"); while (tokens != NULL) { if (strstr(pFiles[j], tokens)) { Com_Printf("- skipping file[%i]: %s%c%s (whitelisted by pattern: %s)\n", j + 1, path, PATH_SEP, pFiles[j], tokens); whitelisted = qtrue; break; } tokens = strtok(NULL, " ,;"); } if (whitelisted) { continue; } if (!pretend) { Com_Printf("- removing file[%i]: %s%c%s\n", j + 1, path, PATH_SEP, pFiles[j]); if (force) { remove(va("%s%c%s", path, PATH_SEP, pFiles[j])); // enable *.so & *.dll lib deletion } else { FS_Remove(va("%s%c%s", path, PATH_SEP, pFiles[j])); } delFiles++; } else { Com_Printf("- pretending to remove file[%i]: %s%c%s\n", j + 1, path, PATH_SEP, pFiles[j]); } } Sys_FreeFileList(pFiles); patternFiles = 0; } Com_Printf("Path of fs_homepath cleaned - %i matches - %i files skipped - %i files deleted.\n", totalFiles, totalFiles - delFiles, delFiles); }
void RadioBroadcast (edict_t * ent, int partner, char *msg) { int j, i, msg_len, numSnds; edict_t *other; radio_msg_t *radio_msgs; int msg_soundIndex = 0; char msgname_num[8], filteredmsg[48]; qboolean found = false; radio_t *radio; if (!IS_ALIVE(ent)) return; if (!teamplay->value) { if (!DMFLAGS( (DF_MODELTEAMS | DF_SKINTEAMS) )) return; // don't allow in a non-team setup... } radio = &ent->client->resp.radio; if (radio->power_off) { gi.centerprintf (ent, "Your radio is off!"); return; } if (partner && radio->partner == NULL) { gi.cprintf (ent, PRINT_HIGH, "You don't have a partner.\n"); return; } if (radio->gender) { radio_msgs = female_radio_msgs; numSnds = numFemaleSnds; } else { radio_msgs = male_radio_msgs; numSnds = numMaleSnds; } i = found = 0; msg_len = 0; Q_strncpyz(filteredmsg, msg, sizeof(filteredmsg)); for(i = 0; i < numSnds; i++) { if (!Q_stricmp(radio_msgs[i].msg, filteredmsg)) { found = true; msg_soundIndex = radio_msgs[i].sndIndex; msg_len = radio_msgs[i].length; break; } } if (!found) { gi.centerprintf (ent, "'%s' is not a valid radio message", filteredmsg); return; } if (radiolog->value) { gi.cprintf (NULL, PRINT_CHAT, "[%s RADIO] %s: %s\n", partner ? "PARTNER" : "TEAM", ent->client->pers.netname, filteredmsg); } //TempFile BEGIN if (Q_stricmp (filteredmsg, "enemyd") == 0) { if (ent->client->radio_num_kills > 1 && ent->client->radio_num_kills <= 10) { // If we are reporting enemy down, add the number of kills. sprintf( msgname_num, "%i", ent->client->radio_num_kills ); ent->client->radio_num_kills = 0; // prevent from getting into an endless loop RadioBroadcast(ent, partner, msgname_num); // Now THAT'S recursion! =) } ent->client->radio_num_kills = 0; } //TempFile END //AQ2:TNG Slicer if (radio_repeat->value) { //SLIC2 Optimization if (CheckForRepeat (ent, i) == false) return; } if (radio_max->value) { if (CheckForFlood (ent) == false) return; } //AQ2:TNG END for (j = 1; j <= game.maxclients; j++) { other = &g_edicts[j]; if (!other->inuse) continue; if (!other->client) continue; if (!OnSameTeam(ent, other)) continue; if (partner && other != radio->partner) continue; AddRadioMsg( &other->client->resp.radio, msg_soundIndex, msg_len, ent ); } }
/* ============ Cmd_ArgsBuffer The interpreted versions use this because they can't have pointers returned to them ============ */ void Cmd_ArgsBuffer(char *buffer, int bufferLength) { Q_strncpyz(buffer, Cmd_Args(), bufferLength); }
/* ============= NET_StringToAdr Traps "localhost" for loopback, passes everything else to system return 0 on address not found, 1 on address found with port, 2 on address found without port. ============= */ int NET_StringToAdr( const char* s, netadr_t* a, netadrtype_t family ) { char base[MAX_STRING_CHARS], *search; char* port = NULL; if ( !strcmp( s, "localhost" ) ) { memset( a, 0, sizeof( *a ) ); a->type = NA_LOOPBACK; // as NA_LOOPBACK doesn't require ports report port was given. return 1; } Q_strncpyz( base, s, sizeof( base ) ); if ( *base == '[' || Q_CountChar( base, ':' ) > 1 ) { // This is an ipv6 address, handle it specially. search = strchr( base, ']' ); if ( search ) { *search = '\0'; search++; if ( *search == ':' ) port = search + 1; } if ( *base == '[' ) search = base + 1; else search = base; } else { // look for a port number port = strchr( base, ':' ); if ( port ) { *port = '\0'; port++; } search = base; } if ( !Sys_StringToAdr( search, a, family ) ) { a->type = NA_BAD; return 0; } if ( port ) { a->port = BigShort( ( short ) atoi( port ) ); return 1; } else { a->port = BigShort( PORT_SERVER ); return 2; } }
/* ================ SV_SpawnServer Change the server to a new map, taking all connected clients along with it. This is NOT called for map_restart ================ */ void SV_SpawnServer( char *server, qboolean killBots ) { int i; int checksum; qboolean isBot; char systemInfo[16384]; const char *p; // shut down the existing game if it is running SV_ShutdownGameProgs(); Com_Printf ("------ Server Initialization ------\n"); Com_Printf ("Server: %s\n",server); // if not running a dedicated server CL_MapLoading will connect the client to the server // also print some status stuff CL_MapLoading(); // make sure all the client stuff is unloaded CL_ShutdownAll(qfalse); // clear the whole hunk because we're (re)loading the server Hunk_Clear(); // clear collision map data CM_ClearMap(); // init client structures and svs.numSnapshotEntities if ( !Cvar_VariableValue("sv_running") ) { SV_Startup(); } else { // check for maxclients change if ( sv_maxclients->modified ) { SV_ChangeMaxClients(); } } // clear pak references FS_ClearPakReferences(0); // allocate the snapshot entities on the hunk svs.snapshotEntities = Hunk_Alloc( sizeof(entityState_t)*svs.numSnapshotEntities, h_high ); svs.nextSnapshotEntities = 0; // toggle the server bit so clients can detect that a // server has changed svs.snapFlagServerBit ^= SNAPFLAG_SERVERCOUNT; // set nextmap to the same map, but it may be overriden // by the game startup or another console command Cvar_Set( "nextmap", "map_restart 0"); // Cvar_Set( "nextmap", va("map %s", server) ); for (i=0 ; i<sv_maxclients->integer ; i++) { // save when the server started for each client already connected if (svs.clients[i].state >= CS_CONNECTED) { svs.clients[i].oldServerTime = sv.time; } } // wipe the entire per-level structure SV_ClearServer(); for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) { sv.configstrings[i] = CopyString(""); } // make sure we are not paused Cvar_Set("cl_paused", "0"); // get a new checksum feed and restart the file system sv.checksumFeed = ( ((int) rand() << 16) ^ rand() ) ^ Com_Milliseconds(); FS_Restart( sv.checksumFeed ); CM_LoadMap( va("maps/%s.bsp", server), qfalse, &checksum ); // set serverinfo visible name Cvar_Set( "mapname", server ); Cvar_Set( "sv_mapChecksum", va("%i",checksum) ); // serverid should be different each time sv.serverId = com_frameTime; sv.restartedServerId = sv.serverId; // I suppose the init here is just to be safe sv.checksumFeedServerId = sv.serverId; Cvar_Set( "sv_serverid", va("%i", sv.serverId ) ); // clear physics interaction links SV_ClearWorld (); // media configstring setting should be done during // the loading stage, so connected clients don't have // to load during actual gameplay sv.state = SS_LOADING; // load and spawn all other entities SV_InitGameProgs(); // don't allow a map_restart if game is modified sv_gametype->modified = qfalse; // run a few frames to allow everything to settle for (i = 0;i < 3; i++) { VM_Call (gvm, GAME_RUN_FRAME, sv.time); SV_BotFrame (sv.time); sv.time += 100; svs.time += 100; } // create a baseline for more efficient communications SV_CreateBaseline (); for (i=0 ; i<sv_maxclients->integer ; i++) { // send the new gamestate to all connected clients if (svs.clients[i].state >= CS_CONNECTED) { char *denied; if ( svs.clients[i].netchan.remoteAddress.type == NA_BOT ) { if ( killBots ) { SV_DropClient( &svs.clients[i], "" ); continue; } isBot = qtrue; } else { isBot = qfalse; } // connect the client again denied = VM_ExplicitArgPtr( gvm, VM_Call( gvm, GAME_CLIENT_CONNECT, i, qfalse, isBot ) ); // firstTime = qfalse if ( denied ) { // this generally shouldn't happen, because the client // was connected before the level change SV_DropClient( &svs.clients[i], denied ); } else { if( !isBot ) { // when we get the next packet from a connected client, // the new gamestate will be sent svs.clients[i].state = CS_CONNECTED; } else { client_t *client; sharedEntity_t *ent; client = &svs.clients[i]; client->state = CS_ACTIVE; ent = SV_GentityNum( i ); ent->s.number = i; client->gentity = ent; client->deltaMessage = -1; client->lastSnapshotTime = 0; // generate a snapshot immediately VM_Call( gvm, GAME_CLIENT_BEGIN, i ); } } } } // run another frame to allow things to look at all the players VM_Call (gvm, GAME_RUN_FRAME, sv.time); SV_BotFrame (sv.time); sv.time += 100; svs.time += 100; if ( sv_pure->integer ) { // the server sends these to the clients so they will only // load pk3s also loaded at the server p = FS_LoadedPakChecksums(); Cvar_Set( "sv_paks", p ); if (strlen(p) == 0) { Com_Printf( "WARNING: sv_pure set but no PK3 files loaded\n" ); } p = FS_LoadedPakNames(); Cvar_Set( "sv_pakNames", p ); // if a dedicated pure server we need to touch the cgame because it could be in a // seperate pk3 file and the client will need to load the latest cgame.qvm if ( com_dedicated->integer ) { SV_TouchCGame(); } } else { Cvar_Set( "sv_paks", "" ); Cvar_Set( "sv_pakNames", "" ); } // the server sends these to the clients so they can figure // out which pk3s should be auto-downloaded p = FS_ReferencedPakChecksums(); Cvar_Set( "sv_referencedPaks", p ); p = FS_ReferencedPakNames(); Cvar_Set( "sv_referencedPakNames", p ); // save systeminfo and serverinfo strings Q_strncpyz( systemInfo, Cvar_InfoString_Big( CVAR_SYSTEMINFO ), sizeof( systemInfo ) ); cvar_modifiedFlags &= ~CVAR_SYSTEMINFO; SV_SetConfigstring( CS_SYSTEMINFO, systemInfo ); SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) ); cvar_modifiedFlags &= ~CVAR_SERVERINFO; // any media configstring setting now should issue a warning // and any configstring changes should be reliably transmitted // to all clients sv.state = SS_GAME; // send a heartbeat now so the master will get up to date info SV_Heartbeat_f(); Hunk_SetMark(); #ifndef DEDICATED if ( com_dedicated->integer ) { // restart renderer in order to show console for dedicated servers // launched through the regular binary CL_StartHunkUsers( qtrue ); } #endif Com_Printf ("-----------------------------------\n"); }
void Rocket_QuakeToRMLBuffer( const char *in, char *out, int length ) { Q_strncpyz( out, Rocket_QuakeToRML( in, RP_EMOTICONS ).CString(), length ); }
/* ============ Cmd_ArgvBuffer The interpreted versions use this because they can't have pointers returned to them ============ */ void Cmd_ArgvBuffer( int arg, char *buffer, int bufferLength ) { Q_strncpyz( buffer, Cmd_Argv( arg ), bufferLength ); }
/** * @brief Loads the given savegame from an xml File. * @return true on load success false on failures * @param[in] file The Filename to load from (without extension) * @param[out] error On failure an errormessage may be set. */ qboolean SAV_GameLoad (const char *file, const char **error) { uLongf len; char filename[MAX_OSPATH]; qFILE f; byte *cbuf, *buf; int i, clen; xmlNode_t *topNode, *node; saveFileHeader_t header; Q_strncpyz(filename, file, sizeof(filename)); /* open file */ FS_OpenFile(va("save/%s.%s", filename, SAVEGAME_EXTENSION), &f, FILE_READ); if (!f.f) { Com_Printf("Couldn't open file '%s'\n", filename); *error = "File not found"; return qfalse; } clen = FS_FileLength(&f); cbuf = (byte *) Mem_PoolAlloc(sizeof(byte) * clen, cp_campaignPool, 0); if (FS_Read(cbuf, clen, &f) != clen) Com_Printf("Warning: Could not read %i bytes from savefile\n", clen); FS_CloseFile(&f); Com_Printf("Loading savegame xml (size %d)\n", clen); memcpy(&header, cbuf, sizeof(header)); /* swap all int values if needed */ header.compressed = LittleLong(header.compressed); header.version = LittleLong(header.version); header.xmlSize = LittleLong(header.xmlSize); /* doing some header verification */ if (!SAV_VerifyHeader(&header)) { /* our header is not valid, we MUST abort loading the game! */ Com_Printf("The Header of the savegame '%s.%s' is corrupted. Loading aborted\n", filename, SAVEGAME_EXTENSION); Mem_Free(cbuf); *error = "Corrupted header"; return qfalse; } Com_Printf("Loading savegame\n" "...version: %i\n" "...game version: %s\n" "...xml Size: %i, compressed? %c\n", header.version, header.gameVersion, header.xmlSize, header.compressed ? 'y' : 'n'); len = header.xmlSize + 50; buf = (byte *) Mem_PoolAlloc(sizeof(byte) * len, cp_campaignPool, 0); if (header.compressed) { /* uncompress data, skipping comment header */ const int res = uncompress(buf, &len, cbuf + sizeof(header), clen - sizeof(header)); Mem_Free(cbuf); if (res != Z_OK) { Mem_Free(buf); *error = _("Error decompressing data"); Com_Printf("Error decompressing data in '%s'.\n", filename); return qfalse; } topNode = XML_Parse((const char*)buf); if (!topNode) { Mem_Free(buf); Com_Printf("Error: Failure in loading the xml data!\n"); *error = "Corrupted xml data"; return qfalse; } } else { /*memcpy(buf, cbuf + sizeof(header), clen - sizeof(header));*/ topNode = XML_Parse((const char*)(cbuf + sizeof(header))); Mem_Free(cbuf); if (!topNode) { Com_Printf("Error: Failure in loading the xml data!\n"); *error = "Corrupted xml data"; return qfalse; } } Mem_Free(buf); /* doing a subsystem run */ GAME_ReloadMode(); node = XML_GetNode(topNode, SAVE_ROOTNODE); if (!node) { Com_Printf("Error: Failure in loading the xml data! (savegame node not found)\n"); mxmlDelete(topNode); *error = "Invalid xml data"; return qfalse; } Com_Printf("Load '%s' %d subsystems\n", filename, saveSubsystemsAmount); for (i = 0; i < saveSubsystemsAmount; i++) { Com_Printf("...Running subsystem '%s'\n", saveSubsystems[i].name); if (!saveSubsystems[i].load(node)) { Com_Printf("...subsystem '%s' returned false - savegame could not be loaded\n", saveSubsystems[i].name); *error = va("Could not load subsystem %s", saveSubsystems[i].name); return qfalse; } else Com_Printf("...subsystem '%s' - loaded.\n", saveSubsystems[i].name); } mxmlDelete(node); mxmlDelete(topNode); if (!SAV_GameActionsAfterLoad()) { Com_Printf("Savegame postprocessing returned false - savegame could not be loaded\n"); *error = "Postprocessing failed"; return qfalse; } Com_Printf("File '%s' successfully loaded from %s xml savegame.\n", filename, header.compressed ? "compressed" : ""); UI_InitStack("geoscape", NULL, qtrue, qtrue); return qtrue; }
// NOTE TTimo define that to track tokenization issues //#define TKN_DBG void Cmd_TokenizeString( const char *text_in ) { const char *text; char *textOut; #ifdef TKN_DBG // FIXME TTimo blunt hook to try to find the tokenization of userinfo Com_DPrintf("Cmd_TokenizeString: %s\n", text_in); #endif // clear previous args cmd_argc = 0; if ( !text_in ) { return; } Q_strncpyz( cmd_cmd, text_in, sizeof(cmd_cmd) ); text = text_in; textOut = cmd_tokenized; while ( 1 ) { if ( cmd_argc == MAX_STRING_TOKENS ) { return; // this is usually something malicious } while ( 1 ) { // skip whitespace while ( *text && *text <= ' ' ) { text++; } if ( !*text ) { return; // all tokens parsed } // skip // comments if ( text[0] == '/' && text[1] == '/' ) { return; // all tokens parsed } // skip /* */ comments if ( text[0] == '/' && text[1] =='*' ) { while ( *text && ( text[0] != '*' || text[1] != '/' ) ) { text++; } if ( !*text ) { return; // all tokens parsed } text += 2; } else { break; // we are ready to parse a token } } // handle quoted strings // NOTE TTimo this doesn't handle \" escaping if ( *text == '"' ) { cmd_argv[cmd_argc] = textOut; cmd_argc++; text++; while ( *text && *text != '"' ) { *textOut++ = *text++; } *textOut++ = 0; if ( !*text ) { return; // all tokens parsed } text++; continue; } // regular token cmd_argv[cmd_argc] = textOut; cmd_argc++; // skip until whitespace, quote, or command while ( *text > ' ' ) { if ( text[0] == '"' ) { break; } if ( text[0] == '/' && text[1] == '/' ) { break; } // skip /* */ comments if ( text[0] == '/' && text[1] =='*' ) { break; } *textOut++ = *text++; } *textOut++ = 0; if ( !*text ) { return; // all tokens parsed } } }
/** * @brief This is a savegame function which stores the game in xml-Format. * @param[in] filename The Filename to save to (without extension) * @param[in] comment Description of the savegame * @param[out] error On failure an errormessage may be set. */ static qboolean SAV_GameSave (const char *filename, const char *comment, char **error) { xmlNode_t *topNode, *node; char savegame[MAX_OSPATH]; int res; int requiredBufferLength; byte *buf, *fbuf; uLongf bufLen; saveFileHeader_t header; char dummy[2]; int i; dateLong_t date; char message[30]; char timeStampBuffer[32]; if (!CP_IsRunning()) { *error = _("No campaign active."); Com_Printf("Error: No campaign active.\n"); return qfalse; } if (!B_AtLeastOneExists()) { *error = _("Nothing to save yet."); Com_Printf("Error: Nothing to save yet.\n"); return qfalse; } Com_MakeTimestamp(timeStampBuffer, sizeof(timeStampBuffer)); Com_sprintf(savegame, sizeof(savegame), "save/%s.%s", filename, SAVEGAME_EXTENSION); topNode = mxmlNewXML("1.0"); node = XML_AddNode(topNode, SAVE_ROOTNODE); /* writing Header */ XML_AddInt(node, SAVE_SAVEVERSION, SAVE_FILE_VERSION); XML_AddString(node, SAVE_COMMENT, comment); XML_AddString(node, SAVE_UFOVERSION, UFO_VERSION); XML_AddString(node, SAVE_REALDATE, timeStampBuffer); CP_DateConvertLong(&ccs.date, &date); Com_sprintf(message, sizeof(message), _("%i %s %02i"), date.year, Date_GetMonthName(date.month - 1), date.day); XML_AddString(node, SAVE_GAMEDATE, message); /* working through all subsystems. perhaps we should redesign it, order is not important anymore */ Com_Printf("Calling subsystems\n"); for (i = 0; i < saveSubsystemsAmount; i++) { if (!saveSubsystems[i].save(node)) Com_Printf("...subsystem '%s' failed to save the data\n", saveSubsystems[i].name); else Com_Printf("...subsystem '%s' - saved\n", saveSubsystems[i].name); } /* calculate the needed buffer size */ OBJZERO(header); header.compressed = LittleLong(save_compressed->integer); header.version = LittleLong(SAVE_FILE_VERSION); header.subsystems = LittleLong(saveSubsystemsAmount); Q_strncpyz(header.name, comment, sizeof(header.name)); Q_strncpyz(header.gameVersion, UFO_VERSION, sizeof(header.gameVersion)); CP_DateConvertLong(&ccs.date, &date); Com_sprintf(header.gameDate, sizeof(header.gameDate), _("%i %s %02i"), date.year, Date_GetMonthName(date.month - 1), date.day); Q_strncpyz(header.realDate, timeStampBuffer, sizeof(header.realDate)); requiredBufferLength = mxmlSaveString(topNode, dummy, 2, MXML_NO_CALLBACK); header.xmlSize = LittleLong(requiredBufferLength); buf = (byte *) Mem_PoolAlloc(sizeof(byte) * requiredBufferLength + 1, cp_campaignPool, 0); if (!buf) { mxmlDelete(topNode); *error = _("Could not allocate enough memory to save this game"); Com_Printf("Error: Could not allocate enough memory to save this game\n"); return qfalse; } res = mxmlSaveString(topNode, (char*)buf, requiredBufferLength + 1, MXML_NO_CALLBACK); mxmlDelete(topNode); Com_Printf("XML Written to buffer (%d Bytes)\n", res); if (header.compressed) bufLen = compressBound(requiredBufferLength); else bufLen = requiredBufferLength; fbuf = (byte *) Mem_PoolAlloc(sizeof(byte) * bufLen + sizeof(header), cp_campaignPool, 0); memcpy(fbuf, &header, sizeof(header)); if (header.compressed) { res = compress(fbuf + sizeof(header), &bufLen, buf, requiredBufferLength + 1); Mem_Free(buf); if (res != Z_OK) { Mem_Free(fbuf); *error = _("Memory error compressing save-game data - set save_compressed cvar to 0"); Com_Printf("Memory error compressing save-game data (%s) (Error: %i)!\n", comment, res); return qfalse; } } else { memcpy(fbuf + sizeof(header), buf, requiredBufferLength + 1); Mem_Free(buf); } /* last step - write data */ res = FS_WriteFile(fbuf, bufLen + sizeof(header), savegame); Mem_Free(fbuf); return qtrue; }
int RE_LerpTagET( orientation_t *tag, const refEntity_t *refent, const char *tagNameIn, int startIndex ) { mdvTag_t *start, *end; int i; float frontLerp, backLerp; model_t *model; char tagName[ MAX_QPATH ]; //, *ch; int retval; qhandle_t handle; int startFrame, endFrame; float frac; handle = refent->hModel; startFrame = refent->oldframe; endFrame = refent->frame; frac = 1.0 - refent->backlerp; Q_strncpyz( tagName, tagNameIn, MAX_QPATH ); /* // if the tagName has a space in it, then it is passing through the starting tag number if (ch = strrchr(tagName, ' ')) { *ch = 0; ch++; startIndex = atoi(ch); } */ model = R_GetModelByHandle( handle ); /* if(!model->mdv[0]) //if(!model->model.md3[0] && !model->model.mdc[0] && !model->model.mds) { AxisClear(tag->axis); VectorClear(tag->origin); return -1; } */ frontLerp = frac; backLerp = 1.0 - frac; start = end = NULL; /* else if(model->type == MOD_MDS) { // use bone lerping retval = R_GetBoneTag(tag, model->model.mds, startIndex, refent, tagNameIn); if(retval >= 0) { return retval; } // failed return -1; } */ if ( model->type == MOD_MDM ) { // use bone lerping retval = R_MDM_GetBoneTag( tag, model->mdm, startIndex, refent, tagNameIn ); if ( retval >= 0 ) { return retval; } // failed return -1; } else if ( model->type == MOD_MD5 ) { vec3_t tmp; retval = RE_BoneIndex( handle, tagName ); if ( retval <= 0 ) { return -1; } VectorCopy( refent->skeleton.bones[ retval ].origin, tag->origin ); QuatToAxis( refent->skeleton.bones[ retval ].rotation, tag->axis ); VectorCopy( tag->axis[ 2 ], tmp ); VectorCopy( tag->axis[ 1 ], tag->axis[ 2 ] ); VectorCopy( tag->axis[ 0 ], tag->axis[ 1 ] ); VectorCopy( tmp, tag->axis[ 0 ] ); VectorNormalize( tag->axis[ 0 ] ); VectorNormalize( tag->axis[ 1 ] ); VectorNormalize( tag->axis[ 2 ] ); return retval; } /* else { // psuedo-compressed MDC tags mdcTag_t *cstart, *cend; retval = R_GetMDCTag((byte *) model->model.mdc[0], startFrame, tagName, startIndex, &cstart); retval = R_GetMDCTag((byte *) model->model.mdc[0], endFrame, tagName, startIndex, &cend); // uncompress the MDC tags into MD3 style tags if(cstart && cend) { for(i = 0; i < 3; i++) { ustart.origin[i] = (float)cstart->xyz[i] * MD3_XYZ_SCALE; uend.origin[i] = (float)cend->xyz[i] * MD3_XYZ_SCALE; sangles[i] = (float)cstart->angles[i] * MDC_TAG_ANGLE_SCALE; eangles[i] = (float)cend->angles[i] * MDC_TAG_ANGLE_SCALE; } AnglesToAxis(sangles, ustart.axis); AnglesToAxis(eangles, uend.axis); start = &ustart; end = &uend; } else { start = NULL; end = NULL; } } */ else if ( model->type == MOD_MESH ) { // old MD3 style retval = R_GetTag( model->mdv[ 0 ], startFrame, tagName, startIndex, &start ); retval = R_GetTag( model->mdv[ 0 ], endFrame, tagName, startIndex, &end ); if ( !start || !end ) { AxisClear( tag->axis ); VectorClear( tag->origin ); return -1; } for ( i = 0; i < 3; i++ ) { tag->origin[ i ] = start->origin[ i ] * backLerp + end->origin[ i ] * frontLerp; tag->axis[ 0 ][ i ] = start->axis[ 0 ][ i ] * backLerp + end->axis[ 0 ][ i ] * frontLerp; tag->axis[ 1 ][ i ] = start->axis[ 1 ][ i ] * backLerp + end->axis[ 1 ][ i ] * frontLerp; tag->axis[ 2 ][ i ] = start->axis[ 2 ][ i ] * backLerp + end->axis[ 2 ][ i ] * frontLerp; } VectorNormalize( tag->axis[ 0 ] ); VectorNormalize( tag->axis[ 1 ] ); VectorNormalize( tag->axis[ 2 ] ); return retval; } return -1; }
/* ================= CG_ServerCommand The string has been tokenized and can be retrieved with Cmd_Argc() / Cmd_Argv() ================= */ 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, "cp" ) ) { CG_CenterPrint( CG_Argv( 1 ), SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH ); return; } if ( !strcmp( cmd, "cs" ) ) { CG_ConfigStringModified(); return; } if ( !strcmp( cmd, "print" ) ) { CG_Printf( "%s", CG_Argv( 1 ) ); 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" ) ) { if ( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_ALIENS ) { trap_S_StartLocalSound( cgs.media.alienTalkSound, CHAN_LOCAL_SOUND ); } else if ( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) { trap_S_StartLocalSound( cgs.media.humanTalkSound, CHAN_LOCAL_SOUND ); } else { 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; } 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 ) ); } } //the server has triggered a menu if ( !strcmp( cmd, "servermenu" ) ) { if ( trap_Argc() == 2 && !cg.demoPlayback ) { CG_Menu( atoi( CG_Argv( 1 ) ) ); } return; } //the server thinks this client should close all menus if ( !strcmp( cmd, "serverclosemenus" ) ) { trap_SendConsoleCommand( "closemenus\n" ); return; } //poison cloud effect needs to be reliable if ( !strcmp( cmd, "poisoncloud" ) ) { cg.poisonedTime = cg.time; if ( CG_IsParticleSystemValid( &cg.poisonCloudPS ) ) { cg.poisonCloudPS = CG_SpawnNewParticleSystem( cgs.media.poisonCloudPS ); CG_SetAttachmentCent( &cg.poisonCloudPS->attachment, &cg.predictedPlayerEntity ); CG_AttachToCent( &cg.poisonCloudPS->attachment ); } return; } if ( !strcmp( cmd, "weaponswitch" ) ) { CG_Printf( "client weaponswitch\n" ); if ( trap_Argc() == 2 ) { cg.weaponSelect = atoi( CG_Argv( 1 ) ); cg.weaponSelectTime = cg.time; } return; } // server requests a ptrc if ( !strcmp( cmd, "ptrcrequest" ) ) { int code = CG_ReadPTRCode(); trap_SendClientCommand( va( "ptrcverify %d", code ) ); return; } // server issues a ptrc if ( !strcmp( cmd, "ptrcissue" ) ) { if ( trap_Argc() == 2 ) { int code = atoi( CG_Argv( 1 ) ); CG_WritePTRCode( code ); } return; } // reply to ptrcverify if ( !strcmp( cmd, "ptrcconfirm" ) ) { trap_SendConsoleCommand( "menu ptrc_popmenu\n" ); return; } CG_Printf( "Unknown client game command: %s\n", cmd ); }
/* =============== RE_RegisterAnimation =============== */ qhandle_t RE_RegisterAnimation( const char *name ) { qhandle_t hAnim; skelAnimation_t *anim; char *buffer; int bufferLen; qboolean loaded = qfalse; if ( !name || !name[ 0 ] ) { ri.Printf( PRINT_WARNING, "Empty name passed to RE_RegisterAnimation\n" ); return 0; } //ri.Printf(PRINT_ALL, "RE_RegisterAnimation(%s)\n", name); if ( strlen( name ) >= MAX_QPATH ) { ri.Printf( PRINT_WARNING, "Animation name exceeds MAX_QPATH\n" ); return 0; } // search the currently loaded animations for ( hAnim = 1; hAnim < tr.numAnimations; hAnim++ ) { anim = tr.animations[ hAnim ]; if ( !Q_stricmp( anim->name, name ) ) { if ( anim->type == AT_BAD ) { return 0; } return hAnim; } } // allocate a new model_t if ( ( anim = R_AllocAnimation() ) == NULL ) { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: R_AllocAnimation() failed for '%s'\n", name ); return 0; } // only set the name after the animation has been successfully allocated Q_strncpyz( anim->name, name, sizeof( anim->name ) ); // make sure the render thread is stopped R_SyncRenderThread(); // load and parse the .md5anim file bufferLen = ri.FS_ReadFile( name, ( void ** ) &buffer ); if ( !buffer ) { return 0; } if ( !Q_stricmpn( ( const char * ) buffer, "MD5Version", 10 ) ) { loaded = R_LoadMD5Anim( anim, buffer, bufferLen, name ); } else { ri.Printf( PRINT_WARNING, "RE_RegisterAnimation: unknown fileid for '%s'\n", name ); } ri.FS_FreeFile( buffer ); if ( !loaded ) { ri.Printf( PRINT_WARNING, "couldn't load '%s'\n", name ); // we still keep the model_t around, so if the model name is asked for // again, we won't bother scanning the filesystem anim->type = AT_BAD; } return anim->index; }
/* ================ CG_ConfigStringModified ================ */ static void CG_ConfigStringModified( void ) { const char *str; int num; num = atoi( CG_Argv( 1 ) ); // get the gamestate from the client system, which will have the // new configstring already integrated trap_GetGameState( &cgs.gameState ); // look up the individual string that was modified str = CG_ConfigString( num ); // do something with it if necessary if ( num == CS_MUSIC ) { CG_StartMusic(); } else if ( num == CS_SERVERINFO ) { CG_ParseServerinfo(); } else if ( num == CS_WARMUP ) { CG_ParseWarmup(); } else if ( num == CS_SCORES1 ) { cgs.scores1 = atoi( str ); } else if ( num == CS_SCORES2 ) { cgs.scores2 = atoi( str ); } else if ( num == CS_BUILDPOINTS ) { sscanf( str, "%d %d %d %d %d", &cgs.alienBuildPoints, &cgs.alienBuildPointsTotal, &cgs.humanBuildPoints, &cgs.humanBuildPointsTotal, &cgs.humanBuildPointsPowered ); } else if ( num == CS_STAGES ) { stage_t oldAlienStage = cgs.alienStage; stage_t oldHumanStage = cgs.humanStage; sscanf( str, "%d %d %d %d %d %d", &cgs.alienStage, &cgs.humanStage, &cgs.alienKills, &cgs.humanKills, &cgs.alienNextStageThreshold, &cgs.humanNextStageThreshold ); if ( cgs.alienStage != oldAlienStage ) { CG_AnnounceAlienStageTransistion( oldAlienStage, cgs.alienStage ); } if ( cgs.humanStage != oldHumanStage ) { CG_AnnounceHumanStageTransistion( oldHumanStage, cgs.humanStage ); } } else if ( num == CS_SPAWNS ) { sscanf( str, "%d %d", &cgs.numAlienSpawns, &cgs.numHumanSpawns ); } else if ( num == CS_LEVEL_START_TIME ) { cgs.levelStartTime = atoi( str ); } else if ( num == CS_VOTE_TIME ) { cgs.voteTime = atoi( str ); cgs.voteModified = qtrue; if ( cgs.voteTime ) { trap_Cvar_Set( "ui_voteActive", "1" ); } else { trap_Cvar_Set( "ui_voteActive", "0" ); } } else if ( num == CS_VOTE_YES ) { cgs.voteYes = atoi( str ); cgs.voteModified = qtrue; } else if ( num == CS_VOTE_NO ) { cgs.voteNo = atoi( str ); cgs.voteModified = qtrue; } else if ( num == CS_VOTE_STRING ) { Q_strncpyz( cgs.voteString, str, sizeof( cgs.voteString ) ); } else if ( num >= CS_TEAMVOTE_TIME && num <= CS_TEAMVOTE_TIME + 1 ) { int cs_offset = num - CS_TEAMVOTE_TIME; cgs.teamVoteTime[ cs_offset ] = atoi( str ); cgs.teamVoteModified[ cs_offset ] = qtrue; if ( cs_offset == 0 ) { if ( cgs.teamVoteTime[ cs_offset ] ) { trap_Cvar_Set( "ui_humanTeamVoteActive", "1" ); } else { trap_Cvar_Set( "ui_humanTeamVoteActive", "0" ); } } else if ( cs_offset == 1 ) { if ( cgs.teamVoteTime[ cs_offset ] ) { trap_Cvar_Set( "ui_alienTeamVoteActive", "1" ); } else { trap_Cvar_Set( "ui_alienTeamVoteActive", "0" ); } } } else if ( num >= CS_TEAMVOTE_YES && num <= CS_TEAMVOTE_YES + 1 ) { cgs.teamVoteYes[ num - CS_TEAMVOTE_YES ] = atoi( str ); cgs.teamVoteModified[ num - CS_TEAMVOTE_YES ] = qtrue; } else if ( num >= CS_TEAMVOTE_NO && num <= CS_TEAMVOTE_NO + 1 ) { cgs.teamVoteNo[ num - CS_TEAMVOTE_NO ] = atoi( str ); cgs.teamVoteModified[ num - CS_TEAMVOTE_NO ] = qtrue; } else if ( num >= CS_TEAMVOTE_STRING && num <= CS_TEAMVOTE_STRING + 1 ) { Q_strncpyz( cgs.teamVoteString[ num - CS_TEAMVOTE_STRING ], str, sizeof( cgs.teamVoteString ) ); } else if ( num == CS_INTERMISSION ) { cg.intermissionStarted = atoi( str ); } else if ( num >= CS_MODELS && num < CS_MODELS + MAX_MODELS ) { cgs.gameModels[ num - CS_MODELS ] = trap_R_RegisterModel( str ); } else if ( num >= CS_SHADERS && num < CS_SHADERS + MAX_GAME_SHADERS ) { cgs.gameShaders[ num - CS_SHADERS ] = trap_R_RegisterShader( str ); } else if ( num >= CS_PARTICLE_SYSTEMS && num < CS_PARTICLE_SYSTEMS + MAX_GAME_PARTICLE_SYSTEMS ) { cgs.gameParticleSystems[ num - CS_PARTICLE_SYSTEMS ] = CG_RegisterParticleSystem( ( char * ) str ); } else if ( num >= CS_SOUNDS && num < CS_SOUNDS + MAX_SOUNDS ) { if ( str[ 0 ] != '*' ) { // player specific sounds don't register here cgs.gameSounds[ num - CS_SOUNDS ] = trap_S_RegisterSound( str, qfalse ); } } else if ( num >= CS_PLAYERS && num < CS_PLAYERS + MAX_CLIENTS ) { CG_NewClientInfo( num - CS_PLAYERS ); CG_BuildSpectatorString(); } else if ( num == CS_FLAGSTATUS ) { } else if ( num == CS_SHADERSTATE ) { CG_ShaderStateChanged(); } }
/* ============== RE_BuildSkeleton ============== */ int RE_BuildSkeleton( refSkeleton_t *skel, qhandle_t hAnim, int startFrame, int endFrame, float frac, qboolean clearOrigin ) { skelAnimation_t *skelAnim; skelAnim = R_GetAnimationByHandle( hAnim ); if ( skelAnim->type == AT_MD5 && skelAnim->md5 ) { int i; md5Animation_t *anim; md5Channel_t *channel; md5Frame_t *newFrame, *oldFrame; vec3_t newOrigin, oldOrigin, lerpedOrigin; quat_t newQuat, oldQuat, lerpedQuat; int componentsApplied; anim = skelAnim->md5; // Validate the frames so there is no chance of a crash. // This will write directly into the entity structure, so // when the surfaces are rendered, they don't need to be // range checked again. /* if((startFrame >= anim->numFrames) || (startFrame < 0) || (endFrame >= anim->numFrames) || (endFrame < 0)) { ri.Printf(PRINT_DEVELOPER, "RE_BuildSkeleton: no such frame %d to %d for '%s'\n", startFrame, endFrame, anim->name); //startFrame = 0; //endFrame = 0; } */ Q_clamp( startFrame, 0, anim->numFrames - 1 ); Q_clamp( endFrame, 0, anim->numFrames - 1 ); // compute frame pointers oldFrame = &anim->frames[ startFrame ]; newFrame = &anim->frames[ endFrame ]; // calculate a bounding box in the current coordinate system for ( i = 0; i < 3; i++ ) { skel->bounds[ 0 ][ i ] = oldFrame->bounds[ 0 ][ i ] < newFrame->bounds[ 0 ][ i ] ? oldFrame->bounds[ 0 ][ i ] : newFrame->bounds[ 0 ][ i ]; skel->bounds[ 1 ][ i ] = oldFrame->bounds[ 1 ][ i ] > newFrame->bounds[ 1 ][ i ] ? oldFrame->bounds[ 1 ][ i ] : newFrame->bounds[ 1 ][ i ]; } for ( i = 0, channel = anim->channels; i < anim->numChannels; i++, channel++ ) { // set baseframe values VectorCopy( channel->baseOrigin, newOrigin ); VectorCopy( channel->baseOrigin, oldOrigin ); QuatCopy( channel->baseQuat, newQuat ); QuatCopy( channel->baseQuat, oldQuat ); componentsApplied = 0; // update tranlation bits if ( channel->componentsBits & COMPONENT_BIT_TX ) { oldOrigin[ 0 ] = oldFrame->components[ channel->componentsOffset + componentsApplied ]; newOrigin[ 0 ] = newFrame->components[ channel->componentsOffset + componentsApplied ]; componentsApplied++; } if ( channel->componentsBits & COMPONENT_BIT_TY ) { oldOrigin[ 1 ] = oldFrame->components[ channel->componentsOffset + componentsApplied ]; newOrigin[ 1 ] = newFrame->components[ channel->componentsOffset + componentsApplied ]; componentsApplied++; } if ( channel->componentsBits & COMPONENT_BIT_TZ ) { oldOrigin[ 2 ] = oldFrame->components[ channel->componentsOffset + componentsApplied ]; newOrigin[ 2 ] = newFrame->components[ channel->componentsOffset + componentsApplied ]; componentsApplied++; } // update quaternion rotation bits if ( channel->componentsBits & COMPONENT_BIT_QX ) { ( ( vec_t * ) oldQuat ) [ 0 ] = oldFrame->components[ channel->componentsOffset + componentsApplied ]; ( ( vec_t * ) newQuat ) [ 0 ] = newFrame->components[ channel->componentsOffset + componentsApplied ]; componentsApplied++; } if ( channel->componentsBits & COMPONENT_BIT_QY ) { ( ( vec_t * ) oldQuat ) [ 1 ] = oldFrame->components[ channel->componentsOffset + componentsApplied ]; ( ( vec_t * ) newQuat ) [ 1 ] = newFrame->components[ channel->componentsOffset + componentsApplied ]; componentsApplied++; } if ( channel->componentsBits & COMPONENT_BIT_QZ ) { ( ( vec_t * ) oldQuat ) [ 2 ] = oldFrame->components[ channel->componentsOffset + componentsApplied ]; ( ( vec_t * ) newQuat ) [ 2 ] = newFrame->components[ channel->componentsOffset + componentsApplied ]; } QuatCalcW( oldQuat ); QuatNormalize( oldQuat ); QuatCalcW( newQuat ); QuatNormalize( newQuat ); #if 1 VectorLerp( oldOrigin, newOrigin, frac, lerpedOrigin ); QuatSlerp( oldQuat, newQuat, frac, lerpedQuat ); #else VectorCopy( newOrigin, lerpedOrigin ); QuatCopy( newQuat, lerpedQuat ); #endif // copy lerped information to the bone + extra data skel->bones[ i ].parentIndex = channel->parentIndex; if ( channel->parentIndex < 0 && clearOrigin ) { VectorClear( skel->bones[ i ].origin ); QuatClear( skel->bones[ i ].rotation ); // move bounding box back VectorSubtract( skel->bounds[ 0 ], lerpedOrigin, skel->bounds[ 0 ] ); VectorSubtract( skel->bounds[ 1 ], lerpedOrigin, skel->bounds[ 1 ] ); } else { VectorCopy( lerpedOrigin, skel->bones[ i ].origin ); } QuatCopy( lerpedQuat, skel->bones[ i ].rotation ); #if defined( REFBONE_NAMES ) Q_strncpyz( skel->bones[ i ].name, channel->name, sizeof( skel->bones[ i ].name ) ); #endif } skel->numBones = anim->numChannels; skel->type = SK_RELATIVE; return qtrue; } //ri.Printf(PRINT_WARNING, "RE_BuildSkeleton: bad animation '%s' with handle %i\n", anim->name, hAnim); // FIXME: clear existing bones and bounds? return qfalse; }
/* ** GLW_LoadOpenGL ** ** GLimp_win.c internal function that attempts to load and use ** a specific OpenGL DLL. */ static qboolean GLW_LoadOpenGL( const char *drivername ) { char buffer[1024]; qboolean cdsFullscreen; Q_strncpyz( buffer, drivername, sizeof( buffer ) ); Q_strlwr( buffer ); // // determine if we're on a standalone driver // if ( strstr( buffer, "opengl32" ) != 0 || r_maskMinidriver->integer ) { glConfig.driverType = GLDRV_ICD; } else { glConfig.driverType = GLDRV_STANDALONE; ri.Printf( PRINT_ALL, "...assuming '%s' is a standalone driver\n", drivername ); if ( strstr( buffer, _3DFX_DRIVER_NAME ) ) { glConfig.driverType = GLDRV_VOODOO; } } // disable the 3Dfx splash screen _putenv( "FX_GLIDE_NO_SPLASH=0" ); // // load the driver and bind our function pointers to it // if ( QGL_Init( buffer ) ) { #if 0 // FIXME: newer 3Dfx drivers means this can go away if ( !Q_stricmp( buffer, _3DFX_DRIVER_NAME ) ) { cdsFullscreen = qfalse; } else #endif { cdsFullscreen = r_fullscreen->integer; } // create the window and set up the context if ( !GLW_StartDriverAndSetMode( drivername, r_mode->integer, r_colorbits->integer, cdsFullscreen ) ) { // if we're on a 24/32-bit desktop and we're going fullscreen on an ICD, // try it again but with a 16-bit desktop if ( glConfig.driverType == GLDRV_ICD ) { if ( r_colorbits->integer != 16 || cdsFullscreen != qtrue || r_mode->integer != 3 ) { if ( !GLW_StartDriverAndSetMode( drivername, 3, 16, qtrue ) ) { goto fail; } } } else { goto fail; } } if ( glConfig.driverType == GLDRV_VOODOO ) { glConfig.isFullscreen = qtrue; } return qtrue; } fail: QGL_Shutdown(); return qfalse; }