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