/* Copyright (C) 2002-2003 Victor Luchits This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "cg_local.h" //================== //CG_SC_Print //================== void CG_SC_Print( void ) { CG_Printf( "%s", trap_Cmd_Argv(1) ); } //================== //CG_SC_Print //================== void CG_SC_ChatPrint( void ) { CG_Printf( "%s", trap_Cmd_Argv(1) ); trap_S_StartSound( NULL, cgs.playerNum+1, 0, CG_MediaSfx( cgs.media.sfxChat ), 1.0f, ATTN_NONE, 0.0f ); } //================== //CG_SC_CenterPrint //================== void CG_SC_CenterPrint( void ) { SCR_CenterPrint( trap_Cmd_Argv(1) ); } extern cvar_t *cg_showObituaries; //================== //CG_SC_Obituary //================== void CG_SC_Obituary( void ) { char message[128]; char message2[128]; cg_clientInfo_t *victim, *attacker; int victimNum = atoi( trap_Cmd_Argv(1) ); int attackerNum = atoi( trap_Cmd_Argv(2) ); int mod = atoi( trap_Cmd_Argv(3) ); int victim_gender = GENDER_MALE; // wsw : jal : extract gender from their player model info, if any if( victimNum >= 0 && victimNum < MAX_EDICTS && cg_entPModels[victimNum].pmodelinfo ) victim_gender = cg_entPModels[victimNum].pmodelinfo->sex; victim = &cgs.clientInfo[victimNum - 1]; if( attackerNum ) { attacker = &cgs.clientInfo[attackerNum - 1]; } else { attacker = NULL; } // wsw : pb : where are obituaries printed if( cg_showObituaries->integer != 0 ) { GS_Obituary( victim, victim_gender, attacker, mod, message, message2 ); if( attackerNum ) { if( victimNum != attackerNum ) { // teamkill if( cg_entities[attackerNum].current.team == cg_entities[victimNum].current.team && GS_Gametype_IsTeamBased(cg.frame.playerState.stats[STAT_GAMETYPE]) ) { if( cg_showObituaries->integer & 1 ) CG_Printf( "%s%s%s %s %s%s %s%s%s\n", S_COLOR_RED, "TEAMKILL:", S_COLOR_WHITE, victim->name, S_COLOR_WHITE, message, attacker->name, S_COLOR_WHITE, message2 ); if( attackerNum == cg.chasedNum+1 && cg_showObituaries->integer & 2 ) { SCR_CenterPrintToUpper( va("%s%s%s %s\n", S_COLOR_RED, "YOU TEAMKILLED", S_COLOR_WHITE, victim->name ) ); } else if( cg_showObituaries->integer & 4 ) { SCR_CenterPrint( va("%s%s%s %s %s%s %s%s%s\n", S_COLOR_RED, "TEAMKILL:", S_COLOR_WHITE, victim->name, S_COLOR_WHITE, message, attacker->name, S_COLOR_WHITE, message2) ); } // good kill } else { if( cg_showObituaries->integer & 1 ) CG_Printf( "%s %s%s %s%s%s\n", victim->name, S_COLOR_WHITE, message, attacker->name, S_COLOR_WHITE, message2 ); if( attackerNum == cg.chasedNum+1 && cg_showObituaries->integer & 2 ) { SCR_CenterPrintToUpper( va("%s%s %s\n", S_COLOR_WHITE, "YOU KILLED", victim->name) ); } else if( cg_showObituaries->integer & 4 ) { SCR_CenterPrint( va("%s %s%s %s%s%s\n", victim->name, S_COLOR_WHITE, message, attacker->name, S_COLOR_WHITE, message2) ); } } // suicide } else { if( cg_showObituaries->integer & 1 ) CG_Printf( "%s %s%s\n", victim->name, S_COLOR_WHITE, message ); if( cg_showObituaries->integer & 4 ) SCR_CenterPrint( va( "%s %s%s\n", victim->name, S_COLOR_WHITE, message ) ); } // world accidents } else { if( cg_showObituaries->integer & 1 ) CG_Printf( "%s %s%s\n", victim->name, S_COLOR_WHITE, message ); if( cg_showObituaries->integer & 4 ) SCR_CenterPrint( va( "%s %s%s\n", victim->name, S_COLOR_WHITE, message ) ); } } } //================ //CG_CS_ConfigString //================ void CG_CS_ConfigString( void ) { int i = atoi( trap_Cmd_Argv(1) ); char *s = trap_Cmd_Argv( 2 ); char olds[MAX_QPATH]; int len; // wsw : jal : warn if configstring overflow len = strlen( s ); if( len >= MAX_QPATH ) CG_Printf( "%sWARNING:%s Configstring %i overflowed\n", S_COLOR_YELLOW, S_COLOR_WHITE, i ); if ( i < 0 || i >= MAX_CONFIGSTRINGS ) { CG_Error( "configstring > MAX_CONFIGSTRINGS" ); } Q_strncpyz( olds, cgs.configStrings[i], sizeof(olds) ); Q_strncpyz( cgs.configStrings[i], s, sizeof(cgs.configStrings[i]) ); // do something apropriate if( i == CS_MAPNAME ) { CG_RegisterLevelShot(); } else if( i == CS_SERVERSETTINGS ) { CG_UpdateServerSettings(); } else if( i >= CS_MODELS && i < CS_MODELS+MAX_MODELS ) { if( cgs.configStrings[i][0] == '$') { // indexed pmodel cgs.pModelsIndex[i-CS_MODELS] = CG_RegisterPlayerModel( cgs.configStrings[i]+1 ); } else cgs.modelDraw[i-CS_MODELS] = CG_RegisterModel( cgs.configStrings[i] ); // skelmod } else if( i >= CS_SOUNDS && i < CS_SOUNDS+MAX_SOUNDS ) { if( cgs.configStrings[i][0] != '*' ) { cgs.soundPrecache[i-CS_SOUNDS] = trap_S_RegisterSound( cgs.configStrings[i] ); } } else if( i >= CS_IMAGES && i < CS_IMAGES+MAX_IMAGES ) { cgs.imagePrecache[i-CS_IMAGES] = trap_R_RegisterPic( cgs.configStrings[i] ); } else if( i >= CS_SKINFILES && i < CS_SKINFILES+MAX_SKINFILES ) { cgs.skinPrecache[i-CS_SKINFILES] = trap_R_RegisterSkinFile( cgs.configStrings[i] ); } else if( i >= CS_LIGHTS && i < CS_LIGHTS+MAX_LIGHTSTYLES ) { CG_SetLightStyle( i - CS_LIGHTS ); } else if( i >= CS_ITEMS && i < CS_ITEMS+MAX_ITEMS ) { CG_ValidateItemDef( i - CS_ITEMS, cgs.configStrings[i] ); } else if( i >= CS_PLAYERINFOS && i < CS_PLAYERINFOS+MAX_CLIENTS ) { CG_LoadClientInfo( &cgs.clientInfo[i-CS_PLAYERINFOS], cgs.configStrings[i], i-CS_PLAYERINFOS ); } else if( i >= CS_GAMECOMMANDS && i < CS_GAMECOMMANDS+MAX_GAMECOMMANDS ) { trap_Cmd_AddCommand( cgs.configStrings[i], NULL ); } } //================ //CG_SC_Inventory //================ void CG_SC_Inventory( void ) { int i, rep; char inv[MAX_TOKEN_CHARS], *s; Q_strncpyz( inv, trap_Cmd_Argv( 1 ), sizeof( inv ) ); cg.inventory[0] = 0; // item 0 is never used for( i = 1, s = inv; (i < MAX_ITEMS) && s && *s; i++ ) { cg.inventory[i] = atoi( COM_Parse(&s) ); if( cg.inventory[i] ) continue; for( rep = atoi( COM_Parse(&s) ); (rep > 0) && (i < MAX_ITEMS); rep-- ) cg.inventory[i++] = 0; i--; } } //================ //CG_SC_Scoreboard // wsw : jal : scoreboard templates //================ void SCR_UpdateScoreboardMessage( char *string ); void CG_SC_Scoreboard( void ) { SCR_UpdateScoreboardMessage( trap_Cmd_Argv(1) ); } //================ //CG_SC_AutoRecord //================ #define CG_AUTORECORD_DO_DEMOS 1 #define CG_AUTORECORD_DO_SCREENSHOT 2 #define CG_AUTORECORD_NOT_WHILE_SPEC 4 //#define CG_AUTORECORD_DO_STATS 8 void CG_SC_AutoRecord( void ) { time_t long_time; struct tm *newtime; char *s = trap_Cmd_Argv(1); static char name[MAX_QPATH]; static char mapname[MAX_QPATH]; char *cleanplayername; char *cleanplayername2; // filter out autorecord commands when playing a demo if( cg.demoPlaying ) return; if( !cg_autoaction->integer ) return; // don't do if spectator and 3rd bit isn't set if( cg.frame.playerState.pmove.pm_type == PM_SPECTATOR || cg.chasedNum != cgs.playerNum ) if( !(cg_autoaction->integer & CG_AUTORECORD_NOT_WHILE_SPEC) && !Q_stricmp(s, "start") ) return; // get date from system time( &long_time ); newtime = localtime( &long_time ); // remove color tokens from player names (doh) cleanplayername = COM_RemoveColorTokens( cgs.clientInfo[cg.chasedNum].name ); // remove junk chars from player names for files cleanplayername2 = COM_RemoveJunkChars ( cleanplayername ); // lowercase mapname Q_strncpyz( mapname, cgs.configStrings[CS_MAPNAME], sizeof(mapname) ); Q_strlwr( mapname ); // make file name // duel_year-month-day_hour-min_map_player Q_snprintfz( name, sizeof(name), "%s_%04d-%02d-%02d_%02d-%02d_%s_%s", GS_Gametype_ShortName( cg.frame.playerState.stats[STAT_GAMETYPE] ), newtime->tm_year + 1900, newtime->tm_mon+1, newtime->tm_mday, newtime->tm_hour, newtime->tm_min, mapname, cleanplayername2 ); if( !Q_stricmp(s, "start") ) { //start recording cg_autoaction = trap_Cvar_Get( "cg_autoaction", "0", CVAR_ARCHIVE ); if( cg_autoaction->integer & CG_AUTORECORD_DO_DEMOS ) // auto record of demos { trap_Cmd_ExecuteText( EXEC_NOW, "stop silent" ); trap_Cmd_ExecuteText( EXEC_NOW, va("record autorecord/%s/%s silent", GS_Gametype_ShortName( cg.frame.playerState.stats[STAT_GAMETYPE]), name) ); } } else if( !Q_stricmp(s, "stop") ) { //stop recording cg_autoaction = trap_Cvar_Get( "cg_autoaction", "0", CVAR_ARCHIVE ); if( cg_autoaction->integer & CG_AUTORECORD_DO_DEMOS ) // automatic demos { trap_Cmd_ExecuteText( EXEC_NOW, "stop silent" ); } if( cg_autoaction->integer & CG_AUTORECORD_DO_SCREENSHOT ) // automatic screenshot { trap_Cmd_ExecuteText( EXEC_NOW, va("screenshot autorecord/%s/%s silent", GS_Gametype_ShortName( cg.frame.playerState.stats[STAT_GAMETYPE]), name) ); } /* if( cg_autoaction->integer & CG_AUTORECORD_DO_STATS ) // automatic stats { //trap_Cmd_ExecuteText( EXEC_NOW, "clear"); trap_Cmd_ExecuteText( EXEC_NOW, "stats"); trap_Cmd_ExecuteText( EXEC_NOW, va("condump stats/%s/%s", GS_Gametype_ShortName( cg.frame.playerState.stats[STAT_GAMETYPE]), name) ); } */ } else if( !Q_stricmp(s, "cancel") ) { // cancel the record trap_Cmd_ExecuteText( EXEC_NOW, "stop cancel silent" ); } else if( developer->integer ) CG_Printf( "CG_SC_AutoRecord: Unknown argument: %s\n", s ); } //======================================================= void CG_SC_MatchMessage( void ) { Q_strncpyz( cg.matchmessage, trap_Cmd_Argv(1), sizeof(cg.matchmessage) ); } void CG_CS_UpdateTeamInfo( void ) { Q_strncpyz( cg.teaminfo, trap_Cmd_Argv(1), sizeof(cg.teaminfo) ); } //======================================================= void CG_SC_Layout( void ) { CG_LoadLayout( trap_Cmd_Argv(1) ); } //======================================================= typedef struct { char *name; void (*func) (void); } svcmd_t; svcmd_t cg_svcmds[] = { { "pr", CG_SC_Print }, { "ch", CG_SC_ChatPrint }, { "cp", CG_SC_CenterPrint }, { "obry", CG_SC_Obituary }, { "cs", CG_CS_ConfigString }, { "inv", CG_SC_Inventory }, { "scb", CG_SC_Scoreboard }, // wsw : jal : scoreboard templates { "autr", CG_SC_AutoRecord }, // wsw : jal : autorecord command { "mm", CG_SC_MatchMessage }, { "layout", CG_CS_ConfigString }, { "ti", CG_CS_UpdateTeamInfo }, { NULL } }; /* ================== CG_ServerCommand ================== */ void CG_ServerCommand (void) { char *s; svcmd_t *cmd; s = trap_Cmd_Argv ( 0 ); for (cmd = cg_svcmds; cmd->name; cmd++) { if (!strcmp (s, cmd->name) ) { cmd->func (); return; } } }