1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 1997, 2005 - 3D Realms Entertainment
4 
5 This file is part of Shadow Warrior version 1.2
6 
7 Shadow Warrior is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 
16 See the GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21 
22 Original Source: 1997 - Frank Maddin and Jim Norwood
23 Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
24 */
25 //-------------------------------------------------------------------------
26 
27 // CONSOLE.C
28 // Handles all argument storing and user console variable modifications.
29 // Copyright (c) 1996 by Jim Norwood
30 
31 #include "build.h"
32 
33 #include "mytypes.h"
34 #include "keys.h"
35 #include "names2.h"
36 #include "panel.h"
37 #include "game.h"
38 #include "tags.h"
39 #include "player.h"
40 #include "lists.h"
41 #include "warp.h"
42 #include "quake.h"
43 
44 #include "mathutil.h"
45 #include "function.h"
46 #include "control.h"
47 #include "trigger.h"
48 
49 #include "menus.h"
50 #include "net.h"
51 #include "pal.h"
52 
53 #include "weapon.h"
54 #include "text.h"
55 #include "jsector.h"
56 
57 // DEFINES ///////////////////////////////////////////////////////////////////////////////////
58 #define MAX_USER_ARGS           100
59 #define MAX_CONSOLE_COMMANDS    100
60 #define MAX_HISTORY             20
61 
62 BOOL SpriteInfo = FALSE;
63 extern BOOL QuitFlag;
64 
65 // FUNCTION PROTOTYPES ///////////////////////////////////////////////////////////////////////
66 void CON_ProcessOptions( void );
67 void CON_ClearConsole( void );
68 BYTE CON_CommandCmp(const char *str1, const char *str2, int len);
69 void CheatInput(void);
70 
71 // Modify actor routines
72 void CON_ModXrepeat( void );
73 void CON_ModYrepeat( void );
74 void CON_ModTranslucent( void );
75 void CON_GetHelp( void );
76 void CON_Sound( void );
77 void CON_Reverb( void );
78 void CON_Heap( void );
79 void CON_Cache( void );
80 void CON_SoundTest( void );
81 void CON_SpriteInfo( void );
82 void CON_KillSprite( void );
83 void CON_SpriteDetail( void );
84 void CON_UserDetail( void );
85 void CON_Quit( void );
86 void CON_LoadSetup( void );
87 void CON_DamageData( void );
88 void CON_WinPachinko( void );
89 void CON_Tweak( void );
90 void CON_Bunny( void );
91 void CON_CheckHeap( void );
92 void CON_DumpHeap( void );
93 void CON_ShowMirror( void );
94 void CON_MultiNameChange( void );
95 void CON_DumpSoundList( void );
96 
97 // STRUCTURES ////////////////////////////////////////////////////////////////////////////////
98 
99 typedef struct
100 {
101     const char *command;              // Text string representing the command that calls this function
102     void (*function)(void);     // Function assigned to the command, take no parameters
103 
104 } CON_COMMAND, *CON_COMMANDp;
105 
106 // Contains any commands that don't get added by particular setup functions
107 CON_COMMAND pre_commands[] = {
108 #if DEBUG
109 {"bobbing",     CON_ProcessOptions},
110 {"swnext",      CheatInput},
111 {"swprev",      CheatInput},
112 {"swsecret",    CheatInput},
113 {"swstart",     CheatInput},
114 {"swres",       CheatInput},
115 {"swloc",       CheatInput},
116 {"swroom",      CheatInput},
117 {"swmap",       CheatInput},
118 {"swvox",       CheatInput},
119 {"swsave",      CheatInput},
120 #endif
121 #if DEBUG
122 {"george",      CheatInput},
123 {"blackburn",   CheatInput},
124 {"reverb",      CON_Reverb},
125 {"mem",         CON_Heap},
126 {"cache",       CON_Cache},
127 {"xrepeat",     CON_ModXrepeat},
128 {"yrepeat",     CON_ModYrepeat},
129 {"translucent", CON_ModTranslucent},
130 {"spriteinfo",  CON_SpriteInfo},
131 {"kill",        CON_KillSprite},
132 {"showsprite",  CON_SpriteDetail},
133 {"showuser",    CON_UserDetail},
134 {"damage",      CON_DamageData},
135 {"tweak",       CON_Tweak},
136 {"checkheap",   CON_CheckHeap},
137 {"dumpheap",    CON_DumpHeap},
138 {"showmirror",  CON_ShowMirror},
139 {"clear",       CON_ClearConsole},
140 {"dumpsounds",  CON_DumpSoundList},
141 {"help",        CON_GetHelp},
142 //{"quit",        CON_Quit},
143 #endif
144 {"swchan",      CheatInput},
145 {"swgimme",     CheatInput},
146 {"swtrek##",    CheatInput},
147 {"swgreed",     CheatInput},
148 {"swghost",     CheatInput},
149 {"swstart",     CheatInput},
150 {"swres",       CheatInput},
151 {"swloc",       CheatInput},
152 {"swmap",       CheatInput},
153 {"swsave",      CheatInput},
154 {"sound",       CON_SoundTest},
155 {"winpachinko", CON_WinPachinko},
156 {"config",      CON_LoadSetup},
157 {"swtrix",      CON_Bunny},
158 {"swname",      CON_MultiNameChange},
159 {NULL, NULL}
160 };
161 
162 
163 // GLOBALS ///////////////////////////////////////////////////////////////////////////////////
164 
165 CON_COMMAND commandlist[MAX_CONSOLE_COMMANDS];  // Console command array
166 CON_COMMANDp commandptr;    // Pointer to a command
167 
168 SHORT numcommands=0;    // Total number of commands in the command list
169 
170 char command_history[MAX_HISTORY][256]; // History of what has been typed in lately
171 SHORT curr_history=0; // Line currently being pointed to in the history array
172 SHORT numhistory=0;
173 
174 // Array which stores all the user arguments passed into the game.
175 static char user_args[MAX_USER_ARGS][256];
176 static BYTE con_argnum=0;   // Total number of arguments that were passed into the game
177 
178 char con_message[80]; // Holds the current console message to send to adduserquote
179 
180 // FUNCTIONS /////////////////////////////////////////////////////////////////////////////////
181 
182 
183 //
184 // Frank's neato input string checker, useful for my stuff too.
185 //
CON_CommandCmp(const char * str1,const char * str2,int len)186 BYTE CON_CommandCmp(const char *str1, const char *str2, int len)
187 {
188     const char *cp1 = str1;
189     const char *cp2 = str2;
190 
191     do
192     {
193         if (*cp1 != *cp2)
194             {
195             if (*cp1 != '#' && *cp2 != '#')
196                 return(FALSE);
197             else
198             if ( (*cp1 == '#' && !isdigit(*cp2)) || (*cp2 == '#' && !isdigit(*cp1)) )
199                 return(FALSE);
200             }
201 
202         cp1++;
203         cp2++;
204     }
205     while (--len);
206 
207     return(TRUE);
208 }
209 
IsCommand(char * str)210 BOOL IsCommand(char *str)
211     {
212     int i;
213     char first[512];
214 
215     sscanf(str,"%s",first);
216 
217     for (i = 0; i < numcommands; i++)
218         {
219         // Don't even try if they aren't the same length
220         if(strlen(first) != strlen(commandlist[i].command))
221             continue;
222 
223         // See if it's in there
224         if (CON_CommandCmp(first, commandlist[i].command, strlen(first)))
225             {
226             return(TRUE);
227             }
228         }
229 
230     return(FALSE);
231     }
232 
233 //
234 // Sends a message to the user quote array
235 //
236 
CON_Message(const char * message,...)237 void CON_Message(const char *message, ...)
238 {
239     va_list argptr;
240 
241     va_start (argptr,message);
242     vsprintf (&con_message[0],message,argptr);
243     va_end (argptr);
244 
245     // Send message to user quote array for immediate display
246     adduserquote(&con_message[0]);
247 }
248 
249 //
250 // Sends a message to the console quote array
251 //
252 
CON_ConMessage(const char * message,...)253 void CON_ConMessage(const char *message, ...)
254 {
255     va_list argptr;
256 
257     va_start (argptr,message);
258     vsprintf (&con_message[0],message,argptr);
259     va_end (argptr);
260 
261     // Send message to user quote array for immediate display
262     addconquote(&con_message[0]);
263 }
264 
265 //
266 // Stores user arguments passed in on the command line for later inspection
267 //
CON_StoreArg(const char * userarg)268 void CON_StoreArg(const char *userarg)
269 {
270     if(con_argnum < MAX_USER_ARGS)
271     {
272         strcpy(&user_args[con_argnum][0],userarg);
273 	Bstrlwr(&user_args[con_argnum][0]);
274         con_argnum++;
275     }
276 }
277 
278 //
279 // Checkes the user command array to see if user did in fact pass in a particular argument
280 //
CON_CheckParm(const char * userarg)281 BOOL CON_CheckParm(const char *userarg)
282 {
283     SHORT i;
284 
285     for(i=0;i<con_argnum;i++)
286     {
287         if(!strcmp(&user_args[i][0],userarg))
288             return(TRUE); // Yep, it's in there
289     }
290 
291     return(FALSE); // Not a parameter that was passed in
292 }
293 
294 //
295 // Scrolls up and down through previous user commands like DosKey
296 // Copies the history text string into the MessageInputCommand
297 //
CON_CommandHistory(signed char dir)298 void CON_CommandHistory(signed char dir)
299 {
300     if(curr_history + dir < numhistory)
301         curr_history += dir;
302     if(curr_history < 0) curr_history = 0;
303     if(curr_history > MAX_HISTORY) curr_history = MAX_HISTORY;
304 
305     strcpy(MessageInputString, command_history[curr_history]);
306 }
307 
CON_AddHistory(const char * commandstr)308 void CON_AddHistory(const char *commandstr)
309 {
310     int i;
311 
312     for(i=MAX_HISTORY-1;i>=0;i--)
313     {
314         strcpy(command_history[i],command_history[i-1]);
315     }
316     strcpy(command_history[0],commandstr);
317     if((++numhistory) > MAX_HISTORY) numhistory = MAX_HISTORY;
318 }
319 
320 
321 //
322 // Adds a command name to the command list and assigns the appropriate function pointer
323 //
CON_AddCommand(const char * command,void (* function)(void))324 BOOL CON_AddCommand(const char *command, void (*function)(void))
325 {
326     if(command != NULL && function != NULL && numcommands < MAX_CONSOLE_COMMANDS)
327     {
328 //      strcpy(commandlist[numcommands].command, command);
329         commandlist[numcommands].command = command;
330         commandlist[numcommands].function = function;
331 
332         // Increment counter to set up for next command insertion
333         numcommands++;
334 
335         ASSERT(numcommands <= MAX_CONSOLE_COMMANDS);
336 
337         return(TRUE);
338     }
339 
340     return(FALSE);
341 }
342 
343 //
344 // Process commands
345 // Returns TRUE upon success
346 //
CON_ProcessUserCommand(void)347 void CON_ProcessUserCommand( void )
348 {
349     SHORT i=0;
350     char temp_message[256],command_str[256];
351 
352     strcpy(temp_message,MessageInputString);
353     sscanf(Bstrlwr(temp_message),"%s", command_str); // Get the base command type
354 
355     for (i = 0; i < numcommands; i++)
356     {
357         // Don't even try if they aren't the same length
358         if(strlen(command_str) != strlen(commandlist[i].command)) continue;
359         // See if it's in there
360         if(CON_CommandCmp(command_str, commandlist[i].command, strlen(command_str)))
361         {
362             if (commandlist[i].function)
363             {
364                 (*commandlist[i].function)();
365                 CON_AddHistory(MessageInputString); // Keep history only of valid input
366                 return;
367             }
368         }
369     }
370 
371     if(ConPanel)
372        CON_ConMessage("Syntax Error or Command not enabled!");
373 }
374 
375 //
376 // Initialize the console command list with the pre_command startup array
377 //
CON_InitConsole(void)378 void CON_InitConsole( void )
379 {
380 	CON_COMMANDp i;
381 
382     for (i = &pre_commands[0]; i->command != NULL; i++)
383     {
384         if(!CON_AddCommand(i->command, i->function))
385         {
386             printf("CON_InitConsole: Failed to add command contained in pre_commands list.\n");
387             TerminateGame();
388             exit(0);
389         }
390     }
391 
392     //printf("CON_InitConsole: Command list initialized.\n");
393 }
394 
395 //
396 // Process as a command, anything that could be set in the options menu as well
397 //
CON_ProcessOptions(void)398 void CON_ProcessOptions( void )
399     {
400 
401     }
402 
403 // Clear the console screen
CON_ClearConsole(void)404 void CON_ClearConsole( void )
405     {
406     short i;
407 
408     for(i=0; i<MAXCONQUOTES; i++)
409         strcpy(con_quote[i],"\0");
410     }
411 
412 /////////////////////////////////////////////////////////////////////////////////////////////
413 // The user console programming function library ////////////////////////////////////////////
414 /////////////////////////////////////////////////////////////////////////////////////////////
415 
CheckValidSprite(short SpriteNum)416 BOOL CheckValidSprite(short SpriteNum)
417     {
418     if(SpriteNum < 0 || SpriteNum > 6144)
419         {
420         CON_ConMessage("ERROR: Sprite %d is out of range.",SpriteNum);
421         return(FALSE);
422         }
423     return(TRUE);
424     }
425 
426 // Get help on a console command
CON_GetHelp(void)427 void CON_GetHelp( void )
428     {
429     char base[80], command[80];
430     short i;
431 
432 
433     if (sscanf(MessageInputString,"%s %s",base,command) < 2)
434         {
435         CON_ConMessage("Usage: help [keyword]");
436         return;
437         }
438 
439     Bstrlwr(command);    // Make sure operator is all lower case
440 
441     if(!strcmp(command, "xrepeat"))
442         {
443             CON_ConMessage("Usage: xrepeat [repeat value 0-255],");
444             CON_ConMessage("   [User ID (-1 for all ID's)], [SpriteNum (-1 for all of type ID)]");
445             return;
446         }else
447     if(!strcmp(command, "yrepeat"))
448         {
449             CON_ConMessage("Usage: yrepeat [repeat value 0-255],");
450             CON_ConMessage("   [User ID (-1 for all ID's)], [SpriteNum (-1 for all of type ID)]");
451             return;
452         }else
453     if(!strcmp(command, "translucent"))
454         {
455             CON_ConMessage("Usage: translucent [OFF/ON 0-1],");
456             CON_ConMessage("   [User ID (-1 for all ID's)], [SpriteNum (-1 for all of type ID)]");
457             return;
458         }else
459         {
460             CON_ConMessage("No help was located on that subject.");
461         }
462     }
463 
464 // Modify sprites xrepeat value
CON_ModXrepeat(void)465 void CON_ModXrepeat( void )
466     {
467     char base[80];
468     SHORT op1=64,op2=-1,op3=-1;
469     short i;
470 
471 
472     if (sscanf(MessageInputString,"%s %hd %hd %hd",base,&op1,&op2,&op3) < 4)
473         {
474         strcpy(MessageInputString,"help xrepeat");
475         CON_GetHelp();
476         return;
477         }
478 
479     if (op3 == -1)
480         {
481         for(i=0; i<MAXSPRITES; i++)
482             {
483             SPRITEp sp = &sprite[i];
484             USERp u = User[i];
485 
486             if(op2 == -1)
487                 sp->xrepeat = op1;
488             else
489                 {
490                 if(u->ID == op2)
491                     sp->xrepeat = op1;
492                 }
493             }
494         if(op2 == -1)
495             CON_ConMessage("Xrepeat set to %d for all u->ID's for all sprites.",op1);
496         else
497             CON_ConMessage("Xrepeat set to %d for u->ID = %d for all sprites.",op1,op2);
498         } else
499         {
500         // Do it only for one sprite
501         SPRITEp sp = &sprite[op3];
502         USERp u = User[op3];
503 
504         if(!CheckValidSprite(op3)) return;
505 
506         sp->xrepeat = op1;
507         CON_ConMessage("Xrepeat set to %d for sprite %d.",op1,op3);
508         }
509     }
510 
511 // Modify sprites yrepeat value
CON_ModYrepeat(void)512 void CON_ModYrepeat( void )
513     {
514     char base[80];
515     SHORT op1=64,op2=-1,op3=-1;
516     short i;
517 
518 
519     if (sscanf(MessageInputString,"%s %hd %hd %hd",base,&op1,&op2,&op3) < 4)
520         {
521         strcpy(MessageInputString,"help yrepeat");
522         CON_GetHelp();
523         return;
524         }
525 
526 
527     if (op3 == -1)
528         {
529         for(i=0; i<MAXSPRITES; i++)
530             {
531             SPRITEp sp = &sprite[i];
532             USERp u = User[i];
533 
534             if(op2 == -1)
535                 sp->yrepeat = op1;
536             else
537                 {
538                 if(u->ID == op2)
539                     sp->yrepeat = op1;
540                 }
541             }
542         if(op2 == -1)
543             CON_ConMessage("Yrepeat set to %d for all u->ID's for all sprites.",op1);
544         else
545             CON_ConMessage("Yrepeat set to %d for u->ID = %d for all sprites.",op1,op2);
546         } else
547         {
548         // Do it only for one sprite
549         SPRITEp sp = &sprite[op3];
550         USERp u = User[op3];
551 
552         if(!CheckValidSprite(op3)) return;
553 
554         sp->yrepeat = op1;
555         CON_ConMessage("Yrepeat set to %d for sprite %d.",op1,op3);
556         }
557     }
558 
CON_ModTranslucent(void)559 void CON_ModTranslucent( void )
560     {
561     char base[80];
562     SHORT op1=0;
563     SPRITEp sp;
564     USERp u;
565 
566     // Format: translucent [SpriteNum]
567     if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2)
568         {
569         strcpy(MessageInputString,"help translucent");
570         CON_GetHelp();
571         return;
572         }
573 
574     if(!CheckValidSprite(op1)) return;
575 
576     sp = &sprite[op1];
577     u = User[op1];
578 
579     if(TEST(sp->cstat,CSTAT_SPRITE_TRANSLUCENT))
580         {
581         RESET(sp->cstat,CSTAT_SPRITE_TRANSLUCENT);
582         CON_ConMessage("Translucence RESET for sprite %d.",op1);
583         } else
584         {
585         SET(sp->cstat,CSTAT_SPRITE_TRANSLUCENT);
586         CON_ConMessage("Translucence SET for sprite %d.",op1);
587         }
588     }
589 
CON_SoundTest(void)590 void CON_SoundTest( void )
591     {
592     int handle;
593     int zero=0;
594     char base[80];
595     SHORT op1=0;
596 
597     // Format: sound [number]
598     if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2)
599         {
600         strcpy(MessageInputString,"help sound");
601         CON_GetHelp();
602         return;
603         }
604 
605     if(op1 < 0 || op1 >= DIGI_MAX)
606         {
607         CON_ConMessage("Sound number out of range.");
608         return;
609         }
610 
611     handle = PlaySound(op1,&zero,&zero,&zero,v3df_none);
612     }
613 
614 
CON_Reverb(void)615 void CON_Reverb( void )
616     {
617     char base[80];
618     SHORT op1=0;
619     PLAYERp pp = Player + screenpeek;
620 
621     // Format: reverb [number]
622     if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2)
623         {
624         strcpy(MessageInputString,"help reverb");
625         CON_GetHelp();
626         return;
627         }
628 
629     CON_ConMessage("Reverb is now set to %d.",op1);
630     COVER_SetReverb(op1);
631     pp->Reverb = op1;
632     }
633 
CON_Heap(void)634 void CON_Heap( void )
635     {
636 	    /*
637     int totalmemory=0;
638     extern int TotalMemory, ActualHeap;
639     int i;
640     void *testheap;
641 
642     totalmemory = Z_AvailHeap();
643     CON_ConMessage("Total heap at game startup = %d", TotalMemory);
644     CON_ConMessage("ActualHeap reserved for non-cache use = %d", ActualHeap);
645     CON_ConMessage("Total unallocated blocks in bytes minus reserved heap = %d", totalmemory);
646     CON_ConMessage("NOTE: Allocation exceeding ActualHeap will result in out of memory");
647     // Find remaining heap space unused
648     i = ActualHeap;
649     while(i>0)
650         {
651         testheap = AllocMem(i);
652         if(!testheap)
653             i-=1024L; // Decrease in 1k increments
654         else
655             {
656             CON_ConMessage("Heap test result (+ or - 1k):");
657             CON_ConMessage("=============================");
658             CON_ConMessage("Unallocated heap space remaining  = %d",i);
659             CON_ConMessage("Unallocated heap space used  = %d",ActualHeap - i);
660             FreeMem(testheap);
661             i=0; // Beam us out of here Scotty!
662             }
663         }
664 
665     if(ActualHeap < 50000L)
666         {
667         CON_ConMessage("ALERT: Memory is critically low!");
668         }
669 	*/
670     }
671 
TileRangeMem(int start)672 int TileRangeMem(int start)
673     {
674     int i;
675     int total=0;
676 
677     switch(start)
678         {
679         case 4096: // Evil Ninja
680          for(i=4096; i<=4239; i++)
681              total += tilesizx[i]*tilesizy[i];
682         break;
683         case 800:  // Hornet
684          for(i=800; i<=811; i++)
685              total += tilesizx[i]*tilesizy[i];
686         break;
687         case 817:
688          for(i=817; i<=819; i++) // Bouncing Betty
689              total += tilesizx[i]*tilesizy[i];
690         break;
691         case 820: // Skull
692          for(i=820; i<=854; i++)
693              total += tilesizx[i]*tilesizy[i];
694         break;
695         case 960:
696          for(i=960; i<=1016; i++) // Serpent God
697              total += tilesizx[i]*tilesizy[i];
698          for(i=1300; i<=1314; i++)
699              total += tilesizx[i]*tilesizy[i];
700         break;
701         case 1024:
702          for(i=1024; i<=1175; i++) // LoWang
703              total += tilesizx[i]*tilesizy[i];
704         break;
705         case 1320:
706          for(i=1320; i<=1396; i++) // Skeletor Priest
707              total += tilesizx[i]*tilesizy[i];
708         break;
709         case 1400:
710          for(i=1400; i<=1440; i++) // Coolie
711              total += tilesizx[i]*tilesizy[i];
712          for(i=4260; i<=4266; i++)
713              total += tilesizx[i]*tilesizy[i];
714         break;
715         case 1441:
716          for(i=1441; i<=1450; i++) // Coolie Ghost
717              total += tilesizx[i]*tilesizy[i];
718          for(i=4267; i<=4312; i++)
719              total += tilesizx[i]*tilesizy[i];
720         break;
721         case 1469:
722          for(i=1469; i<=1497; i++) // Guardian
723              total += tilesizx[i]*tilesizy[i];
724          for(i=1504; i<=1518; i++)
725              total += tilesizx[i]*tilesizy[i];
726         break;
727         case 1580:
728          for(i=1580; i<=1644; i++) // Little Ripper
729              total += tilesizx[i]*tilesizy[i];
730         break;
731         case 4320:
732          for(i=4320; i<=4427; i++) // Big Ripper
733              total += tilesizx[i]*tilesizy[i];
734         break;
735         case 2540:
736          for(i=2540; i<=2546; i++) // Trashcan
737              total += tilesizx[i]*tilesizy[i];
738         break;
739         case 4430:
740          for(i=4430; i<=4479; i++) // Fish
741              total += tilesizx[i]*tilesizy[i];
742         break;
743         case 4490:
744          for(i=4490; i<=4544; i++) // Sumo
745              total += tilesizx[i]*tilesizy[i];
746         break;
747         case 5023:
748          for(i=5023; i<=5026; i++) // Toilet Girl
749              total += tilesizx[i]*tilesizy[i];
750         break;
751         case 5032:
752          for(i=5032; i<=5035; i++) // Wash Girl
753              total += tilesizx[i]*tilesizy[i];
754         break;
755         case 2000:
756          for(i=2000; i<=2002; i++) // Chop Stick Panel
757              total += tilesizx[i]*tilesizy[i];
758         break;
759         case 2004:
760          for(i=2004; i<=2009; i++) // Uzi Panel
761              total += tilesizx[i]*tilesizy[i];
762          for(i=2040; i<=2043; i++) // Uzi Overlays
763              total += tilesizx[i]*tilesizy[i];
764         break;
765         case 2010:
766          for(i=2010; i<=2019; i++) // Rail Panel
767              total += tilesizx[i]*tilesizy[i];
768         break;
769         case 2130:
770          for(i=2130; i<=2137; i++) // Shuriken Panel
771              total += tilesizx[i]*tilesizy[i];
772         break;
773         case 2050:
774          for(i=2050; i<=2053; i++) // Heart Panel
775              total += tilesizx[i]*tilesizy[i];
776         break;
777         case 2054:
778          for(i=2054; i<=2057; i++) // HotHead Panel
779              total += tilesizx[i]*tilesizy[i];
780         break;
781         case 2070:
782          for(i=2070; i<=2077; i++) // Rocket Launcher Panel
783              total += tilesizx[i]*tilesizy[i];
784         break;
785         case 2080:
786          for(i=2080; i<=2083; i++) // Sword Panel
787              total += tilesizx[i]*tilesizy[i];
788         break;
789         case 4090:
790          for(i=4090; i<=4093; i++) // Bloody Sword Panel
791              total += tilesizx[i]*tilesizy[i];
792         break;
793         case 2121:
794          for(i=2121; i<=2126; i++) // 40MM Panel
795              total += tilesizx[i]*tilesizy[i];
796         break;
797         case 2211:
798          for(i=2211; i<=2216; i++) // Shotgun Panel
799              total += tilesizx[i]*tilesizy[i];
800          for(i=2225; i<=2227; i++) // Shotgun Quad-Mode Panel
801              total += tilesizx[i]*tilesizy[i];
802         break;
803         case 2220:
804          for(i=2220; i<=2224; i++) // Sticky Bomb Panel
805              total += tilesizx[i]*tilesizy[i];
806         break;
807         }
808 
809     return(total);
810     }
811 
CON_Cache(void)812 void CON_Cache( void )
813     {
814     char incache[8192]; // 8192 so it can index maxwalls as well
815     int i,j,tottiles,totsprites,totactors;
816 
817 
818     memset(incache,0,8192);
819 
820     // Calculate all level tiles, non-actor stuff
821     for(i=0;i<numsectors;i++)
822         {
823         incache[sector[i].ceilingpicnum] = 1;
824         incache[sector[i].floorpicnum] = 1;
825         }
826 
827     for(i=0;i<numwalls;i++)
828         {
829         incache[wall[i].picnum] = 1;
830         if (wall[i].overpicnum >= 0)
831             incache[wall[i].overpicnum] = 1;
832         }
833 
834     tottiles = 0;
835     for(i=0;i<8192;i++)
836         if (incache[i] > 0)
837             tottiles += tilesizx[i]*tilesizy[i];
838 
839     //////////////////////////////////////////////
840 
841     memset(incache,0,8192);
842 
843     // Sprites on the stat list get counted as cached, others don't
844     for(i=0;i<MAXSPRITES;i++)
845         if (sprite[i].statnum < MAXSTATUS)
846             incache[sprite[i].picnum] = 1;
847 
848     totsprites = 0;
849     totactors = 0;
850 
851     for(i=0;i<MAXSPRITES;i++)
852         {
853         if (incache[i] > 0)
854             {
855             switch(i)
856                {
857                case 4096:
858                     totactors+=TileRangeMem(4096);
859                     incache[4096]=0;
860                break;
861                case 800:
862                     totactors+=TileRangeMem(800);
863                     incache[800]=0;
864                break;
865                case 817:
866                     totactors+=TileRangeMem(817);
867                     incache[817]=0;
868                break;
869                case 820:
870                     totactors+=TileRangeMem(820);
871                     incache[820]=0;
872                break;
873                case 960:
874                     totactors+=TileRangeMem(960);
875                     incache[960]=0;
876                break;
877                //case 1024:   // Lo Wang is calculated later
878                //     totactors+=TileRangeMem(1024);
879                //     incache[1024]=0;
880                //break;
881                case 1320:
882                     totactors+=TileRangeMem(1320);
883                     incache[1320]=0;
884                break;
885                case 1400:
886                     totactors+=TileRangeMem(1400);
887                     incache[1400]=0;
888                break;
889                case 1441:
890                     totactors+=TileRangeMem(1441);
891                     incache[1441]=0;
892                break;
893                case 1469:
894                     totactors+=TileRangeMem(1469);
895                     incache[1469]=0;
896                break;
897                case 1580:
898                     totactors+=TileRangeMem(1580);
899                     incache[1580]=0;
900                break;
901                case 4320:
902                     totactors+=TileRangeMem(4320);
903                     incache[4320]=0;
904                break;
905                case 2540:
906                     totactors+=TileRangeMem(2540);
907                     incache[2540]=0;
908                break;
909                case 4430:
910                     totactors+=TileRangeMem(4430);
911                     incache[4430]=0;
912                break;
913                case 4490:
914                     totactors+=TileRangeMem(4490);
915                     incache[4490]=0;
916                break;
917                case 5023:
918                     totactors+=TileRangeMem(5023);
919                     incache[5023]=0;
920                break;
921                case 5032:
922                     totactors+=TileRangeMem(5032);
923                     incache[5032]=0;
924                break;
925                case 2000:
926                     totactors+=TileRangeMem(2000);
927                     incache[2000]=0;
928                break;
929                case 2004:
930                     totactors+=TileRangeMem(2004);
931                     incache[2004]=0;
932                break;
933                case 2010:
934                     totactors+=TileRangeMem(2010);
935                     incache[2010]=0;
936                break;
937                case 2130:
938                     totactors+=TileRangeMem(2130);
939                     incache[2130]=0;
940                break;
941                case 2050:
942                     totactors+=TileRangeMem(2050);
943                     incache[2050]=0;
944                break;
945                case 2054:
946                     totactors+=TileRangeMem(2054);
947                     incache[2054]=0;
948                break;
949                case 2070:
950                     totactors+=TileRangeMem(2070);
951                     incache[2070]=0;
952                break;
953                case 2080:
954                     totactors+=TileRangeMem(2080);
955                     incache[2080]=0;
956                break;
957                case 4090:
958                     totactors+=TileRangeMem(4090);
959                     incache[4090]=0;
960                break;
961                case 2121:
962                     totactors+=TileRangeMem(2121);
963                     incache[2121]=0;
964                break;
965                case 2211:
966                     totactors+=TileRangeMem(2211);
967                     incache[2211]=0;
968                break;
969                case 2220:
970                     totactors+=TileRangeMem(2220);
971                     incache[2220]=0;
972                break;
973 
974                default: totsprites += tilesizx[i]*tilesizy[i];
975                }
976             }
977         }
978 
979     CON_ConMessage("/////////////////////////////////////////////");
980     CON_ConMessage("Current Memory Consumption:");
981     CON_ConMessage("Total Tiles        = %d",tottiles);
982     CON_ConMessage("Total Sprites      = %d",totsprites);
983     CON_ConMessage("Total Actors       = %d",totactors);
984     CON_ConMessage("Total Memory       = %d",(tottiles+totsprites+totactors));
985     CON_ConMessage("Total with LoWang  = %d",(tottiles+totsprites+totactors+TileRangeMem(1024)));
986     CON_ConMessage("/////////////////////////////////////////////");
987 
988     }
989 
CON_SpriteInfo(void)990 void CON_SpriteInfo( void )
991     {
992     SpriteInfo++;
993     if(SpriteInfo > 2) SpriteInfo = 0;
994 
995     if(SpriteInfo == 0)
996         CON_ConMessage("Sprite information is OFF.");
997     else
998     if(SpriteInfo == 1)
999         CON_ConMessage("Sprite information is ON (Brief Mode).");
1000     else
1001         CON_ConMessage("Sprite information is ON (Verbose Mode).");
1002     }
1003 
CON_KillSprite(void)1004 void CON_KillSprite( void )
1005     {
1006     char base[80];
1007     SHORT op1=0;
1008     SPRITEp sp;
1009     short i;
1010     USERp u;
1011 
1012     // Format: kill [SpriteNum]
1013     if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2)
1014         {
1015         strcpy(MessageInputString,"help kill");
1016         CON_GetHelp();
1017         return;
1018         }
1019 
1020     if(op1 == -1)
1021         {
1022         for(i=0; i<MAXSPRITES; i++)
1023             {
1024             u = User[i];
1025             if(!u->PlayerP)
1026                 SetSuicide(i);
1027             }
1028         CON_ConMessage("Killed all sprites except Players.");
1029         } else
1030         {
1031         if(!CheckValidSprite(op1)) return;
1032 
1033         SetSuicide(op1);
1034         CON_ConMessage("Killed sprite %d.",op1);
1035         }
1036 
1037     }
1038 
CON_SpriteDetail(void)1039 void CON_SpriteDetail( void )
1040     {
1041     char base[80];
1042     SHORT op1=0;
1043     SPRITEp sp;
1044     short i;
1045 
1046     // Format: showsprite [SpriteNum]
1047     if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2)
1048         {
1049         strcpy(MessageInputString,"help showsprite");
1050         CON_GetHelp();
1051         return;
1052         }
1053 
1054     if(!CheckValidSprite(op1)) return;
1055     sp = &sprite[op1];
1056 
1057     CON_ConMessage("x = %d, y = %d, z = %d",sp->x,sp->y,sp->z);
1058     CON_ConMessage("cstat = %d, picnum = %d",sp->cstat,sp->picnum);
1059     CON_ConMessage("shade = %d, pal = %d, clipdist = %d",sp->shade,sp->pal,sp->clipdist);
1060     CON_ConMessage("xrepeat = %d, yrepeat = %d",sp->xrepeat, sp->yrepeat);
1061     CON_ConMessage("xoffset = %d, yoffset = %d",sp->xoffset, sp->yoffset);
1062     CON_ConMessage("sectnum = %d, statnum = %d",sp->sectnum, sp->statnum);
1063     CON_ConMessage("ang = %d, owner = %d",sp->ang,sp->owner);
1064     CON_ConMessage("xvel = %d, yvel = %d, zvel = %d",sp->xvel,sp->yvel,sp->zvel);
1065     CON_ConMessage("lotag = %d, hitag = %d, extra = %d",sp->lotag,sp->hitag,sp->extra);
1066     }
1067 
CON_UserDetail(void)1068 void CON_UserDetail( void )
1069     {
1070     char base[80];
1071     SHORT op1=0;
1072     SPRITEp sp;
1073     short i;
1074     USERp u;
1075 
1076     // Format: showuser [SpriteNum]
1077     if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2)
1078         {
1079         strcpy(MessageInputString,"help showsprite");
1080         CON_GetHelp();
1081         return;
1082         }
1083 
1084     if(!CheckValidSprite(op1)) return;
1085     sp = &sprite[op1];
1086     u = User[op1];
1087 
1088     if(!u) return;
1089 
1090     CON_ConMessage("State = %p, Rot = %p",u->State,u->Rot);
1091     CON_ConMessage("StateStart = %p, StateEnd = %p",u->StateStart,u->StateEnd);
1092     CON_ConMessage("ActorActionFunc = %p",u->ActorActionFunc);
1093     CON_ConMessage("ActorActionSet = %p",u->ActorActionSet);
1094     CON_ConMessage("Personality = %p",u->Personality);
1095     CON_ConMessage("Attrib = %p",u->Attrib);
1096     CON_ConMessage("Flags = %d, Flags2 = %d, Tics = %d",u->Flags,u->Flags2,u->Tics);
1097     CON_ConMessage("RotNum = %d, ID = %d",u->RotNum,u->ID);
1098     CON_ConMessage("Health = %d, MaxHealth = %d",u->Health,u->MaxHealth);
1099     CON_ConMessage("LastDamage = %d, PainThreshold = %d",u->LastDamage,u->PainThreshold);
1100     CON_ConMessage("jump_speed = %d, jump_grav = %d",u->jump_speed,u->jump_grav);
1101     CON_ConMessage("xchange = %d, ychange = %d, zchange = %d",u->xchange,u->ychange,u->zchange);
1102     CON_ConMessage("ret = %d, WaitTics = %d, spal = %d",u->ret,u->WaitTics,u->spal);
1103     }
1104 
CON_Quit(void)1105 void CON_Quit( void )
1106     {
1107     if (CommPlayers >= 2)
1108         MultiPlayQuitFlag = TRUE;
1109     else
1110         QuitFlag = TRUE;
1111     }
1112 
CON_MultiNameChange(void)1113 void CON_MultiNameChange( void )
1114     {
1115     char base[16],command[16];
1116 
1117     // Format: swname [name]
1118     if (sscanf(MessageInputString,"%6s %12s",base,command) < 2)
1119         return;
1120 
1121     SendMulitNameChange(command, -1);
1122     }
1123 
CON_LoadSetup(void)1124 void CON_LoadSetup( void )
1125     {
1126 	    /*
1127     char base[80],command[80];
1128     extern char setupfilename[64];
1129 
1130     // Format: showuser [SpriteNum]
1131     if (sscanf(MessageInputString,"%s %s",base,command) < 2)
1132         {
1133         strcpy(MessageInputString,"help config");
1134         CON_GetHelp();
1135         return;
1136         }
1137 
1138     if (!SafeFileExists(command))
1139         {
1140         CON_ConMessage("CON_LoadSetup: %s does not exist.",command);
1141         return;
1142         } else
1143         {
1144         strcpy(setupfilename,command);
1145         }
1146     initkeys();
1147     CONFIG_ReadSetup();
1148     CONTROL_Startup( ControllerType, &GetTime, 120 );
1149     SetupGameButtons();
1150 
1151     if (CONTROL_JoystickEnabled)
1152        {
1153        CONTROL_CenterJoystick(CenterCenter, UpperLeft, LowerRight, CenterThrottle,
1154           CenterRudder);
1155        }
1156     CON_ConMessage("Loaded new config file.");
1157     */
1158 	    CON_ConMessage("JonoF: Maybe later");
1159     }
1160 
1161 char *damagename[] = {
1162     "WPN_STAR","WPN_UZI",
1163     "WPN_SHOTGUN","WPN_MICRO",
1164     "WPN_GRENADE","WPN_MINE",
1165     "WPN_RAIL","WPN_HEART",
1166     "WPN_HOTHEAD","WPN_NAPALM"
1167     "WPN_RING","WPN_ROCKET",
1168     "WPN_SWORD","WPN_FIST",
1169     "DMG_NAPALM","DMG_MIRV_METEOR",
1170     "DMG_SERP_METEOR","DMG_ELECTRO_SHARD",
1171     "DMG_SECTOR_EXP","DMG_BOLT_EXP",
1172     "DMG_TANK_SHELL_EXP","DMG_FIREBALL_EXP",
1173     "DMG_NAPALM_EXP","DMG_SKULL_EXP",
1174     "DMG_BASIC_EXP","DMG_GRENADE_EXP",
1175     "DMG_MINE_EXP","DMG_MINE_SHRAP",
1176     "DMG_MICRO_EXP","DMG_NUCLEAR_EXP",
1177     "DMG_RADIATION_CLOUD","DMG_FLASHBOMB",
1178     "DMG_FIREBALL_FLAMES","DMG_RIPPER_SLASH",
1179     "DMG_SKEL_SLASH","DMG_COOLG_BASH",
1180     "DMG_COOLG_FIRE","DMG_GORO_CHOP",
1181     "DMG_GORO_FIREBALL","DMG_SERP_SLASH",
1182     "DMG_LAVA_BOULDER","DMG_LAVA_SHARD",
1183     "DMG_HORNET_STING","DMG_EEL_ELECTRO",
1184     "DMG_SPEAR_TRAP","DMG_VOMIT",
1185     "DMG_BLADE"
1186     };
1187 
CON_DamageData(void)1188 void CON_DamageData( void )
1189     {
1190 
1191     char base[80],field[80];
1192     SHORT op1=0;
1193     unsigned int op2, i;
1194     SPRITEp sp;
1195     USERp u;
1196 
1197     // Format: damage [field] [item] [value]
1198     if (sscanf(MessageInputString,"%s %s %hd %u",base,field,&op1,&op2) < 3)
1199         {
1200         strcpy(MessageInputString,"help damage");
1201         CON_GetHelp();
1202         return;
1203         }
1204 
1205     if(op1 < -1 || op1 > 46)
1206         {
1207         CON_ConMessage("Damage Data index is out of range.");
1208         return;
1209         }
1210 
1211     if(!strcmp(field,"damage_lo"))
1212         {
1213         DamageData[op1].damage_lo = op2;
1214         CON_ConMessage("DamageData[%s].damage_lo = %d",damagename[op1],op2);
1215         } else
1216     if(!strcmp(field,"damage_hi"))
1217         {
1218         DamageData[op1].damage_hi = op2;
1219         CON_ConMessage("DamageData[%s].damage_hi = %d",damagename[op1],op2);
1220         } else
1221     if(!strcmp(field,"radius"))
1222         {
1223         DamageData[op1].radius = op2;
1224         CON_ConMessage("DamageData[%s].radius = %d",damagename[op1],op2);
1225         } else
1226     if(!strcmp(field,"max_ammo"))
1227         {
1228         DamageData[op1].max_ammo = op2;
1229         CON_ConMessage("DamageData[%s].max_ammo = %d",damagename[op1],op2);
1230         } else
1231     if(!strcmp(field,"min_ammo"))
1232         {
1233         DamageData[op1].min_ammo = op2;
1234         CON_ConMessage("DamageData[%s].min_ammo = %d",damagename[op1],op2);
1235         }
1236     if(!strcmp(field,"show"))
1237         {
1238         if(op1 == -1)
1239             {
1240             for(i=op2; i<=op2+10; i+=2)
1241                 {
1242                 if(i<47)
1243                     CON_ConMessage("[%d] = %s  [%d] = %s",i,damagename[i],i+1,damagename[i+1]);
1244                 }
1245             } else
1246             {
1247             CON_ConMessage(" ");
1248             CON_ConMessage("Item = %s:",damagename[op1]);
1249             CON_ConMessage("damage_lo = %d, damag_hi = %d",DamageData[op1].damage_lo,DamageData[op1].damage_hi);
1250             CON_ConMessage("radius = %u",DamageData[op1].radius);
1251             CON_ConMessage("min_ammo = %d, max_ammo = %d",DamageData[op1].min_ammo,DamageData[op1].max_ammo);
1252             CON_ConMessage(" ");
1253             }
1254         }
1255     }
1256 
CON_WinPachinko(void)1257 void CON_WinPachinko( void )
1258 	{
1259 	extern BOOL Pachinko_Win_Cheat;
1260 	PLAYERp pp = Player + myconnectindex;
1261     extern void CheckSndData( char *file, int line );
1262 
1263     if (CommEnabled)
1264         return;
1265 
1266 	Pachinko_Win_Cheat = !Pachinko_Win_Cheat;
1267 
1268     //CheckSndData( __FILE__, __LINE__ );
1269 
1270 	if(Pachinko_Win_Cheat)
1271 		PutStringInfo(pp,"Pachinko Win Cheat Enabled");
1272 	else
1273 		PutStringInfo(pp,"Pachinko Win Cheat Disabled");
1274 	}
1275 
CON_Tweak(void)1276 void CON_Tweak( void )
1277     {
1278     char base[80], command[80];
1279     int op1=0;
1280 
1281     // Format: tweak [weapon] [number]
1282     if (sscanf(MessageInputString,"%s %s %d",base,command,&op1) < 3)
1283         {
1284         strcpy(MessageInputString,"help tweak");
1285         CON_GetHelp();
1286         return;
1287         }
1288 
1289     Bstrlwr(command);    // Make sure operator is all lower case
1290     if(!strcmp(command,"adjust"))
1291         {
1292         extern short ADJUST;
1293         ADJUST = op1;
1294         CON_ConMessage("Zvelocity ADJUST set to %d.",op1);
1295         } else
1296     if(!strcmp(command,"adjustv"))
1297         {
1298         extern int ADJUSTV;
1299         ADJUSTV = op1;
1300         CON_ConMessage("Zvelocity ADJUSTV set to %d.",op1);
1301         }
1302     }
1303 
CON_Bunny(void)1304 void CON_Bunny( void )
1305     {
1306     PLAYERp pp = Player + myconnectindex;
1307 
1308     if (CommEnabled)
1309         return;
1310 
1311     pp->BunnyMode = !pp->BunnyMode;
1312     if(pp->BunnyMode)
1313         PutStringInfo(pp,"Bunny rockets enabled!");
1314     else
1315         PutStringInfo(pp,"Bunny rockets disabled!");
1316     }
1317 
CON_CheckHeap(void)1318 void CON_CheckHeap( void )
1319     {
1320 	    /*
1321     switch( _heapchk() )
1322         {
1323         case _HEAPOK:
1324           CON_ConMessage( "OK - heap is good\n" );
1325           break;
1326         case _HEAPEMPTY:
1327           CON_ConMessage( "OK - heap is empty\n" );
1328           break;
1329         case _HEAPBADBEGIN:
1330           CON_ConMessage( "ERROR - heap is damaged\n" );
1331           break;
1332         case _HEAPBADNODE:
1333           CON_ConMessage( "ERROR - bad node in heap\n" );
1334           break;
1335         }
1336 	*/
1337 	CON_ConMessage("JonoF: Not now");
1338     }
1339 
1340 /*
1341 void heap_dump( void )
1342   {
1343     struct _heapinfo h_info;
1344     int heap_status;
1345 
1346     h_info._pentry = NULL;
1347     for(;;) {
1348       heap_status = _heapwalk( &h_info );
1349       if( heap_status != _HEAPOK ) break;
1350       printf( "  %s block at %Fp of size %4.4X\n",
1351         (h_info._useflag == _USEDENTRY ? "USED" : "FREE"),
1352         h_info._pentry, h_info._size );
1353 
1354     }
1355 
1356     switch( heap_status ) {
1357     case _HEAPEND:
1358       printf( "OK - end of heap\n" );
1359       break;
1360     case _HEAPEMPTY:
1361       printf( "OK - heap is empty\n" );
1362       break;
1363     case _HEAPBADBEGIN:
1364       printf( "ERROR - heap is damaged\n" );
1365       break;
1366     case _HEAPBADPTR:
1367       printf( "ERROR - bad pointer to heap\n" );
1368       break;
1369     case _HEAPBADNODE:
1370 
1371       printf( "ERROR - bad node in heap\n" );
1372     }
1373   }
1374   */
1375 
CON_DumpHeap(void)1376 void CON_DumpHeap( void )
1377     {
1378     //heap_dump(); // Dump it.
1379     CON_ConMessage("JonoF: Not now");
1380     }
1381 
CON_ShowMirror(void)1382 void CON_ShowMirror( void )
1383     {
1384     char base[80];
1385     SHORT op1=0;
1386 
1387     // Format: showmirror [SpriteNum]
1388     if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2)
1389         {
1390         strcpy(MessageInputString,"help showmirror");
1391         CON_GetHelp();
1392         return;
1393         }
1394 
1395     if(op1 < 0 || op1 > 9)
1396         {
1397         CON_ConMessage("Mirror number is out of range!");
1398         return;
1399         }
1400 
1401     CON_ConMessage("camera is the ST1 sprite used as the view spot");
1402     CON_ConMessage("camspite is the SpriteNum of the drawtotile tile in editart");
1403     CON_ConMessage("camspic is the tile number of the drawtotile in editart");
1404     CON_ConMessage("iscamera is whether or not this mirror is a camera type");
1405     CON_ConMessage(" ");
1406     CON_ConMessage("mirror[%d].mirrorwall = %d",op1,mirror[op1].mirrorwall);
1407     CON_ConMessage("mirror[%d].mirrorsector = %d",op1,mirror[op1].mirrorsector);
1408     CON_ConMessage("mirror[%d].camera = %d",op1,mirror[op1].camera);
1409     CON_ConMessage("mirror[%d].camsprite = %d",op1,mirror[op1].camsprite);
1410     CON_ConMessage("mirror[%d].campic = %d",op1,mirror[op1].campic);
1411     CON_ConMessage("mirror[%d].iscamera = %d",op1,mirror[op1].ismagic);
1412     }
1413 
CON_DumpSoundList(void)1414 void CON_DumpSoundList( void )
1415     {
1416     extern void DumpSounds(void);
1417 
1418     DumpSounds();
1419     CON_Message("Sounds dumped to dbg.foo");
1420 
1421     }
1422 
1423