1 //
2 // Copyright(C) 1993-1996 Id Software, Inc.
3 // Copyright(C) 1993-2008 Raven Software
4 // Copyright(C) 2005-2014 Simon Howard
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 
17 
18 // HEADER FILES ------------------------------------------------------------
19 
20 #include "h2def.h"
21 #include "i_cdmus.h"
22 #include "i_video.h"
23 #include "m_bbox.h"
24 #include "m_cheat.h"
25 #include "m_misc.h"
26 #include "p_local.h"
27 #include "s_sound.h"
28 #include "v_video.h"
29 #include "i_swap.h"
30 
31 // TYPES -------------------------------------------------------------------
32 
33 typedef struct Cheat_s
34 {
35     void (*func) (player_t * player, struct Cheat_s * cheat);
36     cheatseq_t *seq;
37 } Cheat_t;
38 
39 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
40 
41 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
42 
43 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
44 
45 static void DrawSoundInfo(void);
46 static void DrINumber(signed int val, int x, int y);
47 static void DrRedINumber(signed int val, int x, int y);
48 static void DrBNumber(signed int val, int x, int y);
49 static void DrawCommonBar(void);
50 static void DrawMainBar(void);
51 static void DrawInventoryBar(void);
52 static void DrawKeyBar(void);
53 static void DrawWeaponPieces(void);
54 static void DrawFullScreenStuff(void);
55 static void DrawAnimatedIcons(void);
56 static boolean HandleCheats(byte key);
57 static boolean CheatAddKey(Cheat_t * cheat, byte key, boolean * eat);
58 static void CheatGodFunc(player_t * player, Cheat_t * cheat);
59 static void CheatNoClipFunc(player_t * player, Cheat_t * cheat);
60 static void CheatWeaponsFunc(player_t * player, Cheat_t * cheat);
61 static void CheatHealthFunc(player_t * player, Cheat_t * cheat);
62 static void CheatKeysFunc(player_t * player, Cheat_t * cheat);
63 static void CheatSoundFunc(player_t * player, Cheat_t * cheat);
64 static void CheatTickerFunc(player_t * player, Cheat_t * cheat);
65 static void CheatArtifactAllFunc(player_t * player, Cheat_t * cheat);
66 static void CheatPuzzleFunc(player_t * player, Cheat_t * cheat);
67 static void CheatWarpFunc(player_t * player, Cheat_t * cheat);
68 static void CheatPigFunc(player_t * player, Cheat_t * cheat);
69 static void CheatMassacreFunc(player_t * player, Cheat_t * cheat);
70 static void CheatIDKFAFunc(player_t * player, Cheat_t * cheat);
71 static void CheatQuickenFunc1(player_t * player, Cheat_t * cheat);
72 static void CheatQuickenFunc2(player_t * player, Cheat_t * cheat);
73 static void CheatQuickenFunc3(player_t * player, Cheat_t * cheat);
74 static void CheatClassFunc1(player_t * player, Cheat_t * cheat);
75 static void CheatClassFunc2(player_t * player, Cheat_t * cheat);
76 static void CheatInitFunc(player_t * player, Cheat_t * cheat);
77 static void CheatVersionFunc(player_t * player, Cheat_t * cheat);
78 static void CheatDebugFunc(player_t * player, Cheat_t * cheat);
79 static void CheatScriptFunc1(player_t * player, Cheat_t * cheat);
80 static void CheatScriptFunc2(player_t * player, Cheat_t * cheat);
81 static void CheatScriptFunc3(player_t * player, Cheat_t * cheat);
82 static void CheatRevealFunc(player_t * player, Cheat_t * cheat);
83 static void CheatTrackFunc1(player_t * player, Cheat_t * cheat);
84 static void CheatTrackFunc2(player_t * player, Cheat_t * cheat);
85 
86 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
87 
88 extern int ArmorIncrement[NUMCLASSES][NUMARMOR];
89 extern int AutoArmorSave[NUMCLASSES];
90 
91 // PUBLIC DATA DECLARATIONS ------------------------------------------------
92 
93 boolean DebugSound;             // Debug flag for displaying sound info
94 boolean inventory;
95 int curpos;
96 int inv_ptr;
97 int ArtifactFlash;
98 
99 // PRIVATE DATA DEFINITIONS ------------------------------------------------
100 
101 static int DisplayTicker = 0;
102 static int HealthMarker;
103 //static int ChainWiggle;
104 static player_t *CPlayer;
105 static int SpinFlylump;
106 static int SpinMinotaurLump;
107 static int SpinSpeedLump;
108 static int SpinDefenseLump;
109 
110 static int FontBNumBase;
111 static int PlayPalette;
112 
113 static patch_t *PatchH2BAR;
114 static patch_t *PatchH2TOP;
115 static patch_t *PatchLFEDGE;
116 static patch_t *PatchRTEDGE;
117 static patch_t *PatchARMCLEAR;
118 static patch_t *PatchARTICLEAR;
119 static patch_t *PatchMANACLEAR;
120 static patch_t *PatchKILLS;
121 static patch_t *PatchMANAVIAL1;
122 static patch_t *PatchMANAVIAL2;
123 static patch_t *PatchMANAVIALDIM1;
124 static patch_t *PatchMANAVIALDIM2;
125 static patch_t *PatchMANADIM1;
126 static patch_t *PatchMANADIM2;
127 static patch_t *PatchMANABRIGHT1;
128 static patch_t *PatchMANABRIGHT2;
129 static patch_t *PatchCHAIN;
130 static patch_t *PatchSTATBAR;
131 static patch_t *PatchKEYBAR;
132 static patch_t *PatchLIFEGEM;
133 static patch_t *PatchSELECTBOX;
134 static patch_t *PatchINumbers[10];
135 static patch_t *PatchNEGATIVE;
136 static patch_t *PatchSmNumbers[10];
137 static patch_t *PatchINVBAR;
138 static patch_t *PatchWEAPONSLOT;
139 static patch_t *PatchWEAPONFULL;
140 static patch_t *PatchPIECE1;
141 static patch_t *PatchPIECE2;
142 static patch_t *PatchPIECE3;
143 static patch_t *PatchINVLFGEM1;
144 static patch_t *PatchINVLFGEM2;
145 static patch_t *PatchINVRTGEM1;
146 static patch_t *PatchINVRTGEM2;
147 
148 // Toggle god mode
149 cheatseq_t CheatGodSeq = CHEAT("satan", 0);
150 
151 // Toggle no clipping mode
152 cheatseq_t CheatNoClipSeq = CHEAT("casper", 0);
153 
154 // Get all weapons and mana
155 cheatseq_t CheatWeaponsSeq = CHEAT("nra", 0);
156 
157 // Get full health
158 cheatseq_t CheatHealthSeq =  CHEAT("clubmed", 0);
159 
160 // Get all keys
161 cheatseq_t CheatKeysSeq = CHEAT("locksmith", 0);
162 
163 // Toggle sound debug info
164 cheatseq_t CheatSoundSeq = CHEAT("noise", 0);
165 
166 // Toggle ticker
167 cheatseq_t CheatTickerSeq = CHEAT("ticker", 0);
168 
169 // Get all artifacts
170 cheatseq_t CheatArtifactAllSeq = CHEAT("indiana", 0);
171 
172 // Get all puzzle pieces
173 cheatseq_t CheatPuzzleSeq = CHEAT("sherlock", 0);
174 
175 // Warp to new level
176 cheatseq_t CheatWarpSeq = CHEAT("visit", 2);
177 
178 // Become a pig
179 cheatseq_t CheatPigSeq = CHEAT("deliverance", 0);
180 
181 // Kill all monsters
182 cheatseq_t CheatMassacreSeq = CHEAT("butcher", 0);
183 
184 cheatseq_t CheatIDKFASeq = CHEAT("conan", 0);
185 
186 cheatseq_t CheatQuickenSeq1 = CHEAT("martek", 0);
187 
188 cheatseq_t CheatQuickenSeq2 = CHEAT("martekmartek", 0);
189 
190 cheatseq_t CheatQuickenSeq3 = CHEAT("martekmartekmartek", 0);
191 
192 // New class
193 cheatseq_t CheatClass1Seq = CHEAT("shadowcaster", 0);
194 
195 cheatseq_t CheatClass2Seq = CHEAT("shadowcaster", 1);
196 
197 cheatseq_t CheatInitSeq = CHEAT("init", 0);
198 
199 cheatseq_t CheatVersionSeq = CHEAT("mrjones", 0);
200 
201 cheatseq_t CheatDebugSeq = CHEAT("where", 0);
202 
203 cheatseq_t CheatScriptSeq1 = CHEAT("puke", 0);
204 
205 cheatseq_t CheatScriptSeq2 = CHEAT("puke", 1);
206 
207 cheatseq_t CheatScriptSeq3 = CHEAT("puke", 2);
208 
209 cheatseq_t CheatRevealSeq = CHEAT("mapsco", 0);
210 
211 cheatseq_t CheatTrackSeq1 = CHEAT("`", 0);
212 
213 cheatseq_t CheatTrackSeq2 = CHEAT("`", 2);
214 
215 static Cheat_t Cheats[] = {
216     {CheatTrackFunc1, &CheatTrackSeq1},
217     {CheatTrackFunc2, &CheatTrackSeq2},
218     {CheatGodFunc, &CheatGodSeq},
219     {CheatNoClipFunc, &CheatNoClipSeq},
220     {CheatWeaponsFunc, &CheatWeaponsSeq},
221     {CheatHealthFunc, &CheatHealthSeq},
222     {CheatKeysFunc, &CheatKeysSeq},
223     {CheatSoundFunc, &CheatSoundSeq},
224     {CheatTickerFunc, &CheatTickerSeq},
225     {CheatArtifactAllFunc, &CheatArtifactAllSeq},
226     {CheatPuzzleFunc, &CheatPuzzleSeq},
227     {CheatWarpFunc, &CheatWarpSeq},
228     {CheatPigFunc, &CheatPigSeq},
229     {CheatMassacreFunc, &CheatMassacreSeq},
230     {CheatIDKFAFunc, &CheatIDKFASeq},
231     {CheatQuickenFunc1, &CheatQuickenSeq1},
232     {CheatQuickenFunc2, &CheatQuickenSeq2},
233     {CheatQuickenFunc3, &CheatQuickenSeq3},
234     {CheatClassFunc1, &CheatClass1Seq},
235     {CheatClassFunc2, &CheatClass2Seq},
236     {CheatInitFunc, &CheatInitSeq},
237     {CheatVersionFunc, &CheatVersionSeq},
238     {CheatDebugFunc, &CheatDebugSeq},
239     {CheatScriptFunc1, &CheatScriptSeq1},
240     {CheatScriptFunc2, &CheatScriptSeq2},
241     {CheatScriptFunc3, &CheatScriptSeq3},
242     {CheatRevealFunc, &CheatRevealSeq},
243 };
244 
245 #define SET_CHEAT(cheat, seq) \
246     { memcpy(cheat.sequence, seq, sizeof(seq)); \
247       cheat.sequence_len = sizeof(seq) - 1; }
248 
249 // CODE --------------------------------------------------------------------
250 
251 //==========================================================================
252 //
253 // SB_Init
254 //
255 //==========================================================================
256 
SB_Init(void)257 void SB_Init(void)
258 {
259     int i;
260     int startLump;
261 
262     PatchH2BAR = W_CacheLumpName("H2BAR", PU_STATIC);
263     PatchH2TOP = W_CacheLumpName("H2TOP", PU_STATIC);
264     PatchINVBAR = W_CacheLumpName("INVBAR", PU_STATIC);
265     PatchLFEDGE = W_CacheLumpName("LFEDGE", PU_STATIC);
266     PatchRTEDGE = W_CacheLumpName("RTEDGE", PU_STATIC);
267     PatchSTATBAR = W_CacheLumpName("STATBAR", PU_STATIC);
268     PatchKEYBAR = W_CacheLumpName("KEYBAR", PU_STATIC);
269     PatchSELECTBOX = W_CacheLumpName("SELECTBOX", PU_STATIC);
270     PatchARTICLEAR = W_CacheLumpName("ARTICLS", PU_STATIC);
271     PatchARMCLEAR = W_CacheLumpName("ARMCLS", PU_STATIC);
272     PatchMANACLEAR = W_CacheLumpName("MANACLS", PU_STATIC);
273     PatchMANAVIAL1 = W_CacheLumpName("MANAVL1", PU_STATIC);
274     PatchMANAVIAL2 = W_CacheLumpName("MANAVL2", PU_STATIC);
275     PatchMANAVIALDIM1 = W_CacheLumpName("MANAVL1D", PU_STATIC);
276     PatchMANAVIALDIM2 = W_CacheLumpName("MANAVL2D", PU_STATIC);
277     PatchMANADIM1 = W_CacheLumpName("MANADIM1", PU_STATIC);
278     PatchMANADIM2 = W_CacheLumpName("MANADIM2", PU_STATIC);
279     PatchMANABRIGHT1 = W_CacheLumpName("MANABRT1", PU_STATIC);
280     PatchMANABRIGHT2 = W_CacheLumpName("MANABRT2", PU_STATIC);
281     PatchINVLFGEM1 = W_CacheLumpName("invgeml1", PU_STATIC);
282     PatchINVLFGEM2 = W_CacheLumpName("invgeml2", PU_STATIC);
283     PatchINVRTGEM1 = W_CacheLumpName("invgemr1", PU_STATIC);
284     PatchINVRTGEM2 = W_CacheLumpName("invgemr2", PU_STATIC);
285 
286 //      PatchCHAINBACK = W_CacheLumpName("CHAINBACK", PU_STATIC);
287     startLump = W_GetNumForName("IN0");
288     for (i = 0; i < 10; i++)
289     {
290         PatchINumbers[i] = W_CacheLumpNum(startLump + i, PU_STATIC);
291     }
292     PatchNEGATIVE = W_CacheLumpName("NEGNUM", PU_STATIC);
293     FontBNumBase = W_GetNumForName("FONTB16");
294     startLump = W_GetNumForName("SMALLIN0");
295     for (i = 0; i < 10; i++)
296     {
297         PatchSmNumbers[i] = W_CacheLumpNum(startLump + i, PU_STATIC);
298     }
299     PlayPalette = W_GetNumForName("PLAYPAL");
300     SpinFlylump = W_GetNumForName("SPFLY0");
301     SpinMinotaurLump = W_GetNumForName("SPMINO0");
302     SpinSpeedLump = W_GetNumForName("SPBOOT0");
303     SpinDefenseLump = W_GetNumForName("SPSHLD0");
304 
305     if (deathmatch)
306     {
307         PatchKILLS = W_CacheLumpName("KILLS", PU_STATIC);
308     }
309     SB_SetClassData();
310 
311     if (gamemode == shareware)
312     {
313 	SET_CHEAT(CheatGodSeq, "bgokey");
314 	SET_CHEAT(CheatNoClipSeq, "rjohnson");
315 	SET_CHEAT(CheatWeaponsSeq, "crhinehart");
316 	SET_CHEAT(CheatHealthSeq,"sgurno");
317 	SET_CHEAT(CheatKeysSeq, "mraymondjudy");
318 	SET_CHEAT(CheatSoundSeq, "kschilder");
319 	SET_CHEAT(CheatTickerSeq, "rrettenmund");
320 	SET_CHEAT(CheatArtifactAllSeq, "braffel");
321 	SET_CHEAT(CheatPuzzleSeq, "tmoore");
322 	SET_CHEAT(CheatWarpSeq, "bpelletier");
323 	SET_CHEAT(CheatPigSeq, "ebiessman");
324 	SET_CHEAT(CheatMassacreSeq, "cstika");
325 	SET_CHEAT(CheatIDKFASeq, "rambo");
326 	SET_CHEAT(CheatQuickenSeq1, "quicken");
327 	SET_CHEAT(CheatQuickenSeq2, "quickenquicken");
328 	SET_CHEAT(CheatQuickenSeq3, "quickenquickenquicken");
329 	SET_CHEAT(CheatClass1Seq, "plipo");
330 	SET_CHEAT(CheatClass2Seq, "plipo");
331 	SET_CHEAT(CheatVersionSeq, "pmacarther");
332 	SET_CHEAT(CheatDebugSeq, "jsumwalt");
333 	SET_CHEAT(CheatScriptSeq1, "mwagabaza");
334 	SET_CHEAT(CheatScriptSeq2, "mwagabaza");
335 	SET_CHEAT(CheatScriptSeq3, "mwagabaza");
336 	SET_CHEAT(CheatRevealSeq, "reveal");
337     }
338 }
339 
340 //==========================================================================
341 //
342 // SB_SetClassData
343 //
344 //==========================================================================
345 
SB_SetClassData(void)346 void SB_SetClassData(void)
347 {
348     int class;
349 
350     class = PlayerClass[consoleplayer]; // original player class (not pig)
351     PatchWEAPONSLOT = W_CacheLumpNum(W_GetNumForName("wpslot0")
352                                      + class, PU_STATIC);
353     PatchWEAPONFULL = W_CacheLumpNum(W_GetNumForName("wpfull0")
354                                      + class, PU_STATIC);
355     PatchPIECE1 = W_CacheLumpNum(W_GetNumForName("wpiecef1")
356                                  + class, PU_STATIC);
357     PatchPIECE2 = W_CacheLumpNum(W_GetNumForName("wpiecef2")
358                                  + class, PU_STATIC);
359     PatchPIECE3 = W_CacheLumpNum(W_GetNumForName("wpiecef3")
360                                  + class, PU_STATIC);
361     PatchCHAIN = W_CacheLumpNum(W_GetNumForName("chain") + class, PU_STATIC);
362     if (!netgame)
363     {                           // single player game uses red life gem (the second gem)
364         PatchLIFEGEM = W_CacheLumpNum(W_GetNumForName("lifegem")
365                                       + maxplayers * class + 1, PU_STATIC);
366     }
367     else
368     {
369         PatchLIFEGEM = W_CacheLumpNum(W_GetNumForName("lifegem")
370                                       + maxplayers * class + consoleplayer,
371                                       PU_STATIC);
372     }
373     SB_state = -1;
374     UpdateState |= I_FULLSCRN;
375 }
376 
377 //==========================================================================
378 //
379 // SB_Ticker
380 //
381 //==========================================================================
382 
SB_Ticker(void)383 void SB_Ticker(void)
384 {
385     int delta;
386     int curHealth;
387 
388     curHealth = players[consoleplayer].mo->health;
389     if (curHealth < 0)
390     {
391         curHealth = 0;
392     }
393     if (curHealth < HealthMarker)
394     {
395         delta = (HealthMarker - curHealth) >> 2;
396         if (delta < 1)
397         {
398             delta = 1;
399         }
400         else if (delta > 6)
401         {
402             delta = 6;
403         }
404         HealthMarker -= delta;
405     }
406     else if (curHealth > HealthMarker)
407     {
408         delta = (curHealth - HealthMarker) >> 2;
409         if (delta < 1)
410         {
411             delta = 1;
412         }
413         else if (delta > 6)
414         {
415             delta = 6;
416         }
417         HealthMarker += delta;
418     }
419 }
420 
421 //==========================================================================
422 //
423 // DrINumber
424 //
425 // Draws a three digit number.
426 //
427 //==========================================================================
428 
DrINumber(signed int val,int x,int y)429 static void DrINumber(signed int val, int x, int y)
430 {
431     patch_t *patch;
432     int oldval;
433 
434     oldval = val;
435     if (val < 0)
436     {
437         val = -val;
438         if (val > 99)
439         {
440             val = 99;
441         }
442         if (val > 9)
443         {
444             patch = PatchINumbers[val / 10];
445             V_DrawPatch(x + 8, y, patch);
446             V_DrawPatch(x, y, PatchNEGATIVE);
447         }
448         else
449         {
450             V_DrawPatch(x + 8, y, PatchNEGATIVE);
451         }
452         val = val % 10;
453         patch = PatchINumbers[val];
454         V_DrawPatch(x + 16, y, patch);
455         return;
456     }
457     if (val > 99)
458     {
459         patch = PatchINumbers[val / 100];
460         V_DrawPatch(x, y, patch);
461     }
462     val = val % 100;
463     if (val > 9 || oldval > 99)
464     {
465         patch = PatchINumbers[val / 10];
466         V_DrawPatch(x + 8, y, patch);
467     }
468     val = val % 10;
469     patch = PatchINumbers[val];
470     V_DrawPatch(x + 16, y, patch);
471 }
472 
473 //==========================================================================
474 //
475 // DrRedINumber
476 //
477 // Draws a three digit number using the red font
478 //
479 //==========================================================================
480 
DrRedINumber(signed int val,int x,int y)481 static void DrRedINumber(signed int val, int x, int y)
482 {
483     patch_t *patch;
484     int oldval;
485 
486     oldval = val;
487     if (val < 0)
488     {
489         val = 0;
490     }
491     if (val > 99)
492     {
493         patch =
494             W_CacheLumpNum(W_GetNumForName("inred0") + val / 100, PU_CACHE);
495         V_DrawPatch(x, y, patch);
496     }
497     val = val % 100;
498     if (val > 9 || oldval > 99)
499     {
500         patch =
501             W_CacheLumpNum(W_GetNumForName("inred0") + val / 10, PU_CACHE);
502         V_DrawPatch(x + 8, y, patch);
503     }
504     val = val % 10;
505     patch = W_CacheLumpNum(W_GetNumForName("inred0") + val, PU_CACHE);
506     V_DrawPatch(x + 16, y, patch);
507 }
508 
509 //==========================================================================
510 //
511 // DrBNumber
512 //
513 // Draws a three digit number using FontB
514 //
515 //==========================================================================
516 
DrBNumber(signed int val,int x,int y)517 static void DrBNumber(signed int val, int x, int y)
518 {
519     patch_t *patch;
520     int xpos;
521     int oldval;
522 
523     oldval = val;
524     xpos = x;
525     if (val < 0)
526     {
527         val = 0;
528     }
529     if (val > 99)
530     {
531         patch = W_CacheLumpNum(FontBNumBase + val / 100, PU_CACHE);
532         V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch);
533     }
534     val = val % 100;
535     xpos += 12;
536     if (val > 9 || oldval > 99)
537     {
538         patch = W_CacheLumpNum(FontBNumBase + val / 10, PU_CACHE);
539         V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch);
540     }
541     val = val % 10;
542     xpos += 12;
543     patch = W_CacheLumpNum(FontBNumBase + val, PU_CACHE);
544     V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch);
545 }
546 
547 //==========================================================================
548 //
549 // DrSmallNumber
550 //
551 // Draws a small two digit number.
552 //
553 //==========================================================================
554 
DrSmallNumber(int val,int x,int y)555 static void DrSmallNumber(int val, int x, int y)
556 {
557     patch_t *patch;
558 
559     if (val <= 0)
560     {
561         return;
562     }
563     if (val > 999)
564     {
565         val %= 1000;
566     }
567     if (val > 99)
568     {
569         patch = PatchSmNumbers[val / 100];
570         V_DrawPatch(x, y, patch);
571         patch = PatchSmNumbers[(val % 100) / 10];
572         V_DrawPatch(x + 4, y, patch);
573     }
574     else if (val > 9)
575     {
576         patch = PatchSmNumbers[val / 10];
577         V_DrawPatch(x + 4, y, patch);
578     }
579     val %= 10;
580     patch = PatchSmNumbers[val];
581     V_DrawPatch(x + 8, y, patch);
582 }
583 
584 /*
585 //==========================================================================
586 //
587 // ShadeLine
588 //
589 //==========================================================================
590 
591 static void ShadeLine(int x, int y, int height, int shade)
592 {
593 	byte *dest;
594 	byte *shades;
595 
596 	shades = colormaps+9*256+shade*2*256;
597 	dest = I_VideoBuffer+y*SCREENWIDTH+x;
598 	while(height--)
599 	{
600 		*(dest) = *(shades+*dest);
601 		dest += SCREENWIDTH;
602 	}
603 }
604 
605 //==========================================================================
606 //
607 // ShadeChain
608 //
609 //==========================================================================
610 
611 static void ShadeChain(void)
612 {
613 	int i;
614 
615 	for(i = 0; i < 16; i++)
616 	{
617 		ShadeLine(277+i, 190, 10, i/2);
618 		ShadeLine(19+i, 190, 10, 7-(i/2));
619 	}
620 }
621 */
622 
623 //==========================================================================
624 //
625 // DrawSoundInfo
626 //
627 // Displays sound debugging information.
628 //
629 //==========================================================================
630 
DrawSoundInfo(void)631 static void DrawSoundInfo(void)
632 {
633     int i;
634     SoundInfo_t s;
635     ChanInfo_t *c;
636     char text[32];
637     int x;
638     int y;
639     int xPos[7] = { 1, 75, 112, 156, 200, 230, 260 };
640 
641     if (leveltime & 16)
642     {
643         MN_DrTextA("*** SOUND DEBUG INFO ***", xPos[0], 20);
644     }
645     S_GetChannelInfo(&s);
646     if (s.channelCount == 0)
647     {
648         return;
649     }
650     x = 0;
651     MN_DrTextA("NAME", xPos[x++], 30);
652     MN_DrTextA("MO.T", xPos[x++], 30);
653     MN_DrTextA("MO.X", xPos[x++], 30);
654     MN_DrTextA("MO.Y", xPos[x++], 30);
655     MN_DrTextA("ID", xPos[x++], 30);
656     MN_DrTextA("PRI", xPos[x++], 30);
657     MN_DrTextA("DIST", xPos[x++], 30);
658     for (i = 0; i < s.channelCount; i++)
659     {
660         c = &s.chan[i];
661         x = 0;
662         y = 40 + i * 10;
663         if (c->mo == NULL)
664         {                       // Channel is unused
665             MN_DrTextA("------", xPos[0], y);
666             continue;
667         }
668         M_snprintf(text, sizeof(text), "%s", c->name);
669         M_ForceUppercase(text);
670         MN_DrTextA(text, xPos[x++], y);
671         M_snprintf(text, sizeof(text), "%d", c->mo->type);
672         MN_DrTextA(text, xPos[x++], y);
673         M_snprintf(text, sizeof(text), "%d", c->mo->x >> FRACBITS);
674         MN_DrTextA(text, xPos[x++], y);
675         M_snprintf(text, sizeof(text), "%d", c->mo->y >> FRACBITS);
676         MN_DrTextA(text, xPos[x++], y);
677         M_snprintf(text, sizeof(text), "%d", (int) c->id);
678         MN_DrTextA(text, xPos[x++], y);
679         M_snprintf(text, sizeof(text), "%d", c->priority);
680         MN_DrTextA(text, xPos[x++], y);
681         M_snprintf(text, sizeof(text), "%d", c->distance);
682         MN_DrTextA(text, xPos[x++], y);
683     }
684     UpdateState |= I_FULLSCRN;
685     BorderNeedRefresh = true;
686 }
687 
688 //==========================================================================
689 //
690 // SB_Drawer
691 //
692 //==========================================================================
693 
694 char patcharti[][10] = {
695     {"ARTIBOX"},                // none
696     {"ARTIINVU"},               // invulnerability
697     {"ARTIPTN2"},               // health
698     {"ARTISPHL"},               // superhealth
699     {"ARTIHRAD"},               // healing radius
700     {"ARTISUMN"},               // summon maulator
701     {"ARTITRCH"},               // torch
702     {"ARTIPORK"},               // egg
703     {"ARTISOAR"},               // fly
704     {"ARTIBLST"},               // blast radius
705     {"ARTIPSBG"},               // poison bag
706     {"ARTITELO"},               // teleport other
707     {"ARTISPED"},               // speed
708     {"ARTIBMAN"},               // boost mana
709     {"ARTIBRAC"},               // boost armor
710     {"ARTIATLP"},               // teleport
711     {"ARTISKLL"},               // arti_puzzskull
712     {"ARTIBGEM"},               // arti_puzzgembig
713     {"ARTIGEMR"},               // arti_puzzgemred
714     {"ARTIGEMG"},               // arti_puzzgemgreen1
715     {"ARTIGMG2"},               // arti_puzzgemgreen2
716     {"ARTIGEMB"},               // arti_puzzgemblue1
717     {"ARTIGMB2"},               // arti_puzzgemblue2
718     {"ARTIBOK1"},               // arti_puzzbook1
719     {"ARTIBOK2"},               // arti_puzzbook2
720     {"ARTISKL2"},               // arti_puzzskull2
721     {"ARTIFWEP"},               // arti_puzzfweapon
722     {"ARTICWEP"},               // arti_puzzcweapon
723     {"ARTIMWEP"},               // arti_puzzmweapon
724     {"ARTIGEAR"},               // arti_puzzgear1
725     {"ARTIGER2"},               // arti_puzzgear2
726     {"ARTIGER3"},               // arti_puzzgear3
727     {"ARTIGER4"},               // arti_puzzgear4
728 };
729 
730 int SB_state = -1;
731 static int oldarti = 0;
732 static int oldartiCount = 0;
733 static int oldfrags = -9999;
734 static int oldmana1 = -1;
735 static int oldmana2 = -1;
736 static int oldarmor = -1;
737 static int oldhealth = -1;
738 static int oldlife = -1;
739 static int oldpieces = -1;
740 static int oldweapon = -1;
741 static int oldkeys = -1;
742 
743 extern boolean automapactive;
744 
SB_Drawer(void)745 void SB_Drawer(void)
746 {
747     // Sound info debug stuff
748     if (DebugSound == true)
749     {
750         DrawSoundInfo();
751     }
752     CPlayer = &players[consoleplayer];
753     if (viewheight == SCREENHEIGHT && !automapactive)
754     {
755         DrawFullScreenStuff();
756         SB_state = -1;
757     }
758     else
759     {
760         if (SB_state == -1)
761         {
762             V_DrawPatch(0, 134, PatchH2BAR);
763             oldhealth = -1;
764         }
765         DrawCommonBar();
766         if (!inventory)
767         {
768             if (SB_state != 0)
769             {
770                 // Main interface
771                 if (!automapactive)
772                 {
773                     V_DrawPatch(38, 162, PatchSTATBAR);
774                 }
775                 else
776                 {
777                     V_DrawPatch(38, 162, PatchKEYBAR);
778                 }
779                 oldarti = 0;
780                 oldmana1 = -1;
781                 oldmana2 = -1;
782                 oldarmor = -1;
783                 oldpieces = -1;
784                 oldfrags = -9999;       //can't use -1, 'cuz of negative frags
785                 oldlife = -1;
786                 oldweapon = -1;
787                 oldkeys = -1;
788             }
789             if (!automapactive)
790             {
791                 DrawMainBar();
792             }
793             else
794             {
795                 DrawKeyBar();
796             }
797             SB_state = 0;
798         }
799         else
800         {
801             DrawInventoryBar();
802             SB_state = 1;
803         }
804     }
805     SB_PaletteFlash(false);
806     DrawAnimatedIcons();
807 }
808 
809 //==========================================================================
810 //
811 // DrawAnimatedIcons
812 //
813 //==========================================================================
814 
DrawAnimatedIcons(void)815 static void DrawAnimatedIcons(void)
816 {
817     int frame;
818     static boolean hitCenterFrame;
819 
820     // Wings of wrath
821     if (CPlayer->powers[pw_flight])
822     {
823         if (CPlayer->powers[pw_flight] > BLINKTHRESHOLD
824             || !(CPlayer->powers[pw_flight] & 16))
825         {
826             frame = (leveltime / 3) & 15;
827             if (CPlayer->mo->flags2 & MF2_FLY)
828             {
829                 if (hitCenterFrame && (frame != 15 && frame != 0))
830                 {
831                     V_DrawPatch(20, 19, W_CacheLumpNum(SpinFlylump + 15,
832                                                        PU_CACHE));
833                 }
834                 else
835                 {
836                     V_DrawPatch(20, 19, W_CacheLumpNum(SpinFlylump + frame,
837                                                        PU_CACHE));
838                     hitCenterFrame = false;
839                 }
840             }
841             else
842             {
843                 if (!hitCenterFrame && (frame != 15 && frame != 0))
844                 {
845                     V_DrawPatch(20, 19, W_CacheLumpNum(SpinFlylump + frame,
846                                                        PU_CACHE));
847                     hitCenterFrame = false;
848                 }
849                 else
850                 {
851                     V_DrawPatch(20, 19, W_CacheLumpNum(SpinFlylump + 15,
852                                                        PU_CACHE));
853                     hitCenterFrame = true;
854                 }
855             }
856         }
857         BorderTopRefresh = true;
858         UpdateState |= I_MESSAGES;
859     }
860 
861     // Speed Boots
862     if (CPlayer->powers[pw_speed])
863     {
864         if (CPlayer->powers[pw_speed] > BLINKTHRESHOLD
865             || !(CPlayer->powers[pw_speed] & 16))
866         {
867             frame = (leveltime / 3) & 15;
868             V_DrawPatch(60, 19, W_CacheLumpNum(SpinSpeedLump + frame,
869                                                PU_CACHE));
870         }
871         BorderTopRefresh = true;
872         UpdateState |= I_MESSAGES;
873     }
874 
875     // Defensive power
876     if (CPlayer->powers[pw_invulnerability])
877     {
878         if (CPlayer->powers[pw_invulnerability] > BLINKTHRESHOLD
879             || !(CPlayer->powers[pw_invulnerability] & 16))
880         {
881             frame = (leveltime / 3) & 15;
882             V_DrawPatch(260, 19, W_CacheLumpNum(SpinDefenseLump + frame,
883                                                 PU_CACHE));
884         }
885         BorderTopRefresh = true;
886         UpdateState |= I_MESSAGES;
887     }
888 
889     // Minotaur Active
890     if (CPlayer->powers[pw_minotaur])
891     {
892         if (CPlayer->powers[pw_minotaur] > BLINKTHRESHOLD
893             || !(CPlayer->powers[pw_minotaur] & 16))
894         {
895             frame = (leveltime / 3) & 15;
896             V_DrawPatch(300, 19, W_CacheLumpNum(SpinMinotaurLump + frame,
897                                                 PU_CACHE));
898         }
899         BorderTopRefresh = true;
900         UpdateState |= I_MESSAGES;
901     }
902 }
903 
904 //==========================================================================
905 //
906 // SB_PaletteFlash
907 //
908 // Sets the new palette based upon the current values of
909 // consoleplayer->damagecount and consoleplayer->bonuscount.
910 //
911 //==========================================================================
912 
SB_PaletteFlash(boolean forceChange)913 void SB_PaletteFlash(boolean forceChange)
914 {
915     static int sb_palette = 0;
916     int palette;
917     byte *pal;
918 
919     if (forceChange)
920     {
921         sb_palette = -1;
922     }
923     if (gamestate == GS_LEVEL)
924     {
925         CPlayer = &players[consoleplayer];
926         if (CPlayer->poisoncount)
927         {
928             palette = 0;
929             palette = (CPlayer->poisoncount + 7) >> 3;
930             if (palette >= NUMPOISONPALS)
931             {
932                 palette = NUMPOISONPALS - 1;
933             }
934             palette += STARTPOISONPALS;
935         }
936         else if (CPlayer->damagecount)
937         {
938             palette = (CPlayer->damagecount + 7) >> 3;
939             if (palette >= NUMREDPALS)
940             {
941                 palette = NUMREDPALS - 1;
942             }
943             palette += STARTREDPALS;
944         }
945         else if (CPlayer->bonuscount)
946         {
947             palette = (CPlayer->bonuscount + 7) >> 3;
948             if (palette >= NUMBONUSPALS)
949             {
950                 palette = NUMBONUSPALS - 1;
951             }
952             palette += STARTBONUSPALS;
953         }
954         else if (CPlayer->mo->flags2 & MF2_ICEDAMAGE)
955         {                       // Frozen player
956             palette = STARTICEPAL;
957         }
958         else
959         {
960             palette = 0;
961         }
962     }
963     else
964     {
965         palette = 0;
966     }
967     if (palette != sb_palette)
968     {
969         sb_palette = palette;
970         pal = (byte *) W_CacheLumpNum(PlayPalette, PU_CACHE) + palette * 768;
971         I_SetPalette(pal);
972     }
973 }
974 
975 //==========================================================================
976 //
977 // DrawCommonBar
978 //
979 //==========================================================================
980 
DrawCommonBar(void)981 void DrawCommonBar(void)
982 {
983     int healthPos;
984 
985     V_DrawPatch(0, 134, PatchH2TOP);
986 
987     if (oldhealth != HealthMarker)
988     {
989         oldhealth = HealthMarker;
990         healthPos = HealthMarker;
991         if (healthPos < 0)
992         {
993             healthPos = 0;
994         }
995         if (healthPos > 100)
996         {
997             healthPos = 100;
998         }
999         V_DrawPatch(28 + (((healthPos * 196) / 100) % 9), 193, PatchCHAIN);
1000         V_DrawPatch(7 + ((healthPos * 11) / 5), 193, PatchLIFEGEM);
1001         V_DrawPatch(0, 193, PatchLFEDGE);
1002         V_DrawPatch(277, 193, PatchRTEDGE);
1003 //              ShadeChain();
1004         UpdateState |= I_STATBAR;
1005     }
1006 }
1007 
1008 //==========================================================================
1009 //
1010 // DrawMainBar
1011 //
1012 //==========================================================================
1013 
DrawMainBar(void)1014 void DrawMainBar(void)
1015 {
1016     int i;
1017     int temp;
1018     patch_t *manaPatch1, *manaPatch2;
1019     patch_t *manaVialPatch1, *manaVialPatch2;
1020 
1021     manaPatch1 = NULL;
1022     manaPatch2 = NULL;
1023     manaVialPatch1 = NULL;
1024     manaVialPatch2 = NULL;
1025 
1026     // Ready artifact
1027     if (ArtifactFlash)
1028     {
1029         V_DrawPatch(144, 160, PatchARTICLEAR);
1030         V_DrawPatch(148, 164, W_CacheLumpNum(W_GetNumForName("useartia")
1031                                              + ArtifactFlash - 1, PU_CACHE));
1032         ArtifactFlash--;
1033         oldarti = -1;           // so that the correct artifact fills in after the flash
1034         UpdateState |= I_STATBAR;
1035     }
1036     else if (oldarti != CPlayer->readyArtifact
1037              || oldartiCount != CPlayer->inventory[inv_ptr].count)
1038     {
1039         V_DrawPatch(144, 160, PatchARTICLEAR);
1040         if (CPlayer->readyArtifact > 0)
1041         {
1042             V_DrawPatch(143, 163,
1043                         W_CacheLumpName(patcharti[CPlayer->readyArtifact],
1044                                         PU_CACHE));
1045             if (CPlayer->inventory[inv_ptr].count > 1)
1046             {
1047                 DrSmallNumber(CPlayer->inventory[inv_ptr].count, 162, 184);
1048             }
1049         }
1050         oldarti = CPlayer->readyArtifact;
1051         oldartiCount = CPlayer->inventory[inv_ptr].count;
1052         UpdateState |= I_STATBAR;
1053     }
1054 
1055     // Frags
1056     if (deathmatch)
1057     {
1058         temp = 0;
1059         for (i = 0; i < maxplayers; i++)
1060         {
1061             temp += CPlayer->frags[i];
1062         }
1063         if (temp != oldfrags)
1064         {
1065             V_DrawPatch(38, 162, PatchKILLS);
1066             DrINumber(temp, 40, 176);
1067             oldfrags = temp;
1068             UpdateState |= I_STATBAR;
1069         }
1070     }
1071     else
1072     {
1073         temp = HealthMarker;
1074         if (temp < 0)
1075         {
1076             temp = 0;
1077         }
1078         else if (temp > 100)
1079         {
1080             temp = 100;
1081         }
1082         if (oldlife != temp)
1083         {
1084             oldlife = temp;
1085             V_DrawPatch(41, 178, PatchARMCLEAR);
1086             if (temp >= 25)
1087             {
1088                 DrINumber(temp, 40, 176);
1089             }
1090             else
1091             {
1092                 DrRedINumber(temp, 40, 176);
1093             }
1094             UpdateState |= I_STATBAR;
1095         }
1096     }
1097     // Mana
1098     temp = CPlayer->mana[0];
1099     if (oldmana1 != temp)
1100     {
1101         V_DrawPatch(77, 178, PatchMANACLEAR);
1102         DrSmallNumber(temp, 79, 181);
1103         manaVialPatch1 = (patch_t *) 1; // force a vial update
1104         if (temp == 0)
1105         {                       // Draw Dim Mana icon
1106             manaPatch1 = PatchMANADIM1;
1107         }
1108         else if (oldmana1 == 0)
1109         {
1110             manaPatch1 = PatchMANABRIGHT1;
1111         }
1112         oldmana1 = temp;
1113         UpdateState |= I_STATBAR;
1114     }
1115     temp = CPlayer->mana[1];
1116     if (oldmana2 != temp)
1117     {
1118         V_DrawPatch(109, 178, PatchMANACLEAR);
1119         DrSmallNumber(temp, 111, 181);
1120         manaVialPatch1 = (patch_t *) 1; // force a vial update
1121         if (temp == 0)
1122         {                       // Draw Dim Mana icon
1123             manaPatch2 = PatchMANADIM2;
1124         }
1125         else if (oldmana2 == 0)
1126         {
1127             manaPatch2 = PatchMANABRIGHT2;
1128         }
1129         oldmana2 = temp;
1130         UpdateState |= I_STATBAR;
1131     }
1132     if (oldweapon != CPlayer->readyweapon || manaPatch1 || manaPatch2
1133         || manaVialPatch1)
1134     {                           // Update mana graphics based upon mana count/weapon type
1135         if (CPlayer->readyweapon == WP_FIRST)
1136         {
1137             manaPatch1 = PatchMANADIM1;
1138             manaPatch2 = PatchMANADIM2;
1139             manaVialPatch1 = PatchMANAVIALDIM1;
1140             manaVialPatch2 = PatchMANAVIALDIM2;
1141         }
1142         else if (CPlayer->readyweapon == WP_SECOND)
1143         {
1144             if (!manaPatch1)
1145             {
1146                 manaPatch1 = PatchMANABRIGHT1;
1147             }
1148             manaVialPatch1 = PatchMANAVIAL1;
1149             manaPatch2 = PatchMANADIM2;
1150             manaVialPatch2 = PatchMANAVIALDIM2;
1151         }
1152         else if (CPlayer->readyweapon == WP_THIRD)
1153         {
1154             manaPatch1 = PatchMANADIM1;
1155             manaVialPatch1 = PatchMANAVIALDIM1;
1156             if (!manaPatch2)
1157             {
1158                 manaPatch2 = PatchMANABRIGHT2;
1159             }
1160             manaVialPatch2 = PatchMANAVIAL2;
1161         }
1162         else
1163         {
1164             manaVialPatch1 = PatchMANAVIAL1;
1165             manaVialPatch2 = PatchMANAVIAL2;
1166             if (!manaPatch1)
1167             {
1168                 manaPatch1 = PatchMANABRIGHT1;
1169             }
1170             if (!manaPatch2)
1171             {
1172                 manaPatch2 = PatchMANABRIGHT2;
1173             }
1174         }
1175         V_DrawPatch(77, 164, manaPatch1);
1176         V_DrawPatch(110, 164, manaPatch2);
1177         V_DrawPatch(94, 164, manaVialPatch1);
1178         for (i = 165; i < 187 - (22 * CPlayer->mana[0]) / MAX_MANA; i++)
1179         {
1180             I_VideoBuffer[i * SCREENWIDTH + 95] = 0;
1181             I_VideoBuffer[i * SCREENWIDTH + 96] = 0;
1182             I_VideoBuffer[i * SCREENWIDTH + 97] = 0;
1183         }
1184         V_DrawPatch(102, 164, manaVialPatch2);
1185         for (i = 165; i < 187 - (22 * CPlayer->mana[1]) / MAX_MANA; i++)
1186         {
1187             I_VideoBuffer[i * SCREENWIDTH + 103] = 0;
1188             I_VideoBuffer[i * SCREENWIDTH + 104] = 0;
1189             I_VideoBuffer[i * SCREENWIDTH + 105] = 0;
1190         }
1191         oldweapon = CPlayer->readyweapon;
1192         UpdateState |= I_STATBAR;
1193     }
1194     // Armor
1195     temp = AutoArmorSave[CPlayer->class]
1196         + CPlayer->armorpoints[ARMOR_ARMOR] +
1197         CPlayer->armorpoints[ARMOR_SHIELD] +
1198         CPlayer->armorpoints[ARMOR_HELMET] +
1199         CPlayer->armorpoints[ARMOR_AMULET];
1200     if (oldarmor != temp)
1201     {
1202         oldarmor = temp;
1203         V_DrawPatch(255, 178, PatchARMCLEAR);
1204         DrINumber(FixedDiv(temp, 5 * FRACUNIT) >> FRACBITS, 250, 176);
1205         UpdateState |= I_STATBAR;
1206     }
1207     // Weapon Pieces
1208     if (oldpieces != CPlayer->pieces)
1209     {
1210         DrawWeaponPieces();
1211         oldpieces = CPlayer->pieces;
1212         UpdateState |= I_STATBAR;
1213     }
1214 }
1215 
1216 //==========================================================================
1217 //
1218 // DrawInventoryBar
1219 //
1220 //==========================================================================
1221 
DrawInventoryBar(void)1222 void DrawInventoryBar(void)
1223 {
1224     int i;
1225     int x;
1226 
1227     x = inv_ptr - curpos;
1228     UpdateState |= I_STATBAR;
1229     V_DrawPatch(38, 162, PatchINVBAR);
1230     for (i = 0; i < 7; i++)
1231     {
1232         //V_DrawPatch(50+i*31, 160, W_CacheLumpName("ARTIBOX", PU_CACHE));
1233         if (CPlayer->inventorySlotNum > x + i
1234             && CPlayer->inventory[x + i].type != arti_none)
1235         {
1236             V_DrawPatch(50 + i * 31, 163,
1237                         W_CacheLumpName(patcharti
1238                                         [CPlayer->inventory[x + i].type],
1239                                         PU_CACHE));
1240             if (CPlayer->inventory[x + i].count > 1)
1241             {
1242                 DrSmallNumber(CPlayer->inventory[x + i].count, 68 + i * 31,
1243                               185);
1244             }
1245         }
1246     }
1247     V_DrawPatch(50 + curpos * 31, 163, PatchSELECTBOX);
1248     if (x != 0)
1249     {
1250         V_DrawPatch(42, 163, !(leveltime & 4) ? PatchINVLFGEM1 :
1251                     PatchINVLFGEM2);
1252     }
1253     if (CPlayer->inventorySlotNum - x > 7)
1254     {
1255         V_DrawPatch(269, 163, !(leveltime & 4) ? PatchINVRTGEM1 :
1256                     PatchINVRTGEM2);
1257     }
1258 }
1259 
1260 //==========================================================================
1261 //
1262 // DrawKeyBar
1263 //
1264 //==========================================================================
1265 
DrawKeyBar(void)1266 void DrawKeyBar(void)
1267 {
1268     int i;
1269     int xPosition;
1270     int temp;
1271 
1272     if (oldkeys != CPlayer->keys)
1273     {
1274         xPosition = 46;
1275         for (i = 0; i < NUMKEYS && xPosition <= 126; i++)
1276         {
1277             if (CPlayer->keys & (1 << i))
1278             {
1279                 V_DrawPatch(xPosition, 164,
1280                             W_CacheLumpNum(W_GetNumForName("keyslot1") + i,
1281                                            PU_CACHE));
1282                 xPosition += 20;
1283             }
1284         }
1285         oldkeys = CPlayer->keys;
1286         UpdateState |= I_STATBAR;
1287     }
1288     temp = AutoArmorSave[CPlayer->class]
1289         + CPlayer->armorpoints[ARMOR_ARMOR] +
1290         CPlayer->armorpoints[ARMOR_SHIELD] +
1291         CPlayer->armorpoints[ARMOR_HELMET] +
1292         CPlayer->armorpoints[ARMOR_AMULET];
1293     if (oldarmor != temp)
1294     {
1295         for (i = 0; i < NUMARMOR; i++)
1296         {
1297             if (!CPlayer->armorpoints[i])
1298             {
1299                 continue;
1300             }
1301             if (CPlayer->armorpoints[i] <=
1302                 (ArmorIncrement[CPlayer->class][i] >> 2))
1303             {
1304                 V_DrawTLPatch(150 + 31 * i, 164,
1305                               W_CacheLumpNum(W_GetNumForName("armslot1") +
1306                                              i, PU_CACHE));
1307             }
1308             else if (CPlayer->armorpoints[i] <=
1309                      (ArmorIncrement[CPlayer->class][i] >> 1))
1310             {
1311                 V_DrawAltTLPatch(150 + 31 * i, 164,
1312                                  W_CacheLumpNum(W_GetNumForName("armslot1")
1313                                                 + i, PU_CACHE));
1314             }
1315             else
1316             {
1317                 V_DrawPatch(150 + 31 * i, 164,
1318                             W_CacheLumpNum(W_GetNumForName("armslot1") + i,
1319                                            PU_CACHE));
1320             }
1321         }
1322         oldarmor = temp;
1323         UpdateState |= I_STATBAR;
1324     }
1325 }
1326 
1327 //==========================================================================
1328 //
1329 // DrawWeaponPieces
1330 //
1331 //==========================================================================
1332 
1333 static int PieceX[NUMCLASSES][3] = {
1334     {190, 225, 234},
1335     {190, 212, 225},
1336     {190, 205, 224},
1337     {0, 0, 0}                   // Pig is never used
1338 };
1339 
DrawWeaponPieces(void)1340 static void DrawWeaponPieces(void)
1341 {
1342     if (CPlayer->pieces == 7)
1343     {
1344         V_DrawPatch(190, 162, PatchWEAPONFULL);
1345         return;
1346     }
1347     V_DrawPatch(190, 162, PatchWEAPONSLOT);
1348     if (CPlayer->pieces & WPIECE1)
1349     {
1350         V_DrawPatch(PieceX[PlayerClass[consoleplayer]][0], 162, PatchPIECE1);
1351     }
1352     if (CPlayer->pieces & WPIECE2)
1353     {
1354         V_DrawPatch(PieceX[PlayerClass[consoleplayer]][1], 162, PatchPIECE2);
1355     }
1356     if (CPlayer->pieces & WPIECE3)
1357     {
1358         V_DrawPatch(PieceX[PlayerClass[consoleplayer]][2], 162, PatchPIECE3);
1359     }
1360 }
1361 
1362 //==========================================================================
1363 //
1364 // DrawFullScreenStuff
1365 //
1366 //==========================================================================
1367 
DrawFullScreenStuff(void)1368 void DrawFullScreenStuff(void)
1369 {
1370     int i;
1371     int x;
1372     int temp;
1373 
1374     UpdateState |= I_FULLSCRN;
1375     if (CPlayer->mo->health > 0)
1376     {
1377         DrBNumber(CPlayer->mo->health, 5, 180);
1378     }
1379     else
1380     {
1381         DrBNumber(0, 5, 180);
1382     }
1383     if (deathmatch)
1384     {
1385         temp = 0;
1386         for (i = 0; i < maxplayers; i++)
1387         {
1388             if (playeringame[i])
1389             {
1390                 temp += CPlayer->frags[i];
1391             }
1392         }
1393         DrINumber(temp, 45, 185);
1394     }
1395     if (!inventory)
1396     {
1397         if (CPlayer->readyArtifact > 0)
1398         {
1399             V_DrawTLPatch(286, 170, W_CacheLumpName("ARTIBOX", PU_CACHE));
1400             V_DrawPatch(284, 169,
1401                         W_CacheLumpName(patcharti[CPlayer->readyArtifact],
1402                                         PU_CACHE));
1403             if (CPlayer->inventory[inv_ptr].count > 1)
1404             {
1405                 DrSmallNumber(CPlayer->inventory[inv_ptr].count, 302, 192);
1406             }
1407         }
1408     }
1409     else
1410     {
1411         x = inv_ptr - curpos;
1412         for (i = 0; i < 7; i++)
1413         {
1414             V_DrawTLPatch(50 + i * 31, 168, W_CacheLumpName("ARTIBOX",
1415                                                             PU_CACHE));
1416             if (CPlayer->inventorySlotNum > x + i
1417                 && CPlayer->inventory[x + i].type != arti_none)
1418             {
1419                 V_DrawPatch(49 + i * 31, 167,
1420                             W_CacheLumpName(patcharti
1421                                             [CPlayer->inventory[x + i].type],
1422                                             PU_CACHE));
1423                 if (CPlayer->inventory[x + i].count > 1)
1424                 {
1425                     DrSmallNumber(CPlayer->inventory[x + i].count,
1426                                   66 + i * 31, 188);
1427                 }
1428             }
1429         }
1430         V_DrawPatch(50 + curpos * 31, 167, PatchSELECTBOX);
1431         if (x != 0)
1432         {
1433             V_DrawPatch(40, 167, !(leveltime & 4) ? PatchINVLFGEM1 :
1434                         PatchINVLFGEM2);
1435         }
1436         if (CPlayer->inventorySlotNum - x > 7)
1437         {
1438             V_DrawPatch(268, 167, !(leveltime & 4) ?
1439                         PatchINVRTGEM1 : PatchINVRTGEM2);
1440         }
1441     }
1442 }
1443 
1444 
1445 //==========================================================================
1446 //
1447 // Draw_TeleportIcon
1448 //
1449 //==========================================================================
Draw_TeleportIcon(void)1450 void Draw_TeleportIcon(void)
1451 {
1452     patch_t *patch;
1453     patch = W_CacheLumpNum(W_GetNumForName("teleicon"), PU_CACHE);
1454     V_DrawPatch(100, 68, patch);
1455     UpdateState |= I_FULLSCRN;
1456     I_FinishUpdate();
1457     UpdateState |= I_FULLSCRN;
1458 }
1459 
1460 //==========================================================================
1461 //
1462 // Draw_SaveIcon
1463 //
1464 //==========================================================================
Draw_SaveIcon(void)1465 void Draw_SaveIcon(void)
1466 {
1467     patch_t *patch;
1468     patch = W_CacheLumpNum(W_GetNumForName("saveicon"), PU_CACHE);
1469     V_DrawPatch(100, 68, patch);
1470     UpdateState |= I_FULLSCRN;
1471     I_FinishUpdate();
1472     UpdateState |= I_FULLSCRN;
1473 }
1474 
1475 //==========================================================================
1476 //
1477 // Draw_LoadIcon
1478 //
1479 //==========================================================================
Draw_LoadIcon(void)1480 void Draw_LoadIcon(void)
1481 {
1482     patch_t *patch;
1483     patch = W_CacheLumpNum(W_GetNumForName("loadicon"), PU_CACHE);
1484     V_DrawPatch(100, 68, patch);
1485     UpdateState |= I_FULLSCRN;
1486     I_FinishUpdate();
1487     UpdateState |= I_FULLSCRN;
1488 }
1489 
1490 
1491 
1492 //==========================================================================
1493 //
1494 // SB_Responder
1495 //
1496 //==========================================================================
1497 
SB_Responder(event_t * event)1498 boolean SB_Responder(event_t * event)
1499 {
1500     if (event->type == ev_keydown)
1501     {
1502         if (HandleCheats(event->data1))
1503         {                       // Need to eat the key
1504             return (true);
1505         }
1506     }
1507     return (false);
1508 }
1509 
1510 //==========================================================================
1511 //
1512 // HandleCheats
1513 //
1514 // Returns true if the caller should eat the key.
1515 //
1516 //==========================================================================
1517 
HandleCheats(byte key)1518 static boolean HandleCheats(byte key)
1519 {
1520     int i;
1521     boolean eat;
1522 
1523     if (gameskill == sk_nightmare)
1524     {                           // Can't cheat in nightmare mode
1525         return (false);
1526     }
1527     else if (netgame)
1528     {                           // change CD track is the only cheat available in deathmatch
1529         eat = false;
1530         if (cdmusic)
1531         {
1532             if (CheatAddKey(&Cheats[0], key, &eat))
1533             {
1534                 Cheats[0].func(&players[consoleplayer], &Cheats[0]);
1535                 S_StartSound(NULL, SFX_PLATFORM_STOP);
1536             }
1537             if (CheatAddKey(&Cheats[1], key, &eat))
1538             {
1539                 Cheats[1].func(&players[consoleplayer], &Cheats[1]);
1540                 S_StartSound(NULL, SFX_PLATFORM_STOP);
1541             }
1542         }
1543         return eat;
1544     }
1545     if (players[consoleplayer].health <= 0)
1546     {                           // Dead players can't cheat
1547         return (false);
1548     }
1549     eat = false;
1550     for (i = 0; i<arrlen(Cheats); ++i)
1551     {
1552         if (CheatAddKey(&Cheats[i], key, &eat))
1553         {
1554             Cheats[i].func(&players[consoleplayer], &Cheats[i]);
1555             S_StartSound(NULL, SFX_PLATFORM_STOP);
1556         }
1557     }
1558     return (eat);
1559 }
1560 
1561 //==========================================================================
1562 //
1563 // CheatAddkey
1564 //
1565 // Returns true if the added key completed the cheat, false otherwise.
1566 //
1567 //==========================================================================
1568 
CheatAddKey(Cheat_t * cheat,byte key,boolean * eat)1569 static boolean CheatAddKey(Cheat_t * cheat, byte key, boolean * eat)
1570 {
1571 /*
1572     if (!cheat->pos)
1573     {
1574         cheat->pos = cheat->sequence;
1575         cheat->currentArg = 0;
1576     }
1577     if (*cheat->pos == 0)
1578     {
1579         *eat = true;
1580         cheat->args[cheat->currentArg++] = key;
1581         cheat->pos++;
1582     }
1583     else if (CheatLookup[key] == *cheat->pos)
1584     {
1585         cheat->pos++;
1586     }
1587     else
1588     {
1589         cheat->pos = cheat->sequence;
1590         cheat->currentArg = 0;
1591     }
1592     if (*cheat->pos == 0xff)
1593     {
1594         cheat->pos = cheat->sequence;
1595         cheat->currentArg = 0;
1596         return (true);
1597     }
1598     return (false);
1599     */
1600 
1601     *eat = cht_CheckCheat(cheat->seq, key);
1602 
1603     return *eat;
1604 }
1605 
1606 //==========================================================================
1607 //
1608 // CHEAT FUNCTIONS
1609 //
1610 //==========================================================================
1611 
CheatGodFunc(player_t * player,Cheat_t * cheat)1612 static void CheatGodFunc(player_t * player, Cheat_t * cheat)
1613 {
1614     player->cheats ^= CF_GODMODE;
1615     if (player->cheats & CF_GODMODE)
1616     {
1617         P_SetMessage(player, TXT_CHEATGODON, true);
1618     }
1619     else
1620     {
1621         P_SetMessage(player, TXT_CHEATGODOFF, true);
1622     }
1623     SB_state = -1;
1624 }
1625 
CheatNoClipFunc(player_t * player,Cheat_t * cheat)1626 static void CheatNoClipFunc(player_t * player, Cheat_t * cheat)
1627 {
1628     player->cheats ^= CF_NOCLIP;
1629     if (player->cheats & CF_NOCLIP)
1630     {
1631         P_SetMessage(player, TXT_CHEATNOCLIPON, true);
1632     }
1633     else
1634     {
1635         P_SetMessage(player, TXT_CHEATNOCLIPOFF, true);
1636     }
1637 }
1638 
CheatWeaponsFunc(player_t * player,Cheat_t * cheat)1639 static void CheatWeaponsFunc(player_t * player, Cheat_t * cheat)
1640 {
1641     int i;
1642     //extern boolean *WeaponInShareware;
1643 
1644     for (i = 0; i < NUMARMOR; i++)
1645     {
1646         player->armorpoints[i] = ArmorIncrement[player->class][i];
1647     }
1648     for (i = 0; i < NUMWEAPONS; i++)
1649     {
1650         player->weaponowned[i] = true;
1651     }
1652     for (i = 0; i < NUMMANA; i++)
1653     {
1654         player->mana[i] = MAX_MANA;
1655     }
1656     P_SetMessage(player, TXT_CHEATWEAPONS, true);
1657 }
1658 
CheatHealthFunc(player_t * player,Cheat_t * cheat)1659 static void CheatHealthFunc(player_t * player, Cheat_t * cheat)
1660 {
1661     if (player->morphTics)
1662     {
1663         player->health = player->mo->health = MAXMORPHHEALTH;
1664     }
1665     else
1666     {
1667         player->health = player->mo->health = MAXHEALTH;
1668     }
1669     P_SetMessage(player, TXT_CHEATHEALTH, true);
1670 }
1671 
CheatKeysFunc(player_t * player,Cheat_t * cheat)1672 static void CheatKeysFunc(player_t * player, Cheat_t * cheat)
1673 {
1674     player->keys = 2047;
1675     P_SetMessage(player, TXT_CHEATKEYS, true);
1676 }
1677 
CheatSoundFunc(player_t * player,Cheat_t * cheat)1678 static void CheatSoundFunc(player_t * player, Cheat_t * cheat)
1679 {
1680     DebugSound = !DebugSound;
1681     if (DebugSound)
1682     {
1683         P_SetMessage(player, TXT_CHEATSOUNDON, true);
1684     }
1685     else
1686     {
1687         P_SetMessage(player, TXT_CHEATSOUNDOFF, true);
1688     }
1689 }
1690 
CheatTickerFunc(player_t * player,Cheat_t * cheat)1691 static void CheatTickerFunc(player_t * player, Cheat_t * cheat)
1692 {
1693     DisplayTicker = !DisplayTicker;
1694     if (DisplayTicker)
1695     {
1696         P_SetMessage(player, TXT_CHEATTICKERON, true);
1697     }
1698     else
1699     {
1700         P_SetMessage(player, TXT_CHEATTICKEROFF, true);
1701     }
1702 
1703     I_DisplayFPSDots(DisplayTicker);
1704 }
1705 
CheatArtifactAllFunc(player_t * player,Cheat_t * cheat)1706 static void CheatArtifactAllFunc(player_t * player, Cheat_t * cheat)
1707 {
1708     int i;
1709     int j;
1710 
1711     for (i = arti_none + 1; i < arti_firstpuzzitem; i++)
1712     {
1713         for (j = 0; j < 25; j++)
1714         {
1715             P_GiveArtifact(player, i, NULL);
1716         }
1717     }
1718     P_SetMessage(player, TXT_CHEATARTIFACTS3, true);
1719 }
1720 
CheatPuzzleFunc(player_t * player,Cheat_t * cheat)1721 static void CheatPuzzleFunc(player_t * player, Cheat_t * cheat)
1722 {
1723     int i;
1724 
1725     for (i = arti_firstpuzzitem; i < NUMARTIFACTS; i++)
1726     {
1727         P_GiveArtifact(player, i, NULL);
1728     }
1729     P_SetMessage(player, TXT_CHEATARTIFACTS3, true);
1730 }
1731 
CheatInitFunc(player_t * player,Cheat_t * cheat)1732 static void CheatInitFunc(player_t * player, Cheat_t * cheat)
1733 {
1734     G_DeferedInitNew(gameskill, gameepisode, gamemap);
1735     P_SetMessage(player, TXT_CHEATWARP, true);
1736 }
1737 
CheatWarpFunc(player_t * player,Cheat_t * cheat)1738 static void CheatWarpFunc(player_t * player, Cheat_t * cheat)
1739 {
1740     int tens;
1741     int ones;
1742     int map;
1743     char mapName[9];
1744     char args[2];
1745 
1746     cht_GetParam(cheat->seq, args);
1747 
1748     tens = args[0] - '0';
1749     ones = args[1] - '0';
1750     if (tens < 0 || tens > 9 || ones < 0 || ones > 9)
1751     {                           // Bad map
1752         P_SetMessage(player, TXT_CHEATBADINPUT, true);
1753         return;
1754     }
1755     map = P_TranslateMap((args[0] - '0') * 10 + args[1] - '0');
1756     if (map == -1)
1757     {                           // Not found
1758         P_SetMessage(player, TXT_CHEATNOMAP, true);
1759         return;
1760     }
1761     if (map == gamemap)
1762     {                           // Don't try to teleport to current map
1763         P_SetMessage(player, TXT_CHEATBADINPUT, true);
1764         return;
1765     }
1766     M_snprintf(mapName, sizeof(mapName), "MAP%02d", map);
1767     if (W_CheckNumForName(mapName) == -1)
1768     {                       // Can't find
1769         P_SetMessage(player, TXT_CHEATNOMAP, true);
1770         return;
1771     }
1772     P_SetMessage(player, TXT_CHEATWARP, true);
1773     G_TeleportNewMap(map, 0);
1774 }
1775 
CheatPigFunc(player_t * player,Cheat_t * cheat)1776 static void CheatPigFunc(player_t * player, Cheat_t * cheat)
1777 {
1778     extern boolean P_UndoPlayerMorph(player_t * player);
1779 
1780     if (player->morphTics)
1781     {
1782         P_UndoPlayerMorph(player);
1783     }
1784     else
1785     {
1786         P_MorphPlayer(player);
1787     }
1788     P_SetMessage(player, "SQUEAL!!", true);
1789 }
1790 
CheatMassacreFunc(player_t * player,Cheat_t * cheat)1791 static void CheatMassacreFunc(player_t * player, Cheat_t * cheat)
1792 {
1793     int count;
1794     char buffer[80];
1795 
1796     count = P_Massacre();
1797     M_snprintf(buffer, sizeof(buffer), "%d MONSTERS KILLED\n", count);
1798     P_SetMessage(player, buffer, true);
1799 }
1800 
CheatIDKFAFunc(player_t * player,Cheat_t * cheat)1801 static void CheatIDKFAFunc(player_t * player, Cheat_t * cheat)
1802 {
1803     int i;
1804     if (player->morphTics)
1805     {
1806         return;
1807     }
1808     for (i = 1; i < NUMWEAPONS; i++)
1809     {
1810         player->weaponowned[i] = false;
1811     }
1812 
1813     // In the original code, NUMWEAPONS was 8. So the writes to weaponowned
1814     // overflowed the array. We must set the following fields to zero as
1815     // well:
1816 
1817     player->mana[0] = 0;
1818     player->mana[1] = 0;
1819     player->attackdown = 0;
1820     player->usedown = 0;
1821 
1822     player->pendingweapon = WP_FIRST;
1823     P_SetMessage(player, TXT_CHEATIDKFA, true);
1824 }
1825 
CheatQuickenFunc1(player_t * player,Cheat_t * cheat)1826 static void CheatQuickenFunc1(player_t * player, Cheat_t * cheat)
1827 {
1828     P_SetMessage(player, "TRYING TO CHEAT?  THAT'S ONE....", true);
1829 }
1830 
CheatQuickenFunc2(player_t * player,Cheat_t * cheat)1831 static void CheatQuickenFunc2(player_t * player, Cheat_t * cheat)
1832 {
1833     P_SetMessage(player, "THAT'S TWO....", true);
1834 }
1835 
CheatQuickenFunc3(player_t * player,Cheat_t * cheat)1836 static void CheatQuickenFunc3(player_t * player, Cheat_t * cheat)
1837 {
1838     P_DamageMobj(player->mo, NULL, player->mo, 10000);
1839     P_SetMessage(player, "THAT'S THREE!  TIME TO DIE.", true);
1840 }
1841 
CheatClassFunc1(player_t * player,Cheat_t * cheat)1842 static void CheatClassFunc1(player_t * player, Cheat_t * cheat)
1843 {
1844     P_SetMessage(player, "ENTER NEW PLAYER CLASS (0 - 2)", true);
1845 }
1846 
CheatClassFunc2(player_t * player,Cheat_t * cheat)1847 static void CheatClassFunc2(player_t * player, Cheat_t * cheat)
1848 {
1849     int i;
1850     int class;
1851     char args[2];
1852 
1853     cht_GetParam(cheat->seq, args);
1854 
1855     if (player->morphTics)
1856     {                           // don't change class if the player is morphed
1857         return;
1858     }
1859     class = args[0] - '0';
1860     if (class > 2 || class < 0)
1861     {
1862         P_SetMessage(player, "INVALID PLAYER CLASS", true);
1863         return;
1864     }
1865     player->class = class;
1866     for (i = 0; i < NUMARMOR; i++)
1867     {
1868         player->armorpoints[i] = 0;
1869     }
1870     PlayerClass[consoleplayer] = class;
1871     P_PostMorphWeapon(player, WP_FIRST);
1872     SB_SetClassData();
1873     SB_state = -1;
1874     UpdateState |= I_FULLSCRN;
1875 }
1876 
CheatVersionFunc(player_t * player,Cheat_t * cheat)1877 static void CheatVersionFunc(player_t * player, Cheat_t * cheat)
1878 {
1879     P_SetMessage(player, HEXEN_VERSIONTEXT, true);
1880 }
1881 
CheatDebugFunc(player_t * player,Cheat_t * cheat)1882 static void CheatDebugFunc(player_t * player, Cheat_t * cheat)
1883 {
1884     char textBuffer[50];
1885     M_snprintf(textBuffer, sizeof(textBuffer),
1886                "MAP %d (%d)  X:%5d  Y:%5d  Z:%5d",
1887                P_GetMapWarpTrans(gamemap),
1888                gamemap,
1889                player->mo->x >> FRACBITS,
1890                player->mo->y >> FRACBITS, player->mo->z >> FRACBITS);
1891     P_SetMessage(player, textBuffer, true);
1892 }
1893 
CheatScriptFunc1(player_t * player,Cheat_t * cheat)1894 static void CheatScriptFunc1(player_t * player, Cheat_t * cheat)
1895 {
1896     P_SetMessage(player, "RUN WHICH SCRIPT(01-99)?", true);
1897 }
1898 
CheatScriptFunc2(player_t * player,Cheat_t * cheat)1899 static void CheatScriptFunc2(player_t * player, Cheat_t * cheat)
1900 {
1901     P_SetMessage(player, "RUN WHICH SCRIPT(01-99)?", true);
1902 }
1903 
CheatScriptFunc3(player_t * player,Cheat_t * cheat)1904 static void CheatScriptFunc3(player_t * player, Cheat_t * cheat)
1905 {
1906     int script;
1907     byte script_args[3];
1908     int tens, ones;
1909     char textBuffer[40];
1910     char args[2];
1911 
1912     cht_GetParam(cheat->seq, args);
1913 
1914     tens = args[0] - '0';
1915     ones = args[1] - '0';
1916     script = tens * 10 + ones;
1917     if (script < 1)
1918         return;
1919     if (script > 99)
1920         return;
1921     script_args[0] = script_args[1] = script_args[2] = 0;
1922 
1923     if (P_StartACS(script, 0, script_args, player->mo, NULL, 0))
1924     {
1925         M_snprintf(textBuffer, sizeof(textBuffer),
1926                    "RUNNING SCRIPT %.2d", script);
1927         P_SetMessage(player, textBuffer, true);
1928     }
1929 }
1930 
1931 extern int cheating;
1932 
CheatRevealFunc(player_t * player,Cheat_t * cheat)1933 static void CheatRevealFunc(player_t * player, Cheat_t * cheat)
1934 {
1935     cheating = (cheating + 1) % 3;
1936 }
1937 
1938 //===========================================================================
1939 //
1940 // CheatTrackFunc1
1941 //
1942 //===========================================================================
1943 
CheatTrackFunc1(player_t * player,Cheat_t * cheat)1944 static void CheatTrackFunc1(player_t * player, Cheat_t * cheat)
1945 {
1946     char buffer[80];
1947 
1948     if (!cdmusic)
1949     {
1950         return;
1951     }
1952 
1953     if (I_CDMusInit() == -1)
1954     {
1955         P_SetMessage(player, "ERROR INITIALIZING CD", true);
1956     }
1957 
1958     M_snprintf(buffer, sizeof(buffer), "ENTER DESIRED CD TRACK (%.2d - %.2d):\n",
1959                I_CDMusFirstTrack(), I_CDMusLastTrack());
1960     P_SetMessage(player, buffer, true);
1961 }
1962 
1963 //===========================================================================
1964 //
1965 // CheatTrackFunc2
1966 //
1967 //===========================================================================
1968 
CheatTrackFunc2(player_t * player,Cheat_t * cheat)1969 static void CheatTrackFunc2(player_t * player, Cheat_t * cheat)
1970 {
1971     char buffer[80];
1972     int track;
1973     char args[2];
1974 
1975     cht_GetParam(cheat->seq, args);
1976 
1977     if (!cdmusic)
1978     {
1979         return;
1980     }
1981 
1982     track = (args[0] - '0') * 10 + (args[1] - '0');
1983     if (track < I_CDMusFirstTrack() || track > I_CDMusLastTrack())
1984     {
1985         P_SetMessage(player, "INVALID TRACK NUMBER\n", true);
1986         return;
1987     }
1988 
1989     if (track == S_GetCurrentCDTrack())
1990     {
1991         return;
1992     }
1993 
1994     if (!S_StartCustomCDTrack(track))
1995     {
1996         M_snprintf(buffer, sizeof(buffer),
1997                    "ERROR WHILE TRYING TO PLAY CD TRACK: %.2d\n", track);
1998         P_SetMessage(player, buffer, true);
1999     }
2000     else
2001     {
2002         // No error encountered while attempting to play the track
2003         M_snprintf(buffer, sizeof(buffer), "PLAYING TRACK: %.2d\n", track);
2004         P_SetMessage(player, buffer, true);
2005     }
2006 }
2007