mirror of
https://github.com/DrBeef/JKXR.git
synced 2025-01-27 02:31:23 +00:00
403 lines
9.1 KiB
C
403 lines
9.1 KiB
C
/*
|
|
===========================================================================
|
|
Copyright (C) 1999 - 2005, Id Software, Inc.
|
|
Copyright (C) 2000 - 2013, Raven Software, Inc.
|
|
Copyright (C) 2001 - 2013, Activision, Inc.
|
|
Copyright (C) 2005 - 2015, ioquake3 contributors
|
|
Copyright (C) 2013 - 2015, OpenJK contributors
|
|
|
|
This file is part of the OpenJK source code.
|
|
|
|
OpenJK is free software; you can redistribute it and/or modify it
|
|
under the terms of the GNU General Public License version 2 as
|
|
published by the Free Software Foundation.
|
|
|
|
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, see <http://www.gnu.org/licenses/>.
|
|
===========================================================================
|
|
*/
|
|
|
|
// cg_consolecmds.c -- text commands typed in at the local console, or
|
|
// executed by a key binding
|
|
|
|
#include "cg_local.h"
|
|
#include "game/bg_saga.h"
|
|
#include "ui/ui_shared.h"
|
|
|
|
/*
|
|
=================
|
|
CG_TargetCommand_f
|
|
|
|
=================
|
|
*/
|
|
void CG_TargetCommand_f( void ) {
|
|
int targetNum;
|
|
char test[4];
|
|
|
|
targetNum = CG_CrosshairPlayer();
|
|
if ( targetNum == -1 ) {
|
|
return;
|
|
}
|
|
|
|
trap->Cmd_Argv( 1, test, 4 );
|
|
trap->SendClientCommand( va( "gc %i %i", targetNum, atoi( test ) ) );
|
|
}
|
|
|
|
/*
|
|
=================
|
|
CG_SizeUp_f
|
|
|
|
Keybinding command
|
|
=================
|
|
*/
|
|
static void CG_SizeUp_f (void) {
|
|
trap->Cvar_Set( "cg_viewsize", va( "%i", Q_min( cg_viewsize.integer + 10, 100 ) ) );
|
|
}
|
|
|
|
/*
|
|
=================
|
|
CG_SizeDown_f
|
|
|
|
Keybinding command
|
|
=================
|
|
*/
|
|
static void CG_SizeDown_f (void) {
|
|
trap->Cvar_Set( "cg_viewsize", va( "%i", Q_max( cg_viewsize.integer - 10, 30 ) ) );
|
|
}
|
|
|
|
/*
|
|
=============
|
|
CG_Viewpos_f
|
|
|
|
Debugging command to print the current position
|
|
=============
|
|
*/
|
|
static void CG_Viewpos_f (void) {
|
|
trap->Print ("%s (%i %i %i) : %i\n", cgs.mapname, (int)cg.refdef.vieworg[0],
|
|
(int)cg.refdef.vieworg[1], (int)cg.refdef.vieworg[2],
|
|
(int)cg.refdef.viewangles[YAW]);
|
|
}
|
|
|
|
/*
|
|
=================
|
|
CG_ScoresDown_f
|
|
|
|
=================
|
|
*/
|
|
static void CG_ScoresDown_f( void ) {
|
|
|
|
CG_BuildSpectatorString();
|
|
if ( cg.scoresRequestTime + 2000 < cg.time ) {
|
|
// the scores are more than two seconds out of data,
|
|
// so request new ones
|
|
cg.scoresRequestTime = cg.time;
|
|
trap->SendClientCommand( "score" );
|
|
|
|
// leave the current scores up if they were already
|
|
// displayed, but if this is the first hit, clear them out
|
|
if ( !cg.showScores ) {
|
|
cg.showScores = qtrue;
|
|
cg.numScores = 0;
|
|
}
|
|
} else {
|
|
// show the cached contents even if they just pressed if it
|
|
// is within two seconds
|
|
cg.showScores = qtrue;
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
CG_ScoresUp_f
|
|
|
|
=================
|
|
*/
|
|
static void CG_ScoresUp_f( void ) {
|
|
if ( cg.showScores ) {
|
|
cg.showScores = qfalse;
|
|
cg.scoreFadeTime = cg.time;
|
|
}
|
|
}
|
|
|
|
void CG_ClientList_f( void )
|
|
{
|
|
clientInfo_t *ci;
|
|
int i;
|
|
int count = 0;
|
|
|
|
for( i = 0; i < MAX_CLIENTS; i++ )
|
|
{
|
|
ci = &cgs.clientinfo[ i ];
|
|
if( !ci->infoValid )
|
|
continue;
|
|
|
|
switch( ci->team )
|
|
{
|
|
case TEAM_FREE:
|
|
Com_Printf( "%2d " S_COLOR_YELLOW "F " S_COLOR_WHITE "%s" S_COLOR_WHITE "%s\n", i, ci->name, (ci->botSkill != -1) ? " (bot)" : "" );
|
|
break;
|
|
|
|
case TEAM_RED:
|
|
Com_Printf( "%2d " S_COLOR_RED "R " S_COLOR_WHITE "%s" S_COLOR_WHITE "%s\n", i,
|
|
ci->name, (ci->botSkill != -1) ? " (bot)" : "" );
|
|
break;
|
|
|
|
case TEAM_BLUE:
|
|
Com_Printf( "%2d " S_COLOR_BLUE "B " S_COLOR_WHITE "%s" S_COLOR_WHITE "%s\n", i,
|
|
ci->name, (ci->botSkill != -1) ? " (bot)" : "" );
|
|
break;
|
|
|
|
default:
|
|
case TEAM_SPECTATOR:
|
|
Com_Printf( "%2d " S_COLOR_YELLOW "S " S_COLOR_WHITE "%s" S_COLOR_WHITE "%s\n", i, ci->name, (ci->botSkill != -1) ? " (bot)" : "" );
|
|
break;
|
|
}
|
|
|
|
count++;
|
|
}
|
|
|
|
Com_Printf( "Listed %2d clients\n", count );
|
|
}
|
|
|
|
|
|
static void CG_TellTarget_f( void ) {
|
|
int clientNum;
|
|
char command[MAX_SAY_TEXT+10];
|
|
char message[MAX_SAY_TEXT];
|
|
|
|
clientNum = CG_CrosshairPlayer();
|
|
if ( clientNum == -1 ) {
|
|
return;
|
|
}
|
|
|
|
trap->Cmd_Args( message, sizeof(message) );
|
|
Com_sprintf( command, sizeof(command), "tell %i %s", clientNum, message );
|
|
trap->SendClientCommand( command );
|
|
}
|
|
|
|
static void CG_TellAttacker_f( void ) {
|
|
int clientNum;
|
|
char command[MAX_SAY_TEXT + 10];
|
|
char message[MAX_SAY_TEXT];
|
|
|
|
clientNum = CG_LastAttacker();
|
|
if ( clientNum == -1 ) {
|
|
return;
|
|
}
|
|
|
|
trap->Cmd_Args( message, sizeof(message) );
|
|
Com_sprintf( command, sizeof(command), "tell %i %s", clientNum, message );
|
|
trap->SendClientCommand( command );
|
|
}
|
|
|
|
/*
|
|
==================
|
|
CG_StartOrbit_f
|
|
==================
|
|
*/
|
|
|
|
static void CG_StartOrbit_f( void ) {
|
|
char var[MAX_TOKEN_CHARS];
|
|
|
|
trap->Cvar_VariableStringBuffer( "developer", var, sizeof( var ) );
|
|
if ( !atoi(var) ) {
|
|
return;
|
|
}
|
|
if (cg_cameraOrbit.value != 0) {
|
|
trap->Cvar_Set ("cg_cameraOrbit", "0");
|
|
trap->Cvar_Set("cg_thirdPerson", "0");
|
|
} else {
|
|
trap->Cvar_Set("cg_cameraOrbit", "5");
|
|
trap->Cvar_Set("cg_thirdPerson", "1");
|
|
trap->Cvar_Set("cg_thirdPersonAngle", "0");
|
|
trap->Cvar_Set("cg_thirdPersonRange", "100");
|
|
}
|
|
}
|
|
|
|
void CG_SiegeBriefingDisplay(int team, int dontshow);
|
|
static void CG_SiegeBriefing_f(void)
|
|
{
|
|
int team;
|
|
|
|
if (cgs.gametype != GT_SIEGE)
|
|
{ //Cannot be displayed unless in this gametype
|
|
return;
|
|
}
|
|
|
|
team = cg.predictedPlayerState.persistant[PERS_TEAM];
|
|
|
|
if (team != SIEGETEAM_TEAM1 &&
|
|
team != SIEGETEAM_TEAM2)
|
|
{ //cannot be displayed if not on a valid team
|
|
return;
|
|
}
|
|
|
|
CG_SiegeBriefingDisplay(team, 0);
|
|
}
|
|
|
|
static void CG_SiegeCvarUpdate_f(void)
|
|
{
|
|
int team;
|
|
|
|
if (cgs.gametype != GT_SIEGE)
|
|
{ //Cannot be displayed unless in this gametype
|
|
return;
|
|
}
|
|
|
|
team = cg.predictedPlayerState.persistant[PERS_TEAM];
|
|
|
|
if (team != SIEGETEAM_TEAM1 &&
|
|
team != SIEGETEAM_TEAM2)
|
|
{ //cannot be displayed if not on a valid team
|
|
return;
|
|
}
|
|
|
|
CG_SiegeBriefingDisplay(team, 1);
|
|
}
|
|
|
|
static void CG_SiegeCompleteCvarUpdate_f(void)
|
|
{
|
|
if (cgs.gametype != GT_SIEGE)
|
|
{ //Cannot be displayed unless in this gametype
|
|
return;
|
|
}
|
|
|
|
// Set up cvars for both teams
|
|
CG_SiegeBriefingDisplay(SIEGETEAM_TEAM1, 1);
|
|
CG_SiegeBriefingDisplay(SIEGETEAM_TEAM2, 1);
|
|
}
|
|
|
|
static void CG_LoadHud_f( void ) {
|
|
const char *hudSet = cg_hudFiles.string;
|
|
if ( hudSet[0] == '\0' ) {
|
|
hudSet = "ui/jahud.txt";
|
|
}
|
|
|
|
String_Init();
|
|
Menu_Reset();
|
|
CG_LoadMenus( hudSet );
|
|
}
|
|
|
|
typedef struct consoleCommand_s {
|
|
const char *cmd;
|
|
void (*func)(void);
|
|
} consoleCommand_t;
|
|
|
|
int cmdcmp( const void *a, const void *b ) {
|
|
return Q_stricmp( (const char *)a, ((consoleCommand_t*)b)->cmd );
|
|
}
|
|
|
|
static consoleCommand_t commands[] = {
|
|
{ "+scores", CG_ScoresDown_f },
|
|
{ "-scores", CG_ScoresUp_f },
|
|
{ "briefing", CG_SiegeBriefing_f },
|
|
{ "clientlist", CG_ClientList_f },
|
|
{ "forcenext", CG_NextForcePower_f },
|
|
{ "forceprev", CG_PrevForcePower_f },
|
|
{ "invnext", CG_NextInventory_f },
|
|
{ "invprev", CG_PrevInventory_f },
|
|
{ "loaddeferred", CG_LoadDeferredPlayers },
|
|
{ "loadhud", CG_LoadHud_f },
|
|
{ "nextframe", CG_TestModelNextFrame_f },
|
|
{ "nextskin", CG_TestModelNextSkin_f },
|
|
{ "prevframe", CG_TestModelPrevFrame_f },
|
|
{ "prevskin", CG_TestModelPrevSkin_f },
|
|
{ "siegeCompleteCvarUpdate", CG_SiegeCompleteCvarUpdate_f },
|
|
{ "siegeCvarUpdate", CG_SiegeCvarUpdate_f },
|
|
{ "sizedown", CG_SizeDown_f },
|
|
{ "sizeup", CG_SizeUp_f },
|
|
{ "startOrbit", CG_StartOrbit_f },
|
|
{ "tcmd", CG_TargetCommand_f },
|
|
{ "tell_attacker", CG_TellAttacker_f },
|
|
{ "tell_target", CG_TellTarget_f },
|
|
{ "testgun", CG_TestGun_f },
|
|
{ "testmodel", CG_TestModel_f },
|
|
{ "viewpos", CG_Viewpos_f },
|
|
{ "weapnext", CG_NextWeapon_f },
|
|
{ "weapon", CG_Weapon_f },
|
|
{ "weaponclean", CG_WeaponClean_f },
|
|
{ "weapprev", CG_PrevWeapon_f },
|
|
};
|
|
|
|
static const size_t numCommands = ARRAY_LEN( commands );
|
|
|
|
/*
|
|
=================
|
|
CG_ConsoleCommand
|
|
|
|
The string has been tokenized and can be retrieved with
|
|
Cmd_Argc() / Cmd_Argv()
|
|
=================
|
|
*/
|
|
qboolean CG_ConsoleCommand( void ) {
|
|
consoleCommand_t *command = NULL;
|
|
|
|
command = (consoleCommand_t *)Q_LinearSearch( CG_Argv( 0 ), commands, numCommands, sizeof( commands[0] ), cmdcmp );
|
|
|
|
if ( !command || !command->func )
|
|
return qfalse;
|
|
|
|
command->func();
|
|
return qtrue;
|
|
}
|
|
|
|
static const char *gcmds[] = {
|
|
"addbot",
|
|
"callteamvote",
|
|
"callvote",
|
|
"duelteam",
|
|
"follow",
|
|
"follownext",
|
|
"followprev",
|
|
"forcechanged",
|
|
"give",
|
|
"god",
|
|
"kill",
|
|
"levelshot",
|
|
"loaddefered",
|
|
"noclip",
|
|
"notarget",
|
|
"NPC",
|
|
"say",
|
|
"say_team",
|
|
"setviewpos",
|
|
"siegeclass",
|
|
"stats",
|
|
//"stopfollow",
|
|
"team",
|
|
"teamtask",
|
|
"teamvote",
|
|
"tell",
|
|
"voice_cmd",
|
|
"vote",
|
|
"where",
|
|
"zoom"
|
|
};
|
|
static const size_t numgcmds = ARRAY_LEN( gcmds );
|
|
|
|
/*
|
|
=================
|
|
CG_InitConsoleCommands
|
|
|
|
Let the client system know about all of our commands
|
|
so it can perform tab completion
|
|
=================
|
|
*/
|
|
void CG_InitConsoleCommands( void ) {
|
|
size_t i;
|
|
|
|
for ( i = 0; i < numCommands; i++ )
|
|
trap->AddCommand( commands[i].cmd );
|
|
|
|
//
|
|
// the game server will interpret these commands, which will be automatically
|
|
// forwarded to the server after they are not recognized locally
|
|
//
|
|
for( i = 0; i < numgcmds; i++ )
|
|
trap->AddCommand( gcmds[i] );
|
|
}
|