1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6
7 This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
8
9 Doom 3 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 Doom 3 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the Doom 3 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 Doom 3 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 #include "sys/platform.h"
30 #include "idlib/LangDict.h"
31 #include "framework/async/NetworkSystem.h"
32 #include "framework/FileSystem.h"
33
34 #include "gamesys/TypeInfo.h"
35 #include "gamesys/SysCvar.h"
36 #include "script/Script_Thread.h"
37 #include "ai/AI.h"
38 #include "anim/Anim_Testmodel.h"
39 #include "Entity.h"
40 #include "Moveable.h"
41 #include "WorldSpawn.h"
42 #include "Fx.h"
43 #include "Misc.h"
44
45 #include "SysCmds.h"
46
47 /*
48 ==================
49 Cmd_GetFloatArg
50 ==================
51 */
Cmd_GetFloatArg(const idCmdArgs & args,int & argNum)52 float Cmd_GetFloatArg( const idCmdArgs &args, int &argNum ) {
53 const char *value;
54
55 value = args.Argv( argNum++ );
56 return atof( value );
57 }
58
59 /*
60 ===================
61 Cmd_EntityList_f
62 ===================
63 */
Cmd_EntityList_f(const idCmdArgs & args)64 void Cmd_EntityList_f( const idCmdArgs &args ) {
65 int e;
66 idEntity *check;
67 int count;
68 size_t size;
69 idStr match;
70
71 if ( args.Argc() > 1 ) {
72 match = args.Args();
73 match.Replace( " ", "" );
74 } else {
75 match = "";
76 }
77
78 count = 0;
79 size = 0;
80
81 gameLocal.Printf( "%-4s %-20s %-20s %s\n", " Num", "EntityDef", "Class", "Name" );
82 gameLocal.Printf( "--------------------------------------------------------------------\n" );
83 for( e = 0; e < MAX_GENTITIES; e++ ) {
84 check = gameLocal.entities[ e ];
85
86 if ( !check ) {
87 continue;
88 }
89
90 if ( !check->name.Filter( match, true ) ) {
91 continue;
92 }
93
94 gameLocal.Printf( "%4i: %-20s %-20s %s\n", e,
95 check->GetEntityDefName(), check->GetClassname(), check->name.c_str() );
96
97 count++;
98 size += check->spawnArgs.Allocated();
99 }
100
101 gameLocal.Printf( "...%d entities\n...%zd bytes of spawnargs\n", count, size );
102 }
103
104 /*
105 ===================
106 Cmd_ActiveEntityList_f
107 ===================
108 */
Cmd_ActiveEntityList_f(const idCmdArgs & args)109 void Cmd_ActiveEntityList_f( const idCmdArgs &args ) {
110 idEntity *check;
111 int count;
112
113 count = 0;
114
115 gameLocal.Printf( "%-4s %-20s %-20s %s\n", " Num", "EntityDef", "Class", "Name" );
116 gameLocal.Printf( "--------------------------------------------------------------------\n" );
117 for( check = gameLocal.activeEntities.Next(); check != NULL; check = check->activeNode.Next() ) {
118 char dormant = check->fl.isDormant ? '-' : ' ';
119 gameLocal.Printf( "%4i:%c%-20s %-20s %s\n", check->entityNumber, dormant, check->GetEntityDefName(), check->GetClassname(), check->name.c_str() );
120 count++;
121 }
122
123 gameLocal.Printf( "...%d active entities\n", count );
124 }
125
126 /*
127 ===================
128 Cmd_ListSpawnArgs_f
129 ===================
130 */
Cmd_ListSpawnArgs_f(const idCmdArgs & args)131 void Cmd_ListSpawnArgs_f( const idCmdArgs &args ) {
132 int i;
133 idEntity *ent;
134
135 ent = gameLocal.FindEntity( args.Argv( 1 ) );
136 if ( !ent ) {
137 gameLocal.Printf( "entity not found\n" );
138 return;
139 }
140
141 for ( i = 0; i < ent->spawnArgs.GetNumKeyVals(); i++ ) {
142 const idKeyValue *kv = ent->spawnArgs.GetKeyVal( i );
143 gameLocal.Printf( "\"%s\" " S_COLOR_WHITE "\"%s\"\n", kv->GetKey().c_str(), kv->GetValue().c_str() );
144 }
145 }
146
147 /*
148 ===================
149 Cmd_ReloadScript_f
150 ===================
151 */
Cmd_ReloadScript_f(const idCmdArgs & args)152 void Cmd_ReloadScript_f( const idCmdArgs &args ) {
153 // shutdown the map because entities may point to script objects
154 gameLocal.MapShutdown();
155
156 // recompile the scripts
157 gameLocal.program.Startup( SCRIPT_DEFAULT );
158
159 // error out so that the user can rerun the scripts
160 gameLocal.Error( "Exiting map to reload scripts" );
161 }
162
163 /*
164 ===================
165 Cmd_Script_f
166 ===================
167 */
Cmd_Script_f(const idCmdArgs & args)168 void Cmd_Script_f( const idCmdArgs &args ) {
169 const char * script;
170 idStr text;
171 idStr funcname;
172 static int funccount = 0;
173 idThread * thread;
174 const function_t *func;
175 idEntity *ent;
176
177 if ( !gameLocal.CheatsOk() ) {
178 return;
179 }
180
181 sprintf( funcname, "ConsoleFunction_%d", funccount++ );
182
183 script = args.Args();
184 sprintf( text, "void %s() {%s;}\n", funcname.c_str(), script );
185 if ( gameLocal.program.CompileText( "console", text, true ) ) {
186 func = gameLocal.program.FindFunction( funcname );
187 if ( func ) {
188 // set all the entity names in case the user named one in the script that wasn't referenced in the default script
189 for( ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
190 gameLocal.program.SetEntity( ent->name, ent );
191 }
192
193 thread = new idThread( func );
194 thread->Start();
195 }
196 }
197 }
198
199 /*
200 ==================
201 KillEntities
202
203 Kills all the entities of the given class in a level.
204 ==================
205 */
KillEntities(const idCmdArgs & args,const idTypeInfo & superClass)206 void KillEntities( const idCmdArgs &args, const idTypeInfo &superClass ) {
207 idEntity *ent;
208 idStrList ignore;
209 const char *name;
210 int i;
211
212 if ( !gameLocal.GetLocalPlayer() || !gameLocal.CheatsOk( false ) ) {
213 return;
214 }
215
216 for( i = 1; i < args.Argc(); i++ ) {
217 name = args.Argv( i );
218 ignore.Append( name );
219 }
220
221 for( ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
222 if ( ent->IsType( superClass ) ) {
223 for( i = 0; i < ignore.Num(); i++ ) {
224 if ( ignore[ i ] == ent->name ) {
225 break;
226 }
227 }
228
229 if ( i >= ignore.Num() ) {
230 ent->PostEventMS( &EV_Remove, 0 );
231 }
232 }
233 }
234 }
235
236 /*
237 ==================
238 Cmd_KillMonsters_f
239
240 Kills all the monsters in a level.
241 ==================
242 */
Cmd_KillMonsters_f(const idCmdArgs & args)243 void Cmd_KillMonsters_f( const idCmdArgs &args ) {
244 KillEntities( args, idAI::Type );
245
246 // kill any projectiles as well since they have pointers to the monster that created them
247 KillEntities( args, idProjectile::Type );
248 }
249
250 /*
251 ==================
252 Cmd_KillMovables_f
253
254 Kills all the moveables in a level.
255 ==================
256 */
Cmd_KillMovables_f(const idCmdArgs & args)257 void Cmd_KillMovables_f( const idCmdArgs &args ) {
258 if ( !gameLocal.GetLocalPlayer() || !gameLocal.CheatsOk( false ) ) {
259 return;
260 }
261 KillEntities( args, idMoveable::Type );
262 }
263
264 /*
265 ==================
266 Cmd_KillRagdolls_f
267
268 Kills all the ragdolls in a level.
269 ==================
270 */
Cmd_KillRagdolls_f(const idCmdArgs & args)271 void Cmd_KillRagdolls_f( const idCmdArgs &args ) {
272 if ( !gameLocal.GetLocalPlayer() || !gameLocal.CheatsOk( false ) ) {
273 return;
274 }
275 KillEntities( args, idAFEntity_Generic::Type );
276 KillEntities( args, idAFEntity_WithAttachedHead::Type );
277 }
278
279 /*
280 ==================
281 Cmd_Give_f
282
283 Give items to a client
284 ==================
285 */
Cmd_Give_f(const idCmdArgs & args)286 void Cmd_Give_f( const idCmdArgs &args ) {
287 const char *name;
288 int i;
289 bool give_all;
290 idPlayer *player;
291
292 player = gameLocal.GetLocalPlayer();
293 if ( !player || !gameLocal.CheatsOk() ) {
294 return;
295 }
296
297 name = args.Argv( 1 );
298
299 if ( idStr::Icmp( name, "all" ) == 0 ) {
300 give_all = true;
301 } else {
302 give_all = false;
303 }
304
305 if ( give_all || ( idStr::Cmpn( name, "weapon", 6 ) == 0 ) ) {
306 if ( gameLocal.world->spawnArgs.GetBool( "no_Weapons" ) ) {
307 gameLocal.world->spawnArgs.SetBool( "no_Weapons", false );
308 for( i = 0; i < gameLocal.numClients; i++ ) {
309 if ( gameLocal.entities[ i ] ) {
310 gameLocal.entities[ i ]->PostEventSec( &EV_Player_SelectWeapon, 0.5f, gameLocal.entities[ i ]->spawnArgs.GetString( "def_weapon1" ) );
311 }
312 }
313 }
314 }
315
316 if ( ( idStr::Cmpn( name, "weapon_", 7 ) == 0 ) || ( idStr::Cmpn( name, "item_", 5 ) == 0 ) || ( idStr::Cmpn( name, "ammo_", 5 ) == 0 ) ) {
317 player->GiveItem( name );
318 return;
319 }
320
321 if ( give_all || idStr::Icmp( name, "health" ) == 0 ) {
322 player->health = player->inventory.maxHealth;
323 if ( !give_all ) {
324 return;
325 }
326 }
327
328 if ( give_all || idStr::Icmp( name, "weapons" ) == 0 ) {
329 player->inventory.weapons = BIT( MAX_WEAPONS ) - 1;
330 player->CacheWeapons();
331
332 if ( !give_all ) {
333 return;
334 }
335 }
336
337 if ( give_all || idStr::Icmp( name, "ammo" ) == 0 ) {
338 for ( i = 0 ; i < AMMO_NUMTYPES; i++ ) {
339 player->inventory.ammo[ i ] = player->inventory.MaxAmmoForAmmoClass( player, idWeapon::GetAmmoNameForNum( ( ammo_t )i ) );
340 }
341 if ( !give_all ) {
342 return;
343 }
344 }
345
346 if ( give_all || idStr::Icmp( name, "armor" ) == 0 ) {
347 player->inventory.armor = player->inventory.maxarmor;
348 if ( !give_all ) {
349 return;
350 }
351 }
352
353 if ( idStr::Icmp( name, "berserk" ) == 0 ) {
354 player->GivePowerUp( BERSERK, SEC2MS( 30.0f ) );
355 return;
356 }
357
358 if ( idStr::Icmp( name, "invis" ) == 0 ) {
359 player->GivePowerUp( INVISIBILITY, SEC2MS( 30.0f ) );
360 return;
361 }
362
363 if ( idStr::Icmp( name, "pda" ) == 0 ) {
364 player->GivePDA( args.Argv(2), NULL );
365 return;
366 }
367
368 if ( idStr::Icmp( name, "video" ) == 0 ) {
369 player->GiveVideo( args.Argv(2), NULL );
370 return;
371 }
372
373 if ( !give_all && !player->Give( args.Argv(1), args.Argv(2) ) ) {
374 gameLocal.Printf( "unknown item\n" );
375 }
376 }
377
378 /*
379 ==================
380 Cmd_CenterView_f
381
382 Centers the players pitch
383 ==================
384 */
Cmd_CenterView_f(const idCmdArgs & args)385 void Cmd_CenterView_f( const idCmdArgs &args ) {
386 idPlayer *player;
387 idAngles ang;
388
389 player = gameLocal.GetLocalPlayer();
390 if ( !player ) {
391 return;
392 }
393
394 ang = player->viewAngles;
395 ang.pitch = 0.0f;
396 player->SetViewAngles( ang );
397 }
398
399 /*
400 ==================
401 Cmd_God_f
402
403 Sets client to godmode
404
405 argv(0) god
406 ==================
407 */
Cmd_God_f(const idCmdArgs & args)408 void Cmd_God_f( const idCmdArgs &args ) {
409 const char *msg;
410 idPlayer *player;
411
412 player = gameLocal.GetLocalPlayer();
413 if ( !player || !gameLocal.CheatsOk() ) {
414 return;
415 }
416
417 if ( player->godmode ) {
418 player->godmode = false;
419 msg = "godmode OFF\n";
420 } else {
421 player->godmode = true;
422 msg = "godmode ON\n";
423 }
424
425 gameLocal.Printf( "%s", msg );
426 }
427
428 /*
429 ==================
430 Cmd_Notarget_f
431
432 Sets client to notarget
433
434 argv(0) notarget
435 ==================
436 */
Cmd_Notarget_f(const idCmdArgs & args)437 void Cmd_Notarget_f( const idCmdArgs &args ) {
438 const char *msg;
439 idPlayer *player;
440
441 player = gameLocal.GetLocalPlayer();
442 if ( !player || !gameLocal.CheatsOk() ) {
443 return;
444 }
445
446 if ( player->fl.notarget ) {
447 player->fl.notarget = false;
448 msg = "notarget OFF\n";
449 } else {
450 player->fl.notarget = true;
451 msg = "notarget ON\n";
452 }
453
454 gameLocal.Printf( "%s", msg );
455 }
456
457 /*
458 ==================
459 Cmd_Noclip_f
460
461 argv(0) noclip
462 ==================
463 */
Cmd_Noclip_f(const idCmdArgs & args)464 void Cmd_Noclip_f( const idCmdArgs &args ) {
465 const char *msg;
466 idPlayer *player;
467
468 player = gameLocal.GetLocalPlayer();
469 if ( !player || !gameLocal.CheatsOk() ) {
470 return;
471 }
472
473 if ( player->noclip ) {
474 msg = "noclip OFF\n";
475 } else {
476 msg = "noclip ON\n";
477 }
478 player->noclip = !player->noclip;
479
480 gameLocal.Printf( "%s", msg );
481 }
482
483 /*
484 =================
485 Cmd_Kill_f
486 =================
487 */
Cmd_Kill_f(const idCmdArgs & args)488 void Cmd_Kill_f( const idCmdArgs &args ) {
489 idPlayer *player;
490
491 if ( gameLocal.isMultiplayer ) {
492 if ( gameLocal.isClient ) {
493 idBitMsg outMsg;
494 byte msgBuf[ MAX_GAME_MESSAGE_SIZE ];
495 outMsg.Init( msgBuf, sizeof( msgBuf ) );
496 outMsg.WriteByte( GAME_RELIABLE_MESSAGE_KILL );
497 networkSystem->ClientSendReliableMessage( outMsg );
498 } else {
499 player = gameLocal.GetClientByCmdArgs( args );
500 if ( !player ) {
501 common->Printf( "kill <client nickname> or kill <client index>\n" );
502 return;
503 }
504 player->Kill( false, false );
505 cmdSystem->BufferCommandText( CMD_EXEC_NOW, va( "say killed client %d '%s^0'\n", player->entityNumber, gameLocal.userInfo[ player->entityNumber ].GetString( "ui_name" ) ) );
506 }
507 } else {
508 player = gameLocal.GetLocalPlayer();
509 if ( !player ) {
510 return;
511 }
512 player->Kill( false, false );
513 }
514 }
515
516 /*
517 =================
518 Cmd_PlayerModel_f
519 =================
520 */
Cmd_PlayerModel_f(const idCmdArgs & args)521 void Cmd_PlayerModel_f( const idCmdArgs &args ) {
522 idPlayer *player;
523 const char *name;
524 idVec3 pos;
525 idAngles ang;
526
527 player = gameLocal.GetLocalPlayer();
528 if ( !player || !gameLocal.CheatsOk() ) {
529 return;
530 }
531
532 if ( args.Argc() < 2 ) {
533 gameLocal.Printf( "usage: playerModel <modelname>\n" );
534 return;
535 }
536
537 name = args.Argv( 1 );
538 player->spawnArgs.Set( "model", name );
539
540 pos = player->GetPhysics()->GetOrigin();
541 ang = player->viewAngles;
542 player->SpawnToPoint( pos, ang );
543 }
544
545 /*
546 ==================
547 Cmd_Say
548 ==================
549 */
Cmd_Say(bool team,const idCmdArgs & args)550 static void Cmd_Say( bool team, const idCmdArgs &args ) {
551 const char *name;
552 idStr text;
553 const char *cmd = team ? "sayTeam" : "say" ;
554
555 if ( !gameLocal.isMultiplayer ) {
556 gameLocal.Printf( "%s can only be used in a multiplayer game\n", cmd );
557 return;
558 }
559
560 if ( args.Argc() < 2 ) {
561 gameLocal.Printf( "usage: %s <text>\n", cmd );
562 return;
563 }
564
565 text = args.Args();
566 if ( text.Length() == 0 ) {
567 return;
568 }
569
570 if ( text[ text.Length() - 1 ] == '\n' ) {
571 text[ text.Length() - 1 ] = '\0';
572 }
573 name = "player";
574
575 idPlayer * player;
576
577 // here we need to special case a listen server to use the real client name instead of "server"
578 // "server" will only appear on a dedicated server
579 if ( gameLocal.isClient || cvarSystem->GetCVarInteger( "net_serverDedicated" ) == 0 ) {
580 player = gameLocal.localClientNum >= 0 ? static_cast<idPlayer *>( gameLocal.entities[ gameLocal.localClientNum ] ) : NULL;
581 if ( player ) {
582 name = player->GetUserInfo()->GetString( "ui_name", "player" );
583 }
584 } else {
585 name = "server";
586 }
587
588 if ( gameLocal.isClient ) {
589 idBitMsg outMsg;
590 byte msgBuf[ 256 ];
591 outMsg.Init( msgBuf, sizeof( msgBuf ) );
592 outMsg.WriteByte( team ? GAME_RELIABLE_MESSAGE_TCHAT : GAME_RELIABLE_MESSAGE_CHAT );
593 outMsg.WriteString( name );
594 outMsg.WriteString( text, -1, false );
595 networkSystem->ClientSendReliableMessage( outMsg );
596 } else {
597 gameLocal.mpGame.ProcessChatMessage( gameLocal.localClientNum, team, name, text, NULL );
598 }
599 }
600
601 /*
602 ==================
603 Cmd_Say_f
604 ==================
605 */
Cmd_Say_f(const idCmdArgs & args)606 static void Cmd_Say_f( const idCmdArgs &args ) {
607 Cmd_Say( false, args );
608 }
609
610 /*
611 ==================
612 Cmd_SayTeam_f
613 ==================
614 */
Cmd_SayTeam_f(const idCmdArgs & args)615 static void Cmd_SayTeam_f( const idCmdArgs &args ) {
616 Cmd_Say( true, args );
617 }
618
619 /*
620 ==================
621 Cmd_AddChatLine_f
622 ==================
623 */
Cmd_AddChatLine_f(const idCmdArgs & args)624 static void Cmd_AddChatLine_f( const idCmdArgs &args ) {
625 gameLocal.mpGame.AddChatLine( args.Argv( 1 ) );
626 }
627
628 /*
629 ==================
630 Cmd_Kick_f
631 ==================
632 */
Cmd_Kick_f(const idCmdArgs & args)633 static void Cmd_Kick_f( const idCmdArgs &args ) {
634 idPlayer *player;
635
636 if ( !gameLocal.isMultiplayer ) {
637 gameLocal.Printf( "kick can only be used in a multiplayer game\n" );
638 return;
639 }
640
641 if ( gameLocal.isClient ) {
642 gameLocal.Printf( "You have no such power. This is a server command\n" );
643 return;
644 }
645
646 player = gameLocal.GetClientByCmdArgs( args );
647 if ( !player ) {
648 gameLocal.Printf( "usage: kick <client nickname> or kick <client index>\n" );
649 return;
650 }
651 cmdSystem->BufferCommandText( CMD_EXEC_NOW, va( "say kicking out client %d '%s^0'\n", player->entityNumber, gameLocal.userInfo[ player->entityNumber ].GetString( "ui_name" ) ) );
652 cmdSystem->BufferCommandText( CMD_EXEC_NOW, va( "kick %d\n", player->entityNumber ) );
653 }
654
655 /*
656 ==================
657 Cmd_GetViewpos_f
658 ==================
659 */
Cmd_GetViewpos_f(const idCmdArgs & args)660 void Cmd_GetViewpos_f( const idCmdArgs &args ) {
661 idPlayer *player;
662 idVec3 origin;
663 idMat3 axis;
664
665 player = gameLocal.GetLocalPlayer();
666 if ( !player ) {
667 return;
668 }
669
670 const renderView_t *view = player->GetRenderView();
671 if ( view ) {
672 gameLocal.Printf( "(%s) %.1f\n", view->vieworg.ToString(), view->viewaxis[0].ToYaw() );
673 } else {
674 player->GetViewPos( origin, axis );
675 gameLocal.Printf( "(%s) %.1f\n", origin.ToString(), axis[0].ToYaw() );
676 }
677 }
678
679 /*
680 =================
681 Cmd_SetViewpos_f
682 =================
683 */
Cmd_SetViewpos_f(const idCmdArgs & args)684 void Cmd_SetViewpos_f( const idCmdArgs &args ) {
685 idVec3 origin;
686 idAngles angles;
687 int i;
688 idPlayer *player;
689
690 player = gameLocal.GetLocalPlayer();
691 if ( !player || !gameLocal.CheatsOk() ) {
692 return;
693 }
694
695 if ( ( args.Argc() != 4 ) && ( args.Argc() != 5 ) ) {
696 gameLocal.Printf( "usage: setviewpos <x> <y> <z> <yaw>\n" );
697 return;
698 }
699
700 angles.Zero();
701 if ( args.Argc() == 5 ) {
702 angles.yaw = atof( args.Argv( 4 ) );
703 }
704
705 for ( i = 0 ; i < 3 ; i++ ) {
706 origin[i] = atof( args.Argv( i + 1 ) );
707 }
708 origin.z -= pm_normalviewheight.GetFloat() - 0.25f;
709
710 player->Teleport( origin, angles, NULL );
711 }
712
713 /*
714 =================
715 Cmd_Teleport_f
716 =================
717 */
Cmd_Teleport_f(const idCmdArgs & args)718 void Cmd_Teleport_f( const idCmdArgs &args ) {
719 idVec3 origin;
720 idAngles angles;
721 idPlayer *player;
722 idEntity *ent;
723
724 player = gameLocal.GetLocalPlayer();
725 if ( !player || !gameLocal.CheatsOk() ) {
726 return;
727 }
728
729 if ( args.Argc() != 2 ) {
730 gameLocal.Printf( "usage: teleport <name of entity to teleport to>\n" );
731 return;
732 }
733
734 ent = gameLocal.FindEntity( args.Argv( 1 ) );
735 if ( !ent ) {
736 gameLocal.Printf( "entity not found\n" );
737 return;
738 }
739
740 angles.Zero();
741 angles.yaw = ent->GetPhysics()->GetAxis()[ 0 ].ToYaw();
742 origin = ent->GetPhysics()->GetOrigin();
743
744 player->Teleport( origin, angles, ent );
745 }
746
747 /*
748 =================
749 Cmd_Trigger_f
750 =================
751 */
Cmd_Trigger_f(const idCmdArgs & args)752 void Cmd_Trigger_f( const idCmdArgs &args ) {
753 idVec3 origin;
754 idAngles angles;
755 idPlayer *player;
756 idEntity *ent;
757
758 player = gameLocal.GetLocalPlayer();
759 if ( !player || !gameLocal.CheatsOk() ) {
760 return;
761 }
762
763 if ( args.Argc() != 2 ) {
764 gameLocal.Printf( "usage: trigger <name of entity to trigger>\n" );
765 return;
766 }
767
768 ent = gameLocal.FindEntity( args.Argv( 1 ) );
769 if ( !ent ) {
770 gameLocal.Printf( "entity not found\n" );
771 return;
772 }
773
774 ent->Signal( SIG_TRIGGER );
775 ent->ProcessEvent( &EV_Activate, player );
776 ent->TriggerGuis();
777 }
778
779 /*
780 ===================
781 Cmd_Spawn_f
782 ===================
783 */
Cmd_Spawn_f(const idCmdArgs & args)784 void Cmd_Spawn_f( const idCmdArgs &args ) {
785 const char *key, *value;
786 int i;
787 float yaw;
788 idVec3 org;
789 idPlayer *player;
790 idDict dict;
791
792 player = gameLocal.GetLocalPlayer();
793 if ( !player || !gameLocal.CheatsOk( false ) ) {
794 return;
795 }
796
797 if ( args.Argc() & 1 ) { // must always have an even number of arguments
798 gameLocal.Printf( "usage: spawn classname [key/value pairs]\n" );
799 return;
800 }
801
802 yaw = player->viewAngles.yaw;
803
804 value = args.Argv( 1 );
805 dict.Set( "classname", value );
806 dict.Set( "angle", va( "%f", yaw + 180 ) );
807
808 org = player->GetPhysics()->GetOrigin() + idAngles( 0, yaw, 0 ).ToForward() * 80 + idVec3( 0, 0, 1 );
809 dict.Set( "origin", org.ToString() );
810
811 for( i = 2; i < args.Argc() - 1; i += 2 ) {
812
813 key = args.Argv( i );
814 value = args.Argv( i + 1 );
815
816 dict.Set( key, value );
817 }
818
819 gameLocal.SpawnEntityDef( dict );
820 }
821
822 /*
823 ==================
824 Cmd_Damage_f
825
826 Damages the specified entity
827 ==================
828 */
Cmd_Damage_f(const idCmdArgs & args)829 void Cmd_Damage_f( const idCmdArgs &args ) {
830 if ( !gameLocal.GetLocalPlayer() || !gameLocal.CheatsOk( false ) ) {
831 return;
832 }
833 if ( args.Argc() != 3 ) {
834 gameLocal.Printf( "usage: damage <name of entity to damage> <damage>\n" );
835 return;
836 }
837
838 idEntity *ent = gameLocal.FindEntity( args.Argv( 1 ) );
839 if ( !ent ) {
840 gameLocal.Printf( "entity not found\n" );
841 return;
842 }
843
844 ent->Damage( gameLocal.world, gameLocal.world, idVec3( 0, 0, 1 ), "damage_moverCrush", atoi( args.Argv( 2 ) ), INVALID_JOINT );
845 }
846
847
848 /*
849 ==================
850 Cmd_Remove_f
851
852 Removes the specified entity
853 ==================
854 */
Cmd_Remove_f(const idCmdArgs & args)855 void Cmd_Remove_f( const idCmdArgs &args ) {
856 if ( !gameLocal.GetLocalPlayer() || !gameLocal.CheatsOk( false ) ) {
857 return;
858 }
859 if ( args.Argc() != 2 ) {
860 gameLocal.Printf( "usage: remove <name of entity to remove>\n" );
861 return;
862 }
863
864 idEntity *ent = gameLocal.FindEntity( args.Argv( 1 ) );
865 if ( !ent ) {
866 gameLocal.Printf( "entity not found\n" );
867 return;
868 }
869
870 delete ent;
871 }
872
873 /*
874 ===================
875 Cmd_TestLight_f
876 ===================
877 */
Cmd_TestLight_f(const idCmdArgs & args)878 void Cmd_TestLight_f( const idCmdArgs &args ) {
879 int i;
880 idStr filename;
881 const char *key, *value, *name;
882 idPlayer * player;
883 idDict dict;
884
885 player = gameLocal.GetLocalPlayer();
886 if ( !player || !gameLocal.CheatsOk( false ) ) {
887 return;
888 }
889
890 renderView_t *rv = player->GetRenderView();
891
892 float fov = tan( idMath::M_DEG2RAD * rv->fov_x / 2 );
893
894
895 dict.SetMatrix( "rotation", mat3_default );
896 dict.SetVector( "origin", rv->vieworg );
897 dict.SetVector( "light_target", rv->viewaxis[0] );
898 dict.SetVector( "light_right", rv->viewaxis[1] * -fov );
899 dict.SetVector( "light_up", rv->viewaxis[2] * fov );
900 dict.SetVector( "light_start", rv->viewaxis[0] * 16 );
901 dict.SetVector( "light_end", rv->viewaxis[0] * 1000 );
902
903 if ( args.Argc() >= 2 ) {
904 value = args.Argv( 1 );
905 filename = args.Argv(1);
906 filename.DefaultFileExtension( ".tga" );
907 dict.Set( "texture", filename );
908 }
909
910 dict.Set( "classname", "light" );
911 for( i = 2; i < args.Argc() - 1; i += 2 ) {
912
913 key = args.Argv( i );
914 value = args.Argv( i + 1 );
915
916 dict.Set( key, value );
917 }
918
919 for ( i = 0; i < MAX_GENTITIES; i++ ) {
920 name = va( "spawned_light_%d", i ); // not just light_, or it might pick up a prelight shadow
921 if ( !gameLocal.FindEntity( name ) ) {
922 break;
923 }
924 }
925 dict.Set( "name", name );
926
927 gameLocal.SpawnEntityDef( dict );
928
929 gameLocal.Printf( "Created new light\n");
930 }
931
932 /*
933 ===================
934 Cmd_TestPointLight_f
935 ===================
936 */
Cmd_TestPointLight_f(const idCmdArgs & args)937 void Cmd_TestPointLight_f( const idCmdArgs &args ) {
938 const char *key, *value, *name;
939 int i;
940 idPlayer *player;
941 idDict dict;
942
943 player = gameLocal.GetLocalPlayer();
944 if ( !player || !gameLocal.CheatsOk( false ) ) {
945 return;
946 }
947
948 dict.SetVector("origin", player->GetRenderView()->vieworg);
949
950 if ( args.Argc() >= 2 ) {
951 value = args.Argv( 1 );
952 dict.Set("light", value);
953 } else {
954 dict.Set("light", "300");
955 }
956
957 dict.Set( "classname", "light" );
958 for( i = 2; i < args.Argc() - 1; i += 2 ) {
959
960 key = args.Argv( i );
961 value = args.Argv( i + 1 );
962
963 dict.Set( key, value );
964 }
965
966 for ( i = 0; i < MAX_GENTITIES; i++ ) {
967 name = va( "light_%d", i );
968 if ( !gameLocal.FindEntity( name ) ) {
969 break;
970 }
971 }
972 dict.Set( "name", name );
973
974 gameLocal.SpawnEntityDef( dict );
975
976 gameLocal.Printf( "Created new point light\n");
977 }
978
979 /*
980 ==================
981 Cmd_PopLight_f
982 ==================
983 */
Cmd_PopLight_f(const idCmdArgs & args)984 void Cmd_PopLight_f( const idCmdArgs &args ) {
985 idEntity *ent;
986 idMapEntity *mapEnt;
987 idMapFile *mapFile = gameLocal.GetLevelMap();
988 idLight *lastLight;
989 int last;
990
991 if ( !gameLocal.CheatsOk() ) {
992 return;
993 }
994
995 bool removeFromMap = ( args.Argc() > 1 );
996
997 lastLight = NULL;
998 last = -1;
999 for( ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
1000 if ( !ent->IsType( idLight::Type ) ) {
1001 continue;
1002 }
1003
1004 if ( gameLocal.spawnIds[ ent->entityNumber ] > last ) {
1005 last = gameLocal.spawnIds[ ent->entityNumber ];
1006 lastLight = static_cast<idLight*>( ent );
1007 }
1008 }
1009
1010 if ( lastLight ) {
1011 // find map file entity
1012 mapEnt = mapFile->FindEntity( lastLight->name );
1013
1014 if ( removeFromMap && mapEnt ) {
1015 mapFile->RemoveEntity( mapEnt );
1016 }
1017 gameLocal.Printf( "Removing light %i\n", lastLight->GetLightDefHandle() );
1018 delete lastLight;
1019 } else {
1020 gameLocal.Printf( "No lights to clear.\n" );
1021 }
1022
1023 }
1024
1025 /*
1026 ====================
1027 Cmd_ClearLights_f
1028 ====================
1029 */
Cmd_ClearLights_f(const idCmdArgs & args)1030 void Cmd_ClearLights_f( const idCmdArgs &args ) {
1031 idEntity *ent;
1032 idEntity *next;
1033 idLight *light;
1034 idMapEntity *mapEnt;
1035 idMapFile *mapFile = gameLocal.GetLevelMap();
1036
1037 bool removeFromMap = ( args.Argc() > 1 );
1038
1039 gameLocal.Printf( "Clearing all lights.\n" );
1040 for( ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = next ) {
1041 next = ent->spawnNode.Next();
1042 if ( !ent->IsType( idLight::Type ) ) {
1043 continue;
1044 }
1045
1046 light = static_cast<idLight*>( ent );
1047 mapEnt = mapFile->FindEntity( light->name );
1048
1049 if ( removeFromMap && mapEnt ) {
1050 mapFile->RemoveEntity( mapEnt );
1051 }
1052
1053 delete light;
1054 }
1055 }
1056
1057 /*
1058 ==================
1059 Cmd_TestFx_f
1060 ==================
1061 */
Cmd_TestFx_f(const idCmdArgs & args)1062 void Cmd_TestFx_f( const idCmdArgs &args ) {
1063 idVec3 offset;
1064 const char *name;
1065 idPlayer * player;
1066 idDict dict;
1067
1068 player = gameLocal.GetLocalPlayer();
1069 if ( !player || !gameLocal.CheatsOk() ) {
1070 return;
1071 }
1072
1073 // delete the testModel if active
1074 if ( gameLocal.testFx ) {
1075 delete gameLocal.testFx;
1076 gameLocal.testFx = NULL;
1077 }
1078
1079 if ( args.Argc() < 2 ) {
1080 return;
1081 }
1082
1083 name = args.Argv( 1 );
1084
1085 offset = player->GetPhysics()->GetOrigin() + player->viewAngles.ToForward() * 100.0f;
1086
1087 dict.Set( "origin", offset.ToString() );
1088 dict.Set( "test", "1");
1089 dict.Set( "fx", name );
1090 gameLocal.testFx = ( idEntityFx * )gameLocal.SpawnEntityType( idEntityFx::Type, &dict );
1091 }
1092
1093 #define MAX_DEBUGLINES 128
1094
1095 typedef struct {
1096 bool used;
1097 idVec3 start, end;
1098 int color;
1099 bool blink;
1100 bool arrow;
1101 } gameDebugLine_t;
1102
1103 gameDebugLine_t debugLines[MAX_DEBUGLINES];
1104
1105 /*
1106 ==================
1107 Cmd_AddDebugLine_f
1108 ==================
1109 */
Cmd_AddDebugLine_f(const idCmdArgs & args)1110 static void Cmd_AddDebugLine_f( const idCmdArgs &args ) {
1111 int i, argNum;
1112 const char *value;
1113
1114 if ( !gameLocal.CheatsOk() ) {
1115 return;
1116 }
1117
1118 if ( args.Argc () < 7 ) {
1119 gameLocal.Printf( "usage: addline <x y z> <x y z> <color>\n" );
1120 return;
1121 }
1122 for ( i = 0; i < MAX_DEBUGLINES; i++ ) {
1123 if ( !debugLines[i].used ) {
1124 break;
1125 }
1126 }
1127 if ( i >= MAX_DEBUGLINES ) {
1128 gameLocal.Printf( "no free debug lines\n" );
1129 return;
1130 }
1131 value = args.Argv( 0 );
1132 if ( !idStr::Icmp( value, "addarrow" ) ) {
1133 debugLines[i].arrow = true;
1134 } else {
1135 debugLines[i].arrow = false;
1136 }
1137 debugLines[i].used = true;
1138 debugLines[i].blink = false;
1139 argNum = 1;
1140 debugLines[i].start.x = Cmd_GetFloatArg( args, argNum );
1141 debugLines[i].start.y = Cmd_GetFloatArg( args, argNum );
1142 debugLines[i].start.z = Cmd_GetFloatArg( args, argNum );
1143 debugLines[i].end.x = Cmd_GetFloatArg( args, argNum );
1144 debugLines[i].end.y = Cmd_GetFloatArg( args, argNum );
1145 debugLines[i].end.z = Cmd_GetFloatArg( args, argNum );
1146 debugLines[i].color = Cmd_GetFloatArg( args, argNum );
1147 }
1148
1149 /*
1150 ==================
1151 Cmd_RemoveDebugLine_f
1152 ==================
1153 */
Cmd_RemoveDebugLine_f(const idCmdArgs & args)1154 static void Cmd_RemoveDebugLine_f( const idCmdArgs &args ) {
1155 int i, num;
1156 const char *value;
1157
1158 if ( !gameLocal.CheatsOk() ) {
1159 return;
1160 }
1161
1162 if ( args.Argc () < 2 ) {
1163 gameLocal.Printf( "usage: removeline <num>\n" );
1164 return;
1165 }
1166 value = args.Argv( 1 );
1167 num = atoi(value);
1168 for ( i = 0; i < MAX_DEBUGLINES; i++ ) {
1169 if ( debugLines[i].used ) {
1170 if ( --num < 0 ) {
1171 break;
1172 }
1173 }
1174 }
1175 if ( i >= MAX_DEBUGLINES ) {
1176 gameLocal.Printf( "line not found\n" );
1177 return;
1178 }
1179 debugLines[i].used = false;
1180 }
1181
1182 /*
1183 ==================
1184 Cmd_BlinkDebugLine_f
1185 ==================
1186 */
Cmd_BlinkDebugLine_f(const idCmdArgs & args)1187 static void Cmd_BlinkDebugLine_f( const idCmdArgs &args ) {
1188 int i, num;
1189 const char *value;
1190
1191 if ( !gameLocal.CheatsOk() ) {
1192 return;
1193 }
1194
1195 if ( args.Argc () < 2 ) {
1196 gameLocal.Printf( "usage: blinkline <num>\n" );
1197 return;
1198 }
1199 value = args.Argv( 1 );
1200 num = atoi( value );
1201 for ( i = 0; i < MAX_DEBUGLINES; i++ ) {
1202 if ( debugLines[i].used ) {
1203 if ( --num < 0 ) {
1204 break;
1205 }
1206 }
1207 }
1208 if ( i >= MAX_DEBUGLINES ) {
1209 gameLocal.Printf( "line not found\n" );
1210 return;
1211 }
1212 debugLines[i].blink = !debugLines[i].blink;
1213 }
1214
1215 /*
1216 ==================
1217 PrintFloat
1218 ==================
1219 */
PrintFloat(float f)1220 static void PrintFloat( float f ) {
1221 char buf[128];
1222 int i;
1223
1224 for ( i = sprintf( buf, "%3.2f", f ); i < 7; i++ ) {
1225 buf[i] = ' ';
1226 }
1227 buf[i] = '\0';
1228 gameLocal.Printf( buf );
1229 }
1230
1231 /*
1232 ==================
1233 Cmd_ListDebugLines_f
1234 ==================
1235 */
Cmd_ListDebugLines_f(const idCmdArgs & args)1236 static void Cmd_ListDebugLines_f( const idCmdArgs &args ) {
1237 int i, num;
1238
1239 if ( !gameLocal.CheatsOk() ) {
1240 return;
1241 }
1242
1243 num = 0;
1244 gameLocal.Printf( "line num: x1 y1 z1 x2 y2 z2 c b a\n" );
1245 for ( i = 0; i < MAX_DEBUGLINES; i++ ) {
1246 if ( debugLines[i].used ) {
1247 gameLocal.Printf( "line %3d: ", num );
1248 PrintFloat( debugLines[i].start.x );
1249 PrintFloat( debugLines[i].start.y );
1250 PrintFloat( debugLines[i].start.z );
1251 PrintFloat( debugLines[i].end.x );
1252 PrintFloat( debugLines[i].end.y );
1253 PrintFloat( debugLines[i].end.z );
1254 gameLocal.Printf( "%d %d %d\n", debugLines[i].color, debugLines[i].blink, debugLines[i].arrow );
1255 num++;
1256 }
1257 }
1258 if ( !num ) {
1259 gameLocal.Printf( "no debug lines\n" );
1260 }
1261 }
1262
1263 /*
1264 ==================
1265 D_DrawDebugLines
1266 ==================
1267 */
D_DrawDebugLines(void)1268 void D_DrawDebugLines( void ) {
1269 int i;
1270 idVec3 forward, right, up, p1, p2;
1271 idVec4 color;
1272 float l;
1273
1274 for ( i = 0; i < MAX_DEBUGLINES; i++ ) {
1275 if ( debugLines[i].used ) {
1276 if ( !debugLines[i].blink || (gameLocal.time & (1<<9)) ) {
1277 color = idVec4( debugLines[i].color&1, (debugLines[i].color>>1)&1, (debugLines[i].color>>2)&1, 1 );
1278 gameRenderWorld->DebugLine( color, debugLines[i].start, debugLines[i].end );
1279 //
1280 if ( debugLines[i].arrow ) {
1281 // draw a nice arrow
1282 forward = debugLines[i].end - debugLines[i].start;
1283 l = forward.Normalize() * 0.2f;
1284 forward.NormalVectors( right, up);
1285
1286 if ( l > 3.0f ) {
1287 l = 3.0f;
1288 }
1289 p1 = debugLines[i].end - l * forward + (l * 0.4f) * right;
1290 p2 = debugLines[i].end - l * forward - (l * 0.4f) * right;
1291 gameRenderWorld->DebugLine( color, debugLines[i].end, p1 );
1292 gameRenderWorld->DebugLine( color, debugLines[i].end, p2 );
1293 gameRenderWorld->DebugLine( color, p1, p2 );
1294 }
1295 }
1296 }
1297 }
1298 }
1299
1300 /*
1301 ==================
1302 Cmd_ListCollisionModels_f
1303 ==================
1304 */
Cmd_ListCollisionModels_f(const idCmdArgs & args)1305 static void Cmd_ListCollisionModels_f( const idCmdArgs &args ) {
1306 if ( !gameLocal.CheatsOk() ) {
1307 return;
1308 }
1309
1310 collisionModelManager->ListModels();
1311 }
1312
1313 /*
1314 ==================
1315 Cmd_CollisionModelInfo_f
1316 ==================
1317 */
Cmd_CollisionModelInfo_f(const idCmdArgs & args)1318 static void Cmd_CollisionModelInfo_f( const idCmdArgs &args ) {
1319 const char *value;
1320
1321 if ( !gameLocal.CheatsOk() ) {
1322 return;
1323 }
1324
1325 if ( args.Argc () < 2 ) {
1326 gameLocal.Printf( "usage: collisionModelInfo <modelNum>\n"
1327 "use 'all' instead of the model number for accumulated info\n" );
1328 return;
1329 }
1330
1331 value = args.Argv( 1 );
1332 if ( !idStr::Icmp( value, "all" ) ) {
1333 collisionModelManager->ModelInfo( -1 );
1334 } else {
1335 collisionModelManager->ModelInfo( atoi(value) );
1336 }
1337 }
1338
1339 /*
1340 ==================
1341 Cmd_ExportModels_f
1342 ==================
1343 */
Cmd_ExportModels_f(const idCmdArgs & args)1344 static void Cmd_ExportModels_f( const idCmdArgs &args ) {
1345 idModelExport exporter;
1346 idStr name;
1347
1348 // don't allow exporting models when cheats are disabled,
1349 // but if we're not in the game, it's ok
1350 if ( gameLocal.GetLocalPlayer() && !gameLocal.CheatsOk( false ) ) {
1351 return;
1352 }
1353
1354 if ( args.Argc() < 2 ) {
1355 exporter.ExportModels( "def", ".def" );
1356 } else {
1357 name = args.Argv( 1 );
1358 name = "def/" + name;
1359 name.DefaultFileExtension( ".def" );
1360 exporter.ExportDefFile( name );
1361 }
1362 }
1363
1364 /*
1365 ==================
1366 Cmd_ReexportModels_f
1367 ==================
1368 */
Cmd_ReexportModels_f(const idCmdArgs & args)1369 static void Cmd_ReexportModels_f( const idCmdArgs &args ) {
1370 idModelExport exporter;
1371 idStr name;
1372
1373 // don't allow exporting models when cheats are disabled,
1374 // but if we're not in the game, it's ok
1375 if ( gameLocal.GetLocalPlayer() && !gameLocal.CheatsOk( false ) ) {
1376 return;
1377 }
1378
1379 idAnimManager::forceExport = true;
1380 if ( args.Argc() < 2 ) {
1381 exporter.ExportModels( "def", ".def" );
1382 } else {
1383 name = args.Argv( 1 );
1384 name = "def/" + name;
1385 name.DefaultFileExtension( ".def" );
1386 exporter.ExportDefFile( name );
1387 }
1388 idAnimManager::forceExport = false;
1389 }
1390
1391 /*
1392 ==================
1393 Cmd_ReloadAnims_f
1394 ==================
1395 */
Cmd_ReloadAnims_f(const idCmdArgs & args)1396 static void Cmd_ReloadAnims_f( const idCmdArgs &args ) {
1397 // don't allow reloading anims when cheats are disabled,
1398 // but if we're not in the game, it's ok
1399 if ( gameLocal.GetLocalPlayer() && !gameLocal.CheatsOk( false ) ) {
1400 return;
1401 }
1402
1403 animationLib.ReloadAnims();
1404 }
1405
1406 /*
1407 ==================
1408 Cmd_ListAnims_f
1409 ==================
1410 */
Cmd_ListAnims_f(const idCmdArgs & args)1411 static void Cmd_ListAnims_f( const idCmdArgs &args ) {
1412 idEntity * ent;
1413 int num;
1414 size_t size;
1415 size_t alloced;
1416 idAnimator * animator;
1417 const char * classname;
1418 const idDict * dict;
1419 int i;
1420
1421 if ( args.Argc() > 1 ) {
1422 idAnimator animator;
1423
1424 classname = args.Argv( 1 );
1425
1426 dict = gameLocal.FindEntityDefDict( classname, false );
1427 if ( !dict ) {
1428 gameLocal.Printf( "Entitydef '%s' not found\n", classname );
1429 return;
1430 }
1431 animator.SetModel( dict->GetString( "model" ) );
1432
1433 gameLocal.Printf( "----------------\n" );
1434 num = animator.NumAnims();
1435 for( i = 0; i < num; i++ ) {
1436 gameLocal.Printf( "%s\n", animator.AnimFullName( i ) );
1437 }
1438 gameLocal.Printf( "%d anims\n", num );
1439 } else {
1440 animationLib.ListAnims();
1441
1442 size = 0;
1443 num = 0;
1444 for( ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
1445 animator = ent->GetAnimator();
1446 if ( animator ) {
1447 alloced = animator->Allocated();
1448 size += alloced;
1449 num++;
1450 }
1451 }
1452
1453 gameLocal.Printf( "%zd memory used in %d entity animators\n", size, num );
1454 }
1455 }
1456
1457 /*
1458 ==================
1459 Cmd_AASStats_f
1460 ==================
1461 */
Cmd_AASStats_f(const idCmdArgs & args)1462 static void Cmd_AASStats_f( const idCmdArgs &args ) {
1463 int aasNum;
1464
1465 if ( !gameLocal.CheatsOk() ) {
1466 return;
1467 }
1468
1469 aasNum = aas_test.GetInteger();
1470 idAAS *aas = gameLocal.GetAAS( aasNum );
1471 if ( !aas ) {
1472 gameLocal.Printf( "No aas #%d loaded\n", aasNum );
1473 } else {
1474 aas->Stats();
1475 }
1476 }
1477
1478 /*
1479 ==================
1480 Cmd_TestDamage_f
1481 ==================
1482 */
Cmd_TestDamage_f(const idCmdArgs & args)1483 static void Cmd_TestDamage_f( const idCmdArgs &args ) {
1484 idPlayer *player;
1485 const char *damageDefName;
1486
1487 player = gameLocal.GetLocalPlayer();
1488 if ( !player || !gameLocal.CheatsOk() ) {
1489 return;
1490 }
1491
1492 if ( args.Argc() < 2 || args.Argc() > 3 ) {
1493 gameLocal.Printf( "usage: testDamage <damageDefName> [angle]\n" );
1494 return;
1495 }
1496
1497 damageDefName = args.Argv( 1 );
1498
1499 idVec3 dir;
1500 if ( args.Argc() == 3 ) {
1501 float angle = atof( args.Argv( 2 ) );
1502
1503 idMath::SinCos( DEG2RAD( angle ), dir[1], dir[0] );
1504 dir[2] = 0;
1505 } else {
1506 dir.Zero();
1507 }
1508
1509 // give the player full health before and after
1510 // running the damage
1511 player->health = player->inventory.maxHealth;
1512 player->Damage( NULL, NULL, dir, damageDefName, 1.0f, INVALID_JOINT );
1513 player->health = player->inventory.maxHealth;
1514 }
1515
1516 /*
1517 ==================
1518 Cmd_TestBoneFx_f
1519 ==================
1520 */
Cmd_TestBoneFx_f(const idCmdArgs & args)1521 static void Cmd_TestBoneFx_f( const idCmdArgs &args ) {
1522 idPlayer *player;
1523 const char *bone, *fx;
1524
1525 player = gameLocal.GetLocalPlayer();
1526 if ( !player || !gameLocal.CheatsOk() ) {
1527 return;
1528 }
1529
1530 if ( args.Argc() < 3 || args.Argc() > 4 ) {
1531 gameLocal.Printf( "usage: testBoneFx <fxName> <boneName>\n" );
1532 return;
1533 }
1534
1535 fx = args.Argv( 1 );
1536 bone = args.Argv( 2 );
1537
1538 player->StartFxOnBone( fx, bone );
1539 }
1540
1541 /*
1542 ==================
1543 Cmd_TestDamage_f
1544 ==================
1545 */
Cmd_TestDeath_f(const idCmdArgs & args)1546 static void Cmd_TestDeath_f( const idCmdArgs &args ) {
1547 idPlayer *player;
1548
1549 player = gameLocal.GetLocalPlayer();
1550 if ( !player || !gameLocal.CheatsOk() ) {
1551 return;
1552 }
1553
1554 idVec3 dir;
1555 idMath::SinCos( DEG2RAD( 45.0f ), dir[1], dir[0] );
1556 dir[2] = 0;
1557
1558 g_testDeath.SetBool( 1 );
1559 player->Damage( NULL, NULL, dir, "damage_triggerhurt_1000", 1.0f, INVALID_JOINT );
1560 if ( args.Argc() >= 2) {
1561 player->SpawnGibs( dir, "damage_triggerhurt_1000" );
1562 }
1563
1564 }
1565
1566 /*
1567 ==================
1568 Cmd_WeaponSplat_f
1569 ==================
1570 */
Cmd_WeaponSplat_f(const idCmdArgs & args)1571 static void Cmd_WeaponSplat_f( const idCmdArgs &args ) {
1572 idPlayer *player;
1573
1574 player = gameLocal.GetLocalPlayer();
1575 if ( !player || !gameLocal.CheatsOk() ) {
1576 return;
1577 }
1578
1579 player->weapon.GetEntity()->BloodSplat( 2.0f );
1580 }
1581
1582 /*
1583 ==================
1584 Cmd_SaveSelected_f
1585 ==================
1586 */
Cmd_SaveSelected_f(const idCmdArgs & args)1587 static void Cmd_SaveSelected_f( const idCmdArgs &args ) {
1588 int i;
1589 idPlayer *player;
1590 idEntity *s;
1591 idMapEntity *mapEnt;
1592 idMapFile *mapFile = gameLocal.GetLevelMap();
1593 idDict dict;
1594 idStr mapName;
1595 const char *name;
1596
1597 player = gameLocal.GetLocalPlayer();
1598 if ( !player || !gameLocal.CheatsOk() ) {
1599 return;
1600 }
1601
1602 s = player->dragEntity.GetSelected();
1603 if ( !s ) {
1604 gameLocal.Printf( "no entity selected, set g_dragShowSelection 1 to show the current selection\n" );
1605 return;
1606 }
1607
1608 if ( args.Argc() > 1 ) {
1609 mapName = args.Argv( 1 );
1610 mapName = "maps/" + mapName;
1611 }
1612 else {
1613 mapName = mapFile->GetName();
1614 }
1615
1616 // find map file entity
1617 mapEnt = mapFile->FindEntity( s->name );
1618 // create new map file entity if there isn't one for this articulated figure
1619 if ( !mapEnt ) {
1620 mapEnt = new idMapEntity();
1621 mapFile->AddEntity( mapEnt );
1622 for ( i = 0; i < 9999; i++ ) {
1623 name = va( "%s_%d", s->GetEntityDefName(), i );
1624 if ( !gameLocal.FindEntity( name ) ) {
1625 break;
1626 }
1627 }
1628 s->name = name;
1629 mapEnt->epairs.Set( "classname", s->GetEntityDefName() );
1630 mapEnt->epairs.Set( "name", s->name );
1631 }
1632
1633 if ( s->IsType( idMoveable::Type ) ) {
1634 // save the moveable state
1635 mapEnt->epairs.Set( "origin", s->GetPhysics()->GetOrigin().ToString( 8 ) );
1636 mapEnt->epairs.Set( "rotation", s->GetPhysics()->GetAxis().ToString( 8 ) );
1637 }
1638 else if ( s->IsType( idAFEntity_Generic::Type ) || s->IsType( idAFEntity_WithAttachedHead::Type ) ) {
1639 // save the articulated figure state
1640 dict.Clear();
1641 static_cast<idAFEntity_Base *>(s)->SaveState( dict );
1642 mapEnt->epairs.Copy( dict );
1643 }
1644
1645 // write out the map file
1646 mapFile->Write( mapName, ".map" );
1647 }
1648
1649 /*
1650 ==================
1651 Cmd_DeleteSelected_f
1652 ==================
1653 */
Cmd_DeleteSelected_f(const idCmdArgs & args)1654 static void Cmd_DeleteSelected_f( const idCmdArgs &args ) {
1655 idPlayer *player;
1656
1657 player = gameLocal.GetLocalPlayer();
1658 if ( !player || !gameLocal.CheatsOk() ) {
1659 return;
1660 }
1661
1662 if ( player ) {
1663 player->dragEntity.DeleteSelected();
1664 }
1665 }
1666
1667 /*
1668 ==================
1669 Cmd_SaveMoveables_f
1670 ==================
1671 */
Cmd_SaveMoveables_f(const idCmdArgs & args)1672 static void Cmd_SaveMoveables_f( const idCmdArgs &args ) {
1673 int e, i;
1674 idMoveable *m;
1675 idMapEntity *mapEnt;
1676 idMapFile *mapFile = gameLocal.GetLevelMap();
1677 idStr mapName;
1678 const char *name;
1679
1680 if ( !gameLocal.CheatsOk() ) {
1681 return;
1682 }
1683
1684 for( e = 0; e < MAX_GENTITIES; e++ ) {
1685 m = static_cast<idMoveable *>(gameLocal.entities[ e ]);
1686
1687 if ( !m || !m->IsType( idMoveable::Type ) ) {
1688 continue;
1689 }
1690
1691 if ( m->IsBound() ) {
1692 continue;
1693 }
1694
1695 if ( !m->IsAtRest() ) {
1696 break;
1697 }
1698 }
1699
1700 if ( e < MAX_GENTITIES ) {
1701 gameLocal.Warning( "map not saved because the moveable entity %s is not at rest", gameLocal.entities[ e ]->name.c_str() );
1702 return;
1703 }
1704
1705 if ( args.Argc() > 1 ) {
1706 mapName = args.Argv( 1 );
1707 mapName = "maps/" + mapName;
1708 }
1709 else {
1710 mapName = mapFile->GetName();
1711 }
1712
1713 for( e = 0; e < MAX_GENTITIES; e++ ) {
1714 m = static_cast<idMoveable *>(gameLocal.entities[ e ]);
1715
1716 if ( !m || !m->IsType( idMoveable::Type ) ) {
1717 continue;
1718 }
1719
1720 if ( m->IsBound() ) {
1721 continue;
1722 }
1723
1724 // find map file entity
1725 mapEnt = mapFile->FindEntity( m->name );
1726 // create new map file entity if there isn't one for this articulated figure
1727 if ( !mapEnt ) {
1728 mapEnt = new idMapEntity();
1729 mapFile->AddEntity( mapEnt );
1730 for ( i = 0; i < 9999; i++ ) {
1731 name = va( "%s_%d", m->GetEntityDefName(), i );
1732 if ( !gameLocal.FindEntity( name ) ) {
1733 break;
1734 }
1735 }
1736 m->name = name;
1737 mapEnt->epairs.Set( "classname", m->GetEntityDefName() );
1738 mapEnt->epairs.Set( "name", m->name );
1739 }
1740 // save the moveable state
1741 mapEnt->epairs.Set( "origin", m->GetPhysics()->GetOrigin().ToString( 8 ) );
1742 mapEnt->epairs.Set( "rotation", m->GetPhysics()->GetAxis().ToString( 8 ) );
1743 }
1744
1745 // write out the map file
1746 mapFile->Write( mapName, ".map" );
1747 }
1748
1749 /*
1750 ==================
1751 Cmd_SaveRagdolls_f
1752 ==================
1753 */
Cmd_SaveRagdolls_f(const idCmdArgs & args)1754 static void Cmd_SaveRagdolls_f( const idCmdArgs &args ) {
1755 int e, i;
1756 idAFEntity_Base *af;
1757 idMapEntity *mapEnt;
1758 idMapFile *mapFile = gameLocal.GetLevelMap();
1759 idDict dict;
1760 idStr mapName;
1761 const char *name;
1762
1763 if ( !gameLocal.CheatsOk() ) {
1764 return;
1765 }
1766
1767 if ( args.Argc() > 1 ) {
1768 mapName = args.Argv( 1 );
1769 mapName = "maps/" + mapName;
1770 }
1771 else {
1772 mapName = mapFile->GetName();
1773 }
1774
1775 for( e = 0; e < MAX_GENTITIES; e++ ) {
1776 af = static_cast<idAFEntity_Base *>(gameLocal.entities[ e ]);
1777
1778 if ( !af ) {
1779 continue;
1780 }
1781
1782 if ( !af->IsType( idAFEntity_WithAttachedHead::Type ) && !af->IsType( idAFEntity_Generic::Type ) ) {
1783 continue;
1784 }
1785
1786 if ( af->IsBound() ) {
1787 continue;
1788 }
1789
1790 if ( !af->IsAtRest() ) {
1791 gameLocal.Warning( "the articulated figure for entity %s is not at rest", gameLocal.entities[ e ]->name.c_str() );
1792 }
1793
1794 dict.Clear();
1795 af->SaveState( dict );
1796
1797 // find map file entity
1798 mapEnt = mapFile->FindEntity( af->name );
1799 // create new map file entity if there isn't one for this articulated figure
1800 if ( !mapEnt ) {
1801 mapEnt = new idMapEntity();
1802 mapFile->AddEntity( mapEnt );
1803 for ( i = 0; i < 9999; i++ ) {
1804 name = va( "%s_%d", af->GetEntityDefName(), i );
1805 if ( !gameLocal.FindEntity( name ) ) {
1806 break;
1807 }
1808 }
1809 af->name = name;
1810 mapEnt->epairs.Set( "classname", af->GetEntityDefName() );
1811 mapEnt->epairs.Set( "name", af->name );
1812 }
1813 // save the articulated figure state
1814 mapEnt->epairs.Copy( dict );
1815 }
1816
1817 // write out the map file
1818 mapFile->Write( mapName, ".map" );
1819 }
1820
1821 /*
1822 ==================
1823 Cmd_BindRagdoll_f
1824 ==================
1825 */
Cmd_BindRagdoll_f(const idCmdArgs & args)1826 static void Cmd_BindRagdoll_f( const idCmdArgs &args ) {
1827 idPlayer *player;
1828
1829 player = gameLocal.GetLocalPlayer();
1830 if ( !player || !gameLocal.CheatsOk() ) {
1831 return;
1832 }
1833
1834 if ( player ) {
1835 player->dragEntity.BindSelected();
1836 }
1837 }
1838
1839 /*
1840 ==================
1841 Cmd_UnbindRagdoll_f
1842 ==================
1843 */
Cmd_UnbindRagdoll_f(const idCmdArgs & args)1844 static void Cmd_UnbindRagdoll_f( const idCmdArgs &args ) {
1845 idPlayer *player;
1846
1847 player = gameLocal.GetLocalPlayer();
1848 if ( !player || !gameLocal.CheatsOk() ) {
1849 return;
1850 }
1851
1852 if ( player ) {
1853 player->dragEntity.UnbindSelected();
1854 }
1855 }
1856
1857 /*
1858 ==================
1859 Cmd_GameError_f
1860 ==================
1861 */
Cmd_GameError_f(const idCmdArgs & args)1862 static void Cmd_GameError_f( const idCmdArgs &args ) {
1863 gameLocal.Error( "game error" );
1864 }
1865
1866 /*
1867 ==================
1868 Cmd_SaveLights_f
1869 ==================
1870 */
Cmd_SaveLights_f(const idCmdArgs & args)1871 static void Cmd_SaveLights_f( const idCmdArgs &args ) {
1872 int e, i;
1873 idLight *light;
1874 idMapEntity *mapEnt;
1875 idMapFile *mapFile = gameLocal.GetLevelMap();
1876 idDict dict;
1877 idStr mapName;
1878 const char *name;
1879
1880 if ( !gameLocal.CheatsOk() ) {
1881 return;
1882 }
1883
1884 if ( args.Argc() > 1 ) {
1885 mapName = args.Argv( 1 );
1886 mapName = "maps/" + mapName;
1887 }
1888 else {
1889 mapName = mapFile->GetName();
1890 }
1891
1892 for( e = 0; e < MAX_GENTITIES; e++ ) {
1893 light = static_cast<idLight*>(gameLocal.entities[ e ]);
1894
1895 if ( !light || !light->IsType( idLight::Type ) ) {
1896 continue;
1897 }
1898
1899 dict.Clear();
1900 light->SaveState( &dict );
1901
1902 // find map file entity
1903 mapEnt = mapFile->FindEntity( light->name );
1904 // create new map file entity if there isn't one for this light
1905 if ( !mapEnt ) {
1906 mapEnt = new idMapEntity();
1907 mapFile->AddEntity( mapEnt );
1908 for ( i = 0; i < 9999; i++ ) {
1909 name = va( "%s_%d", light->GetEntityDefName(), i );
1910 if ( !gameLocal.FindEntity( name ) ) {
1911 break;
1912 }
1913 }
1914 light->name = name;
1915 mapEnt->epairs.Set( "classname", light->GetEntityDefName() );
1916 mapEnt->epairs.Set( "name", light->name );
1917 }
1918 // save the light state
1919 mapEnt->epairs.Copy( dict );
1920 }
1921
1922 // write out the map file
1923 mapFile->Write( mapName, ".map" );
1924 }
1925
1926
1927 /*
1928 ==================
1929 Cmd_SaveParticles_f
1930 ==================
1931 */
Cmd_SaveParticles_f(const idCmdArgs & args)1932 static void Cmd_SaveParticles_f( const idCmdArgs &args ) {
1933 int e;
1934 idEntity *ent;
1935 idMapEntity *mapEnt;
1936 idMapFile *mapFile = gameLocal.GetLevelMap();
1937 idDict dict;
1938 idStr mapName, strModel;
1939
1940 if ( !gameLocal.CheatsOk() ) {
1941 return;
1942 }
1943
1944 if ( args.Argc() > 1 ) {
1945 mapName = args.Argv( 1 );
1946 mapName = "maps/" + mapName;
1947 }
1948 else {
1949 mapName = mapFile->GetName();
1950 }
1951
1952 for( e = 0; e < MAX_GENTITIES; e++ ) {
1953
1954 ent = static_cast<idStaticEntity*> ( gameLocal.entities[ e ] );
1955
1956 if ( !ent ) {
1957 continue;
1958 }
1959
1960 strModel = ent->spawnArgs.GetString( "model" );
1961 if ( strModel.Length() && strModel.Find( ".prt") > 0 ) {
1962 dict.Clear();
1963 dict.Set( "model", ent->spawnArgs.GetString( "model" ) );
1964 dict.SetVector( "origin", ent->GetPhysics()->GetOrigin() );
1965
1966 // find map file entity
1967 mapEnt = mapFile->FindEntity( ent->name );
1968 // create new map file entity if there isn't one for this entity
1969 if ( !mapEnt ) {
1970 continue;
1971 }
1972 // save the particle state
1973 mapEnt->epairs.Copy( dict );
1974 }
1975 }
1976
1977 // write out the map file
1978 mapFile->Write( mapName, ".map" );
1979 }
1980
1981
1982 /*
1983 ==================
1984 Cmd_DisasmScript_f
1985 ==================
1986 */
Cmd_DisasmScript_f(const idCmdArgs & args)1987 static void Cmd_DisasmScript_f( const idCmdArgs &args ) {
1988 gameLocal.program.Disassemble();
1989 }
1990
1991 /*
1992 ==================
1993 Cmd_TestSave_f
1994 ==================
1995 */
Cmd_TestSave_f(const idCmdArgs & args)1996 static void Cmd_TestSave_f( const idCmdArgs &args ) {
1997 idFile *f;
1998
1999 f = fileSystem->OpenFileWrite( "test.sav" );
2000 gameLocal.SaveGame( f );
2001 fileSystem->CloseFile( f );
2002 }
2003
2004 /*
2005 ==================
2006 Cmd_RecordViewNotes_f
2007 ==================
2008 */
Cmd_RecordViewNotes_f(const idCmdArgs & args)2009 static void Cmd_RecordViewNotes_f( const idCmdArgs &args ) {
2010 idPlayer *player;
2011 idVec3 origin;
2012 idMat3 axis;
2013
2014 if ( args.Argc() <= 3 ) {
2015 return;
2016 }
2017
2018 player = gameLocal.GetLocalPlayer();
2019 if ( !player ) {
2020 return;
2021 }
2022
2023 player->GetViewPos( origin, axis );
2024
2025 // Argv(1) = filename for map (viewnotes/mapname/person)
2026 // Argv(2) = note number (person0001)
2027 // Argv(3) = comments
2028
2029 idStr str = args.Argv(1);
2030 str.SetFileExtension( ".txt" );
2031 idFile *file = fileSystem->OpenFileAppend( str );
2032 if ( file ) {
2033 file->WriteFloatString( "\"view\"\t( %s )\t( %s )\r\n", origin.ToString(), axis.ToString() );
2034 file->WriteFloatString( "\"comments\"\t\"%s: %s\"\r\n\r\n", args.Argv(2), args.Argv(3) );
2035 fileSystem->CloseFile( file );
2036 }
2037
2038 idStr viewComments = args.Argv(1);
2039 viewComments.StripLeading("viewnotes/");
2040 viewComments += " -- Loc: ";
2041 viewComments += origin.ToString();
2042 viewComments += "\n";
2043 viewComments += args.Argv(3);
2044 player->hud->SetStateString( "viewcomments", viewComments );
2045 player->hud->HandleNamedEvent( "showViewComments" );
2046 }
2047
2048 /*
2049 ==================
2050 Cmd_CloseViewNotes_f
2051 ==================
2052 */
Cmd_CloseViewNotes_f(const idCmdArgs & args)2053 static void Cmd_CloseViewNotes_f( const idCmdArgs &args ) {
2054 idPlayer *player = gameLocal.GetLocalPlayer();
2055
2056 if ( !player ) {
2057 return;
2058 }
2059
2060 player->hud->SetStateString( "viewcomments", "" );
2061 player->hud->HandleNamedEvent( "hideViewComments" );
2062 }
2063
2064 /*
2065 ==================
2066 Cmd_ShowViewNotes_f
2067 ==================
2068 */
Cmd_ShowViewNotes_f(const idCmdArgs & args)2069 static void Cmd_ShowViewNotes_f( const idCmdArgs &args ) {
2070 static idLexer parser( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS | LEXFL_NOSTRINGCONCAT | LEXFL_NOFATALERRORS );
2071 idToken token;
2072 idPlayer *player;
2073 idVec3 origin;
2074 idMat3 axis;
2075
2076 player = gameLocal.GetLocalPlayer();
2077
2078 if ( !player ) {
2079 return;
2080 }
2081
2082 if ( !parser.IsLoaded() ) {
2083 idStr str = "viewnotes/";
2084 str += gameLocal.GetMapName();
2085 str.StripFileExtension();
2086 str += "/";
2087 if ( args.Argc() > 1 ) {
2088 str += args.Argv( 1 );
2089 } else {
2090 str += "comments";
2091 }
2092 str.SetFileExtension( ".txt" );
2093 if ( !parser.LoadFile( str ) ) {
2094 gameLocal.Printf( "No view notes for %s\n", gameLocal.GetMapName() );
2095 return;
2096 }
2097 }
2098
2099 if ( parser.ExpectTokenString( "view" ) && parser.Parse1DMatrix( 3, origin.ToFloatPtr() ) &&
2100 parser.Parse1DMatrix( 9, axis.ToFloatPtr() ) && parser.ExpectTokenString( "comments" ) && parser.ReadToken( &token ) ) {
2101 player->hud->SetStateString( "viewcomments", token );
2102 player->hud->HandleNamedEvent( "showViewComments" );
2103 player->Teleport( origin, axis.ToAngles(), NULL );
2104 } else {
2105 parser.FreeSource();
2106 player->hud->HandleNamedEvent( "hideViewComments" );
2107 return;
2108 }
2109 }
2110
2111 /*
2112 =================
2113 FindEntityGUIs
2114
2115 helper function for Cmd_NextGUI_f. Checks the passed entity to determine if it
2116 has any valid gui surfaces.
2117 =================
2118 */
FindEntityGUIs(idEntity * ent,const modelSurface_t ** surfaces,int maxSurfs,int & guiSurfaces)2119 bool FindEntityGUIs( idEntity *ent, const modelSurface_t ** surfaces, int maxSurfs, int &guiSurfaces ) {
2120 renderEntity_t *renderEnt;
2121 idRenderModel *renderModel;
2122 const modelSurface_t *surf;
2123 const idMaterial *shader;
2124 int i;
2125
2126 assert( surfaces != NULL );
2127 assert( ent != NULL );
2128
2129 memset( surfaces, 0x00, sizeof( modelSurface_t *) * maxSurfs );
2130 guiSurfaces = 0;
2131
2132 renderEnt = ent->GetRenderEntity();
2133 renderModel = renderEnt->hModel;
2134 if ( renderModel == NULL ) {
2135 return false;
2136 }
2137
2138 for( i = 0; i < renderModel->NumSurfaces(); i++ ) {
2139 surf = renderModel->Surface( i );
2140 if ( surf == NULL ) {
2141 continue;
2142 }
2143 shader = surf->shader;
2144 if ( shader == NULL ) {
2145 continue;
2146 }
2147 if ( shader->GetEntityGui() > 0 ) {
2148 surfaces[ guiSurfaces++ ] = surf;
2149 }
2150 }
2151
2152 return ( guiSurfaces != 0 );
2153 }
2154
2155 /*
2156 =================
2157 Cmd_NextGUI_f
2158 =================
2159 */
Cmd_NextGUI_f(const idCmdArgs & args)2160 void Cmd_NextGUI_f( const idCmdArgs &args ) {
2161 idVec3 origin;
2162 idAngles angles;
2163 idPlayer *player;
2164 idEntity *ent;
2165 int guiSurfaces;
2166 bool newEnt;
2167 renderEntity_t *renderEnt;
2168 int surfIndex;
2169 srfTriangles_t *geom;
2170 idMat4 modelMatrix;
2171 idVec3 normal;
2172 idVec3 center;
2173 const modelSurface_t *surfaces[ MAX_RENDERENTITY_GUI ];
2174
2175 player = gameLocal.GetLocalPlayer();
2176 if ( !player || !gameLocal.CheatsOk() ) {
2177 return;
2178 }
2179
2180 if ( args.Argc() != 1 ) {
2181 gameLocal.Printf( "usage: nextgui\n" );
2182 return;
2183 }
2184
2185 // start at the last entity
2186 ent = gameLocal.lastGUIEnt.GetEntity();
2187
2188 // see if we have any gui surfaces left to go to on the current entity.
2189 guiSurfaces = 0;
2190 newEnt = false;
2191 if ( ent == NULL ) {
2192 newEnt = true;
2193 } else if ( FindEntityGUIs( ent, surfaces, MAX_RENDERENTITY_GUI, guiSurfaces ) == true ) {
2194 if ( gameLocal.lastGUI >= guiSurfaces ) {
2195 newEnt = true;
2196 }
2197 } else {
2198 // no actual gui surfaces on this ent, so skip it
2199 newEnt = true;
2200 }
2201
2202 if ( newEnt == true ) {
2203 // go ahead and skip to the next entity with a gui...
2204 if ( ent == NULL ) {
2205 ent = gameLocal.spawnedEntities.Next();
2206 } else {
2207 ent = ent->spawnNode.Next();
2208 }
2209
2210 for ( ; ent != NULL; ent = ent->spawnNode.Next() ) {
2211 if ( ent->spawnArgs.GetString( "gui", NULL ) != NULL ) {
2212 break;
2213 }
2214
2215 if ( ent->spawnArgs.GetString( "gui2", NULL ) != NULL ) {
2216 break;
2217 }
2218
2219 if ( ent->spawnArgs.GetString( "gui3", NULL ) != NULL ) {
2220 break;
2221 }
2222
2223 // try the next entity
2224 gameLocal.lastGUIEnt = ent;
2225 }
2226
2227 gameLocal.lastGUIEnt = ent;
2228 gameLocal.lastGUI = 0;
2229
2230 if ( !ent ) {
2231 gameLocal.Printf( "No more gui entities. Starting over...\n" );
2232 return;
2233 }
2234 }
2235
2236 if ( FindEntityGUIs( ent, surfaces, MAX_RENDERENTITY_GUI, guiSurfaces ) == false ) {
2237 gameLocal.Printf( "Entity \"%s\" has gui properties but no gui surfaces.\n", ent->name.c_str() );
2238 }
2239
2240 if ( guiSurfaces == 0 ) {
2241 gameLocal.Printf( "Entity \"%s\" has gui properties but no gui surfaces!\n", ent->name.c_str() );
2242 return;
2243 }
2244
2245 gameLocal.Printf( "Teleporting to gui entity \"%s\", gui #%d.\n" , ent->name.c_str (), gameLocal.lastGUI );
2246
2247 renderEnt = ent->GetRenderEntity();
2248 surfIndex = gameLocal.lastGUI++;
2249 geom = surfaces[ surfIndex ]->geometry;
2250 if ( geom == NULL ) {
2251 gameLocal.Printf( "Entity \"%s\" has gui surface %d without geometry!\n", ent->name.c_str(), surfIndex );
2252 return;
2253 }
2254
2255 assert( geom->facePlanes != NULL );
2256
2257 modelMatrix = idMat4( renderEnt->axis, renderEnt->origin );
2258 normal = geom->facePlanes[ 0 ].Normal() * renderEnt->axis;
2259 center = geom->bounds.GetCenter() * modelMatrix;
2260
2261 origin = center + (normal * 32.0f);
2262 origin.z -= player->EyeHeight();
2263 normal *= -1.0f;
2264 angles = normal.ToAngles ();
2265
2266 // make sure the player is in noclip
2267 player->noclip = true;
2268 player->Teleport( origin, angles, NULL );
2269 }
2270
ArgCompletion_DefFile(const idCmdArgs & args,void (* callback)(const char * s))2271 static void ArgCompletion_DefFile( const idCmdArgs &args, void(*callback)( const char *s ) ) {
2272 cmdSystem->ArgCompletion_FolderExtension( args, callback, "def/", true, ".def", NULL );
2273 }
2274
2275 /*
2276 ===============
2277 Cmd_TestId_f
2278 outputs a string from the string table for the specified id
2279 ===============
2280 */
Cmd_TestId_f(const idCmdArgs & args)2281 void Cmd_TestId_f( const idCmdArgs &args ) {
2282 idStr id;
2283 int i;
2284 if ( args.Argc() == 1 ) {
2285 common->Printf( "usage: testid <string id>\n" );
2286 return;
2287 }
2288
2289 for ( i = 1; i < args.Argc(); i++ ) {
2290 id += args.Argv( i );
2291 }
2292 if ( idStr::Cmpn( id, STRTABLE_ID, STRTABLE_ID_LENGTH ) != 0 ) {
2293 id = STRTABLE_ID + id;
2294 }
2295 gameLocal.mpGame.AddChatLine( common->GetLanguageDict()->GetString( id ), "<nothing>", "<nothing>", "<nothing>" );
2296 }
2297
2298 /*
2299 =================
2300 idGameLocal::InitConsoleCommands
2301
2302 Let the system know about all of our commands
2303 so it can perform tab completion
2304 =================
2305 */
InitConsoleCommands(void)2306 void idGameLocal::InitConsoleCommands( void ) {
2307 cmdSystem->AddCommand( "listTypeInfo", ListTypeInfo_f, CMD_FL_GAME, "list type info" );
2308 cmdSystem->AddCommand( "writeGameState", WriteGameState_f, CMD_FL_GAME, "write game state" );
2309 cmdSystem->AddCommand( "testSaveGame", TestSaveGame_f, CMD_FL_GAME|CMD_FL_CHEAT, "test a save game for a level" );
2310 cmdSystem->AddCommand( "game_memory", idClass::DisplayInfo_f, CMD_FL_GAME, "displays game class info" );
2311 cmdSystem->AddCommand( "listClasses", idClass::ListClasses_f, CMD_FL_GAME, "lists game classes" );
2312 cmdSystem->AddCommand( "listThreads", idThread::ListThreads_f, CMD_FL_GAME|CMD_FL_CHEAT, "lists script threads" );
2313 cmdSystem->AddCommand( "listEntities", Cmd_EntityList_f, CMD_FL_GAME|CMD_FL_CHEAT, "lists game entities" );
2314 cmdSystem->AddCommand( "listActiveEntities", Cmd_ActiveEntityList_f, CMD_FL_GAME|CMD_FL_CHEAT, "lists active game entities" );
2315 cmdSystem->AddCommand( "listMonsters", idAI::List_f, CMD_FL_GAME|CMD_FL_CHEAT, "lists monsters" );
2316 cmdSystem->AddCommand( "listSpawnArgs", Cmd_ListSpawnArgs_f, CMD_FL_GAME|CMD_FL_CHEAT, "list the spawn args of an entity", idGameLocal::ArgCompletion_EntityName );
2317 cmdSystem->AddCommand( "say", Cmd_Say_f, CMD_FL_GAME, "text chat" );
2318 cmdSystem->AddCommand( "sayTeam", Cmd_SayTeam_f, CMD_FL_GAME, "team text chat" );
2319 cmdSystem->AddCommand( "addChatLine", Cmd_AddChatLine_f, CMD_FL_GAME, "internal use - core to game chat lines" );
2320 cmdSystem->AddCommand( "gameKick", Cmd_Kick_f, CMD_FL_GAME, "same as kick, but recognizes player names" );
2321 cmdSystem->AddCommand( "give", Cmd_Give_f, CMD_FL_GAME|CMD_FL_CHEAT, "gives one or more items" );
2322 cmdSystem->AddCommand( "centerview", Cmd_CenterView_f, CMD_FL_GAME, "centers the view" );
2323 cmdSystem->AddCommand( "god", Cmd_God_f, CMD_FL_GAME|CMD_FL_CHEAT, "enables god mode" );
2324 cmdSystem->AddCommand( "notarget", Cmd_Notarget_f, CMD_FL_GAME|CMD_FL_CHEAT, "disables the player as a target" );
2325 cmdSystem->AddCommand( "noclip", Cmd_Noclip_f, CMD_FL_GAME|CMD_FL_CHEAT, "disables collision detection for the player" );
2326 cmdSystem->AddCommand( "kill", Cmd_Kill_f, CMD_FL_GAME, "kills the player" );
2327 cmdSystem->AddCommand( "where", Cmd_GetViewpos_f, CMD_FL_GAME|CMD_FL_CHEAT, "prints the current view position" );
2328 cmdSystem->AddCommand( "getviewpos", Cmd_GetViewpos_f, CMD_FL_GAME|CMD_FL_CHEAT, "prints the current view position" );
2329 cmdSystem->AddCommand( "setviewpos", Cmd_SetViewpos_f, CMD_FL_GAME|CMD_FL_CHEAT, "sets the current view position" );
2330 cmdSystem->AddCommand( "teleport", Cmd_Teleport_f, CMD_FL_GAME|CMD_FL_CHEAT, "teleports the player to an entity location", idGameLocal::ArgCompletion_EntityName );
2331 cmdSystem->AddCommand( "trigger", Cmd_Trigger_f, CMD_FL_GAME|CMD_FL_CHEAT, "triggers an entity", idGameLocal::ArgCompletion_EntityName );
2332 cmdSystem->AddCommand( "spawn", Cmd_Spawn_f, CMD_FL_GAME|CMD_FL_CHEAT, "spawns a game entity", idCmdSystem::ArgCompletion_Decl<DECL_ENTITYDEF> );
2333 cmdSystem->AddCommand( "damage", Cmd_Damage_f, CMD_FL_GAME|CMD_FL_CHEAT, "apply damage to an entity", idGameLocal::ArgCompletion_EntityName );
2334 cmdSystem->AddCommand( "remove", Cmd_Remove_f, CMD_FL_GAME|CMD_FL_CHEAT, "removes an entity", idGameLocal::ArgCompletion_EntityName );
2335 cmdSystem->AddCommand( "killMonsters", Cmd_KillMonsters_f, CMD_FL_GAME|CMD_FL_CHEAT, "removes all monsters" );
2336 cmdSystem->AddCommand( "killMoveables", Cmd_KillMovables_f, CMD_FL_GAME|CMD_FL_CHEAT, "removes all moveables" );
2337 cmdSystem->AddCommand( "killRagdolls", Cmd_KillRagdolls_f, CMD_FL_GAME|CMD_FL_CHEAT, "removes all ragdolls" );
2338 cmdSystem->AddCommand( "addline", Cmd_AddDebugLine_f, CMD_FL_GAME|CMD_FL_CHEAT, "adds a debug line" );
2339 cmdSystem->AddCommand( "addarrow", Cmd_AddDebugLine_f, CMD_FL_GAME|CMD_FL_CHEAT, "adds a debug arrow" );
2340 cmdSystem->AddCommand( "removeline", Cmd_RemoveDebugLine_f, CMD_FL_GAME|CMD_FL_CHEAT, "removes a debug line" );
2341 cmdSystem->AddCommand( "blinkline", Cmd_BlinkDebugLine_f, CMD_FL_GAME|CMD_FL_CHEAT, "blinks a debug line" );
2342 cmdSystem->AddCommand( "listLines", Cmd_ListDebugLines_f, CMD_FL_GAME|CMD_FL_CHEAT, "lists all debug lines" );
2343 cmdSystem->AddCommand( "playerModel", Cmd_PlayerModel_f, CMD_FL_GAME|CMD_FL_CHEAT, "sets the given model on the player", idCmdSystem::ArgCompletion_Decl<DECL_MODELDEF> );
2344 cmdSystem->AddCommand( "testFx", Cmd_TestFx_f, CMD_FL_GAME|CMD_FL_CHEAT, "tests an FX system", idCmdSystem::ArgCompletion_Decl<DECL_FX> );
2345 cmdSystem->AddCommand( "testBoneFx", Cmd_TestBoneFx_f, CMD_FL_GAME|CMD_FL_CHEAT, "tests an FX system bound to a joint", idCmdSystem::ArgCompletion_Decl<DECL_FX> );
2346 cmdSystem->AddCommand( "testLight", Cmd_TestLight_f, CMD_FL_GAME|CMD_FL_CHEAT, "tests a light" );
2347 cmdSystem->AddCommand( "testPointLight", Cmd_TestPointLight_f, CMD_FL_GAME|CMD_FL_CHEAT, "tests a point light" );
2348 cmdSystem->AddCommand( "popLight", Cmd_PopLight_f, CMD_FL_GAME|CMD_FL_CHEAT, "removes the last created light" );
2349 cmdSystem->AddCommand( "testDeath", Cmd_TestDeath_f, CMD_FL_GAME|CMD_FL_CHEAT, "tests death" );
2350 cmdSystem->AddCommand( "testSave", Cmd_TestSave_f, CMD_FL_GAME|CMD_FL_CHEAT, "writes out a test savegame" );
2351 cmdSystem->AddCommand( "testModel", idTestModel::TestModel_f, CMD_FL_GAME|CMD_FL_CHEAT, "tests a model", idTestModel::ArgCompletion_TestModel );
2352 cmdSystem->AddCommand( "testSkin", idTestModel::TestSkin_f, CMD_FL_GAME|CMD_FL_CHEAT, "tests a skin on an existing testModel", idCmdSystem::ArgCompletion_Decl<DECL_SKIN> );
2353 cmdSystem->AddCommand( "testShaderParm", idTestModel::TestShaderParm_f, CMD_FL_GAME|CMD_FL_CHEAT, "sets a shaderParm on an existing testModel" );
2354 cmdSystem->AddCommand( "keepTestModel", idTestModel::KeepTestModel_f, CMD_FL_GAME|CMD_FL_CHEAT, "keeps the last test model in the game" );
2355 cmdSystem->AddCommand( "testAnim", idTestModel::TestAnim_f, CMD_FL_GAME|CMD_FL_CHEAT, "tests an animation", idTestModel::ArgCompletion_TestAnim );
2356 cmdSystem->AddCommand( "testParticleStopTime", idTestModel::TestParticleStopTime_f,CMD_FL_GAME|CMD_FL_CHEAT, "tests particle stop time on a test model" );
2357 cmdSystem->AddCommand( "nextAnim", idTestModel::TestModelNextAnim_f, CMD_FL_GAME|CMD_FL_CHEAT, "shows next animation on test model" );
2358 cmdSystem->AddCommand( "prevAnim", idTestModel::TestModelPrevAnim_f, CMD_FL_GAME|CMD_FL_CHEAT, "shows previous animation on test model" );
2359 cmdSystem->AddCommand( "nextFrame", idTestModel::TestModelNextFrame_f, CMD_FL_GAME|CMD_FL_CHEAT, "shows next animation frame on test model" );
2360 cmdSystem->AddCommand( "prevFrame", idTestModel::TestModelPrevFrame_f, CMD_FL_GAME|CMD_FL_CHEAT, "shows previous animation frame on test model" );
2361 cmdSystem->AddCommand( "testBlend", idTestModel::TestBlend_f, CMD_FL_GAME|CMD_FL_CHEAT, "tests animation blending" );
2362 cmdSystem->AddCommand( "reloadScript", Cmd_ReloadScript_f, CMD_FL_GAME|CMD_FL_CHEAT, "reloads scripts" );
2363 cmdSystem->AddCommand( "script", Cmd_Script_f, CMD_FL_GAME|CMD_FL_CHEAT, "executes a line of script" );
2364 cmdSystem->AddCommand( "listCollisionModels", Cmd_ListCollisionModels_f, CMD_FL_GAME, "lists collision models" );
2365 cmdSystem->AddCommand( "collisionModelInfo", Cmd_CollisionModelInfo_f, CMD_FL_GAME, "shows collision model info" );
2366 cmdSystem->AddCommand( "reexportmodels", Cmd_ReexportModels_f, CMD_FL_GAME|CMD_FL_CHEAT, "reexports models", ArgCompletion_DefFile );
2367 cmdSystem->AddCommand( "reloadanims", Cmd_ReloadAnims_f, CMD_FL_GAME|CMD_FL_CHEAT, "reloads animations" );
2368 cmdSystem->AddCommand( "listAnims", Cmd_ListAnims_f, CMD_FL_GAME, "lists all animations" );
2369 cmdSystem->AddCommand( "aasStats", Cmd_AASStats_f, CMD_FL_GAME, "shows AAS stats" );
2370 cmdSystem->AddCommand( "testDamage", Cmd_TestDamage_f, CMD_FL_GAME|CMD_FL_CHEAT, "tests a damage def", idCmdSystem::ArgCompletion_Decl<DECL_ENTITYDEF> );
2371 cmdSystem->AddCommand( "weaponSplat", Cmd_WeaponSplat_f, CMD_FL_GAME|CMD_FL_CHEAT, "projects a blood splat on the player weapon" );
2372 cmdSystem->AddCommand( "saveSelected", Cmd_SaveSelected_f, CMD_FL_GAME|CMD_FL_CHEAT, "saves the selected entity to the .map file" );
2373 cmdSystem->AddCommand( "deleteSelected", Cmd_DeleteSelected_f, CMD_FL_GAME|CMD_FL_CHEAT, "deletes selected entity" );
2374 cmdSystem->AddCommand( "saveMoveables", Cmd_SaveMoveables_f, CMD_FL_GAME|CMD_FL_CHEAT, "save all moveables to the .map file" );
2375 cmdSystem->AddCommand( "saveRagdolls", Cmd_SaveRagdolls_f, CMD_FL_GAME|CMD_FL_CHEAT, "save all ragdoll poses to the .map file" );
2376 cmdSystem->AddCommand( "bindRagdoll", Cmd_BindRagdoll_f, CMD_FL_GAME|CMD_FL_CHEAT, "binds ragdoll at the current drag position" );
2377 cmdSystem->AddCommand( "unbindRagdoll", Cmd_UnbindRagdoll_f, CMD_FL_GAME|CMD_FL_CHEAT, "unbinds the selected ragdoll" );
2378 cmdSystem->AddCommand( "saveLights", Cmd_SaveLights_f, CMD_FL_GAME|CMD_FL_CHEAT, "saves all lights to the .map file" );
2379 cmdSystem->AddCommand( "saveParticles", Cmd_SaveParticles_f, CMD_FL_GAME|CMD_FL_CHEAT, "saves all lights to the .map file" );
2380 cmdSystem->AddCommand( "clearLights", Cmd_ClearLights_f, CMD_FL_GAME|CMD_FL_CHEAT, "clears all lights" );
2381 cmdSystem->AddCommand( "gameError", Cmd_GameError_f, CMD_FL_GAME|CMD_FL_CHEAT, "causes a game error" );
2382
2383 cmdSystem->AddCommand( "disasmScript", Cmd_DisasmScript_f, CMD_FL_GAME|CMD_FL_CHEAT, "disassembles script" );
2384 cmdSystem->AddCommand( "recordViewNotes", Cmd_RecordViewNotes_f, CMD_FL_GAME|CMD_FL_CHEAT, "record the current view position with notes" );
2385 cmdSystem->AddCommand( "showViewNotes", Cmd_ShowViewNotes_f, CMD_FL_GAME|CMD_FL_CHEAT, "show any view notes for the current map, successive calls will cycle to the next note" );
2386 cmdSystem->AddCommand( "closeViewNotes", Cmd_CloseViewNotes_f, CMD_FL_GAME|CMD_FL_CHEAT, "close the view showing any notes for this map" );
2387 cmdSystem->AddCommand( "exportmodels", Cmd_ExportModels_f, CMD_FL_GAME|CMD_FL_CHEAT, "exports models", ArgCompletion_DefFile );
2388
2389 // multiplayer client commands ( replaces old impulses stuff )
2390 cmdSystem->AddCommand( "clientDropWeapon", idMultiplayerGame::DropWeapon_f, CMD_FL_GAME, "drop current weapon" );
2391 cmdSystem->AddCommand( "clientMessageMode", idMultiplayerGame::MessageMode_f, CMD_FL_GAME, "ingame gui message mode" );
2392 // FIXME: implement
2393 // cmdSystem->AddCommand( "clientVote", idMultiplayerGame::Vote_f, CMD_FL_GAME, "cast your vote: clientVote yes | no" );
2394 // cmdSystem->AddCommand( "clientCallVote", idMultiplayerGame::CallVote_f, CMD_FL_GAME, "call a vote: clientCallVote si_.. proposed_value" );
2395 cmdSystem->AddCommand( "clientVoiceChat", idMultiplayerGame::VoiceChat_f, CMD_FL_GAME, "voice chats: clientVoiceChat <sound shader>" );
2396 cmdSystem->AddCommand( "clientVoiceChatTeam", idMultiplayerGame::VoiceChatTeam_f, CMD_FL_GAME, "team voice chats: clientVoiceChat <sound shader>" );
2397
2398 // multiplayer server commands
2399 cmdSystem->AddCommand( "serverMapRestart", idGameLocal::MapRestart_f, CMD_FL_GAME, "restart the current game" );
2400 cmdSystem->AddCommand( "serverForceReady", idMultiplayerGame::ForceReady_f,CMD_FL_GAME, "force all players ready" );
2401 cmdSystem->AddCommand( "serverNextMap", idGameLocal::NextMap_f, CMD_FL_GAME, "change to the next map" );
2402
2403 // localization help commands
2404 cmdSystem->AddCommand( "nextGUI", Cmd_NextGUI_f, CMD_FL_GAME|CMD_FL_CHEAT, "teleport the player to the next func_static with a gui" );
2405 cmdSystem->AddCommand( "testid", Cmd_TestId_f, CMD_FL_GAME|CMD_FL_CHEAT, "output the string for the specified id." );
2406 }
2407
2408 /*
2409 =================
2410 idGameLocal::ShutdownConsoleCommands
2411 =================
2412 */
ShutdownConsoleCommands(void)2413 void idGameLocal::ShutdownConsoleCommands( void ) {
2414 cmdSystem->RemoveFlaggedCommands( CMD_FL_GAME );
2415 }
2416