//Scoreboard entry point // This will be called even if the scoreboard is not showing - and will return false if it has faded aka 'not showing' // It will return true if the scoreboard is showing qboolean CG_DrawQ3PScoreboard( void ) { vector4 fadeWhite = { 1.0f, 1.0f, 1.0f, 1.0f }; float fade = 1.0f; if ( cg.warmup && !cg.showScores ) return qfalse; if ( !cg.showScores && cg.snap->ps.pm_type != PM_DEAD && cg.snap->ps.pm_type != PM_INTERMISSION ) { if ( CG_FadeColor2( &fadeWhite, cg.scoreFadeTime, 300.0f ) ) return qfalse; fade = fadeWhite.a; } DrawPlayerCount( fade ); DrawPlayers( fade ); DrawServerInfo( fade ); DrawClientInfo( fade ); CG_LoadDeferredPlayers(); return qtrue; }
// 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]; qboolean IRCG = qfalse; if ( JPLua_Event_ServerCommand() ) return; cmd = CG_Argv( 0 ); // server claimed the command if ( !cmd[0] ) return; if ( !strcmp( cmd, "sxd" ) ) { // siege extended data, contains extra info certain classes may want to know about other clients CG_ParseSiegeExtendedData(); return; } if ( !strcmp( cmd, "sb" ) ) { // siege briefing display CG_SiegeBriefingDisplay( atoi( CG_Argv( 1 ) ), qfalse ); return; } if ( !strcmp( cmd, "scl" ) ) { trap->OpenUIMenu( UIMENU_CLASSSEL ); return; } if ( !strcmp( cmd, "spc" ) ) { if ( !cg.demoPlayback ) { trap->Cvar_Set( "ui_myteam", "3" ); trap->OpenUIMenu( UIMENU_PLAYERCONFIG ); } return; } if ( !strcmp( cmd, "nfr" ) ) { // new force rank int doMenu = 0, setTeam = 0, newRank = 0; if ( trap->Cmd_Argc() < 3 ) { #ifdef _DEBUG Com_Printf( "WARNING: Invalid newForceRank string\n" ); #endif return; } newRank = atoi( CG_Argv( 1 ) ); doMenu = atoi( CG_Argv( 2 ) ); setTeam = atoi( CG_Argv( 3 ) ); trap->Cvar_Set( "ui_rankChange", va( "%i", newRank ) ); trap->Cvar_Set( "ui_myteam", va( "%i", setTeam ) ); if ( !(trap->Key_GetCatcher() & KEYCATCH_UI) && doMenu && !cg.demoPlayback ) trap->OpenUIMenu( UIMENU_PLAYERCONFIG ); return; } if ( !strcmp( cmd, "kg2" ) ) { // Kill a ghoul2 instance in this slot. // If it has been occupied since this message was sent somehow, the worst that can (should) happen is the instance // will have to reinit with its current info. int i, indexNum = 0, argNum = trap->Cmd_Argc(); if ( argNum < 1 ) return; for ( i = 1; i < argNum; i++ ) { indexNum = atoi( CG_Argv( i ) ); if ( cg_entities[indexNum].ghoul2 && trap->G2_HaveWeGhoul2Models( cg_entities[indexNum].ghoul2 ) ) { if ( indexNum < MAX_CLIENTS ) { //You try to do very bad thing! #ifdef _DEBUG Com_Printf( "WARNING: Tried to kill a client ghoul2 instance with a kg2 command!\n" ); #endif return; } CG_KillCEntityG2( indexNum ); } } return; } if ( !strcmp( cmd, "kls" ) ) { // kill looping sounds int indexNum = 0, argNum = trap->Cmd_Argc(); centity_t *clent = NULL, *trackerent = NULL; if ( argNum < 1 ) { assert( 0 ); return; } indexNum = atoi( CG_Argv( 1 ) ); if ( indexNum != -1 ) clent = &cg_entities[indexNum]; if ( argNum >= 2 ) { indexNum = atoi( CG_Argv( 2 ) ); if ( indexNum != -1 ) trackerent = &cg_entities[indexNum]; } if ( clent ) CG_S_StopLoopingSound( clent->currentState.number, -1 ); if ( trackerent ) CG_S_StopLoopingSound( trackerent->currentState.number, -1 ); return; } // this means param 2 is the body index and we want to copy to bodyqueue on it if ( !strcmp( cmd, "ircg" ) ) IRCG = qtrue; if ( !strcmp( cmd, "rcg" ) || IRCG ) { //rcg - Restore Client Ghoul (make sure limbs are reattached and ragdoll state is reset - this must be done reliably) int indexNum = 0, argNum = trap->Cmd_Argc(); centity_t *clent; if ( argNum < 1 ) { assert( 0 ); return; } indexNum = atoi( CG_Argv( 1 ) ); if ( indexNum < 0 || indexNum >= MAX_CLIENTS ) { assert( 0 ); return; } clent = &cg_entities[indexNum]; // this can happen while connecting as a client if ( !clent->ghoul2 ) return; #ifdef _DEBUG if ( !trap->G2_HaveWeGhoul2Models( clent->ghoul2 ) ) assert( !"Tried to reset state on a bad instance. Crash is inevitable." ); #endif if ( IRCG ) { int bodyIndex = 0, weaponIndex = 0, side = 0; centity_t *body; assert( argNum >= 3 ); bodyIndex = atoi( CG_Argv( 2 ) ); weaponIndex = atoi( CG_Argv( 3 ) ); side = atoi( CG_Argv( 4 ) ); body = &cg_entities[bodyIndex]; body->teamPowerType = side ? 1 : 0; CG_BodyQueueCopy( body, clent->currentState.number, weaponIndex ); } // reattach any missing limbs if ( clent->torsoBolt ) CG_ReattachLimb( clent ); // make sure ragdoll state is reset if ( clent->isRagging ) { clent->isRagging = qfalse; trap->G2API_SetRagDoll( clent->ghoul2, NULL ); //calling with null parms resets to no ragdoll. } // clear all the decals as well trap->G2API_ClearSkinGore( clent->ghoul2 ); clent->weapon = 0; clent->ghoul2weapon = NULL; //force a weapon reinit return; } if ( !strcmp( cmd, "cp" ) ) { char strEd[MAX_STRINGED_SV_STRING]; CG_CheckSVStringEdRef( strEd, CG_Argv( 1 ) ); CG_CenterPrint( strEd, SCREEN_HEIGHT * 0.30f, BIGCHAR_WIDTH ); return; } if ( !strcmp( cmd, "cps" ) ) { char strEd[MAX_STRINGED_SV_STRING]; char *x = (char *)CG_Argv( 1 ); if ( x[0] == '@' ) x++; trap->SE_GetStringTextString( x, strEd, MAX_STRINGED_SV_STRING ); //Raz: From OJP // CG_CenterPrint( strEd, SCREEN_HEIGHT * 0.30f, BIGCHAR_WIDTH ); CG_CenterPrint( strEd, SCREEN_HEIGHT * 0.20f, BIGCHAR_WIDTH ); return; } if ( !strcmp( cmd, "cs" ) ) { CG_ConfigStringModified(); return; } if ( !strcmp( cmd, "print" ) ) { char strEd[MAX_STRINGED_SV_STRING]; CG_CheckSVStringEdRef( strEd, CG_Argv( 1 ) ); CG_LogPrintf( cg.log.console, strEd ); trap->Print( "%s", strEd ); return; } if ( !strcmp( cmd, "chat" ) ) { char *msg = JPLua_Event_ChatMessageRecieved( CG_Argv( 1 ) ); //If a JPLua plugin cancelled it, bail if ( !msg ) return; if ( !cg_teamChatsOnly.integer ) { char cbName[MAX_CHATBOX_IDENTIFIER_SIZE] = "normal"; trap->S_StartLocalSound( media.sounds.interface.talk, CHAN_LOCAL_SOUND ); Q_strncpyz( text, msg, MAX_SAY_TEXT ); if ( CG_ContainsChannelEscapeChar( text ) ) Q_strncpyz( cbName, CG_RemoveChannelEscapeChar( text ), sizeof(cbName) ); CG_RemoveChatEscapeChar( text ); CG_LogPrintf( cg.log.console, va( "%s\n", text ) ); if ( cg_newChatbox.integer ) CG_ChatboxAddMessage( text, qfalse, cbName ); else CG_ChatBox_AddString( text ); trap->Print( "*%s\n", text ); Q_CleanString( text, STRIP_COLOUR ); CG_LogPrintf( cg.log.chat, va( "%s\n", text ) ); } return; } if ( !strcmp( cmd, "tchat" ) ) { trap->S_StartLocalSound( media.sounds.interface.talk, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv( 1 ), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); CG_LogPrintf( cg.log.console, va( "%s\n", text ) ); if ( cg_newChatbox.integer ) CG_ChatboxAddMessage( text, qfalse, "team" ); else CG_ChatBox_AddString( text ); trap->Print( "*%s\n", text ); Q_CleanString( text, STRIP_COLOUR ); CG_LogPrintf( cg.log.chat, va( "%s\n", text ) ); return; } //chat with location, possibly localized. if ( !strcmp( cmd, "lchat" ) ) { if ( !cg_teamChatsOnly.integer ) { char name[MAX_STRING_CHARS], loc[MAX_STRING_CHARS], color[8], message[MAX_STRING_CHARS]; if ( trap->Cmd_Argc() < 4 ) return; Q_strncpyz( name, CG_Argv( 1 ), sizeof(name) ); Q_strncpyz( loc, CG_Argv( 2 ), sizeof(loc) ); Q_strncpyz( color, CG_Argv( 3 ), sizeof(color) ); Q_strncpyz( message, CG_Argv( 4 ), sizeof(message) ); if ( loc[0] == '@' ) trap->SE_GetStringTextString( loc + 1, loc, sizeof(loc) ); trap->S_StartLocalSound( media.sounds.interface.talk, CHAN_LOCAL_SOUND ); // Q_strncpyz( text, CG_Argv( 1 ), MAX_SAY_TEXT ); Com_sprintf( text, sizeof(text), "%s" S_COLOR_WHITE "<%s> ^%s%s", name, loc, color, message ); CG_RemoveChatEscapeChar( text ); //Raz: Siege chat now uses the fancy new chatbox if ( cg_newChatbox.integer ) CG_ChatboxAddMessage( text, qfalse, "normal" ); else CG_ChatBox_AddString( text ); trap->Print( "*%s\n", text ); Q_CleanString( text, STRIP_COLOUR ); CG_LogPrintf( cg.log.chat, va( "%s\n", text ) ); } return; } if ( !strcmp( cmd, "ltchat" ) ) { char name[MAX_STRING_CHARS], loc[MAX_STRING_CHARS], color[8], message[MAX_STRING_CHARS]; if ( trap->Cmd_Argc() < 4 ) return; Q_strncpyz( name, CG_Argv( 1 ), sizeof(name) ); Q_strncpyz( loc, CG_Argv( 2 ), sizeof(loc) ); Q_strncpyz( color, CG_Argv( 3 ), sizeof(color) ); Q_strncpyz( message, CG_Argv( 4 ), sizeof(message) ); if ( loc[0] == '@' ) trap->SE_GetStringTextString( loc + 1, loc, sizeof(loc) ); trap->S_StartLocalSound( media.sounds.interface.talk, CHAN_LOCAL_SOUND ); // Q_strncpyz( text, CG_Argv( 1 ), MAX_SAY_TEXT ); Com_sprintf( text, sizeof(text), "%s" S_COLOR_WHITE "<%s> ^%s%s", name, loc, color, message ); CG_RemoveChatEscapeChar( text ); if ( cg_newChatbox.integer ) CG_ChatboxAddMessage( text, qfalse, "team" ); else CG_ChatBox_AddString( text ); trap->Print( "*%s\n", text ); Q_CleanString( text, STRIP_COLOUR ); CG_LogPrintf( cg.log.chat, va( "%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" ) ) { if ( trap->Cmd_Argc() == 4 ) { char shader1[MAX_QPATH], shader2[MAX_QPATH]; Q_strncpyz( shader1, CG_Argv( 1 ), sizeof(shader1) ); Q_strncpyz( shader2, CG_Argv( 2 ), sizeof(shader2) ); trap->R_RemapShader( shader1, shader2, CG_Argv( 3 ) ); return; } return; } // loaddeferred can be both a servercmd and a consolecmd if ( !strcmp( cmd, "loaddefered" ) ) { // FIXME: spelled wrong, but not changing for demo CG_LoadDeferredPlayers(); return; } // clientLevelShot is sent before taking a special screenshot for the menu system during development if ( !strcmp( cmd, "clientLevelShot" ) ) { cg.levelShot = qtrue; return; } trap->Print( "Unknown client game command: %s\n", cmd ); }
/* ======================================================================================================================================= CG_DrawOldScoreboard Draw the normal in-game scoreboard. ======================================================================================================================================= */ qboolean CG_DrawOldScoreboard(void) { int x, y, w, i, n1, n2; float fade; float *fadeColor; char *s; int maxClients; int lineHeight; int topBorderSize, bottomBorderSize; // don't draw amuthing if the menu or console is up if (cg_paused.integer) { cg.deferredPlayerLoading = 0; return qfalse; } if (cgs.gametype == GT_SINGLE_PLAYER && cg.predictedPlayerState.pm_type == PM_INTERMISSION) { cg.deferredPlayerLoading = 0; return qfalse; } // don't draw scoreboard during death while warmup up if (cg.warmup && !cg.showScores) { return qfalse; } if (cg.showScores || cg.predictedPlayerState.pm_type == PM_DEAD || cg.predictedPlayerState.pm_type == PM_INTERMISSION) { fade = 1.0; fadeColor = colorWhite; } else { fadeColor = CG_FadeColor(cg.scoreFadeTime, FADE_TIME); if (!fadeColor) { // next time scoreboard comes up, don't print killer cg.deferredPlayerLoading = 0; cg.killerName[0] = 0; return qfalse; } fade = *fadeColor; } // fragged by ... line if (cg.killerName[0]) { s = va("Fragged by %s", cg.killerName); w = CG_DrawStrlen(s) * BIGCHAR_WIDTH; x = (SCREEN_WIDTH - w) / 2; y = 40; CG_DrawBigString(x, y, s, fade); } // current rank if (cgs.gametype < GT_TEAM) { if (cg.snap->ps.persistant[PERS_TEAM] != TEAM_SPECTATOR) { s = va("%s place with %i", CG_PlaceString(cg.snap->ps.persistant[PERS_RANK] + 1), cg.snap->ps.persistant[PERS_SCORE]); w = CG_DrawStrlen(s) * BIGCHAR_WIDTH; x = (SCREEN_WIDTH - w) / 2; y = 60; CG_DrawBigString(x, y, s, fade); } } else { if (cg.teamScores[0] == cg.teamScores[1]) { s = va("Teams are tied at %i", cg.teamScores[0]); } else if (cg.teamScores[0] >= cg.teamScores[1]) { s = va("Red leads %i to %i", cg.teamScores[0], cg.teamScores[1]); } else { s = va("Blue leads %i to %i", cg.teamScores[1], cg.teamScores[0]); } w = CG_DrawStrlen(s) * BIGCHAR_WIDTH; x = (SCREEN_WIDTH - w) / 2; y = 60; CG_DrawBigString(x, y, s, fade); } // scoreboard y = SB_HEADER; CG_DrawPic(SB_SCORE_X + (SB_RATING_WIDTH / 2), y, 64, 32, cgs.media.scoreboardScore); CG_DrawPic(SB_PING_X - (SB_RATING_WIDTH / 2), y, 64, 32, cgs.media.scoreboardPing); CG_DrawPic(SB_TIME_X - (SB_RATING_WIDTH / 2), y, 64, 32, cgs.media.scoreboardTime); CG_DrawPic(SB_NAME_X - (SB_RATING_WIDTH / 2), y, 64, 32, cgs.media.scoreboardName); y = SB_TOP; // If there are more than SB_MAXCLIENTS_NORMAL, use the interleaved scores if (cg.numScores > SB_MAXCLIENTS_NORMAL) { maxClients = SB_MAXCLIENTS_INTER; lineHeight = SB_INTER_HEIGHT; topBorderSize = 8; bottomBorderSize = 16; } else { maxClients = SB_MAXCLIENTS_NORMAL; lineHeight = SB_NORMAL_HEIGHT; topBorderSize = 16; bottomBorderSize = 16; } localClient = qfalse; if (cgs.gametype >= GT_TEAM) { // teamplay scoreboard y += lineHeight / 2; if (cg.teamScores[0] >= cg.teamScores[1]) { n1 = CG_TeamScoreboard(y, TEAM_RED, fade, maxClients, lineHeight); CG_DrawTeamBackground(0, y - topBorderSize, 640, n1 * lineHeight + bottomBorderSize, 0.33f, TEAM_RED); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; maxClients -= n1; n2 = CG_TeamScoreboard(y, TEAM_BLUE, fade, maxClients, lineHeight); CG_DrawTeamBackground(0, y - topBorderSize, 640, n2 * lineHeight + bottomBorderSize, 0.33f, TEAM_BLUE); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; maxClients -= n2; } else { n1 = CG_TeamScoreboard(y, TEAM_BLUE, fade, maxClients, lineHeight); CG_DrawTeamBackground(0, y - topBorderSize, 640, n1 * lineHeight + bottomBorderSize, 0.33f, TEAM_BLUE); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; maxClients -= n1; n2 = CG_TeamScoreboard(y, TEAM_RED, fade, maxClients, lineHeight); CG_DrawTeamBackground(0, y - topBorderSize, 640, n2 * lineHeight + bottomBorderSize, 0.33f, TEAM_RED); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; maxClients -= n2; } n1 = CG_TeamScoreboard(y, TEAM_SPECTATOR, fade, maxClients, lineHeight); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; } else { // free for all scoreboard n1 = CG_TeamScoreboard(y, TEAM_FREE, fade, maxClients, lineHeight); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; n2 = CG_TeamScoreboard(y, TEAM_SPECTATOR, fade, maxClients - n1, lineHeight); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; } if (!localClient) { // draw local client at the bottom for (i = 0; i < cg.numScores; i++) { if (cg.scores[i].client == cg.snap->ps.clientNum) { CG_DrawClientScore(y, &cg.scores[i], fadeColor, fade, lineHeight == SB_NORMAL_HEIGHT); break; } } } // load any models that have been deferred if (++cg.deferredPlayerLoading > 10) { CG_LoadDeferredPlayers(); } return qtrue; }
static void CG_ServerCommand( void ) { const char *cmd; char text[MAX_NOTIFICATION_CHARS]; // extra bytes for name qboolean IRCG = qfalse; cmd = CG_Argv(0); if ( !cmd[0] ) { // server claimed the command return; } // Jedi Knight Galaxies // Check the crossover if ( uiImports->HandleServerCommand( cmd ) ) return; if (!strcmp(cmd, "svr")) { // Server redirect CG_ServerRedirect(); return; } if (!strcmp(cmd, "cin")) { Cin_ProcessCinematic_f(); return; } if (!strcmp(cmd, "cinb")) { Cin_ProcessCinematicBinary_f(); return; } if (!strcmp(cmd, "cb")) { CinBuild_Cmd_f(); return; } if (!strcmp(cmd, "cbb")) { Cmd_CBB_f(); return; } if (!strcmp(cmd, "dc")) { cg.deathcamFadeStart = cg.time; cg.deathcamTime = atoi(_Cmd_Argv(1)); cg.deathcamRadius = atoi(_Cmd_Argv(2)); VectorSet(cg.deathcamCenter, atof(_Cmd_Argv(3)),atof(_Cmd_Argv(4)),atof(_Cmd_Argv(5))); ChatBox_CloseChat(); return; } if (!strcmp(cmd, "dcr")) { cg.deathcamFadeStart = 0; cg.deathcamTime = 0; cg.deathcamRadius = 0; VectorSet(cg.deathcamCenter, 0, 0, 0); return; } // Forced weapon change if (!strcmp(cmd, "chw")) { cg.weaponSelect = atoi(CG_Argv(1)); return; } if (!strcmp(cmd, "clearinv")) { cg.playerInventory->clear(); return; } if ( !strcmp( cmd, "spc" ) ) { trap->Cvar_Set("ui_myteam", "3"); trap->OpenUIMenu(UIMENU_PLAYERCONFIG); //UIMENU_CLASSSEL return; } if ( !strcmp( cmd, "nfr" ) ) { //"nfr" == "new force rank" (want a short string) int doMenu = 0; int setTeam = 0; int newRank = 0; if (trap->Cmd_Argc() < 3) { #ifdef _DEBUG Com_Printf("WARNING: Invalid newForceRank string\n"); #endif return; } newRank = atoi(CG_Argv(1)); doMenu = atoi(CG_Argv(2)); setTeam = atoi(CG_Argv(3)); trap->Cvar_Set("ui_rankChange", va("%i", newRank)); trap->Cvar_Set("ui_myteam", va("%i", setTeam)); if (!( trap->Key_GetCatcher() & KEYCATCH_UI ) && doMenu) { trap->OpenUIMenu(UIMENU_PLAYERCONFIG); } return; } if ( !strcmp( cmd, "kg2" ) ) { //Kill a ghoul2 instance in this slot. //If it has been occupied since this message was sent somehow, the worst that can (should) happen //is the instance will have to reinit with its current info. int indexNum = 0; int argNum = trap->Cmd_Argc(); int i = 1; if (argNum < 1) { return; } while (i < argNum) { indexNum = atoi(CG_Argv(i)); if (cg_entities[indexNum].ghoul2 && trap->G2_HaveWeGhoul2Models(cg_entities[indexNum].ghoul2)) { if (indexNum < MAX_CLIENTS) { //You try to do very bad thing! #ifdef _DEBUG Com_Printf("WARNING: Tried to kill a client ghoul2 instance with a kg2 command!\n"); #endif return; } CG_KillCEntityG2(indexNum); } i++; } return; } if (!strcmp(cmd, "kls")) { //kill looping sounds int indexNum = 0; int argNum = trap->Cmd_Argc(); centity_t *clent = NULL; centity_t *trackerent = NULL; if (argNum < 1) { assert(0); return; } indexNum = atoi(CG_Argv(1)); if (indexNum != -1) { clent = &cg_entities[indexNum]; } if (argNum >= 2) { indexNum = atoi(CG_Argv(2)); if (indexNum != -1) { trackerent = &cg_entities[indexNum]; } } if (clent) { CG_S_StopLoopingSound(clent->currentState.number, -1); } if (trackerent) { CG_S_StopLoopingSound(trackerent->currentState.number, -1); } return; } //eezstreet add if ( !strcmp (cmd, "aciset") ) { int number = atoi(CG_Argv(1)); cg.weaponSelect = number; return; } if ( !strcmp (cmd, "ieq") ) { if ( trap->Cmd_Argc() == 3 ) { int newItem = atoi (CG_Argv (1)); int oldItem = atoi (CG_Argv (2)); (*cg.playerInventory)[newItem].equipped = true; if (oldItem != -1) { (*cg.playerInventory)[oldItem].equipped = false; } uiImports->InventoryNotify( INVENTORYNOTIFY_UPDATE ); } return; } if ( !strcmp (cmd, "iueq") ) { if ( trap->Cmd_Argc() == 2 ) { int slot = atoi (CG_Argv (1)); (*cg.playerInventory)[slot].equipped = false; uiImports->InventoryNotify( INVENTORYNOTIFY_UPDATE ); } return; } if ( !strcmp (cmd, "inventory_update") ) { cg.predictedPlayerState.credits = atoi(CG_Argv(1)); uiImports->InventoryNotify (INVENTORYNOTIFY_UPDATE); return; } if(!strcmp(cmd, "frcaci")) { // Force ACI JKG_CG_FillACISlot(atoi(CG_Argv(0)), atoi(CG_Argv(1))); return; } if (!strcmp(cmd, "ircg")) { //this means param 2 is the body index and we want to copy to bodyqueue on it IRCG = qtrue; } if (!strcmp(cmd, "rcg") || IRCG) { //rcg - Restore Client Ghoul (make sure limbs are reattached and ragdoll state is reset - this must be done reliably) int indexNum = 0; int argNum = trap->Cmd_Argc(); centity_t *clent; if (argNum < 1) { assert(0); return; } indexNum = atoi(CG_Argv(1)); if (indexNum < 0 || indexNum >= MAX_CLIENTS) { assert(0); return; } clent = &cg_entities[indexNum]; //assert(clent->ghoul2); if (!clent->ghoul2) { //this can happen while connecting as a client return; } #ifdef _DEBUG if (!trap->G2_HaveWeGhoul2Models(clent->ghoul2)) { assert(!"Tried to reset state on a bad instance. Crash is inevitable."); } #endif if (IRCG) { int bodyIndex = 0; int weaponIndex = 0; int weaponVariation = 0; int side = 0; centity_t *body; assert(argNum >= 4); bodyIndex = atoi(CG_Argv(2)); weaponIndex = atoi(CG_Argv(3)); weaponVariation = atoi (CG_Argv (4)); side = atoi(CG_Argv(5)); body = &cg_entities[bodyIndex]; if (side) { body->teamPowerType = qtrue; //light side } else { body->teamPowerType = qfalse; //dark side } CG_BodyQueueCopy(body, clent->currentState.number, weaponIndex, weaponVariation); } //reattach any missing limbs if (clent->torsoBolt) { CG_ReattachLimb(clent); } //make sure ragdoll state is reset if (clent->isRagging) { clent->isRagging = qfalse; trap->G2API_SetRagDoll(clent->ghoul2, NULL); //calling with null parms resets to no ragdoll. } //clear all the decals as well trap->G2API_ClearSkinGore(clent->ghoul2); clent->weapon = 0; clent->ghoul2weapon = NULL; //force a weapon reinit return; } if ( !strcmp( cmd, "cp" ) ) { char strEd[MAX_STRINGED_SV_STRING]; CG_CheckSVStringEdRef(strEd, CG_Argv(1)); CG_CenterPrint( strEd, SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH ); return; } if ( !strcmp( cmd, "cps" ) ) { char strEd[MAX_STRINGED_SV_STRING]; char *x = (char *)CG_Argv(1); if (x[0] == '@') { x++; } trap->SE_GetStringTextString(x, strEd, MAX_STRINGED_SV_STRING); CG_CenterPrint( strEd, SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH ); return; } if ( !strcmp( cmd, "cs" ) ) { CG_ConfigStringModified(); return; } // Warzone Tickets... if ( !strcmp( cmd, "tkt" ) ) { //CG_Printf("CG_Argv(0) = %s. CG_Argv(1) = %s. CG_Argv(2) = %s. CG_Argv(3) = %s.\n", CG_Argv(0), CG_Argv(1), CG_Argv(2), CG_Argv(3)); cgs.redtickets = atoi(CG_Argv(1)); cgs.bluetickets = atoi(CG_Argv(2)); return; } if ( !strcmp( cmd, "print" ) ) { char strEd[MAX_STRINGED_SV_STRING]; CG_CheckSVStringEdRef(strEd, CG_Argv(1)); trap->Print( "%s", strEd ); return; } if ( !strcmp( cmd, "chat" ) ) { if ( !cg_teamChatsOnly.integer ) { trap->S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv(2), sizeof (text) ); CG_RemoveChatEscapeChar( text ); CG_ChatBox_AddString(text, atoi(CG_Argv(1))); trap->Print( "*%s\n", text ); } return; } if ( !strcmp( cmd, "tchat" ) ) { trap->S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv(2), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); CG_ChatBox_AddString(text, atoi(CG_Argv(1))); trap->Print( "*%s\n", text ); return; } //chat with location, possibly localized. if ( !strcmp( cmd, "lchat" ) ) { if ( !cg_teamChatsOnly.integer ) { char name[MAX_STRING_CHARS]; char loc[MAX_STRING_CHARS]; char color[8]; char message[MAX_STRING_CHARS]; int fadeLevel; if (trap->Cmd_Argc() < 4) { return; } fadeLevel = atoi(CG_Argv(1)); strcpy(name, CG_Argv(2)); strcpy(loc, CG_Argv(3)); strcpy(color, CG_Argv(4)); strcpy(message, CG_Argv(5)); if (loc[0] == '@') { //get localized text trap->SE_GetStringTextString(loc+1, loc, MAX_STRING_CHARS); } trap->S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); //Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT ); Com_sprintf(text, MAX_SAY_TEXT, "%s<%s>^%s%s", name, loc, color, message); CG_RemoveChatEscapeChar( text ); CG_ChatBox_AddString(text, fadeLevel); trap->Print( "*%s\n", text ); } return; } if ( !strcmp( cmd, "ltchat" ) ) { char name[MAX_STRING_CHARS]; char loc[MAX_STRING_CHARS]; char color[8]; char message[MAX_STRING_CHARS]; int fadeLevel; if (trap->Cmd_Argc() < 4) { return; } fadeLevel = atoi(CG_Argv(1)); strcpy(name, CG_Argv(2)); strcpy(loc, CG_Argv(3)); strcpy(color, CG_Argv(4)); strcpy(message, CG_Argv(5)); if (loc[0] == '@') { //get localized text trap->SE_GetStringTextString(loc+1, loc, MAX_STRING_CHARS); } trap->S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); //Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT ); Com_sprintf(text, MAX_SAY_TEXT, "%s<%s> ^%s%s", name, loc, color, message); CG_RemoveChatEscapeChar( text ); CG_ChatBox_AddString(text, fadeLevel); trap->Print( "*%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 ( !strcmp( cmd, "fmrefresh" ) ) { JKG_FireModeUpdate(); return; } //[OverflowProtection] //this command was vulnerable to buffer overflow and could cause problems due to not properly returning //after processing the command. if ( !strcmp( cmd, "remapShader" ) ) { if ( trap->Cmd_Argc() == 4 ) { char shader1[MAX_QPATH]; char shader2[MAX_QPATH]; Q_strncpyz( shader1, CG_Argv( 1 ), sizeof( shader1 ) ); Q_strncpyz( shader2, CG_Argv( 2 ), sizeof( shader2 ) ); trap->R_RemapShader( shader1, shader2, CG_Argv( 3 ) ); return; } return; } //[/OverflowProtection] // loaddeferred can be both a servercmd and a consolecmd if ( !strcmp( cmd, "loaddefered" ) ) { // FIXME: spelled wrong, but not changing for demo CG_LoadDeferredPlayers(); return; } // clientLevelShot is sent before taking a special screenshot for // the menu system during development if ( !strcmp( cmd, "clientLevelShot" ) ) { cg.levelShot = qtrue; return; } // Team Party List if ( !strcmp( cmd, "tpl" )) { int i, iID, iLen; for ( i = 0, iLen = (( trap->Cmd_Argc() - 1 ) / 5 ); i < iLen; i++ ) { iID = atoi( CG_Argv( i * 5 + 1 )); cgs.partyList[iID].id = atoi( CG_Argv( i * 5 + 2 )); cgs.partyList[iID].classId = atoi( CG_Argv( i * 5 + 3 )); cgs.partyList[iID].time = atoi( CG_Argv( i * 5 + 4 )); Q_strncpyz( cgs.partyList[iID].message, ( char * ) CG_Argv( i * 5 + 5 ), sizeof( cgs.partyList[iID].message )); if ( cgs.partyList[iID].time > cgs.partyListTime ) { cgs.partyListTime = cgs.partyList[iID].time; } } /* Notify UI */ uiImports->PartyMngtNotify( PARTYNOTIFY_UPDATESEEKERS ); return; } // Team Party Invites if ( !strcmp( cmd, "tpi" )) { /* Can't do this with an active party o.o */ cgs.party.active = 0; /* Scan the incoming string into the party struct */ sscanf( CG_Argv( 1 ), "%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i", &cgs.party.invites[0].id, &cgs.party.invites[0].leaderId, &cgs.party.invites[0].memberCount, &cgs.party.invites[1].id, &cgs.party.invites[1].leaderId, &cgs.party.invites[1].memberCount, &cgs.party.invites[2].id, &cgs.party.invites[2].leaderId, &cgs.party.invites[2].memberCount, &cgs.party.invites[3].id, &cgs.party.invites[3].leaderId, &cgs.party.invites[3].memberCount, &cgs.party.invites[4].id, &cgs.party.invites[4].leaderId, &cgs.party.invites[4].memberCount ); /* Win cake */ /* Notify UI */ uiImports->PartyMngtNotify( PARTYNOTIFY_UPDATESTATE ); return; } // Team Party Update if ( !strcmp( cmd, "tpu" )) { int i; /* Set the party status to active */ cgs.party.active = 1; /* Scan the incoming string into the party struct */ sscanf( CG_Argv( 1 ), "%i %i %i %i %i %i %i %i %i %i %i", &cgs.party.number, &cgs.party.members[0].id, &cgs.party.members[0].classId, &cgs.party.members[1].id, &cgs.party.members[1].classId, &cgs.party.members[2].id, &cgs.party.members[2].classId, &cgs.party.members[3].id, &cgs.party.members[3].classId, &cgs.party.members[4].id, &cgs.party.members[4].classId ); /* Parse the members and fix the status and ID's! */ for ( i = 0; i < 5; i++ ) { if ( cgs.party.members[i].id < 0 ) { cgs.party.members[i].id = abs( cgs.party.members[i].id + 1 ); cgs.party.members[i].status = -1; } else { cgs.party.members[i].status = 0; } } /* Set the party leader status accordingly */ cgs.party.members[0].status = 1; /* Notify UI */ uiImports->PartyMngtNotify( PARTYNOTIFY_UPDATESTATE ); return; } if( !strcmp( cmd, "pInv" )) { BG_ReceivedItemPacket(BG_ItemPacketFromName(CG_Argv(1))); uiImports->ItemsUpdated(); return; } if (!strcmp(cmd, "pTrade")) { BG_ReceivedTradePacket(BG_TradePacketFromName(CG_Argv(1))); uiImports->ItemsUpdated(); return; } // UQ1: Use an event!!!! // eez: Again, this is only getting sent to one client, so no go if( !strcmp( cmd, "hitmarker") ) { // All this does is make a hitmarker display. Nothing too fancy. trap->S_StartSound(NULL, cg.clientNum, CHAN_AUTO, cgs.media.hitmarkerSound); cg.hitmarkerLastTime = cg.time + 1000; return; } if( !strcmp( cmd, "notify") ) { // add a notification to the display CG_Notifications_Add((char *)CG_Argv(2), qfalse); // first arg is ignored. it's supposed to specify the type of message but it's unused. return; } if (!strcmp(cmd, "apc")) { // Ammo price check response uiImports->InventoryPriceCheckResult(atoi(CG_Argv(1)), atoi(CG_Argv(2))); return; } if (!strcmp(cmd, "cbi")) { // Client bought item char* playerName = va("%s", CG_Argv(2)); for (int i = 3; i < trap->Cmd_Argc(); i++) { playerName = va("%s %s", playerName, CG_Argv(i)); } JKG_ClientBoughtItem(playerName, atoi(CG_Argv(1))); return; } //eezstreet end trap->Print( "Unknown client game command: %s\n", cmd ); }
/* ================= 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) ); #ifdef MISSIONPACK cmd = CG_Argv(1); // yes, this is obviously a hack, but so is the way we hear about // votes passing or failing if ( !Q_stricmpn( cmd, "vote failed", 11 ) || !Q_stricmpn( cmd, "team vote failed", 16 )) { trap_S_StartLocalSound( cgs.media.voteFailed, CHAN_ANNOUNCER ); } else if ( !Q_stricmpn( cmd, "vote passed", 11 ) || !Q_stricmpn( cmd, "team vote passed", 16 ) ) { trap_S_StartLocalSound( cgs.media.votePassed, CHAN_ANNOUNCER ); } #endif return; } if ( !strcmp( cmd, "chat" ) ) { if ( !cg_teamChatsOnly.integer ) { trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); CG_Printf( "%s\n", text ); } return; } if ( !strcmp( cmd, "tchat" ) ) { trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); CG_AddToTeamChat( text ); CG_Printf( "%s\n", text ); return; } if ( !strcmp( cmd, "vchat" ) ) { CG_VoiceChat( SAY_ALL ); return; } if ( !strcmp( cmd, "vtchat" ) ) { CG_VoiceChat( SAY_TEAM ); return; } if ( !strcmp( cmd, "vtell" ) ) { CG_VoiceChat( SAY_TELL ); return; } if ( !strcmp( cmd, "scores" ) ) { CG_ParseScores(); return; } if ( !strcmp( cmd, "tinfo" ) ) { CG_ParseTeamInfo(); return; } if ( !strcmp( cmd, "map_restart" ) ) { CG_MapRestart(); return; } if ( Q_stricmp (cmd, "remapShader") == 0 ) { if (trap_Argc() == 4) { trap_R_RemapShader(CG_Argv(1), CG_Argv(2), CG_Argv(3)); } } // loaddeferred can be both a servercmd and a consolecmd if ( !strcmp( cmd, "loaddefered" ) ) { // FIXME: spelled wrong, but not changing for demo CG_LoadDeferredPlayers(); return; } // clientLevelShot is sent before taking a special screenshot for // the menu system during development if ( !strcmp( cmd, "clientLevelShot" ) ) { cg.levelShot = qtrue; return; } // CORKSCREW accuracy challenge if ( !strcmp( cmd, "drawchallengeinfo" ) ) { cg.encryptChallengeInfo = ( rand() % 9000 ) + 1000; cg.drawChallengeInfoScreenshotTime = 0; cg.drawChallengeInfo = qtrue; cg.drawChallengeInfoScreenshot = qtrue; cg.showScores = qtrue; return; } CG_Printf( "Unknown client game command: %s\n", cmd ); }
/* ================= CG_DrawActiveFrame Generates and draws a game scene and status information at the given time. ================= */ void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demoPlayback ) { int inwater; qboolean renderClientViewport[MAX_SPLITVIEW]; int i; cg.time = serverTime; cg.demoPlayback = demoPlayback; // update cvars CG_UpdateCvars(); // if we are only updating the screen as a loading // pacifier, don't even try to read snapshots if ( cg.infoScreenText[0] != 0 ) { CG_DrawInformation(); return; } // any looped sounds will be respecified as entities // are added to the render list trap_S_ClearLoopingSounds(qfalse); // clear all the render lists trap_R_ClearScene(); // set up cg.snap and possibly cg.nextSnap CG_ProcessSnapshots(); // if we haven't received any snapshots yet, all // we can draw is the information screen if ( !cg.snap || ( cg.snap->snapFlags & SNAPFLAG_NOT_ACTIVE ) ) { CG_DrawInformation(); return; } // this counter will be bumped for every valid scene we generate cg.clientFrame++; // Use single camera/viewport at intermission for (i = 0; i < CG_MaxSplitView(); i++) { if (cg.snap->lcIndex[i] != -1 && cg.snap->pss[i].pm_type != PM_INTERMISSION) { // client present and not at intermission, keep viewports separate. break; } } cg.singleCamera = (cg.snap->numPSs > 1) && (i == CG_MaxSplitView()); cg.numViewports = 0; for (i = 0; i < CG_MaxSplitView(); i++) { if (cg.snap->lcIndex[i] == -1) { renderClientViewport[i] = qfalse; continue; } cg.cur_localClientNum = i; cg.cur_lc = &cg.localClients[i]; cg.cur_ps = &cg.snap->pss[cg.snap->lcIndex[i]]; // Check if viewport should be drawn. if ( cg.singleCamera && cg.numViewports >= 1 ) { renderClientViewport[i] = qfalse; } else { cg.numViewports++; renderClientViewport[i] = qtrue; } // let the client system know what our weapon and zoom settings are trap_SetUserCmdValue( cg.cur_lc->weaponSelect, cg.cur_lc->zoomSensitivity, cg.cur_localClientNum ); // update cg.predictedPlayerState CG_PredictPlayerState(); // Remove expired console lines if( cg.cur_lc->consoleLines[ 0 ].time + cg_consoleLatency.integer < cg.time && cg_consoleLatency.integer > 0 ) { CG_RemoveNotifyLine( cg.cur_lc ); } } // If all local clients dropped out from playing still draw main local client. if (cg.numViewports == 0) { cg.numViewports = 1; renderClientViewport[0] = qtrue; } // play lead change annoucement and time/frag limit warnings CG_CheckGameSounds(); // add buffered sounds CG_PlayBufferedSounds(); #ifdef MISSIONPACK // play buffered voice chats CG_PlayBufferedVoiceChats(); #endif for (i = 0, cg.viewport = -1; i < CG_MaxSplitView(); i++) { if (!renderClientViewport[i]) { continue; } cg.viewport++; cg.cur_localClientNum = i; cg.cur_lc = &cg.localClients[i]; cg.cur_ps = &cg.snap->pss[cg.snap->lcIndex[i]]; // decide on third person view cg.cur_lc->renderingThirdPerson = cg_thirdPerson[cg.cur_localClientNum].integer || (cg.cur_ps->stats[STAT_HEALTH] <= 0); CG_PB_ClearPolyBuffers(); // build cg.refdef inwater = CG_CalcViewValues(); CG_SetupFrustum(); // first person blend blobs, done after AnglesToAxis if ( !cg.cur_lc->renderingThirdPerson ) { CG_DamageBlendBlob(); } // build the render lists if ( !cg.cur_lc->hyperspace ) { CG_AddPacketEntities(); // adter calcViewValues, so predicted player state is correct CG_AddMarks(); CG_AddParticles (); CG_AddLocalEntities(); CG_AddAtmosphericEffects(); } CG_AddViewWeapon( &cg.cur_lc->predictedPlayerState ); // finish up the rest of the refdef if ( cg.testModelEntity.hModel ) { CG_AddTestModel(); } cg.refdef.time = cg.time; memcpy( cg.refdef.areamask, cg.snap->areamask, sizeof( cg.refdef.areamask ) ); // warning sounds when powerup is wearing off CG_PowerupTimerSounds(); // update audio positions trap_S_Respatialize( cg.cur_ps->clientNum, cg.refdef.vieworg, cg.refdef.viewaxis, inwater, !cg.cur_lc->renderingThirdPerson ); // make sure the lagometerSample and frame timing isn't done twice when in stereo if ( stereoView != STEREO_RIGHT && cg.viewport == 0 ) { cg.frametime = cg.time - cg.oldTime; if ( cg.frametime < 0 ) { cg.frametime = 0; } cg.oldTime = cg.time; CG_AddLagometerFrameInfo(); } if (cg_timescale.value != cg_timescaleFadeEnd.value) { if (cg_timescale.value < cg_timescaleFadeEnd.value) { cg_timescale.value += cg_timescaleFadeSpeed.value * ((float)cg.frametime) / 1000; if (cg_timescale.value > cg_timescaleFadeEnd.value) cg_timescale.value = cg_timescaleFadeEnd.value; } else { cg_timescale.value -= cg_timescaleFadeSpeed.value * ((float)cg.frametime) / 1000; if (cg_timescale.value < cg_timescaleFadeEnd.value) cg_timescale.value = cg_timescaleFadeEnd.value; } if (cg_timescaleFadeSpeed.value) { trap_Cvar_Set("timescale", va("%f", cg_timescale.value)); } } // actually issue the rendering calls CG_DrawActive( stereoView ); } // load any models that have been deferred if a scoreboard is shown if ( !CG_AnyScoreboardShowing() ) { cg.deferredPlayerLoading = 0; } else if ( ++cg.deferredPlayerLoading > 10 ) { CG_LoadDeferredPlayers(); } if (cg.numViewports != 1) { // Setup single viewport cg.numViewports = 1; cg.viewport = 0; // calculate size of viewport CG_CalcVrect(); } // Not drawing single client view. cg.cur_lc = NULL; cg.cur_ps = NULL; cg.cur_localClientNum = -1; // Draw over all viewports CG_DrawScreen2D( stereoView ); if ( cg_stats.integer ) { CG_Printf( "cg.clientFrame:%i\n", cg.clientFrame ); } }
/* ================= 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) ); #ifdef MISSIONPACK cmd = CG_Argv(1); // yes, this is obviously a hack, but so is the way we hear about // votes passing or failing if ( !Q_stricmpn( cmd, "vote failed", 11 ) || !Q_stricmpn( cmd, "team vote failed", 16 )) { trap_S_StartLocalSound( cgs.media.voteFailed, CHAN_ANNOUNCER ); } else if ( !Q_stricmpn( cmd, "vote passed", 11 ) || !Q_stricmpn( cmd, "team vote passed", 16 ) ) { trap_S_StartLocalSound( cgs.media.votePassed, CHAN_ANNOUNCER ); } #endif return; } if ( !strcmp( cmd, "chat" ) ) { if ( !cg_teamChatsOnly.integer ) { if( cg_chatBeep.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_teamChatBeep.integer ) 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, "vchat" ) ) { CG_VoiceChat( SAY_ALL ); return; } if ( !strcmp( cmd, "vtchat" ) ) { CG_VoiceChat( SAY_TEAM ); return; } if ( !strcmp( cmd, "vtell" ) ) { CG_VoiceChat( SAY_TELL ); return; } if ( !strcmp( cmd, "scores" ) ) { CG_ParseScores(); return; } if ( !strcmp( cmd, "accs" ) ) { CG_ParseAccuracy(); return; } if ( !strcmp( cmd, "ddtaken" ) ) { CG_ParseDDtimetaken(); return; } if ( !strcmp( cmd, "dompointnames" ) ) { CG_ParseDomPointNames(); return; } if ( !strcmp( cmd, "domStatus" ) ) { CG_ParseDomStatus(); return; } if ( !strcmp( cmd, "elimination" ) ) { CG_ParseElimination(); return; } if ( !strcmp( cmd, "mappage" ) ) { CG_ParseMappage(); return; } if ( !strcmp( cmd, "attackingteam" ) ) { CG_ParseAttackingTeam(); 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) { char shader1[MAX_QPATH]; char shader2[MAX_QPATH]; char shader3[MAX_QPATH]; Q_strncpyz(shader1, CG_Argv(1), sizeof(shader1)); Q_strncpyz(shader2, CG_Argv(2), sizeof(shader2)); Q_strncpyz(shader3, CG_Argv(3), sizeof(shader3)); trap_R_RemapShader(shader1, shader2, shader3); } return; } // loaddeferred can be both a servercmd and a consolecmd if ( !strcmp( cmd, "loaddefered" ) ) { // FIXME: spelled wrong, but not changing for demo CG_LoadDeferredPlayers(); return; } // clientLevelShot is sent before taking a special screenshot for // the menu system during development if ( !strcmp( cmd, "clientLevelShot" ) ) { cg.levelShot = qtrue; return; } // challenge completed is determened by the server. A client should consider this message valid: if ( !strcmp( cmd, "ch" ) ) { CG_ParseChallenge(); return; } if ( !strcmp (cmd, "oh") ) { CG_ParseObeliskHealth(); return; } if ( !strcmp( cmd, "respawn" ) ) { CG_ParseRespawnTime(); return; } if ( !strcmp( cmd, "team" ) ) { CG_ParseTeam(); return; } if ( !strcmp( cmd, "customvotes" ) ) { char infoString[1024]; int i; //TODO: Create a ParseCustomvotes function memset(&infoString,0,sizeof(infoString)); for(i=1;i<=12;i++) { Q_strcat(infoString,sizeof(infoString),CG_Argv( i )); Q_strcat(infoString,sizeof(infoString)," "); } trap_Cvar_Set("cg_vote_custom_commands",infoString); return; } CG_Printf( "Unknown client game command: %s\n", cmd ); }
qboolean CG_DrawOldScoreboard( void ) { int x, y, i, n1, n2; float fade; vector4 *fadeColor; char *s; int maxClients, realMaxClients; int lineHeight; int topBorderSize, bottomBorderSize; #if 0 // don't draw amuthing if the menu or console is up if ( cg_paused.integer ) { cg.deferredPlayerLoading = 0; return qfalse; } #endif // don't draw scoreboard during death while warmup up if ( cg.warmup && !cg.showScores ) { return qfalse; } if ( cg.showScores || cg.predictedPlayerState.pm_type == PM_DEAD || cg.predictedPlayerState.pm_type == PM_INTERMISSION ) { fade = 1.0; fadeColor = &colorWhite; } else { fadeColor = CG_FadeColor( cg.scoreFadeTime, FADE_TIME ); if ( !fadeColor ) { // next time scoreboard comes up, don't print killer cg.deferredPlayerLoading = 0; cg.killerName[0] = 0; return qfalse; } fade = fadeColor->a; } // fragged by ... line // or if in intermission and duel, prints the winner of the duel round if ((cgs.gametype == GT_DUEL || cgs.gametype == GT_POWERDUEL) && cgs.duelWinner != -1 && cg.predictedPlayerState.pm_type == PM_INTERMISSION) { s = va("%s^7 %s", cgs.clientinfo[cgs.duelWinner].name, CG_GetStringEdString("MP_INGAME", "DUEL_WINS") ); /*w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; x = ( SCREEN_WIDTH - w ) / 2; y = 40; CG_DrawBigString( x, y, s, fade ); */ x = ( SCREEN_WIDTH ) / 2; y = 40; CG_Text_Paint ( x - CG_Text_Width ( s, 1.0f, FONT_MEDIUM ) / 2, y, 1.0f, &colorWhite, s, 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } else if ((cgs.gametype == GT_DUEL || cgs.gametype == GT_POWERDUEL) && cgs.duelist1 != -1 && cgs.duelist2 != -1 && cg.predictedPlayerState.pm_type == PM_INTERMISSION) { if (cgs.gametype == GT_POWERDUEL && cgs.duelist3 != -1) { s = va("%s^7 %s %s^7 %s %s", cgs.clientinfo[cgs.duelist1].name, CG_GetStringEdString("MP_INGAME", "SPECHUD_VERSUS"), cgs.clientinfo[cgs.duelist2].name, CG_GetStringEdString("MP_INGAME", "AND"), cgs.clientinfo[cgs.duelist3].name ); } else { s = va("%s^7 %s %s", cgs.clientinfo[cgs.duelist1].name, CG_GetStringEdString("MP_INGAME", "SPECHUD_VERSUS"), cgs.clientinfo[cgs.duelist2].name ); } /*w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; x = ( SCREEN_WIDTH - w ) / 2; y = 40; CG_DrawBigString( x, y, s, fade ); */ x = ( SCREEN_WIDTH ) / 2; y = 40; CG_Text_Paint ( x - CG_Text_Width ( s, 1.0f, FONT_MEDIUM ) / 2, y, 1.0f, &colorWhite, s, 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } else if ( cg.killerName[0] ) { s = va("%s %s", CG_GetStringEdString("MP_INGAME", "KILLEDBY"), cg.killerName ); /*w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; x = ( SCREEN_WIDTH - w ) / 2; y = 40; CG_DrawBigString( x, y, s, fade ); */ x = ( SCREEN_WIDTH ) / 2; y = 32; CG_Text_Paint ( x - CG_Text_Width ( s, 1.0f, FONT_MEDIUM ) / 2, y, 1.0f, &colorWhite, s, 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } else { x = ( SCREEN_WIDTH ) / 2; y = SB_HEADER; //CG_DrawBigString( x, y, s, fade ); s = cgs.japp.serverName; CG_Text_Paint( x-(CG_Text_Width( s, 0.75f, FONT_NONE )/2), y, 0.75f, &colorTable[CT_WHITE], s, 0.0f, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_NONE ); if ( cgs.gametype >= GT_TEAM ) { int redCount=0, blueCount=0, specCount=0; for ( i=0; i<cg.numScores; i++ ) { if ( cgs.clientinfo[cg.scores[i].client].team == TEAM_RED ) redCount++; else if ( cgs.clientinfo[cg.scores[i].client].team == TEAM_BLUE ) blueCount++; else if ( cgs.clientinfo[cg.scores[i].client].team == TEAM_SPECTATOR ) specCount++; } s = va( "Players: ^2%i^7/^2%i ^7(^1%i^7/^5%i^7) - %i spectators", cg.numScores, cgs.maxclients, redCount, blueCount, specCount ); } else { int specCount=0; for ( i=0; i<cg.numScores; i++ ) { if ( cgs.clientinfo[cg.scores[i].client].team == TEAM_SPECTATOR ) specCount++; } s = va( "Players: %i/%i - %i spectators", cg.numScores, cgs.maxclients, specCount ); } CG_Text_Paint( x-(CG_Text_Width( s, 0.75f, FONT_NONE )/2), y+15, 0.75f, &colorTable[CT_WHITE], s, 0.0f, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_NONE ); s = va( "%s (%s)", (char *)CG_ConfigString( CS_MESSAGE ), cgs.mapname ); CG_Text_Paint( x-(CG_Text_Width( s, 0.75f, FONT_NONE )/2), y+30, 0.75f, &colorTable[CT_WHITE], s, 0.0f, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_NONE ); } // current rank if (cgs.gametype == GT_POWERDUEL) { //do nothing? } else if ( cgs.gametype < GT_TEAM) { #if 0 if (cg.snap->ps.persistant[PERS_TEAM] != TEAM_SPECTATOR ) { char sPlace[256]; char sOf[256]; char sWith[256]; trap->SE_GetStringTextString("MP_INGAME_PLACE", sPlace, sizeof(sPlace)); trap->SE_GetStringTextString("MP_INGAME_OF", sOf, sizeof(sOf)); trap->SE_GetStringTextString("MP_INGAME_WITH", sWith, sizeof(sWith)); s = va("%s %s (%s %i) %s %i", CG_PlaceString( cg.snap->ps.persistant[PERS_RANK] + 1 ), sPlace, sOf, cg.numScores, sWith, cg.snap->ps.persistant[PERS_SCORE] ); w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; // x = ( 480 ) / 2; // y = SB_HEADER-24; x = ( SCREEN_WIDTH ) / 2; y = SB_HEADER-24; //CG_DrawBigString( x, y, s, fade ); UI_DrawProportionalString(x, y, s, UI_CENTER|UI_DROPSHADOW, colorTable[CT_WHITE]); } #else #endif } else if (cgs.gametype != GT_SIEGE) { if ( cg.teamScores[0] == cg.teamScores[1] ) { s = va("%s %i", CG_GetStringEdString("MP_INGAME", "TIEDAT"), cg.teamScores[0] ); } else if ( cg.teamScores[0] >= cg.teamScores[1] ) { s = va("%s, %i / %i", CG_GetStringEdString("MP_INGAME", "RED_LEADS"), cg.teamScores[0], cg.teamScores[1] ); } else { s = va("%s, %i / %i", CG_GetStringEdString("MP_INGAME", "BLUE_LEADS"), cg.teamScores[1], cg.teamScores[0] ); } // x = ( 460 ) / 2; // y = SB_HEADER-24; x = ( SCREEN_WIDTH ) / 2; y = SB_HEADER-24; CG_Text_Paint ( x - CG_Text_Width ( s, 1.0f, FONT_MEDIUM ) / 2, y, 1.0f, &colorWhite, s, 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } else if (cgs.gametype == GT_SIEGE && (cg_siegeWinTeam == 1 || cg_siegeWinTeam == 2)) { if (cg_siegeWinTeam == 1) { s = va("%s", CG_GetStringEdString("MP_INGAME", "SIEGETEAM1WIN") ); } else { s = va("%s", CG_GetStringEdString("MP_INGAME", "SIEGETEAM2WIN") ); } x = ( SCREEN_WIDTH ) / 2; y = 60; CG_Text_Paint ( x - CG_Text_Width ( s, 1.0f, FONT_MEDIUM ) / 2, y, 1.0f, &colorWhite, s, 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } // scoreboard y = SB_TOP-24; //SB_HEADER // CG_DrawPic ( SB_SCORELINE_X - 40, y - 5, SB_SCORELINE_WIDTH + 80, 40, trap->R_RegisterShaderNoMip ( "gfx/menus/menu_buttonback.tga" ) ); CG_Text_Paint ( SB_NAME_X, y, 1.0f, &colorWhite, CG_GetStringEdString("MP_INGAME", "NAME"),0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); if (cgs.gametype == GT_DUEL || cgs.gametype == GT_POWERDUEL) { char sWL[100]; trap->SE_GetStringTextString("MP_INGAME_W_L", sWL, sizeof(sWL)); CG_Text_Paint ( SB_SCORE_X, y, 1.0f, &colorWhite, sWL, 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } else { CG_Text_Paint ( SB_SCORE_X, y, 1.0f, &colorWhite, CG_GetStringEdString("MP_INGAME", "SCORE"), 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } CG_Text_Paint ( SB_PING_X, y, 1.0f, &colorWhite, CG_GetStringEdString("MP_INGAME", "PING"), 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); CG_Text_Paint ( SB_TIME_X, y, 1.0f, &colorWhite, CG_GetStringEdString("MP_INGAME", "TIME"), 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); y = SB_TOP; // If there are more than SB_MAXCLIENTS_NORMAL, use the interleaved scores if ( cg.numScores > SB_MAXCLIENTS_NORMAL ) { maxClients = SB_MAXCLIENTS_INTER; lineHeight = SB_INTER_HEIGHT; topBorderSize = 8; bottomBorderSize = 16; } else { maxClients = SB_MAXCLIENTS_NORMAL; lineHeight = SB_NORMAL_HEIGHT; topBorderSize = 8; bottomBorderSize = 8; } realMaxClients = maxClients; localClient = qfalse; //I guess this should end up being able to display 19 clients at once. //In a team game, if there are 9 or more clients on the team not in the lead, //we only want to show 10 of the clients on the team in the lead, so that we //have room to display the clients in the lead on the losing team. //I guess this can be accomplished simply by printing the first teams score with a maxClients //value passed in related to how many players are on both teams. if ( cgs.gametype >= GT_TEAM ) { // // teamplay scoreboard // y += lineHeight/2; if ( cg.teamScores[0] >= cg.teamScores[1] ) { int team1MaxCl = CG_GetTeamCount(TEAM_RED, maxClients); int team2MaxCl = CG_GetTeamCount(TEAM_BLUE, maxClients); if (team1MaxCl > 10 && (team1MaxCl+team2MaxCl) > maxClients) { team1MaxCl -= team2MaxCl; //subtract as many as you have to down to 10, once we get there //we just set it to 10 if (team1MaxCl < 10) { team1MaxCl = 10; } } team2MaxCl = (maxClients-team1MaxCl); //team2 can display however many is left over after team1's display n1 = CG_TeamScoreboard( y, TEAM_RED, fade, team1MaxCl, lineHeight, qtrue ); CG_DrawTeamBackground( SB_SCORELINE_X - 5, y - topBorderSize, 640 - SB_SCORELINE_X * 2 + 10, n1 * lineHeight + bottomBorderSize, 0.33f, TEAM_RED ); CG_TeamScoreboard( y, TEAM_RED, fade, team1MaxCl, lineHeight, qfalse ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; //maxClients -= n1; n2 = CG_TeamScoreboard( y, TEAM_BLUE, fade, team2MaxCl, lineHeight, qtrue ); CG_DrawTeamBackground( SB_SCORELINE_X - 5, y - topBorderSize, 640 - SB_SCORELINE_X * 2 + 10, n2 * lineHeight + bottomBorderSize, 0.33f, TEAM_BLUE ); CG_TeamScoreboard( y, TEAM_BLUE, fade, team2MaxCl, lineHeight, qfalse ); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; //maxClients -= n2; maxClients -= (team1MaxCl+team2MaxCl); } else { int team1MaxCl = CG_GetTeamCount(TEAM_BLUE, maxClients); int team2MaxCl = CG_GetTeamCount(TEAM_RED, maxClients); if (team1MaxCl > 10 && (team1MaxCl+team2MaxCl) > maxClients) { team1MaxCl -= team2MaxCl; //subtract as many as you have to down to 10, once we get there //we just set it to 10 if (team1MaxCl < 10) { team1MaxCl = 10; } } team2MaxCl = (maxClients-team1MaxCl); //team2 can display however many is left over after team1's display n1 = CG_TeamScoreboard( y, TEAM_BLUE, fade, team1MaxCl, lineHeight, qtrue ); CG_DrawTeamBackground( SB_SCORELINE_X - 5, y - topBorderSize, 640 - SB_SCORELINE_X * 2 + 10, n1 * lineHeight + bottomBorderSize, 0.33f, TEAM_BLUE ); CG_TeamScoreboard( y, TEAM_BLUE, fade, team1MaxCl, lineHeight, qfalse ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; //maxClients -= n1; n2 = CG_TeamScoreboard( y, TEAM_RED, fade, team2MaxCl, lineHeight, qtrue ); CG_DrawTeamBackground( SB_SCORELINE_X - 5, y - topBorderSize, 640 - SB_SCORELINE_X * 2 + 10, n2 * lineHeight + bottomBorderSize, 0.33f, TEAM_RED ); CG_TeamScoreboard( y, TEAM_RED, fade, team2MaxCl, lineHeight, qfalse ); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; //maxClients -= n2; maxClients -= (team1MaxCl+team2MaxCl); } maxClients = realMaxClients; n1 = CG_TeamScoreboard( y, TEAM_SPECTATOR, fade, maxClients, lineHeight, qfalse ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; } else { // // free for all scoreboard // n1 = CG_TeamScoreboard( y, TEAM_FREE, fade, maxClients, lineHeight, qfalse ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; n2 = CG_TeamScoreboard( y, TEAM_SPECTATOR, fade, maxClients - n1, lineHeight, qfalse ); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; } if (!localClient) { // draw local client at the bottom for ( i = 0 ; i < cg.numScores ; i++ ) { if ( cg.scores[i].client == cg.snap->ps.clientNum ) { CG_DrawClientScore( y, &cg.scores[i], fadeColor, fade, lineHeight == SB_NORMAL_HEIGHT ); break; } } } // load any models that have been deferred if ( ++cg.deferredPlayerLoading > 10 ) { CG_LoadDeferredPlayers(); } return qtrue; }
static void CG_ServerCommand( void ) { const char *cmd; char text[MAX_SAY_TEXT]; qboolean IRCG = qfalse; cmd = CG_Argv(0); if ( !cmd[0] ) { // server claimed the command return; } #if 0 // never seems to get used -Ste if ( !strcmp( cmd, "spd" ) ) { const char *ID; int holdInt,count,i; char string[1204]; count = trap_Argc(); ID = CG_Argv(1); holdInt = atoi(ID); memset( &string, 0, sizeof( string ) ); Com_sprintf( string,sizeof(string)," \"%s\"", (const char *) CG_Argv(2)); for (i=3;i<count;i++) { Com_sprintf( string,sizeof(string)," %s \"%s\"", string, (const char *) CG_Argv(i)); } trap_SP_Print(holdInt, (byte *)string); return; } #endif if (!strcmp(cmd, "sxd")) { //siege extended data, contains extra info certain classes may want to know about other clients CG_ParseSiegeExtendedData(); return; } if (!strcmp(cmd, "sb")) { //siege briefing display CG_SiegeBriefingDisplay(atoi(CG_Argv(1)), 0); return; } if ( !strcmp( cmd, "scl" ) ) { //if (!( trap_Key_GetCatcher() & KEYCATCH_UI )) //Well, I want it to come up even if the briefing display is up. { trap_OpenUIMenu(UIMENU_CLASSSEL); //UIMENU_CLASSSEL } return; } if ( !strcmp( cmd, "spc" ) ) { trap_Cvar_Set("ui_myteam", "3"); trap_OpenUIMenu(UIMENU_PLAYERCONFIG); //UIMENU_CLASSSEL return; } if ( !strcmp( cmd, "nfr" ) ) { //"nfr" == "new force rank" (want a short string) int doMenu = 0; int setTeam = 0; int newRank = 0; if (trap_Argc() < 3) { #ifdef _DEBUG Com_Printf("WARNING: Invalid newForceRank string\n"); #endif return; } newRank = atoi(CG_Argv(1)); doMenu = atoi(CG_Argv(2)); setTeam = atoi(CG_Argv(3)); trap_Cvar_Set("ui_rankChange", va("%i", newRank)); trap_Cvar_Set("ui_myteam", va("%i", setTeam)); if (!( trap_Key_GetCatcher() & KEYCATCH_UI ) && doMenu) { trap_OpenUIMenu(UIMENU_PLAYERCONFIG); } return; } if ( !strcmp( cmd, "kg2" ) ) { //Kill a ghoul2 instance in this slot. //If it has been occupied since this message was sent somehow, the worst that can (should) happen //is the instance will have to reinit with its current info. int indexNum = 0; int argNum = trap_Argc(); int i = 1; if (argNum < 1) { return; } while (i < argNum) { indexNum = atoi(CG_Argv(i)); if (cg_entities[indexNum].ghoul2 && trap_G2_HaveWeGhoul2Models(cg_entities[indexNum].ghoul2)) { if (indexNum < MAX_CLIENTS) { //You try to do very bad thing! #ifdef _DEBUG Com_Printf("WARNING: Tried to kill a client ghoul2 instance with a kg2 command!\n"); #endif return; } CG_KillCEntityG2(indexNum); } i++; } return; } if (!strcmp(cmd, "kls")) { //kill looping sounds int indexNum = 0; int argNum = trap_Argc(); centity_t *clent = NULL; centity_t *trackerent = NULL; if (argNum < 1) { assert(0); return; } indexNum = atoi(CG_Argv(1)); if (indexNum != -1) { clent = &cg_entities[indexNum]; } if (argNum >= 2) { indexNum = atoi(CG_Argv(2)); if (indexNum != -1) { trackerent = &cg_entities[indexNum]; } } if (clent) { CG_S_StopLoopingSound(clent->currentState.number, -1); } if (trackerent) { CG_S_StopLoopingSound(trackerent->currentState.number, -1); } return; } if (!strcmp(cmd, "ircg")) { //this means param 2 is the body index and we want to copy to bodyqueue on it IRCG = qtrue; } if (!strcmp(cmd, "rcg") || IRCG) { //rcg - Restore Client Ghoul (make sure limbs are reattached and ragdoll state is reset - this must be done reliably) int indexNum = 0; int argNum = trap_Argc(); centity_t *clent; if (argNum < 1) { assert(0); return; } indexNum = atoi(CG_Argv(1)); if (indexNum < 0 || indexNum >= MAX_CLIENTS) { assert(0); return; } clent = &cg_entities[indexNum]; //assert(clent->ghoul2); if (!clent->ghoul2) { //this can happen while connecting as a client return; } #ifdef _DEBUG if (!trap_G2_HaveWeGhoul2Models(clent->ghoul2)) { assert(!"Tried to reset state on a bad instance. Crash is inevitable."); } #endif if (IRCG) { int bodyIndex = 0; int weaponIndex = 0; int side = 0; centity_t *body; assert(argNum >= 3); bodyIndex = atoi(CG_Argv(2)); weaponIndex = atoi(CG_Argv(3)); side = atoi(CG_Argv(4)); body = &cg_entities[bodyIndex]; if (side) { body->teamPowerType = qtrue; //light side } else { body->teamPowerType = qfalse; //dark side } CG_BodyQueueCopy(body, clent->currentState.number, weaponIndex); } //reattach any missing limbs if (clent->torsoBolt) { CG_ReattachLimb(clent); } //make sure ragdoll state is reset if (clent->isRagging) { clent->isRagging = qfalse; trap_G2API_SetRagDoll(clent->ghoul2, NULL); //calling with null parms resets to no ragdoll. } //clear all the decals as well trap_G2API_ClearSkinGore(clent->ghoul2); clent->weapon = 0; clent->ghoul2weapon = NULL; //force a weapon reinit return; } if ( !strcmp( cmd, "cp" ) ) { char strEd[MAX_STRINGED_SV_STRING]; CG_CheckSVStringEdRef(strEd, CG_Argv(1)); CG_CenterPrint( strEd, SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH ); return; } if ( !strcmp( cmd, "cps" ) ) { char strEd[MAX_STRINGED_SV_STRING]; char *x = (char *)CG_Argv(1); if (x[0] == '@') { x++; } trap_SP_GetStringTextString(x, strEd, MAX_STRINGED_SV_STRING); CG_CenterPrint( strEd, SCREEN_HEIGHT * 0.20, BIGCHAR_WIDTH ); return; } if ( !strcmp( cmd, "cs" ) ) { CG_ConfigStringModified(); return; } if ( !strcmp( cmd, "print" ) ) { char strEd[MAX_STRINGED_SV_STRING]; CG_CheckSVStringEdRef(strEd, CG_Argv(1)); CG_Printf( "%s", strEd ); 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_ChatBox_AddString(text); CG_Printf( "*%s\n", text ); } return; } if ( !strcmp( cmd, "tchat" ) ) { trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); CG_ChatBox_AddString(text); CG_Printf( "*%s\n", text ); return; } //chat with location, possibly localized. if ( !strcmp( cmd, "lchat" ) ) { if ( !cg_teamChatsOnly.integer ) { char name[MAX_STRING_CHARS]; char loc[MAX_STRING_CHARS]; char color[8]; char message[MAX_STRING_CHARS]; if (trap_Argc() < 4) { return; } strcpy(name, CG_Argv(1)); strcpy(loc, CG_Argv(2)); strcpy(color, CG_Argv(3)); strcpy(message, CG_Argv(4)); if (loc[0] == '@') { //get localized text trap_SP_GetStringTextString(loc+1, loc, MAX_STRING_CHARS); } trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); //Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT ); Com_sprintf(text, MAX_SAY_TEXT, "%s<%s>^%s%s", name, loc, color, message); CG_RemoveChatEscapeChar( text ); CG_ChatBox_AddString(text); CG_Printf( "*%s\n", text ); } return; } if ( !strcmp( cmd, "ltchat" ) ) { char name[MAX_STRING_CHARS]; char loc[MAX_STRING_CHARS]; char color[8]; char message[MAX_STRING_CHARS]; if (trap_Argc() < 4) { return; } strcpy(name, CG_Argv(1)); strcpy(loc, CG_Argv(2)); strcpy(color, CG_Argv(3)); strcpy(message, CG_Argv(4)); if (loc[0] == '@') { //get localized text trap_SP_GetStringTextString(loc+1, loc, MAX_STRING_CHARS); } trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); //Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT ); Com_sprintf(text, MAX_SAY_TEXT, "%s<%s> ^%s%s", name, loc, color, message); CG_RemoveChatEscapeChar( text ); CG_ChatBox_AddString(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)); } } // loaddeferred can be both a servercmd and a consolecmd if ( !strcmp( cmd, "loaddefered" ) ) { // FIXME: spelled wrong, but not changing for demo CG_LoadDeferredPlayers(); return; } // clientLevelShot is sent before taking a special screenshot for // the menu system during development if ( !strcmp( cmd, "clientLevelShot" ) ) { cg.levelShot = qtrue; return; } CG_Printf( "Unknown client game command: %s\n", cmd ); }
/* ================= CG_DrawScoreboard Draw the normal in-game scoreboard ================= */ qboolean CG_DrawScoreboard( void ) { int x = 0, y = 0; float fade; float *fadeColor; char *s; // don't draw amuthing if the menu or console is up if ( cg_paused.integer ) { cg.deferredPlayerLoading = 0; return qfalse; } // don't draw scoreboard during death while warmup up if ( cg.warmup && !cg.showScores ) { return qfalse; } // NERVE - SMF - added mp wolf check if ( cg.showScores || ( cg.predictedPlayerState.pm_type == PM_DEAD && cgs.gametype < GT_WOLF ) || cg.predictedPlayerState.pm_type == PM_INTERMISSION ) { fade = 1.0; fadeColor = colorWhite; } else { fadeColor = CG_FadeColor( cg.scoreFadeTime, FADE_TIME ); if ( !fadeColor ) { // next time scoreboard comes up, don't print killer cg.deferredPlayerLoading = 0; cg.killerName[0] = 0; return qfalse; } fade = *fadeColor; } // fragged by ... line if ( cg.killerName[0] ) { int w; s = va( "Killed by %s", cg.killerName ); w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; x = ( SCREEN_WIDTH - w ) / 2; y = 40; CG_DrawBigString( x, y, s, fade ); } // current rank // NERVE - SMF if ( cgs.gametype >= GT_WOLF ) { INFO_PLAYER_WIDTH = 140; INFO_SCORE_WIDTH = 50; INFO_CLASS_WIDTH = 50; INFO_LATENCY_WIDTH = 40; INFO_TEAM_HEIGHT = 24; INFO_BORDER = 2; INFO_TOTAL_WIDTH = INFO_PLAYER_WIDTH + INFO_CLASS_WIDTH + INFO_SCORE_WIDTH + INFO_LATENCY_WIDTH; x = 20; y = 10; WM_DrawObjectives( x, y, 595, fade ); if ( cgs.gametype == GT_WOLF_STOPWATCH && ( cg.snap->ps.pm_type == PM_INTERMISSION ) ) { y = WM_DrawInfoLine( x, 155, fade ); WM_TeamScoreboard( x, y, TEAM_RED, fade, 18 ); x = 335; WM_TeamScoreboard( x, y, TEAM_BLUE, fade, 18 ); } else { y = 155; WM_TeamScoreboard( x, y, TEAM_RED, fade, 20 ); x = 335; WM_TeamScoreboard( x, y, TEAM_BLUE, fade, 20 ); } } // -NERVE - SMF else if ( cgs.gametype >= GT_TEAM ) { // // teamplay scoreboard // if ( cg.teamScores[0] >= cg.teamScores[1] ) { y = CG_TeamScoreboard( x, y, TEAM_RED, fade ); y = CG_TeamScoreboard( x, y, TEAM_BLUE, fade ); } else { y = CG_TeamScoreboard( x, y, TEAM_BLUE, fade ); y = CG_TeamScoreboard( x, y, TEAM_RED, fade ); } y = CG_TeamScoreboard( x, y, TEAM_SPECTATOR, fade ); } else { //----(SA) modified // // free for all scoreboard // y = CG_TeamScoreboard( x, y, TEAM_FREE, fade ); y = CG_TeamScoreboard( x, y, TEAM_SPECTATOR, fade ); } // load any models that have been deferred if ( ++cg.deferredPlayerLoading > 1 ) { CG_LoadDeferredPlayers(); } return qtrue; }
/* ================= CG_DrawOldScoreboard Draw the normal in-game scoreboard ================= */ qboolean CG_DrawOldScoreboard( void ) { int x, y, w, i, n1, n2; float fade; const float *fadeColor; const char *s; int maxClients; int lineHeight; int topBorderSize, bottomBorderSize; QLWideScreen = WIDESCREEN_CENTER; // don't draw amuthing if the menu or console is up if ( cg_paused.integer ) { cg.deferredPlayerLoading = 0; return qfalse; } if ( cgs.gametype == GT_SINGLE_PLAYER && cg.predictedPlayerState.pm_type == PM_INTERMISSION ) { cg.deferredPlayerLoading = 0; return qfalse; } // don't draw scoreboard during death while warmup up if ( cg.warmup && !cg.showScores ) { return qfalse; } if ( cg.showScores || cg.predictedPlayerState.pm_type == PM_DEAD || cg.predictedPlayerState.pm_type == PM_INTERMISSION ) { fade = 1.0; fadeColor = colorWhite; } else { fadeColor = CG_FadeColor( cg.scoreFadeTime, FADE_TIME ); if ( !fadeColor ) { // next time scoreboard comes up, don't print killer cg.deferredPlayerLoading = 0; cg.killerName[0] = 0; return qfalse; } fade = *fadeColor; } // fragged by ... line if ( cg.killerName[0] ) { s = va("Fragged by %s", cg.killerName ); w = CG_DrawStrlen( s, &cgs.media.bigchar ); x = ( SCREEN_WIDTH - w ) / 2; y = 40; CG_DrawBigString( x, y, s, fade ); } // current rank if (!CG_IsTeamGame(cgs.gametype)) { if (!wolfcam_following || (wolfcam_following && wcg.clientNum == cg.snap->ps.clientNum)) { if (cg.snap->ps.persistant[PERS_TEAM] != TEAM_SPECTATOR ) { s = va("%s place with %i", CG_PlaceString( cg.snap->ps.persistant[PERS_RANK] + 1 ), cg.snap->ps.persistant[PERS_SCORE] ); w = CG_DrawStrlen( s, &cgs.media.bigchar ); x = ( SCREEN_WIDTH - w ) / 2; y = 60; CG_DrawBigString( x, y, s, fade ); } } else { // wolfcam_following if (cgs.clientinfo[wcg.clientNum].team != TEAM_SPECTATOR) { if (CG_IsCpmaMvd()) { int rank; int i; rank = 1; for (i = 0; i < MAX_CLIENTS; i++) { if (!cgs.clientinfo[i].infoValid) { continue; } if (cgs.clientinfo[i].team == TEAM_SPECTATOR) { continue; } if (cgs.clientinfo[i].score > cgs.clientinfo[wcg.clientNum].score) { rank++; } } s = va("%s ^7place with %i", CG_PlaceString(rank), cgs.clientinfo[wcg.clientNum].score); w = CG_DrawStrlen( s, &cgs.media.bigchar ); x = ( SCREEN_WIDTH - w ) / 2; y = 60; CG_DrawBigString( x, y, s, fade ); } else { // not cpma mvd // following someone who is ingame but not the main demo view if (CG_IsDuelGame(cgs.gametype)) { // we are following the other dueler if (cgs.scores1 == cgs.scores2) { s = va("%s ^7place with %i", CG_PlaceString(1), cgs.scores1); } else { if (cg.snap->ps.persistant[PERS_RANK] == 0) { // we are second s = va("%s ^7place with %i", CG_PlaceString(2), cgs.scores2); } else { // we are first s = va("%s ^7place with %i", CG_PlaceString(1), cgs.scores1); } } w = CG_DrawStrlen( s, &cgs.media.bigchar ); x = ( SCREEN_WIDTH - w ) / 2; y = 60; CG_DrawBigString( x, y, s, fade ); } else { // we don't have enough information // pass, don't draw ranking } } } } } else { if ( cg.teamScores[0] == cg.teamScores[1] ) { s = va("Teams are tied at %i", cg.teamScores[0] ); } else if ( cg.teamScores[0] >= cg.teamScores[1] ) { s = va("Red leads %i to %i",cg.teamScores[0], cg.teamScores[1] ); } else { s = va("Blue leads %i to %i",cg.teamScores[1], cg.teamScores[0] ); } w = CG_DrawStrlen( s, &cgs.media.bigchar ); x = ( SCREEN_WIDTH - w ) / 2; y = 60; CG_DrawBigString( x, y, s, fade ); } // scoreboard y = SB_HEADER; CG_DrawPic( SB_SCORE_X + (SB_RATING_WIDTH / 2), y, 64, 32, cgs.media.scoreboardScore ); CG_DrawPic( SB_PING_X - (SB_RATING_WIDTH / 2), y, 64, 32, cgs.media.scoreboardPing ); CG_DrawPic( SB_TIME_X - (SB_RATING_WIDTH / 2), y, 64, 32, cgs.media.scoreboardTime ); CG_DrawPic( SB_NAME_X - (SB_RATING_WIDTH / 2), y, 64, 32, cgs.media.scoreboardName ); y = SB_TOP; // If there are more than SB_MAXCLIENTS_NORMAL, use the interleaved scores if (1) { //( cg.numScores > SB_MAXCLIENTS_NORMAL ) { maxClients = SB_MAXCLIENTS_INTER; lineHeight = SB_INTER_HEIGHT; topBorderSize = 8; bottomBorderSize = 16; } else { maxClients = SB_MAXCLIENTS_NORMAL; lineHeight = SB_NORMAL_HEIGHT; topBorderSize = 16; bottomBorderSize = 16; } localClient = qfalse; if ( cgs.gametype >= GT_TEAM ) { // // teamplay scoreboard // y += lineHeight/2; if ( cg.teamScores[0] >= cg.teamScores[1] ) { n1 = CG_TeamScoreboard( y, TEAM_RED, fade, maxClients, lineHeight ); CG_DrawTeamBackground( 0, y - topBorderSize, 640, n1 * lineHeight + bottomBorderSize, 0.33f, TEAM_RED ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; maxClients -= n1; n2 = CG_TeamScoreboard( y, TEAM_BLUE, fade, maxClients, lineHeight ); CG_DrawTeamBackground( 0, y - topBorderSize, 640, n2 * lineHeight + bottomBorderSize, 0.33f, TEAM_BLUE ); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; maxClients -= n2; } else { n1 = CG_TeamScoreboard( y, TEAM_BLUE, fade, maxClients, lineHeight ); CG_DrawTeamBackground( 0, y - topBorderSize, 640, n1 * lineHeight + bottomBorderSize, 0.33f, TEAM_BLUE ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; maxClients -= n1; n2 = CG_TeamScoreboard( y, TEAM_RED, fade, maxClients, lineHeight ); CG_DrawTeamBackground( 0, y - topBorderSize, 640, n2 * lineHeight + bottomBorderSize, 0.33f, TEAM_RED ); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; maxClients -= n2; } n1 = CG_TeamScoreboard( y, TEAM_SPECTATOR, fade, maxClients, lineHeight ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; } else { // // free for all scoreboard // n1 = CG_TeamScoreboard( y, TEAM_FREE, fade, maxClients, lineHeight ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; n2 = CG_TeamScoreboard( y, TEAM_SPECTATOR, fade, maxClients - n1, lineHeight ); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; } if (!localClient) { // draw local client at the bottom for ( i = 0 ; i < cg.numScores ; i++ ) { if ( cg.scores[i].client == cg.snap->ps.clientNum ) { CG_DrawClientScore( y, &cg.scores[i], fadeColor, fade, lineHeight == SB_NORMAL_HEIGHT ); break; } } } // load any models that have been deferred if ( ++cg.deferredPlayerLoading > 10 ) { CG_LoadDeferredPlayers(); } return qtrue; }
static void CG_ServerCommand( void ) { const char *cmd; char text[MAX_SAY_TEXT]; cmd = CG_Argv( 0 ); if ( !cmd[0] ) { // server claimed the command return; } if ( !strcmp( cmd, "startCam" ) ) { CG_StartCamera( CG_Argv( 1 ), atoi( CG_Argv( 2 ) ) ); return; } if ( !strcmp( cmd, "stopCam" ) ) { CG_StopCamera(); return; } if ( !strcmp( cmd, "mvspd" ) ) { CG_RequestMoveSpeed( CG_Argv( 1 ) ); return; } if ( !strcmp( cmd, "dp" ) ) { // dynamite print (what a hack :( CG_CenterPrint( va( "%s %d %s", CG_translateString( "dynamitetimer" ), atoi( CG_Argv( 1 ) ), CG_translateString( "seconds" ) ), SCREEN_HEIGHT - ( SCREEN_HEIGHT * 0.25 ), SMALLCHAR_WIDTH ); return; } if ( !strcmp( cmd, "cp" ) ) { CG_CenterPrint( CG_Argv( 1 ), SCREEN_HEIGHT - ( SCREEN_HEIGHT * 0.25 ), SMALLCHAR_WIDTH ); return; } if ( !strcmp( cmd, "cs" ) ) { CG_ConfigStringModified(); return; } if ( !strcmp( cmd, "print" ) ) { CG_Printf( "%s", CG_Argv( 1 ) ); #ifdef MISSIONPACK cmd = CG_Argv( 1 ); // yes, this is obviously a hack, but so is the way we hear about // votes passing or failing if ( !Q_stricmpn( cmd, "vote failed", 11 ) || !Q_stricmpn( cmd, "team vote failed", 16 ) ) { trap_S_StartLocalSound( cgs.media.voteFailed, CHAN_ANNOUNCER ); } else if ( !Q_stricmpn( cmd, "vote passed", 11 ) || !Q_stricmpn( cmd, "team vote passed", 16 ) ) { trap_S_StartLocalSound( cgs.media.votePassed, CHAN_ANNOUNCER ); } #endif return; } if ( !strcmp( cmd, "chat" ) ) { if ( !cg_teamChatsOnly.integer ) { trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv( 1 ), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); CG_Printf( "%s\n", text ); } return; } if ( !strcmp( cmd, "tchat" ) ) { trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv( 1 ), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); CG_AddToTeamChat( text ); CG_Printf( "%s\n", text ); return; } // NERVE - SMF - limbo chat if ( !strcmp( cmd, "lchat" ) ) { trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv( 1 ), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); // CG_AddToLimboChat( text ); trap_UI_LimboChat( text ); CG_Printf( "%s\n", text ); return; } // -NERVE - SMF if ( !strcmp( cmd, "vchat" ) ) { // CG_VoiceChat( SAY_ALL ); return; } if ( !strcmp( cmd, "vtchat" ) ) { // CG_VoiceChat( SAY_TEAM ); return; } if ( !strcmp( cmd, "vtell" ) ) { // CG_VoiceChat( SAY_TELL ); return; } if ( !strcmp( cmd, "scores" ) ) { CG_ParseScores(); return; } if ( !strcmp( cmd, "tinfo" ) ) { CG_ParseTeamInfo(); return; } if ( !strcmp( cmd, "map_restart" ) ) { CG_MapRestart(); return; } if ( Q_stricmp( cmd, "remapShader" ) == 0 ) { if ( trap_Argc() == 4 ) { trap_R_RemapShader( CG_Argv( 1 ), CG_Argv( 2 ), CG_Argv( 3 ) ); } } // loaddeferred can be both a servercmd and a consolecmd if ( !strcmp( cmd, "loaddeferred" ) ) { // spelling fixed (SA) CG_LoadDeferredPlayers(); return; } // clientLevelShot is sent before taking a special screenshot for // the menu system during development if ( !strcmp( cmd, "clientLevelShot" ) ) { cg.levelShot = qtrue; return; } // NERVE - SMF if ( !Q_stricmp( cmd, "oid" ) ) { CG_ObjectivePrint( CG_Argv( 2 ), SMALLCHAR_WIDTH, atoi( CG_Argv( 1 ) ) ); return; } // -NERVE - SMF // // music // // loops \/ if ( !strcmp( cmd, "mu_start" ) ) { // has optional parameter for fade-up time int fadeTime = 0; // default to instant start Q_strncpyz( text, CG_Argv( 2 ), MAX_SAY_TEXT ); if ( text && strlen( text ) ) { fadeTime = atoi( text ); } trap_S_StartBackgroundTrack( CG_Argv( 1 ), CG_Argv( 1 ), fadeTime ); return; } // plays once then back to whatever the loop was \/ if ( !strcmp( cmd, "mu_play" ) ) { // has optional parameter for fade-up time int fadeTime = 0; // default to instant start Q_strncpyz( text, CG_Argv( 2 ), MAX_SAY_TEXT ); if ( text && strlen( text ) ) { fadeTime = atoi( text ); } trap_S_StartBackgroundTrack( CG_Argv( 1 ), "onetimeonly", fadeTime ); return; } if ( !strcmp( cmd, "mu_stop" ) ) { // has optional parameter for fade-down time int fadeTime = 0; // default to instant stop Q_strncpyz( text, CG_Argv( 1 ), MAX_SAY_TEXT ); if ( text && strlen( text ) ) { fadeTime = atoi( text ); } trap_S_FadeBackgroundTrack( 0.0f, fadeTime, 0 ); trap_S_StartBackgroundTrack( "", "", -2 ); // '-2' for 'queue looping track' (QUEUED_PLAY_LOOPED) return; } if ( !strcmp( cmd, "mu_fade" ) ) { trap_S_FadeBackgroundTrack( atof( CG_Argv( 1 ) ), atoi( CG_Argv( 2 ) ), 0 ); return; } if ( !strcmp( cmd, "snd_fade" ) ) { trap_S_FadeAllSound( atof( CG_Argv( 1 ) ), atoi( CG_Argv( 2 ) ) ); return; } if ( !strcmp( cmd, "rockandroll" ) ) { // map loaded, game is ready to begin. CG_Fade( 0, 0, 0, 255, cg.time, 0 ); // go black trap_UI_Popup( "pregame" ); // start pregame menu trap_Cvar_Set( "cg_norender", "1" ); // don't render the world until the player clicks in and the 'playerstart' func has been called (g_main in G_UpdateCvars() ~ilne 949) trap_S_FadeAllSound( 1.0f, 1000 ); // fade sound up return; } // ensure a file gets into a build (mainly for scripted music calls) if ( !strcmp( cmd, "addToBuild" ) ) { fileHandle_t f; if ( !cg_buildScript.integer ) { return; } // just open the file so it gets copied to the build dir //CG_FileTouchForBuild(CG_Argv(1)); trap_FS_FOpenFile( CG_Argv( 1 ), &f, FS_READ ); trap_FS_FCloseFile( f ); return; } CG_Printf( "Unknown client game command: %s\n", cmd ); }
/* ================= CG_DrawScoreboard Draw the normal in-game scoreboard ================= */ qboolean CG_DrawScoreboard( void ) { int x = 0, y = 0, w; float fade; float *fadeColor; const char *s; // don't draw amuthing if the menu or console is up if ( cg_paused.integer ) { cg.deferredPlayerLoading = 0; return qfalse; } if ( cgs.gametype == GT_SINGLE_PLAYER && cg.predictedPlayerState.pm_type == PM_INTERMISSION ) { cg.deferredPlayerLoading = 0; return qfalse; } // don't draw scoreboard during death while warmup up if ( cg.warmup && !cg.showScores ) { return qfalse; } // NERVE - SMF - added mp wolf check if ( cg.showScores || ( cg.predictedPlayerState.pm_type == PM_DEAD && cgs.gametype < GT_WOLF ) || cg.predictedPlayerState.pm_type == PM_INTERMISSION ) { fade = 1.0; fadeColor = colorWhite; } else { fadeColor = CG_FadeColor( cg.scoreFadeTime, FADE_TIME ); if ( !fadeColor ) { // next time scoreboard comes up, don't print killer cg.deferredPlayerLoading = 0; cg.killerName[0] = 0; return qfalse; } fade = *fadeColor; } // fragged by ... line if ( cg.killerName[0] ) { s = va( "Killed by %s", cg.killerName ); w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; x = ( SCREEN_WIDTH - w ) / 2; y = 40; CG_DrawBigString( x, y, s, fade ); } // current rank //----(SA) enclosed this so it doesn't draw for SP if ( cgs.gametype != GT_SINGLE_PLAYER && cgs.gametype < GT_WOLF ) { // NERVE - SMF - added wolf multiplayer check if ( cg.snap->ps.persistant[PERS_TEAM] != TEAM_SPECTATOR ) { if ( cgs.gametype < GT_TEAM ) { s = va( "%s place with %i", CG_PlaceString( cg.snap->ps.persistant[PERS_RANK] + 1 ), cg.snap->ps.persistant[PERS_SCORE] ); w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; x = ( SCREEN_WIDTH - w ) / 2; y = 60; CG_DrawBigString( x, y, s, fade ); } else { if ( cg.teamScores[0] == cg.teamScores[1] ) { s = va( "Teams are tied at %i", cg.teamScores[0] ); } else if ( cg.teamScores[0] >= cg.teamScores[1] ) { s = va( "Red leads %i to %i",cg.teamScores[0], cg.teamScores[1] ); } else { s = va( "Blue leads %i to %i",cg.teamScores[1], cg.teamScores[0] ); } w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; x = ( SCREEN_WIDTH - w ) / 2; y = 60; CG_DrawBigString( x, y, s, fade ); } } // scoreboard x = 320 - SCOREBOARD_WIDTH / 2; y = 86; #if 0 CG_DrawBigStringColor( x, y, "SCORE PING TIME NAME", fadeColor ); CG_DrawBigStringColor( x, y + 12, "----- ---- ---- ---------------", fadeColor ); #endif CG_DrawPic( x + 1 * 16, y, 64, 32, cgs.media.scoreboardScore ); CG_DrawPic( x + 6 * 16 + 8, y, 64, 32, cgs.media.scoreboardPing ); CG_DrawPic( x + 11 * 16 + 8, y, 64, 32, cgs.media.scoreboardTime ); CG_DrawPic( x + 16 * 16, y, 64, 32, cgs.media.scoreboardName ); y += 32; } //----(SA) added // Secrets if ( cgs.gametype == GT_SINGLE_PLAYER ) { s = "Secrets: 0/12"; w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; x = ( SCREEN_WIDTH - w ) / 2; y = 60; // CG_DrawBigStringColor( x, y, s, fadeColor ); } //----(SA) end // NERVE - SMF if ( cgs.gametype >= GT_WOLF ) { INFO_PLAYER_WIDTH = 140; INFO_SCORE_WIDTH = 50; INFO_CLASS_WIDTH = 50; INFO_LATENCY_WIDTH = 40; INFO_TEAM_HEIGHT = 24; INFO_BORDER = 2; INFO_TOTAL_WIDTH = INFO_PLAYER_WIDTH + INFO_CLASS_WIDTH + INFO_SCORE_WIDTH + INFO_LATENCY_WIDTH; x = 20; y = 10; WM_DrawObjectives( x, y, 595, fade ); if ( cgs.gametype == GT_WOLF_STOPWATCH && ( cg.snap->ps.pm_type == PM_INTERMISSION ) ) { y = WM_DrawInfoLine( x, 155, fade ); WM_TeamScoreboard( x, y, TEAM_RED, fade, 18 ); x = 335; WM_TeamScoreboard( x, y, TEAM_BLUE, fade, 18 ); } else { y = 155; WM_TeamScoreboard( x, y, TEAM_RED, fade, 20 ); x = 335; WM_TeamScoreboard( x, y, TEAM_BLUE, fade, 20 ); } } // -NERVE - SMF else if ( cgs.gametype >= GT_TEAM ) { // // teamplay scoreboard // if ( cg.teamScores[0] >= cg.teamScores[1] ) { y = CG_TeamScoreboard( x, y, TEAM_RED, fade ); y = CG_TeamScoreboard( x, y, TEAM_BLUE, fade ); } else { y = CG_TeamScoreboard( x, y, TEAM_BLUE, fade ); y = CG_TeamScoreboard( x, y, TEAM_RED, fade ); } y = CG_TeamScoreboard( x, y, TEAM_SPECTATOR, fade ); } else if ( cgs.gametype != GT_SINGLE_PLAYER ) { //----(SA) modified // // free for all scoreboard // y = CG_TeamScoreboard( x, y, TEAM_FREE, fade ); y = CG_TeamScoreboard( x, y, TEAM_SPECTATOR, fade ); } // load any models that have been deferred if ( ++cg.deferredPlayerLoading > 1 ) { CG_LoadDeferredPlayers(); } return qtrue; }
/* ================= CG_DrawScoreboard Draw the normal in-game scoreboard ================= */ qboolean CG_DrawOldScoreboard( void ) { int x, y, w, i, n1, n2; float fade; float *fadeColor; char *s; int maxClients; int lineHeight; int topBorderSize, bottomBorderSize; // don't draw amuthing if the menu or console is up if ( cg_paused.integer ) { cg.deferredPlayerLoading = 0; return qfalse; } // don't draw scoreboard during death while warmup up if ( cg.warmup && !cg.showScores ) { return qfalse; } if ( cg.showScores || cg.predictedPlayerState.pm_type == PM_DEAD || cg.predictedPlayerState.pm_type == PM_INTERMISSION ) { fade = 1.0; fadeColor = colorWhite; } else { fadeColor = CG_FadeColor( cg.scoreFadeTime, FADE_TIME ); if ( !fadeColor ) { // next time scoreboard comes up, don't print killer cg.deferredPlayerLoading = 0; cg.killerName[0] = 0; return qfalse; } fade = *fadeColor; } // fragged by ... line // or if in intermission and duel, prints the winner of the duel round if (cgs.gametype == GT_TOURNAMENT && cgs.duelWinner != -1 && cg.predictedPlayerState.pm_type == PM_INTERMISSION) { s = va("%s %s", cgs.clientinfo[cgs.duelWinner].name, CG_GetStripEdString("INGAMETEXT", "DUEL_WINS") ); /*w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; x = ( SCREEN_WIDTH - w ) / 2; y = 40; CG_DrawBigString( x, y, s, fade ); */ x = ( SCREEN_WIDTH ) / 2; y = 40; CG_Text_Paint ( x - CG_Text_Width ( s, 1.0f, FONT_MEDIUM ) / 2, y, 1.0f, colorWhite, s, 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } else if (cgs.gametype == GT_TOURNAMENT && cgs.duelist1 != -1 && cgs.duelist2 != -1 && cg.predictedPlayerState.pm_type == PM_INTERMISSION) { s = va("%s %s %s", cgs.clientinfo[cgs.duelist1].name, CG_GetStripEdString("INGAMETEXT", "SPECHUD_VERSUS"), cgs.clientinfo[cgs.duelist2].name ); /*w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; x = ( SCREEN_WIDTH - w ) / 2; y = 40; CG_DrawBigString( x, y, s, fade ); */ x = ( SCREEN_WIDTH ) / 2; y = 40; CG_Text_Paint ( x - CG_Text_Width ( s, 1.0f, FONT_MEDIUM ) / 2, y, 1.0f, colorWhite, s, 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } else if ( cg.killerName[0] ) { s = va("%s %s", CG_GetStripEdString("INGAMETEXT", "KILLEDBY"), cg.killerName ); /*w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; x = ( SCREEN_WIDTH - w ) / 2; y = 40; CG_DrawBigString( x, y, s, fade ); */ x = ( SCREEN_WIDTH ) / 2; y = 40; CG_Text_Paint ( x - CG_Text_Width ( s, 1.0f, FONT_MEDIUM ) / 2, y, 1.0f, colorWhite, s, 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } // current rank if ( !GT_Team(cgs.gametype)) { if (cg.snap->ps.persistant[PERS_TEAM] != TEAM_SPECTATOR ) { char sPlace[256]; char sOf[256]; char sWith[256]; trap_SP_GetStringTextString("INGAMETEXT_PLACE", sPlace, sizeof(sPlace)); trap_SP_GetStringTextString("INGAMETEXT_OF", sOf, sizeof(sOf)); trap_SP_GetStringTextString("INGAMETEXT_WITH", sWith, sizeof(sWith)); s = va("%s %s (%s %i) %s %i", CG_PlaceString( cg.snap->ps.persistant[PERS_RANK] + 1 ), sPlace, sOf, cg.numScores, sWith, cg.snap->ps.persistant[PERS_SCORE] ); w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; x = ( SCREEN_WIDTH ) / 2; y = 60; //CG_DrawBigString( x, y, s, fade ); UI_DrawProportionalString(x, y, s, UI_CENTER|UI_DROPSHADOW, colorTable[CT_WHITE]); } } else { if ( cg.teamScores[0] == cg.teamScores[1] ) { s = va("Teams are tied at %i", cg.teamScores[0] ); } else if ( cg.teamScores[0] >= cg.teamScores[1] ) { s = va("Red leads %i to %i",cg.teamScores[0], cg.teamScores[1] ); } else { s = va("Blue leads %i to %i",cg.teamScores[1], cg.teamScores[0] ); } x = ( SCREEN_WIDTH ) / 2; y = 60; CG_Text_Paint ( x - CG_Text_Width ( s, 1.0f, FONT_MEDIUM ) / 2, y, 1.0f, colorWhite, s, 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } // scoreboard y = SB_HEADER; CG_DrawPic ( SB_SCORELINE_X - 40, y - 5, SB_SCORELINE_WIDTH + 80, 40, trap_R_RegisterShaderNoMip ( "gfx/menus/menu_buttonback.tga" ) ); // "NAME", "SCORE", "PING", "TIME" weren't localised, GODDAMMIT!!!!!!!! // // Unfortunately, since it's so sodding late now and post release I can't enable the localisation code (REM'd) since some of // the localised strings don't fit - since no-one's ever seen them to notice this. Smegging brilliant. Thanks people. // CG_Text_Paint ( SB_NAME_X, y, 1.0f, colorWhite, /*CG_GetStripEdString("MENUS3", "NAME")*/"Name",0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); if (cgs.gametype == GT_TOURNAMENT) { char sWL[100]; trap_SP_GetStringTextString("INGAMETEXT_W_L", sWL, sizeof(sWL)); CG_Text_Paint ( SB_SCORE_X, y, 1.0f, colorWhite, sWL, 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } else { CG_Text_Paint ( SB_SCORE_X, y, 1.0f, colorWhite, /*CG_GetStripEdString("MENUS3", "SCORE")*/"Score", 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } CG_Text_Paint ( SB_PING_X, y, 1.0f, colorWhite, /*CG_GetStripEdString("MENUS0", "PING")*/"Ping", 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); CG_Text_Paint ( SB_TIME_X, y, 1.0f, colorWhite, /*CG_GetStripEdString("MENUS3", "TIME")*/"Time", 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); y = SB_TOP; // If there are more than SB_MAXCLIENTS_NORMAL, use the interleaved scores if ( cg.numScores > SB_MAXCLIENTS_NORMAL ) { maxClients = SB_MAXCLIENTS_INTER; lineHeight = SB_INTER_HEIGHT; topBorderSize = 8; bottomBorderSize = 16; } else { maxClients = SB_MAXCLIENTS_NORMAL; lineHeight = SB_NORMAL_HEIGHT; topBorderSize = 8; bottomBorderSize = 8; } localClient = qfalse; //I guess this should end up being able to display 19 clients at once. //In a team game, if there are 9 or more clients on the team not in the lead, //we only want to show 10 of the clients on the team in the lead, so that we //have room to display the clients in the lead on the losing team. //I guess this can be accomplished simply by printing the first teams score with a maxClients //value passed in related to how many players are on both teams. if ( GT_Team(cgs.gametype) ) { // // teamplay scoreboard // y += lineHeight/2; if ( cg.teamScores[0] >= cg.teamScores[1] ) { int team1MaxCl = CG_GetTeamCount(TEAM_RED, maxClients); int team2MaxCl = CG_GetTeamCount(TEAM_BLUE, maxClients); if (team1MaxCl > 10 && (team1MaxCl+team2MaxCl) > maxClients) { team1MaxCl -= team2MaxCl; //subtract as many as you have to down to 10, once we get there //we just set it to 10 if (team1MaxCl < 10) { team1MaxCl = 10; } } team2MaxCl = (maxClients-team1MaxCl); //team2 can display however many is left over after team1's display n1 = CG_TeamScoreboard( y, TEAM_RED, fade, team1MaxCl, lineHeight, qtrue ); CG_DrawTeamBackground( SB_SCORELINE_X - 5, y - topBorderSize, 640 - SB_SCORELINE_X * 2 + 10, n1 * lineHeight + bottomBorderSize, 0.33f, TEAM_RED ); CG_TeamScoreboard( y, TEAM_RED, fade, team1MaxCl, lineHeight, qfalse ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; //maxClients -= n1; n2 = CG_TeamScoreboard( y, TEAM_BLUE, fade, team2MaxCl, lineHeight, qtrue ); CG_DrawTeamBackground( SB_SCORELINE_X - 5, y - topBorderSize, 640 - SB_SCORELINE_X * 2 + 10, n2 * lineHeight + bottomBorderSize, 0.33f, TEAM_BLUE ); CG_TeamScoreboard( y, TEAM_BLUE, fade, team2MaxCl, lineHeight, qfalse ); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; //maxClients -= n2; maxClients -= (team1MaxCl+team2MaxCl); } else { int team1MaxCl = CG_GetTeamCount(TEAM_BLUE, maxClients); int team2MaxCl = CG_GetTeamCount(TEAM_RED, maxClients); if (team1MaxCl > 10 && (team1MaxCl+team2MaxCl) > maxClients) { team1MaxCl -= team2MaxCl; //subtract as many as you have to down to 10, once we get there //we just set it to 10 if (team1MaxCl < 10) { team1MaxCl = 10; } } team2MaxCl = (maxClients-team1MaxCl); //team2 can display however many is left over after team1's display n1 = CG_TeamScoreboard( y, TEAM_BLUE, fade, team1MaxCl, lineHeight, qtrue ); CG_DrawTeamBackground( SB_SCORELINE_X - 5, y - topBorderSize, 640 - SB_SCORELINE_X * 2 + 10, n1 * lineHeight + bottomBorderSize, 0.33f, TEAM_BLUE ); CG_TeamScoreboard( y, TEAM_BLUE, fade, team1MaxCl, lineHeight, qfalse ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; //maxClients -= n1; n2 = CG_TeamScoreboard( y, TEAM_RED, fade, team2MaxCl, lineHeight, qtrue ); CG_DrawTeamBackground( SB_SCORELINE_X - 5, y - topBorderSize, 640 - SB_SCORELINE_X * 2 + 10, n2 * lineHeight + bottomBorderSize, 0.33f, TEAM_RED ); CG_TeamScoreboard( y, TEAM_RED, fade, team2MaxCl, lineHeight, qfalse ); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; //maxClients -= n2; maxClients -= (team1MaxCl+team2MaxCl); } n1 = CG_TeamScoreboard( y, TEAM_SPECTATOR, fade, maxClients, lineHeight, qfalse ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; } else { // // free for all scoreboard // n1 = CG_TeamScoreboard( y, TEAM_FREE, fade, maxClients, lineHeight, qfalse ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; n2 = CG_TeamScoreboard( y, TEAM_SPECTATOR, fade, maxClients - n1, lineHeight, qfalse ); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; } if (!localClient) { // draw local client at the bottom for ( i = 0 ; i < cg.numScores ; i++ ) { if ( cg.scores[i].client == cg.snap->ps.clientNum ) { CG_DrawClientScore( y, &cg.scores[i], fadeColor, fade, lineHeight == SB_NORMAL_HEIGHT ); break; } } } // load any models that have been deferred if ( ++cg.deferredPlayerLoading > 10 ) { CG_LoadDeferredPlayers(); } return qtrue; }
/* ================= 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, "spd" ) ) { const char *ID; int holdInt,count,i; char string[1204]; count = trap_Argc(); ID = CG_Argv(1); holdInt = atoi(ID); memset( &string, 0, sizeof( string ) ); Com_sprintf( string,sizeof(string)," \"%s\"", (const char *) CG_Argv(2)); for (i=3;i<count;i++) { Com_sprintf( string,sizeof(string)," %s \"%s\"", string, (const char *) CG_Argv(i)); } trap_SP_Print(holdInt, (byte *)string); return; } if ( !strcmp( cmd, "nfr" ) ) { //"nfr" == "new force rank" (want a short string) int doMenu = 0; int setTeam = 0; int newRank = 0; if (trap_Argc() < 3) { #ifdef _DEBUG Com_Printf("WARNING: Invalid newForceRank string\n"); #endif return; } newRank = atoi(CG_Argv(1)); doMenu = atoi(CG_Argv(2)); setTeam = atoi(CG_Argv(3)); trap_Cvar_Set("ui_rankChange", va("%i", newRank)); trap_Cvar_Set("ui_myteam", va("%i", setTeam)); if (!( trap_Key_GetCatcher() & KEYCATCH_UI ) && doMenu) { trap_OpenUIMenu(3); } return; } if ( !strcmp( cmd, "kg2" ) ) { //Kill a ghoul2 instance in this slot. //If it has been occupied since this message was sent somehow, the worst that can (should) happen //is the instance will have to reinit with its current info. int indexNum = 0; int argNum = trap_Argc(); int i = 1; if (argNum < 1) { return; } while (i < argNum) { indexNum = atoi(CG_Argv(i)); if (cg_entities[indexNum].ghoul2 && trap_G2_HaveWeGhoul2Models(cg_entities[indexNum].ghoul2)) { if (indexNum < MAX_CLIENTS) { //You try to do very bad thing! #ifdef _DEBUG Com_Printf("WARNING: Tried to kill a client ghoul2 instance with a kg2 command!\n"); #endif return; } trap_G2API_CleanGhoul2Models(&(cg_entities[indexNum].ghoul2)); } i++; } return; } if ( !strcmp( cmd, "cp" ) ) { char strEd[MAX_STRIPED_SV_STRING]; CG_CheckSVStripEdRef(strEd, CG_Argv(1)); CG_CenterPrint( strEd, SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH ); return; } if ( !strcmp( cmd, "cs" ) ) { CG_ConfigStringModified(); return; } if ( !strcmp( cmd, "print" ) ) { char strEd[MAX_STRIPED_SV_STRING]; CG_CheckSVStripEdRef(strEd, CG_Argv(1)); CG_Printf( "%s", strEd ); return; } if ( !strcmp( cmd, "chat" ) ) { if ( !cg_teamChatsOnly.integer ) { trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); CG_Printf( "%s\n", text ); } return; } if ( !strcmp( cmd, "tchat" ) ) { trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); CG_AddToTeamChat( text ); CG_Printf( "%s\n", text ); return; } if ( !strcmp( cmd, "vchat" ) ) { CG_VoiceChat( SAY_ALL ); return; } if ( !strcmp( cmd, "vtchat" ) ) { CG_VoiceChat( SAY_TEAM ); return; } if ( !strcmp( cmd, "vtell" ) ) { CG_VoiceChat( SAY_TELL ); return; } if ( !strcmp( cmd, "scores" ) ) { CG_ParseScores(); return; } if ( !strcmp( cmd, "tinfo" ) ) { CG_ParseTeamInfo(); return; } if ( !strcmp( cmd, "map_restart" ) ) { CG_MapRestart(); return; } if ( Q_stricmp (cmd, "remapShader") == 0 ) { if (trap_Argc() == 4) { trap_R_RemapShader(CG_Argv(1), CG_Argv(2), CG_Argv(3)); } } // loaddeferred can be both a servercmd and a consolecmd if ( !strcmp( cmd, "loaddefered" ) ) { // FIXME: spelled wrong, but not changing for demo CG_LoadDeferredPlayers(); return; } // clientLevelShot is sent before taking a special screenshot for // the menu system during development if ( !strcmp( cmd, "clientLevelShot" ) ) { cg.levelShot = qtrue; return; } CG_Printf( "Unknown client game command: %s\n", cmd ); }
/* ================= 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)); cmd = CG_Argv(1); // yes, this is obviously a hack, but so is the way we hear about // votes passing or failing if(!Q_stricmpn(cmd, "vote failed", 11) || !Q_stricmpn(cmd, "team vote failed", 16)) { trap_S_StartLocalSound(cgs.media.voteFailed, CHAN_ANNOUNCER); } else if(!Q_stricmpn(cmd, "vote passed", 11) || !Q_stricmpn(cmd, "team vote passed", 16)) { trap_S_StartLocalSound(cgs.media.votePassed, CHAN_ANNOUNCER); } return; } if(!strcmp(cmd, "chat")) { if(!cg_teamChatsOnly.integer) { trap_S_StartLocalSound(cgs.media.talkSound, CHAN_LOCAL_SOUND); Q_strncpyz(text, CG_Argv(1), MAX_SAY_TEXT); CG_RemoveChatEscapeChar(text); CG_Printf("%s\n", text); } return; } if(!strcmp(cmd, "tchat")) { trap_S_StartLocalSound(cgs.media.talkSound, CHAN_LOCAL_SOUND); Q_strncpyz(text, CG_Argv(1), MAX_SAY_TEXT); CG_RemoveChatEscapeChar(text); CG_AddToTeamChat(text); CG_Printf("%s\n", text); return; } if(!strcmp(cmd, "vchat")) { CG_VoiceChat(SAY_ALL); return; } if(!strcmp(cmd, "vtchat")) { CG_VoiceChat(SAY_TEAM); return; } if(!strcmp(cmd, "vtell")) { CG_VoiceChat(SAY_TELL); return; } if(!strcmp(cmd, "scores")) { CG_ParseScores(); return; } if(!strcmp(cmd, "tinfo")) { CG_ParseTeamInfo(); return; } if(!strcmp(cmd, "map_restart")) { CG_MapRestart(); return; } if(Q_stricmp(cmd, "remapShader") == 0) { if(trap_Argc() == 4) { char shader1[MAX_QPATH]; char shader2[MAX_QPATH]; char shader3[MAX_QPATH]; Q_strncpyz(shader1, CG_Argv(1), sizeof(shader1)); Q_strncpyz(shader2, CG_Argv(2), sizeof(shader2)); Q_strncpyz(shader3, CG_Argv(3), sizeof(shader3)); trap_R_RemapShader(shader1, shader2, shader3); } return; } // loaddeferred can be both a servercmd and a consolecmd if(!strcmp(cmd, "loaddeferred")) { CG_LoadDeferredPlayers(); return; } // clientLevelShot is sent before taking a special screenshot for // the menu system during development if(!strcmp(cmd, "clientLevelShot")) { cg.levelShot = qtrue; return; } if(!strcmp(cmd, "spWin")) { CG_spWin(); return; } if(!strcmp(cmd, "spLose")) { CG_spLose(); return; } CG_Printf("Unknown client game command: %s\n", cmd); }
/* ================= CG_DrawQ3Scoreboard Draw the normal in-game scoreboard ================= */ qboolean CG_DrawQ3Scoreboard( void ) { int x, y, w, i, n1, n2; float *fadeColor, fade; char *s; int maxClients; int lineHeight; int topBorderSize, bottomBorderSize; // don't draw anything if the menu or console is up if ( cg_paused.integer ) { cg.deferredPlayerLoading = 0; return qfalse; } if ( cgs.gametype == GT_SINGLE_PLAYER && cg.predictedPlayerState.pm_type == PM_INTERMISSION ) { cg.deferredPlayerLoading = 0; return qfalse; } // don't draw scoreboard during death while warmup up if ( cg.warmup && !cg.showScores && cg.time > cg.scoreFadeTime + FADE_TIME ) { return qfalse; } //#if 0 if ( cg.showScores || cg.predictedPlayerState.pm_type == PM_DEAD || cg.predictedPlayerState.pm_type == PM_INTERMISSION ) { fadeColor = colorWhite; } else { fadeColor = CG_FadeColor( cg.scoreFadeTime, FADE_TIME ); if ( !fadeColor ) { // next time scoreboard comes up, don't print killer cg.deferredPlayerLoading = 0; cg.killerName[0] = 0; return qfalse; } } //#endif //fadeColor = colorWhite; fade = fadeColor[3]; //#if 0 // request more scores regularly if ( cg.scoresRequestTime + 2000 < cg.time ) { cg.scoresRequestTime = cg.time; trap_SendClientCommand( "score" ); } //CG_Printf( "scoresRequestTime = %i\n", cg.scoresRequestTime ); //CG_Printf( "scoreFadeTime = %i, fade = %f\n", cg.scoreFadeTime, fade ); //#endif // fragged by ... line if ( !cg.warmup ) { if ( cg.killerName[0] ) { s = va( "Fragged by %s", cg.killerName ); y = 40; if ( cg_highResFonts.integer ) { float scale = 0.35; int h; w = CG_Text_Width(s, scale, 0); h = CG_Text_Height(s, scale, 0); x = (SCREEN_WIDTH - w) / 2; CG_Text_Paint( x, y + h, scale, fadeColor, s, 0, 0, ITEM_TEXTSTYLE_SHADOWED, SCR_CENTER ); } else { w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; x = ( SCREEN_WIDTH - w ) / 2; CG_DrawBigString( x, y, s, fade, SCR_CENTER ); } } // current rank { s = CG_GetGameStatusText(); if ( s[0] ) { y = 60; if ( cg_highResFonts.integer ) { float scale = 0.35f; int h; w = CG_Text_Width(s, scale, 0); h = CG_Text_Height(s, scale, 0); x = (SCREEN_WIDTH - w) / 2; CG_Text_Paint( x, y + h, scale, fadeColor, s, 0, 0, ITEM_TEXTSTYLE_SHADOWED, SCR_CENTER ); } else { w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; x = ( SCREEN_WIDTH - w ) / 2; CG_DrawBigString( x, y, s, fade, SCR_CENTER ); } } } } // scoreboard y = SB_HEADER; CG_DrawColorPic( SB_SCORE_X + (SB_RATING_WIDTH / 2), y, 64, 32, cgs.media.scoreboardScore, SCR_CENTER, fadeColor ); CG_DrawColorPic( SB_PING_X - (SB_RATING_WIDTH / 2), y, 64, 32, cgs.media.scoreboardPing, SCR_CENTER, fadeColor ); CG_DrawColorPic( SB_TIME_X - (SB_RATING_WIDTH / 2), y, 64, 32, cgs.media.scoreboardTime, SCR_CENTER, fadeColor ); CG_DrawColorPic( SB_NAME_X - (SB_RATING_WIDTH / 2), y, 64, 32, cgs.media.scoreboardName, SCR_CENTER, fadeColor ); y = SB_TOP; // If there are more than SB_MAXCLIENTS_NORMAL, use the interleaved scores if ( cg.numScores > SB_MAXCLIENTS_NORMAL ) { maxClients = SB_MAXCLIENTS_INTER; lineHeight = SB_INTER_HEIGHT; topBorderSize = 8; bottomBorderSize = 16; } else { maxClients = SB_MAXCLIENTS_NORMAL; lineHeight = SB_NORMAL_HEIGHT; topBorderSize = 16; bottomBorderSize = 16; } localClient = qfalse; if ( gt[cgs.gametype].teams ) { float team_opacity = 0.33f; // // teamplay scoreboard // y += lineHeight/2; if ( cg.teamScores[0] >= cg.teamScores[1] ) { n1 = CG_TeamScoreCount( TEAM_RED, maxClients ); CG_DrawTeamBackground( 0, y - topBorderSize, SCREEN_WIDTH, n1 * lineHeight + bottomBorderSize, team_opacity, TEAM_RED, SCR_NONE ); CG_TeamScoreboard( y, TEAM_RED, fade, maxClients, lineHeight ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; maxClients -= n1; n2 = CG_TeamScoreCount( TEAM_BLUE, maxClients ); CG_DrawTeamBackground( 0, y - topBorderSize, SCREEN_WIDTH, n2 * lineHeight + bottomBorderSize, team_opacity, TEAM_BLUE, SCR_NONE ); CG_TeamScoreboard( y, TEAM_BLUE, fade, maxClients, lineHeight ); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; maxClients -= n2; } else { n1 = CG_TeamScoreCount( TEAM_BLUE, maxClients ); CG_DrawTeamBackground( 0, y - topBorderSize, SCREEN_WIDTH, n1 * lineHeight + bottomBorderSize, team_opacity, TEAM_BLUE, SCR_NONE ); CG_TeamScoreboard( y, TEAM_BLUE, fade, maxClients, lineHeight ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; maxClients -= n1; n2 = CG_TeamScoreCount( TEAM_RED, maxClients ); CG_DrawTeamBackground( 0, y - topBorderSize, SCREEN_WIDTH, n2 * lineHeight + bottomBorderSize, team_opacity, TEAM_RED, SCR_NONE ); CG_TeamScoreboard( y, TEAM_RED, fade, maxClients, lineHeight ); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; maxClients -= n2; } /* n1 = CG_TeamScoreCount( TEAM_SPECTATOR, maxClients ); CG_TeamScoreboard( y, TEAM_SPECTATOR, fade, maxClients, lineHeight ); */ n1 = CG_TeamScoreboard( y, TEAM_SPECTATOR, fade, maxClients, lineHeight ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; } else { // // free for all scoreboard // /* n1 = CG_TeamScoreCount( TEAM_SPECTATOR, maxClients ); CG_TeamScoreboard( y, TEAM_FREE, fade, maxClients, lineHeight ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; n2 = CG_TeamScoreCount( TEAM_SPECTATOR, maxClients ); CG_TeamScoreboard( y, TEAM_SPECTATOR, fade, maxClients - n1, lineHeight ); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; */ n1 = CG_TeamScoreboard( y, TEAM_FREE, fade, maxClients, lineHeight ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; n2 = CG_TeamScoreboard( y, TEAM_SPECTATOR, fade, maxClients - n1, lineHeight ); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; } if (!localClient) { // draw local client at the bottom for ( i = 0 ; i < cg.numScores ; i++ ) { if ( cg.scores[i].client == cg.snap->ps.clientNum ) { CG_DrawClientScore( y, &cg.scores[i], fadeColor, fade, lineHeight == SB_NORMAL_HEIGHT ); break; } } } // load any models that have been deferred if ( ++cg.deferredPlayerLoading > 10 ) { CG_LoadDeferredPlayers(); } return qtrue; }