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