/* =========================================================================== Wolfenstein: Enemy Territory GPL Source Code Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company. This file is part of the Wolfenstein: Enemy Territory GPL Source Code (“Wolf ET Source Code”). Wolf ET Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Wolf ET Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Wolf ET Source Code. If not, see . In addition, the Wolf: ET Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Wolf ET Source Code. If not, please request a copy in writing from id Software at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. =========================================================================== */ #include "cg_local.h" int CG_DrawField( int x, int y, int width, int value, int charWidth, int charHeight, qboolean dodrawpic, qboolean leftAlign ); // NERVE - SMF /*void CG_FitTextToWidth( char* instr, int w, int size) { char buffer[1024]; char *s, *p, *c, *ls; int l; strcpy(buffer, instr); memset(instr, 0, size); c = s = instr; p = buffer; ls = NULL; l = 0; while(*p) { *c = *p++; l++; if(*c == ' ') { ls = c; } // store last space, to try not to break mid word c++; if(*p == '\n') { s = c+1; l = 0; } else if(l > w) { if(ls) { *ls = '\n'; l = strlen(ls+1); } else { *c = *(c-1); *(c-1) = '\n'; s = c++; l = 0; } ls = NULL; } } if(c != buffer && (*(c-1) != '\n')) { *c++ = '\n'; } *c = '\0'; }*/ int CG_TrimLeftPixels( char* instr, float scale, float w, int size ) { char buffer[1024]; char *p, *s; int tw; int i; Q_strncpyz( buffer, instr, 1024 ); memset( instr, 0, size ); for ( i = 0, p = buffer; *p; p++, i++ ) { instr[i] = *p; tw = CG_Text_Width( instr, scale, 0 ); if ( tw >= w ) { memset( instr, 0, size ); for ( s = instr, p = &buffer[i + 1]; *p && ( ( s - instr ) < size ); p++, s++ ) { *s = *p; } return tw - w; } } return -1; } void CG_FitTextToWidth_Ext( char* instr, float scale, float w, int size, fontInfo_t* font ) { char buffer[1024]; char *s, *p, *c, *ls; int l; Q_strncpyz( buffer, instr, 1024 ); memset( instr, 0, size ); c = s = instr; p = buffer; ls = NULL; l = 0; while ( *p ) { *c = *p++; l++; if ( *c == ' ' ) { ls = c; } // store last space, to try not to break mid word c++; if ( *p == '\n' ) { s = c + 1; l = 0; } else if ( CG_Text_Width_Ext( s, scale, 0, font ) > w ) { if ( ls ) { *ls = '\n'; s = ls + 1; } else { *c = *( c - 1 ); *( c - 1 ) = '\n'; s = c++; } ls = NULL; l = 0; } } if ( c != buffer && ( *( c - 1 ) != '\n' ) ) { *c++ = '\n'; } *c = '\0'; } void CG_FitTextToWidth2( char* instr, float scale, float w, int size ) { char buffer[1024]; char *s, *p, *c, *ls; int l; Q_strncpyz( buffer, instr, 1024 ); memset( instr, 0, size ); c = s = instr; p = buffer; ls = NULL; l = 0; while ( *p ) { *c = *p++; l++; if ( *c == ' ' ) { ls = c; } // store last space, to try not to break mid word c++; if ( *p == '\n' ) { s = c + 1; l = 0; } else if ( CG_Text_Width( s, scale, 0 ) > w ) { if ( ls ) { *ls = '\n'; s = ls + 1; } else { *c = *( c - 1 ); *( c - 1 ) = '\n'; s = c++; } ls = NULL; l = 0; } } if ( c != buffer && ( *( c - 1 ) != '\n' ) ) { *c++ = '\n'; } *c = '\0'; } void CG_FitTextToWidth_SingleLine( char* instr, float scale, float w, int size ) { char *s, *p; char buffer[1024]; Q_strncpyz( buffer, instr, 1024 ); memset( instr, 0, size ); p = instr; for ( s = buffer; *s; s++, p++ ) { *p = *s; if ( CG_Text_Width( instr, scale, 0 ) > w ) { *p = '\0'; return; } } } /* ============== weapIconDrawSize ============== */ static int weapIconDrawSize( int weap ) { switch ( weap ) { // weapons to not draw // case WP_KNIFE: // return 0; // weapons with 'wide' icons case WP_THOMPSON: case WP_MP40: case WP_STEN: case WP_PANZERFAUST: case WP_FLAMETHROWER: // case WP_SPEARGUN: case WP_GARAND: case WP_FG42: case WP_FG42SCOPE: case WP_KAR98: case WP_GPG40: case WP_CARBINE: case WP_M7: case WP_MOBILE_MG42: case WP_MOBILE_MG42_SET: case WP_K43: case WP_GARAND_SCOPE: case WP_K43_SCOPE: case WP_MORTAR: case WP_MORTAR_SET: return 2; } return 1; } /* ============== CG_DrawPlayerWeaponIcon ============== */ void CG_DrawPlayerWeaponIcon( rectDef_t *rect, qboolean drawHighlighted, int align, vec4_t *refcolor ) { int size; int realweap; // DHM - Nerve qhandle_t icon; float scale,halfScale; vec4_t hcolor; VectorCopy( *refcolor, hcolor ); hcolor[3] = 1.f; if ( cg.predictedPlayerEntity.currentState.eFlags & EF_MG42_ACTIVE || cg.predictedPlayerEntity.currentState.eFlags & EF_MOUNTEDTANK ) { realweap = WP_MOBILE_MG42; } else { realweap = cg.predictedPlayerState.weapon; } size = weapIconDrawSize( realweap ); if ( !size ) { return; } if ( cg.predictedPlayerEntity.currentState.eFlags & EF_MOUNTEDTANK && cg_entities[cg_entities[ cg_entities[ cg.snap->ps.clientNum ].tagParent ].tankparent].currentState.density & 8 ) { icon = cgs.media.browningIcon; } else { if ( drawHighlighted ) { //icon = cg_weapons[ realweap ].weaponIcon[1]; icon = cg_weapons[ realweap ].weaponIcon[1]; // we don't have icon[0]; } else { icon = cg_weapons[ realweap ].weaponIcon[1]; } } // pulsing grenade icon to help the player 'count' in their head if ( cg.predictedPlayerState.grenadeTimeLeft ) { // grenades and dynamite set this // these time differently if ( realweap == WP_DYNAMITE ) { if ( ( ( cg.grenLastTime ) % 1000 ) > ( ( cg.predictedPlayerState.grenadeTimeLeft ) % 1000 ) ) { trap_S_StartLocalSound( cgs.media.grenadePulseSound4, CHAN_LOCAL_SOUND ); } } else { if ( ( ( cg.grenLastTime ) % 1000 ) < ( ( cg.predictedPlayerState.grenadeTimeLeft ) % 1000 ) ) { switch ( cg.predictedPlayerState.grenadeTimeLeft / 1000 ) { case 3: trap_S_StartLocalSound( cgs.media.grenadePulseSound4, CHAN_LOCAL_SOUND ); break; case 2: trap_S_StartLocalSound( cgs.media.grenadePulseSound3, CHAN_LOCAL_SOUND ); break; case 1: trap_S_StartLocalSound( cgs.media.grenadePulseSound2, CHAN_LOCAL_SOUND ); break; case 0: trap_S_StartLocalSound( cgs.media.grenadePulseSound1, CHAN_LOCAL_SOUND ); break; } } } scale = (float)( ( cg.predictedPlayerState.grenadeTimeLeft ) % 1000 ) / 100.0f; halfScale = scale * 0.5f; cg.grenLastTime = cg.predictedPlayerState.grenadeTimeLeft; } else { scale = halfScale = 0; } if ( icon ) { float x, y, w, h; if ( size == 1 ) { // draw half width to match the icon asset // start at left x = rect->x - halfScale; y = rect->y - halfScale; w = rect->w / 2 + scale; h = rect->h + scale; switch ( align ) { case ITEM_ALIGN_CENTER: x += rect->w / 4; break; case ITEM_ALIGN_RIGHT: x += rect->w / 2; break; case ITEM_ALIGN_LEFT: default: break; } } else { x = rect->x - halfScale; y = rect->y - halfScale; w = rect->w + scale; h = rect->h + scale; } trap_R_SetColor( hcolor ); // JPW NERVE CG_DrawPic( x, y, w, h, icon ); } } #define CURSORHINT_SCALE 10 /* ============== CG_DrawCursorHints cg_cursorHints.integer == 0: no hints 1: sin size pulse 2: one way size pulse 3: alpha pulse 4+: static image ============== */ void CG_DrawCursorhint( rectDef_t *rect ) { float *color; qhandle_t icon, icon2 = 0; float scale, halfscale; //qboolean redbar = qfalse; qboolean yellowbar = qfalse; if ( !cg_cursorHints.integer ) { return; } CG_CheckForCursorHints(); switch ( cg.cursorHintIcon ) { case HINT_NONE: case HINT_FORCENONE: icon = 0; break; case HINT_DOOR: icon = cgs.media.doorHintShader; break; case HINT_DOOR_ROTATING: icon = cgs.media.doorRotateHintShader; break; case HINT_DOOR_LOCKED: icon = cgs.media.doorLockHintShader; break; case HINT_DOOR_ROTATING_LOCKED: icon = cgs.media.doorRotateLockHintShader; break; case HINT_MG42: icon = cgs.media.mg42HintShader; break; case HINT_BREAKABLE: icon = cgs.media.breakableHintShader; break; case HINT_BREAKABLE_DYNAMITE: icon = cgs.media.dynamiteHintShader; break; case HINT_TANK: icon = cgs.media.tankHintShader; break; case HINT_SATCHELCHARGE: icon = cgs.media.satchelchargeHintShader; break; case HINT_CONSTRUCTIBLE: icon = cgs.media.buildHintShader; break; case HINT_UNIFORM: icon = cgs.media.uniformHintShader; break; case HINT_LANDMINE: icon = cgs.media.landmineHintShader; break; case HINT_CHAIR: icon = cgs.media.notUsableHintShader; // only show 'pickupable' if you're not armed, or are armed with a single handed weapon // rain - WEAPS_ONE_HANDED isn't valid anymore, because // WP_SILENCED_COLT uses a bit >31 (and, therefore, is too large // to be shifted in the way WEAPS_ONE_HANDED does on a 32-bit // system.) If you want to use HINT_CHAIR, you'll need to fix // this. #if 0 if ( !( cg.predictedPlayerState.weapon ) || WEAPS_ONE_HANDED & ( 1 << ( cg.predictedPlayerState.weapon ) ) ) { icon = cgs.media.chairHintShader; } #endif break; case HINT_ALARM: icon = cgs.media.alarmHintShader; break; case HINT_HEALTH: icon = cgs.media.healthHintShader; break; case HINT_TREASURE: icon = cgs.media.treasureHintShader; break; case HINT_KNIFE: icon = cgs.media.knifeHintShader; break; case HINT_LADDER: icon = cgs.media.ladderHintShader; break; case HINT_BUTTON: icon = cgs.media.buttonHintShader; break; case HINT_WATER: icon = cgs.media.waterHintShader; break; case HINT_CAUTION: icon = cgs.media.cautionHintShader; break; case HINT_DANGER: icon = cgs.media.dangerHintShader; break; case HINT_SECRET: icon = cgs.media.secretHintShader; break; case HINT_QUESTION: icon = cgs.media.qeustionHintShader; break; case HINT_EXCLAMATION: icon = cgs.media.exclamationHintShader; break; case HINT_CLIPBOARD: icon = cgs.media.clipboardHintShader; break; case HINT_WEAPON: icon = cgs.media.weaponHintShader; break; case HINT_AMMO: icon = cgs.media.ammoHintShader; break; case HINT_ARMOR: icon = cgs.media.armorHintShader; break; case HINT_POWERUP: icon = cgs.media.powerupHintShader; break; case HINT_HOLDABLE: icon = cgs.media.holdableHintShader; break; case HINT_INVENTORY: icon = cgs.media.inventoryHintShader; break; case HINT_PLYR_FRIEND: icon = cgs.media.hintPlrFriendShader; break; case HINT_PLYR_NEUTRAL: icon = cgs.media.hintPlrNeutralShader; break; case HINT_PLYR_ENEMY: icon = cgs.media.hintPlrEnemyShader; break; case HINT_PLYR_UNKNOWN: icon = cgs.media.hintPlrUnknownShader; break; // DHM - Nerve :: multiplayer hints case HINT_BUILD: icon = cgs.media.buildHintShader; break; case HINT_DISARM: icon = cgs.media.disarmHintShader; break; case HINT_REVIVE: icon = cgs.media.reviveHintShader; break; case HINT_DYNAMITE: icon = cgs.media.dynamiteHintShader; break; // dhm - end // Mad Doc - TDF case HINT_LOCKPICK: icon = cgs.media.doorLockHintShader; // TAT 1/30/2003 - use the locked door hint cursor yellowbar = qtrue; // draw the status bar in yellow so it shows up better break; case HINT_ACTIVATE: case HINT_PLAYER: default: icon = cgs.media.usableHintShader; break; } if ( !icon ) { return; } // color color = CG_FadeColor( cg.cursorHintTime, cg.cursorHintFade ); if ( !color ) { trap_R_SetColor( NULL ); return; } if ( cg_cursorHints.integer == 3 ) { color[3] *= 0.5 + 0.5 * sin( (float)cg.time / 150.0 ); } // size if ( cg_cursorHints.integer >= 3 ) { // no size pulsing scale = halfscale = 0; } else { if ( cg_cursorHints.integer == 2 ) { scale = (float)( ( cg.cursorHintTime ) % 1000 ) / 100.0f; // one way size pulse } else { scale = CURSORHINT_SCALE * ( 0.5 + 0.5 * sin( (float)cg.time / 150.0 ) ); // sin pulse } halfscale = scale * 0.5f; } // set color and draw the hint trap_R_SetColor( color ); CG_DrawPic( rect->x - halfscale, rect->y - halfscale, rect->w + scale, rect->h + scale, icon ); if ( icon2 ) { CG_DrawPic( rect->x - halfscale, rect->y - halfscale, rect->w + scale, rect->h + scale, icon2 ); } trap_R_SetColor( NULL ); // draw status bar under the cursor hint if ( cg.cursorHintValue ) { if ( yellowbar ) { Vector4Set( color, 1, 1, 0, 1.0f ); } else { Vector4Set( color, 0, 0, 1, 0.5f ); } CG_FilledBar( rect->x, rect->y + rect->h + 4, rect->w, 8, color, NULL, NULL, (float)cg.cursorHintValue / 255.0f, 0 ); } } float CG_GetValue( int ownerDraw, int type ) { switch ( ownerDraw ) { default: break; } return -1; } qboolean CG_OtherTeamHasFlag() { return qfalse; } qboolean CG_YourTeamHasFlag() { return qfalse; } // THINKABOUTME: should these be exclusive or inclusive.. // qboolean CG_OwnerDrawVisible( int flags ) { return qfalse; } #define PIC_WIDTH 12 /* ============== CG_DrawWeapStability draw a bar showing current stability level (0-255), max at current weapon/ability, and 'perfect' reference mark probably only drawn for scoped weapons ============== */ void CG_DrawWeapStability( rectDef_t *rect ) { vec4_t goodColor = {0, 1, 0, 0.5f}, badColor = {1, 0, 0, 0.5f}; if ( !cg_drawSpreadScale.integer ) { return; } if ( cg_drawSpreadScale.integer == 1 && !BG_IsScopedWeapon( cg.predictedPlayerState.weapon ) ) { // cg_drawSpreadScale of '1' means only draw for scoped weapons, '2' means draw all the time (for debugging) return; } if ( cg.predictedPlayerState.weaponstate != WEAPON_READY ) { return; } if ( !( cg.snap->ps.aimSpreadScale ) ) { return; } if ( cg.renderingThirdPerson ) { return; } CG_FilledBar( rect->x, rect->y, rect->w, rect->h, goodColor, badColor, NULL, (float)cg.snap->ps.aimSpreadScale / 255.0f, 2 | 4 | 256 ); // flags (BAR_CENTER|BAR_VERT|BAR_LERP_COLOR) } /* ============== CG_DrawWeapHeat ============== */ void CG_DrawWeapHeat( rectDef_t *rect, int align ) { vec4_t color = {1, 0, 0, 0.2f}, color2 = {1, 0, 0, 0.5f}; int flags = 0; if ( !( cg.snap->ps.curWeapHeat ) ) { return; } if ( align != HUD_HORIZONTAL ) { flags |= 4; // BAR_VERT } flags |= 1; // BAR_LEFT - this is hardcoded now, but will be decided by the menu script flags |= 16; // BAR_BG - draw the filled contrast box // flags|=32; // BAR_BGSPACING_X0Y5 - different style flags |= 256; // BAR_COLOR_LERP CG_FilledBar( rect->x, rect->y, rect->w, rect->h, color, color2, NULL, (float)cg.snap->ps.curWeapHeat / 255.0f, flags ); } /* ============== CG_OwnerDraw ============== */ void CG_OwnerDraw( float x, float y, float w, float h, float text_x, float text_y, int ownerDraw, int ownerDrawFlags, int align, float special, float scale, vec4_t color, qhandle_t shader, int textStyle ) { rectDef_t rect; if ( cg_drawStatus.integer == 0 ) { return; } rect.x = x; rect.y = y; rect.w = w; rect.h = h; switch ( ownerDraw ) { default: break; } } void CG_MouseEvent( int x, int y ) { switch ( cgs.eventHandling ) { case CGAME_EVENT_SPEAKEREDITOR: case CGAME_EVENT_GAMEVIEW: case CGAME_EVENT_CAMPAIGNBREIFING: case CGAME_EVENT_FIRETEAMMSG: cgs.cursorX += x; if ( cgs.cursorX < 0 ) { cgs.cursorX = 0; } else if ( cgs.cursorX > 640 ) { cgs.cursorX = 640; } cgs.cursorY += y; if ( cgs.cursorY < 0 ) { cgs.cursorY = 0; } else if ( cgs.cursorY > 480 ) { cgs.cursorY = 480; } if ( cgs.eventHandling == CGAME_EVENT_SPEAKEREDITOR ) { CG_SpeakerEditorMouseMove_Handling( x, y ); } break; case CGAME_EVENT_DEMO: cgs.cursorX += x; if ( cgs.cursorX < 0 ) { cgs.cursorX = 0; } else if ( cgs.cursorX > 640 ) { cgs.cursorX = 640; } cgs.cursorY += y; if ( cgs.cursorY < 0 ) { cgs.cursorY = 0; } else if ( cgs.cursorY > 480 ) { cgs.cursorY = 480; } if ( x != 0 || y != 0 ) { cgs.cursorUpdate = cg.time + 5000; } break; default: if ( cg.snap->ps.pm_type == PM_INTERMISSION ) { CG_Debriefing_MouseEvent( x, y ); return; } // default handling if ( ( cg.predictedPlayerState.pm_type == PM_NORMAL || cg.predictedPlayerState.pm_type == PM_SPECTATOR ) && cg.showScores == qfalse ) { trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_CGAME ); return; } break; } } /* ================== CG_EventHandling ================== */ void CG_EventHandling( int type, qboolean fForced ) { if ( cg.demoPlayback && type == CGAME_EVENT_NONE && !fForced ) { type = CGAME_EVENT_DEMO; } if ( type != CGAME_EVENT_NONE ) { trap_Cvar_Set( "cl_bypassMouseInput", 0 ); } switch ( type ) { // OSP - Demo support case CGAME_EVENT_DEMO: cgs.fResize = qfalse; cgs.fSelect = qfalse; cgs.cursorUpdate = cg.time + 10000; cgs.timescaleUpdate = cg.time + 4000; CG_ScoresUp_f(); break; case CGAME_EVENT_SPEAKEREDITOR: case CGAME_EVENT_GAMEVIEW: case CGAME_EVENT_NONE: case CGAME_EVENT_CAMPAIGNBREIFING: case CGAME_EVENT_FIRETEAMMSG: default: // default handling (cleanup mostly) if ( cgs.eventHandling == CGAME_EVENT_GAMEVIEW ) { cg.showGameView = qfalse; trap_S_FadeBackgroundTrack( 0.0f, 500, 0 ); trap_S_StopStreamingSound( -1 ); cg.limboEndCinematicTime = 0; if ( fForced ) { if ( cgs.limboLoadoutModified ) { trap_SendClientCommand( "rs" ); cgs.limboLoadoutSelected = qfalse; } } } else if ( cgs.eventHandling == CGAME_EVENT_SPEAKEREDITOR ) { if ( type == -CGAME_EVENT_SPEAKEREDITOR ) { type = CGAME_EVENT_NONE; } else { trap_Key_SetCatcher( KEYCATCH_CGAME ); return; } } else if ( cgs.eventHandling == CGAME_EVENT_CAMPAIGNBREIFING ) { type = CGAME_EVENT_GAMEVIEW; } else if ( cgs.eventHandling == CGAME_EVENT_FIRETEAMMSG ) { cg.showFireteamMenu = qfalse; trap_Cvar_Set( "cl_bypassmouseinput", "0" ); } else if ( cg.snap && cg.snap->ps.pm_type == PM_INTERMISSION && fForced ) { trap_UI_Popup( UIMENU_INGAME ); } break; } cgs.eventHandling = type; if ( type == CGAME_EVENT_NONE ) { trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_CGAME ); ccInitial = qfalse; if ( cg.demoPlayback && cg.demohelpWindow != SHOW_OFF ) { CG_ShowHelp_Off( &cg.demohelpWindow ); } } else if ( type == CGAME_EVENT_GAMEVIEW ) { cg.showGameView = qtrue; CG_LimboPanel_Setup(); trap_Key_SetCatcher( KEYCATCH_CGAME ); } else if ( type == CGAME_EVENT_FIRETEAMMSG ) { cgs.ftMenuPos = -1; cgs.ftMenuMode = 0; cg.showFireteamMenu = qtrue; trap_Cvar_Set( "cl_bypassmouseinput", "1" ); trap_Key_SetCatcher( KEYCATCH_CGAME ); } else { trap_Key_SetCatcher( KEYCATCH_CGAME ); } } void CG_KeyEvent( int key, qboolean down ) { switch ( cgs.eventHandling ) { // Demos get their own keys case CGAME_EVENT_DEMO: CG_DemoClick( key, down ); return; case CGAME_EVENT_CAMPAIGNBREIFING: CG_LoadPanel_KeyHandling( key, down ); break; case CGAME_EVENT_FIRETEAMMSG: CG_Fireteams_KeyHandling( key, down ); break; case CGAME_EVENT_GAMEVIEW: CG_LimboPanel_KeyHandling( key, down ); break; case CGAME_EVENT_SPEAKEREDITOR: CG_SpeakerEditor_KeyHandling( key, down ); break; default: if ( cg.snap->ps.pm_type == PM_INTERMISSION ) { CG_Debriefing_KeyEvent( key, down ); return; } // default handling if ( !down ) { return; } if ( ( cg.predictedPlayerState.pm_type == PM_NORMAL || ( cg.predictedPlayerState.pm_type == PM_SPECTATOR && cg.showScores == qfalse ) ) ) { CG_EventHandling( CGAME_EVENT_NONE, qfalse ); return; } break; } } int CG_ClientNumFromName( const char *p ) { int i; for ( i = 0; i < cgs.maxclients; i++ ) { if ( cgs.clientinfo[i].infoValid && Q_stricmp( cgs.clientinfo[i].name, p ) == 0 ) { return i; } } return -1; } void CG_GetTeamColor( vec4_t *color ) { if ( cg.snap->ps.persistant[PERS_TEAM] == TEAM_AXIS ) { ( *color )[0] = 1; ( *color )[3] = .25f; ( *color )[1] = ( *color )[2] = 0; } else if ( cg.snap->ps.persistant[PERS_TEAM] == TEAM_ALLIES ) { ( *color )[0] = ( *color )[1] = 0; ( *color )[2] = 1; ( *color )[3] = .25f; } else { ( *color )[0] = ( *color )[2] = 0; ( *color )[1] = .17f; ( *color )[3] = .25f; } } void CG_RunMenuScript( char **args ) { }