1 /*
2 ===========================================================================
3
4 Return to Castle Wolfenstein single player GPL Source Code
5 Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
6
7 This file is part of the Return to Castle Wolfenstein single player GPL Source Code (RTCW SP Source Code).
8
9 RTCW SP Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 RTCW SP Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28
29 /*
30 * name: cg_consolecmds.c
31 *
32 * desc: text commands typed in at the local console, or executed by a key binding
33 *
34 */
35
36
37 #include "cg_local.h"
38 #include "../ui/ui_shared.h"
39
40
41
CG_TargetCommand_f(void)42 void CG_TargetCommand_f( void ) {
43 int targetNum;
44 char test[4];
45
46 targetNum = CG_CrosshairPlayer();
47 if ( targetNum == -1 ) {
48 return;
49 }
50
51 trap_Argv( 1, test, 4 );
52 trap_SendClientCommand( va( "gc %i %i", targetNum, atoi( test ) ) );
53 }
54
55
56
57 /*
58 =================
59 CG_SizeUp_f
60
61 Keybinding command
62 =================
63 */
CG_SizeUp_f(void)64 static void CG_SizeUp_f( void ) {
65 trap_Cvar_Set( "cg_viewsize", va( "%i",(int)( cg_viewsize.integer + 10 ) ) );
66 }
67
68
69 /*
70 =================
71 CG_SizeDown_f
72
73 Keybinding command
74 =================
75 */
CG_SizeDown_f(void)76 static void CG_SizeDown_f( void ) {
77 trap_Cvar_Set( "cg_viewsize", va( "%i",(int)( cg_viewsize.integer - 10 ) ) );
78 }
79
80
81 /*
82 =============
83 CG_Viewpos_f
84
85 Debugging command to print the current position
86 =============
87 */
CG_Viewpos_f(void)88 static void CG_Viewpos_f( void ) {
89 CG_Printf( "(%i %i %i) : %i\n", (int)cg.refdef.vieworg[0],
90 (int)cg.refdef.vieworg[1], (int)cg.refdef.vieworg[2],
91 (int)cg.refdefViewAngles[YAW] );
92 }
93
94
CG_ScoresDown_f(void)95 static void CG_ScoresDown_f( void ) {
96 if ( cg.scoresRequestTime + 2000 < cg.time ) {
97 // the scores are more than two seconds out of data,
98 // so request new ones
99 cg.scoresRequestTime = cg.time;
100 trap_SendClientCommand( "score" );
101
102 // leave the current scores up if they were already
103 // displayed, but if this is the first hit, clear them out
104 if ( !cg.showScores ) {
105 cg.showScores = qtrue;
106 cg.numScores = 0;
107 }
108 } else {
109 // show the cached contents even if they just pressed if it
110 // is within two seconds
111 cg.showScores = qtrue;
112 }
113 }
114
CG_ScoresUp_f(void)115 static void CG_ScoresUp_f( void ) {
116 if ( cg.showScores ) {
117 cg.showScores = qfalse;
118 cg.scoreFadeTime = cg.time;
119 }
120 }
121
122
123 extern menuDef_t *menuScoreboard;
124 void Menu_Reset( void ); // FIXME: add to right include file
125
CG_LoadHud_f(void)126 static void CG_LoadHud_f( void ) {
127 char buff[1024];
128 const char *hudSet;
129 memset( buff, 0, sizeof( buff ) );
130
131 String_Init();
132 Menu_Reset();
133
134 trap_Cvar_VariableStringBuffer( "cg_hudFiles", buff, sizeof( buff ) );
135 hudSet = buff;
136 if ( hudSet[0] == '\0' ) {
137 hudSet = "ui/hud.txt";
138 }
139
140 CG_LoadMenus( hudSet );
141 menuScoreboard = NULL;
142 }
143
144 // TTimo: defined but not used
145 /*
146 static void CG_scrollScoresDown_f( void) {
147 if (menuScoreboard && cg.scoreBoardShowing) {
148 Menu_ScrollFeeder(menuScoreboard, FEEDER_SCOREBOARD, qtrue);
149 Menu_ScrollFeeder(menuScoreboard, FEEDER_REDTEAM_LIST, qtrue);
150 Menu_ScrollFeeder(menuScoreboard, FEEDER_BLUETEAM_LIST, qtrue);
151 }
152 }
153
154
155 static void CG_scrollScoresUp_f( void) {
156 if (menuScoreboard && cg.scoreBoardShowing) {
157 Menu_ScrollFeeder(menuScoreboard, FEEDER_SCOREBOARD, qfalse);
158 Menu_ScrollFeeder(menuScoreboard, FEEDER_REDTEAM_LIST, qfalse);
159 Menu_ScrollFeeder(menuScoreboard, FEEDER_BLUETEAM_LIST, qfalse);
160 }
161 }
162
163
164 static void CG_spWin_f( void) {
165 trap_Cvar_Set("cg_cameraOrbit", "2");
166 trap_Cvar_Set("cg_cameraOrbitDelay", "35");
167 trap_Cvar_Set("cg_thirdPerson", "1");
168 trap_Cvar_Set("cg_thirdPersonAngle", "0");
169 trap_Cvar_Set("cg_thirdPersonRange", "100");
170 // CG_AddBufferedSound(cgs.media.winnerSound);
171 //trap_S_StartLocalSound(cgs.media.winnerSound, CHAN_ANNOUNCER);
172 CG_CenterPrint("YOU WIN!", SCREEN_HEIGHT * .30, 0);
173 }
174
175 static void CG_spLose_f( void) {
176 trap_Cvar_Set("cg_cameraOrbit", "2");
177 trap_Cvar_Set("cg_cameraOrbitDelay", "35");
178 trap_Cvar_Set("cg_thirdPerson", "1");
179 trap_Cvar_Set("cg_thirdPersonAngle", "0");
180 trap_Cvar_Set("cg_thirdPersonRange", "100");
181 // CG_AddBufferedSound(cgs.media.loserSound);
182 //trap_S_StartLocalSound(cgs.media.loserSound, CHAN_ANNOUNCER);
183 CG_CenterPrint("YOU LOSE...", SCREEN_HEIGHT * .30, 0);
184 }
185 */
186
187 //----(SA) item (key/pickup) drawing
CG_InventoryDown_f(void)188 static void CG_InventoryDown_f( void ) {
189 cg.showItems = qtrue;
190 }
191
CG_InventoryUp_f(void)192 static void CG_InventoryUp_f( void ) {
193 cg.showItems = qfalse;
194 cg.itemFadeTime = cg.time;
195 }
196
197 //----(SA) end
198
CG_TellTarget_f(void)199 static void CG_TellTarget_f( void ) {
200 int clientNum;
201 char command[128];
202 char message[128];
203
204 clientNum = CG_CrosshairPlayer();
205 if ( clientNum == -1 ) {
206 return;
207 }
208
209 trap_Args( message, 128 );
210 Com_sprintf( command, 128, "tell %i %s", clientNum, message );
211 trap_SendClientCommand( command );
212 }
213
CG_TellAttacker_f(void)214 static void CG_TellAttacker_f( void ) {
215 int clientNum;
216 char command[128];
217 char message[128];
218
219 clientNum = CG_LastAttacker();
220 if ( clientNum == -1 ) {
221 return;
222 }
223
224 trap_Args( message, 128 );
225 Com_sprintf( command, 128, "tell %i %s", clientNum, message );
226 trap_SendClientCommand( command );
227 }
228
229
230 // TTimo: defined but not used
231 /*
232 static void CG_NextTeamMember_f( void ) {
233 CG_SelectNextPlayer();
234 }
235
236 static void CG_PrevTeamMember_f( void ) {
237 CG_SelectPrevPlayer();
238 }
239 */
240
241 /////////// cameras
242
243 #define MAX_CAMERAS 64 // matches define in splines.cpp
244 qboolean cameraInuse[MAX_CAMERAS];
245
CG_LoadCamera(const char * name)246 int CG_LoadCamera( const char *name ) {
247 int i;
248 for ( i = 1; i < MAX_CAMERAS; i++ ) { // start at '1' since '0' is always taken by the cutscene camera
249 if ( !cameraInuse[i] ) {
250 if ( trap_loadCamera( i, name ) ) {
251 cameraInuse[i] = qtrue;
252 return i;
253 }
254 }
255 }
256 return -1;
257 }
258
CG_FreeCamera(int camNum)259 void CG_FreeCamera( int camNum ) {
260 cameraInuse[camNum] = qfalse;
261 }
262
263 /*
264 ==============
265 CG_StartCamera
266 ==============
267 */
CG_StartCamera(const char * name,qboolean startBlack)268 void CG_StartCamera( const char *name, qboolean startBlack ) {
269 char lname[MAX_QPATH];
270
271 //if ( cg.predictedPlayerState.stats[STAT_HEALTH] <= 0 ) // don't allow camera to start if you're dead
272 // return;
273
274 COM_StripExtension( name, lname, sizeof( lname ) ); //----(SA) added
275 Q_strcat( lname, sizeof( lname ), ".camera" );
276
277 if ( trap_loadCamera( CAM_PRIMARY, va( "cameras/%s", lname ) ) ) {
278 cg.cameraMode = qtrue; // camera on in cgame
279 if ( startBlack ) {
280 CG_Fade( 0, 0, 0, 255, cg.time, 0 ); // go black
281 }
282 trap_Cvar_Set( "cg_letterbox", "1" ); // go letterbox
283 trap_SendClientCommand( "startCamera" ); // camera on in game
284 trap_startCamera( CAM_PRIMARY, cg.time ); // camera on in client
285 } else {
286 //----(SA) removed check for cams in main dir
287 cg.cameraMode = qfalse; // camera off in cgame
288 trap_SendClientCommand( "stopCamera" ); // camera off in game
289 trap_stopCamera( CAM_PRIMARY ); // camera off in client
290 CG_Fade( 0, 0, 0, 0, cg.time, 0 ); // ensure fadeup
291 trap_Cvar_Set( "cg_letterbox", "0" );
292 CG_Printf( "Unable to load camera %s\n",lname );
293 }
294 }
295
296 /*
297 ==============
298 CG_StopCamera
299 ==============
300 */
CG_StopCamera(void)301 void CG_StopCamera( void ) {
302 cg.cameraMode = qfalse; // camera off in cgame
303 trap_SendClientCommand( "stopCamera" ); // camera off in game
304 trap_stopCamera( CAM_PRIMARY ); // camera off in client
305 trap_Cvar_Set( "cg_letterbox", "0" );
306
307 // fade back into world
308 CG_Fade( 0, 0, 0, 255, 0, 0 );
309 CG_Fade( 0, 0, 0, 0, cg.time + 500, 2000 );
310
311 }
312
CG_Camera_f(void)313 static void CG_Camera_f( void ) {
314 char name[MAX_QPATH];
315
316 trap_Argv( 1, name, sizeof( name ) );
317
318 CG_StartCamera( name, qfalse );
319 }
320
CG_Fade_f(void)321 static void CG_Fade_f( void ) {
322 int r, g, b, a;
323 float duration;
324
325 if ( trap_Argc() < 6 ) {
326 return;
327 }
328
329 r = atof( CG_Argv( 1 ) );
330 g = atof( CG_Argv( 2 ) );
331 b = atof( CG_Argv( 3 ) );
332 a = atof( CG_Argv( 4 ) );
333
334 duration = atof( CG_Argv( 5 ) ) * 1000;
335
336 CG_Fade( r, g, b, a, cg.time, duration );
337 }
338
339 // NERVE - SMF
CG_QuickMessage_f(void)340 static void CG_QuickMessage_f( void ) {
341 if ( cgs.gametype != GT_WOLF ) {
342 return;
343 }
344 trap_UI_Popup( "UIMENU_WM_QUICKMESSAGE" );
345 }
346
CG_OpenLimbo_f(void)347 static void CG_OpenLimbo_f( void ) {
348 if ( cgs.gametype != GT_WOLF ) {
349 return;
350 }
351 trap_UI_Popup( "UIMENU_WM_LIMBO" );
352 }
353
CG_CloseLimbo_f(void)354 static void CG_CloseLimbo_f( void ) {
355 if ( cgs.gametype != GT_WOLF ) {
356 return;
357 }
358 trap_UI_ClosePopup( "UIMENU_WM_LIMBO" );
359 }
360
CG_LimboMessage_f(void)361 static void CG_LimboMessage_f( void ) {
362 char teamStr[80], classStr[80], weapStr[80];
363
364 if ( cgs.gametype != GT_WOLF ) {
365 return;
366 }
367
368 Q_strncpyz( teamStr, CG_Argv( 1 ), 80 );
369 Q_strncpyz( classStr, CG_Argv( 2 ), 80 );
370 Q_strncpyz( weapStr, CG_Argv( 3 ), 80 );
371
372 CG_CenterPrint( va( "You will spawn as a %s \n%s with a %s.", teamStr, classStr, weapStr ),
373 SCREEN_HEIGHT - ( SCREEN_HEIGHT * 0.25 ), SMALLCHAR_WIDTH );
374 }
375 // -NERVE - SMF
376
377 typedef struct {
378 char *cmd;
379 void ( *function )( void );
380 } consoleCommand_t;
381
382 static consoleCommand_t commands[] = {
383 { "testgun", CG_TestGun_f },
384 { "testmodel", CG_TestModel_f },
385 { "nextframe", CG_TestModelNextFrame_f },
386 { "prevframe", CG_TestModelPrevFrame_f },
387 { "nextskin", CG_TestModelNextSkin_f },
388 { "prevskin", CG_TestModelPrevSkin_f },
389 { "viewpos", CG_Viewpos_f },
390 { "+scores", CG_ScoresDown_f },
391 { "-scores", CG_ScoresUp_f },
392 { "+inventory", CG_InventoryDown_f },
393 { "-inventory", CG_InventoryUp_f },
394 // { "+zoom", CG_ZoomDown_f }, // (SA) zoom moved to a wbutton so server can determine weapon firing based on zoom status
395 // { "-zoom", CG_ZoomUp_f },
396 { "zoomin", CG_ZoomIn_f },
397 { "zoomout", CG_ZoomOut_f },
398 { "sizeup", CG_SizeUp_f },
399 { "sizedown", CG_SizeDown_f },
400 { "weaplastused", CG_LastWeaponUsed_f },
401 { "weapnextinbank", CG_NextWeaponInBank_f },
402 { "weapprevinbank", CG_PrevWeaponInBank_f },
403 { "weapnext", CG_NextWeapon_f },
404 { "weapprev", CG_PrevWeapon_f },
405 { "weapalt", CG_AltWeapon_f },
406 { "weapon", CG_Weapon_f },
407 { "weaponbank", CG_WeaponBank_f },
408 { "itemnext", CG_NextItem_f },
409 { "itemprev", CG_PrevItem_f },
410 { "item", CG_Item_f },
411 { "tell_target", CG_TellTarget_f },
412 { "tell_attacker", CG_TellAttacker_f },
413 { "tcmd", CG_TargetCommand_f },
414 { "loadhud", CG_LoadHud_f },
415 { "loaddeferred", CG_LoadDeferredPlayers }, // spelling fixed (SA)
416 { "camera", CG_Camera_f }, // duffy
417 { "fade", CG_Fade_f }, // duffy
418
419 // NERVE - SMF
420 { "mp_QuickMessage", CG_QuickMessage_f },
421 { "OpenLimboMenu", CG_OpenLimbo_f },
422 { "CloseLimboMenu", CG_CloseLimbo_f },
423 { "LimboMessage", CG_LimboMessage_f }
424 // -NERVE - SMF
425 };
426
427
428 /*
429 =================
430 CG_ConsoleCommand
431
432 The string has been tokenized and can be retrieved with
433 Cmd_Argc() / Cmd_Argv()
434 =================
435 */
CG_ConsoleCommand(void)436 qboolean CG_ConsoleCommand( void ) {
437 const char *cmd;
438 int i;
439
440 cmd = CG_Argv( 0 );
441
442 for ( i = 0 ; i < ARRAY_LEN( commands ) ; i++ ) {
443 if ( !Q_stricmp( cmd, commands[i].cmd ) ) {
444 commands[i].function();
445 return qtrue;
446 }
447 }
448
449 return qfalse;
450 }
451
452
453 /*
454 =================
455 CG_InitConsoleCommands
456
457 Let the client system know about all of our commands
458 so it can perform tab completion
459 =================
460 */
CG_InitConsoleCommands(void)461 void CG_InitConsoleCommands( void ) {
462 int i;
463
464 for ( i = 0 ; i < ARRAY_LEN( commands ) ; i++ ) {
465 trap_AddCommand( commands[i].cmd );
466 }
467
468 //
469 // the game server will interpret these commands, which will be automatically
470 // forwarded to the server after they are not recognized locally
471 //
472 trap_AddCommand( "kill" );
473 trap_AddCommand( "say" );
474 trap_AddCommand( "say_team" );
475 trap_AddCommand( "say_limbo" ); // NERVE - SMF
476 trap_AddCommand( "tell" );
477 // trap_AddCommand( "vsay" );
478 // trap_AddCommand( "vsay_team" );
479 // trap_AddCommand( "vtell" );
480 // trap_AddCommand( "vtaunt" );
481 // trap_AddCommand( "vosay" );
482 // trap_AddCommand( "vosay_team" );
483 // trap_AddCommand( "votell" );
484 trap_AddCommand( "give" );
485 trap_AddCommand( "god" );
486 trap_AddCommand( "notarget" );
487 trap_AddCommand( "noclip" );
488 trap_AddCommand( "where" );
489 trap_AddCommand( "team" );
490 trap_AddCommand( "follow" );
491 trap_AddCommand( "follownext" );
492 trap_AddCommand( "followprev" );
493 trap_AddCommand( "levelshot" );
494 trap_AddCommand( "addbot" );
495 trap_AddCommand( "setviewpos" );
496 trap_AddCommand( "callvote" );
497 trap_AddCommand( "vote" );
498 // trap_AddCommand( "callteamvote" );
499 // trap_AddCommand( "teamvote" );
500 trap_AddCommand( "stats" );
501 // trap_AddCommand( "teamtask" );
502 trap_AddCommand( "loaddeferred" ); // spelling fixed (SA)
503
504 trap_AddCommand( "startCamera" );
505 trap_AddCommand( "stopCamera" );
506 trap_AddCommand( "setCameraOrigin" );
507
508 // Rafael
509 trap_AddCommand( "nofatigue" );
510
511 // NERVE - SMF
512 trap_AddCommand( "setspawnpt" );
513 // NERVE - SMF
514 }
515