1 //
2 // Copyright(C) 1993-1996 Id Software, Inc.
3 // Copyright(C) 2005-2014 Simon Howard
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // DESCRIPTION:
16 // Intermission screens.
17 //
18
19
20 #include <stdio.h>
21
22 #include "z_zone.h"
23
24 #include "m_misc.h"
25 #include "m_random.h"
26
27 #include "deh_main.h"
28 #include "i_swap.h"
29 #include "i_system.h"
30
31 #include "w_wad.h"
32
33 #include "g_game.h"
34
35 #include "r_local.h"
36 #include "s_sound.h"
37
38 #include "doomstat.h"
39
40 // Data.
41 #include "sounds.h"
42
43 // Needs access to LFB.
44 #include "v_video.h"
45
46 #include "wi_stuff.h"
47
48 //
49 // Data needed to add patches to full screen intermission pics.
50 // Patches are statistics messages, and animations.
51 // Loads of by-pixel layout and placement, offsets etc.
52 //
53
54
55 //
56 // Different vetween registered DOOM (1994) and
57 // Ultimate DOOM - Final edition (retail, 1995?).
58 // This is supposedly ignored for commercial
59 // release (aka DOOM II), which had 34 maps
60 // in one episode. So there.
61 #define NUMEPISODES 4
62 #define NUMMAPS 9
63
64
65 // in tics
66 //U #define PAUSELEN (TICRATE*2)
67 //U #define SCORESTEP 100
68 //U #define ANIMPERIOD 32
69 // pixel distance from "(YOU)" to "PLAYER N"
70 //U #define STARDIST 10
71 //U #define WK 1
72
73
74 // GLOBAL LOCATIONS
75 #define WI_TITLEY 2
76 #define WI_SPACINGY 33
77
78 // SINGPLE-PLAYER STUFF
79 #define SP_STATSX 50
80 #define SP_STATSY 50
81
82 #define SP_TIMEX 16
83 #define SP_TIMEY (SCREENHEIGHT-32)
84
85
86 // NET GAME STUFF
87 #define NG_STATSY 50
88 #define NG_STATSX (32 + SHORT(star->width)/2 + 32*!dofrags)
89
90 #define NG_SPACINGX 64
91
92
93 // DEATHMATCH STUFF
94 #define DM_MATRIXX 42
95 #define DM_MATRIXY 68
96
97 #define DM_SPACINGX 40
98
99 #define DM_TOTALSX 269
100
101 #define DM_KILLERSX 10
102 #define DM_KILLERSY 100
103 #define DM_VICTIMSX 5
104 #define DM_VICTIMSY 50
105
106
107
108
109 typedef enum
110 {
111 ANIM_ALWAYS,
112 ANIM_RANDOM,
113 ANIM_LEVEL
114
115 } animenum_t;
116
117 typedef struct
118 {
119 int x;
120 int y;
121
122 } point_t;
123
124
125 //
126 // Animation.
127 // There is another anim_t used in p_spec.
128 //
129 typedef struct
130 {
131 animenum_t type;
132
133 // period in tics between animations
134 int period;
135
136 // number of animation frames
137 int nanims;
138
139 // location of animation
140 point_t loc;
141
142 // ALWAYS: n/a,
143 // RANDOM: period deviation (<256),
144 // LEVEL: level
145 int data1;
146
147 // ALWAYS: n/a,
148 // RANDOM: random base period,
149 // LEVEL: n/a
150 int data2;
151
152 // actual graphics for frames of animations
153 patch_t* p[3];
154
155 // following must be initialized to zero before use!
156
157 // next value of bcnt (used in conjunction with period)
158 int nexttic;
159
160 // last drawn animation frame
161 int lastdrawn;
162
163 // next frame number to animate
164 int ctr;
165
166 // used by RANDOM and LEVEL when animating
167 int state;
168
169 } anim_t;
170
171
172 static point_t lnodes[NUMEPISODES][NUMMAPS] =
173 {
174 // Episode 0 World Map
175 {
176 { 185, 164 }, // location of level 0 (CJ)
177 { 148, 143 }, // location of level 1 (CJ)
178 { 69, 122 }, // location of level 2 (CJ)
179 { 209, 102 }, // location of level 3 (CJ)
180 { 116, 89 }, // location of level 4 (CJ)
181 { 166, 55 }, // location of level 5 (CJ)
182 { 71, 56 }, // location of level 6 (CJ)
183 { 135, 29 }, // location of level 7 (CJ)
184 { 71, 24 } // location of level 8 (CJ)
185 },
186
187 // Episode 1 World Map should go here
188 {
189 { 254, 25 }, // location of level 0 (CJ)
190 { 97, 50 }, // location of level 1 (CJ)
191 { 188, 64 }, // location of level 2 (CJ)
192 { 128, 78 }, // location of level 3 (CJ)
193 { 214, 92 }, // location of level 4 (CJ)
194 { 133, 130 }, // location of level 5 (CJ)
195 { 208, 136 }, // location of level 6 (CJ)
196 { 148, 140 }, // location of level 7 (CJ)
197 { 235, 158 } // location of level 8 (CJ)
198 },
199
200 // Episode 2 World Map should go here
201 {
202 { 156, 168 }, // location of level 0 (CJ)
203 { 48, 154 }, // location of level 1 (CJ)
204 { 174, 95 }, // location of level 2 (CJ)
205 { 265, 75 }, // location of level 3 (CJ)
206 { 130, 48 }, // location of level 4 (CJ)
207 { 279, 23 }, // location of level 5 (CJ)
208 { 198, 48 }, // location of level 6 (CJ)
209 { 140, 25 }, // location of level 7 (CJ)
210 { 281, 136 } // location of level 8 (CJ)
211 }
212
213 };
214
215
216 //
217 // Animation locations for episode 0 (1).
218 // Using patches saves a lot of space,
219 // as they replace 320x200 full screen frames.
220 //
221
222 #define ANIM(type, period, nanims, x, y, nexttic) \
223 { (type), (period), (nanims), { (x), (y) }, (nexttic), \
224 0, { NULL, NULL, NULL }, 0, 0, 0, 0 }
225
226
227 static anim_t epsd0animinfo[] =
228 {
229 ANIM(ANIM_ALWAYS, TICRATE/3, 3, 224, 104, 0),
230 ANIM(ANIM_ALWAYS, TICRATE/3, 3, 184, 160, 0),
231 ANIM(ANIM_ALWAYS, TICRATE/3, 3, 112, 136, 0),
232 ANIM(ANIM_ALWAYS, TICRATE/3, 3, 72, 112, 0),
233 ANIM(ANIM_ALWAYS, TICRATE/3, 3, 88, 96, 0),
234 ANIM(ANIM_ALWAYS, TICRATE/3, 3, 64, 48, 0),
235 ANIM(ANIM_ALWAYS, TICRATE/3, 3, 192, 40, 0),
236 ANIM(ANIM_ALWAYS, TICRATE/3, 3, 136, 16, 0),
237 ANIM(ANIM_ALWAYS, TICRATE/3, 3, 80, 16, 0),
238 ANIM(ANIM_ALWAYS, TICRATE/3, 3, 64, 24, 0),
239 };
240
241 static anim_t epsd1animinfo[] =
242 {
243 ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 1),
244 ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 2),
245 ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 3),
246 ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 4),
247 ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 5),
248 ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 6),
249 ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 7),
250 ANIM(ANIM_LEVEL, TICRATE/3, 3, 192, 144, 8),
251 ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 8),
252 };
253
254 static anim_t epsd2animinfo[] =
255 {
256 ANIM(ANIM_ALWAYS, TICRATE/3, 3, 104, 168, 0),
257 ANIM(ANIM_ALWAYS, TICRATE/3, 3, 40, 136, 0),
258 ANIM(ANIM_ALWAYS, TICRATE/3, 3, 160, 96, 0),
259 ANIM(ANIM_ALWAYS, TICRATE/3, 3, 104, 80, 0),
260 ANIM(ANIM_ALWAYS, TICRATE/3, 3, 120, 32, 0),
261 ANIM(ANIM_ALWAYS, TICRATE/4, 3, 40, 0, 0),
262 };
263
264 static int NUMANIMS[NUMEPISODES] =
265 {
266 arrlen(epsd0animinfo),
267 arrlen(epsd1animinfo),
268 arrlen(epsd2animinfo),
269 };
270
271 static anim_t *anims[NUMEPISODES] =
272 {
273 epsd0animinfo,
274 epsd1animinfo,
275 epsd2animinfo
276 };
277
278
279 //
280 // GENERAL DATA
281 //
282
283 //
284 // Locally used stuff.
285 //
286
287 // States for single-player
288 #define SP_KILLS 0
289 #define SP_ITEMS 2
290 #define SP_SECRET 4
291 #define SP_FRAGS 6
292 #define SP_TIME 8
293 #define SP_PAR ST_TIME
294
295 #define SP_PAUSE 1
296
297 // in seconds
298 #define SHOWNEXTLOCDELAY 4
299 //#define SHOWLASTLOCDELAY SHOWNEXTLOCDELAY
300
301
302 // used to accelerate or skip a stage
303 static int acceleratestage;
304
305 // wbs->pnum
306 static int me;
307
308 // specifies current state
309 static stateenum_t state;
310
311 // contains information passed into intermission
312 static wbstartstruct_t* wbs;
313
314 static wbplayerstruct_t* plrs; // wbs->plyr[]
315
316 // used for general timing
317 static int cnt;
318
319 // used for timing of background animation
320 static int bcnt;
321
322 // signals to refresh everything for one frame
323 static int firstrefresh;
324
325 static int cnt_kills[MAXPLAYERS];
326 static int cnt_items[MAXPLAYERS];
327 static int cnt_secret[MAXPLAYERS];
328 static int cnt_time;
329 static int cnt_par;
330 static int cnt_pause;
331
332 // # of commercial levels
333 static int NUMCMAPS;
334
335
336 //
337 // GRAPHICS
338 //
339
340 // You Are Here graphic
341 static patch_t* yah[3] = { NULL, NULL, NULL };
342
343 // splat
344 static patch_t* splat[2] = { NULL, NULL };
345
346 // %, : graphics
347 static patch_t* percent;
348 static patch_t* colon;
349
350 // 0-9 graphic
351 static patch_t* num[10];
352
353 // minus sign
354 static patch_t* wiminus;
355
356 // "Finished!" graphics
357 static patch_t* finished;
358
359 // "Entering" graphic
360 static patch_t* entering;
361
362 // "secret"
363 static patch_t* sp_secret;
364
365 // "Kills", "Scrt", "Items", "Frags"
366 static patch_t* kills;
367 static patch_t* secret;
368 static patch_t* items;
369 static patch_t* frags;
370
371 // Time sucks.
372 static patch_t* timepatch;
373 static patch_t* par;
374 static patch_t* sucks;
375
376 // "killers", "victims"
377 static patch_t* killers;
378 static patch_t* victims;
379
380 // "Total", your face, your dead face
381 static patch_t* total;
382 static patch_t* star;
383 static patch_t* bstar;
384
385 // "red P[1..MAXPLAYERS]"
386 static patch_t* p[MAXPLAYERS];
387
388 // "gray P[1..MAXPLAYERS]"
389 static patch_t* bp[MAXPLAYERS];
390
391 // Name graphics of each level (centered)
392 static patch_t** lnames;
393
394 // Buffer storing the backdrop
395 static patch_t *background;
396
397 //
398 // CODE
399 //
400
401 // slam background
WI_slamBackground(void)402 void WI_slamBackground(void)
403 {
404 V_DrawPatch(0, 0, background);
405 }
406
407 // The ticker is used to detect keys
408 // because of timing issues in netgames.
WI_Responder(event_t * ev)409 boolean WI_Responder(event_t* ev)
410 {
411 return false;
412 }
413
414
415 // Draws "<Levelname> Finished!"
WI_drawLF(void)416 void WI_drawLF(void)
417 {
418 int y = WI_TITLEY;
419
420 if (gamemode != commercial || wbs->last < NUMCMAPS)
421 {
422 // draw <LevelName>
423 V_DrawPatch((SCREENWIDTH - SHORT(lnames[wbs->last]->width))/2,
424 y, lnames[wbs->last]);
425
426 // draw "Finished!"
427 y += (5*SHORT(lnames[wbs->last]->height))/4;
428
429 V_DrawPatch((SCREENWIDTH - SHORT(finished->width)) / 2, y, finished);
430 }
431 else if (wbs->last == NUMCMAPS)
432 {
433 // MAP33 - nothing is displayed!
434 }
435 else if (wbs->last > NUMCMAPS)
436 {
437 // > MAP33. Doom bombs out here with a Bad V_DrawPatch error.
438 // I'm pretty sure that doom2.exe is just reading into random
439 // bits of memory at this point, but let's try to be accurate
440 // anyway. This deliberately triggers a V_DrawPatch error.
441
442 patch_t tmp = { SCREENWIDTH, SCREENHEIGHT, 1, 1,
443 { 0, 0, 0, 0, 0, 0, 0, 0 } };
444
445 V_DrawPatch(0, y, &tmp);
446 }
447 }
448
449
450
451 // Draws "Entering <LevelName>"
WI_drawEL(void)452 void WI_drawEL(void)
453 {
454 int y = WI_TITLEY;
455
456 // draw "Entering"
457 V_DrawPatch((SCREENWIDTH - SHORT(entering->width))/2,
458 y,
459 entering);
460
461 // draw level
462 y += (5*SHORT(lnames[wbs->next]->height))/4;
463
464 V_DrawPatch((SCREENWIDTH - SHORT(lnames[wbs->next]->width))/2,
465 y,
466 lnames[wbs->next]);
467
468 }
469
470 void
WI_drawOnLnode(int n,patch_t * c[])471 WI_drawOnLnode
472 ( int n,
473 patch_t* c[] )
474 {
475
476 int i;
477 int left;
478 int top;
479 int right;
480 int bottom;
481 boolean fits = false;
482
483 i = 0;
484 do
485 {
486 left = lnodes[wbs->epsd][n].x - SHORT(c[i]->leftoffset);
487 top = lnodes[wbs->epsd][n].y - SHORT(c[i]->topoffset);
488 right = left + SHORT(c[i]->width);
489 bottom = top + SHORT(c[i]->height);
490
491 if (left >= 0
492 && right < SCREENWIDTH
493 && top >= 0
494 && bottom < SCREENHEIGHT)
495 {
496 fits = true;
497 }
498 else
499 {
500 i++;
501 }
502 } while (!fits && i!=2 && c[i] != NULL);
503
504 if (fits && i<2)
505 {
506 V_DrawPatch(lnodes[wbs->epsd][n].x,
507 lnodes[wbs->epsd][n].y,
508 c[i]);
509 }
510 else
511 {
512 // DEBUG
513 printf("Could not place patch on level %d", n+1);
514 }
515 }
516
517
518
WI_initAnimatedBack(void)519 void WI_initAnimatedBack(void)
520 {
521 int i;
522 anim_t* a;
523
524 if (gamemode == commercial)
525 return;
526
527 if (wbs->epsd > 2)
528 return;
529
530 for (i=0;i<NUMANIMS[wbs->epsd];i++)
531 {
532 a = &anims[wbs->epsd][i];
533
534 // init variables
535 a->ctr = -1;
536
537 // specify the next time to draw it
538 if (a->type == ANIM_ALWAYS)
539 a->nexttic = bcnt + 1 + (M_Random()%a->period);
540 else if (a->type == ANIM_RANDOM)
541 a->nexttic = bcnt + 1 + a->data2+(M_Random()%a->data1);
542 else if (a->type == ANIM_LEVEL)
543 a->nexttic = bcnt + 1;
544 }
545
546 }
547
WI_updateAnimatedBack(void)548 void WI_updateAnimatedBack(void)
549 {
550 int i;
551 anim_t* a;
552
553 if (gamemode == commercial)
554 return;
555
556 if (wbs->epsd > 2)
557 return;
558
559 for (i=0;i<NUMANIMS[wbs->epsd];i++)
560 {
561 a = &anims[wbs->epsd][i];
562
563 if (bcnt == a->nexttic)
564 {
565 switch (a->type)
566 {
567 case ANIM_ALWAYS:
568 if (++a->ctr >= a->nanims) a->ctr = 0;
569 a->nexttic = bcnt + a->period;
570 break;
571
572 case ANIM_RANDOM:
573 a->ctr++;
574 if (a->ctr == a->nanims)
575 {
576 a->ctr = -1;
577 a->nexttic = bcnt+a->data2+(M_Random()%a->data1);
578 }
579 else a->nexttic = bcnt + a->period;
580 break;
581
582 case ANIM_LEVEL:
583 // gawd-awful hack for level anims
584 if (!(state == StatCount && i == 7)
585 && wbs->next == a->data1)
586 {
587 a->ctr++;
588 if (a->ctr == a->nanims) a->ctr--;
589 a->nexttic = bcnt + a->period;
590 }
591 break;
592 }
593 }
594
595 }
596
597 }
598
WI_drawAnimatedBack(void)599 void WI_drawAnimatedBack(void)
600 {
601 int i;
602 anim_t* a;
603
604 if (gamemode == commercial)
605 return;
606
607 if (wbs->epsd > 2)
608 return;
609
610 for (i=0 ; i<NUMANIMS[wbs->epsd] ; i++)
611 {
612 a = &anims[wbs->epsd][i];
613
614 if (a->ctr >= 0)
615 V_DrawPatch(a->loc.x, a->loc.y, a->p[a->ctr]);
616 }
617
618 }
619
620 //
621 // Draws a number.
622 // If digits > 0, then use that many digits minimum,
623 // otherwise only use as many as necessary.
624 // Returns new x position.
625 //
626
627 int
WI_drawNum(int x,int y,int n,int digits)628 WI_drawNum
629 ( int x,
630 int y,
631 int n,
632 int digits )
633 {
634
635 int fontwidth = SHORT(num[0]->width);
636 int neg;
637 int temp;
638
639 if (digits < 0)
640 {
641 if (!n)
642 {
643 // make variable-length zeros 1 digit long
644 digits = 1;
645 }
646 else
647 {
648 // figure out # of digits in #
649 digits = 0;
650 temp = n;
651
652 while (temp)
653 {
654 temp /= 10;
655 digits++;
656 }
657 }
658 }
659
660 neg = n < 0;
661 if (neg)
662 n = -n;
663
664 // if non-number, do not draw it
665 if (n == 1994)
666 return 0;
667
668 // draw the new number
669 while (digits--)
670 {
671 x -= fontwidth;
672 V_DrawPatch(x, y, num[ n % 10 ]);
673 n /= 10;
674 }
675
676 // draw a minus sign if necessary
677 if (neg)
678 V_DrawPatch(x-=8, y, wiminus);
679
680 return x;
681
682 }
683
684 void
WI_drawPercent(int x,int y,int p)685 WI_drawPercent
686 ( int x,
687 int y,
688 int p )
689 {
690 if (p < 0)
691 return;
692
693 V_DrawPatch(x, y, percent);
694 WI_drawNum(x, y, p, -1);
695 }
696
697
698
699 //
700 // Display level completion time and par,
701 // or "sucks" message if overflow.
702 //
703 void
WI_drawTime(int x,int y,int t)704 WI_drawTime
705 ( int x,
706 int y,
707 int t )
708 {
709
710 int div;
711 int n;
712
713 if (t<0)
714 return;
715
716 if (t <= 61*59)
717 {
718 div = 1;
719
720 do
721 {
722 n = (t / div) % 60;
723 x = WI_drawNum(x, y, n, 2) - SHORT(colon->width);
724 div *= 60;
725
726 // draw
727 if (div==60 || t / div)
728 V_DrawPatch(x, y, colon);
729
730 } while (t / div);
731 }
732 else
733 {
734 // "sucks"
735 V_DrawPatch(x - SHORT(sucks->width), y, sucks);
736 }
737 }
738
739
WI_End(void)740 void WI_End(void)
741 {
742 void WI_unloadData(void);
743 WI_unloadData();
744 }
745
WI_initNoState(void)746 void WI_initNoState(void)
747 {
748 state = NoState;
749 acceleratestage = 0;
750 cnt = 10;
751 }
752
WI_updateNoState(void)753 void WI_updateNoState(void) {
754
755 WI_updateAnimatedBack();
756
757 if (!--cnt)
758 {
759 // Don't call WI_End yet. G_WorldDone doesnt immediately
760 // change gamestate, so WI_Drawer is still going to get
761 // run until that happens. If we do that after WI_End
762 // (which unloads all the graphics), we're in trouble.
763 //WI_End();
764 G_WorldDone();
765 }
766
767 }
768
769 static boolean snl_pointeron = false;
770
771
WI_initShowNextLoc(void)772 void WI_initShowNextLoc(void)
773 {
774 state = ShowNextLoc;
775 acceleratestage = 0;
776 cnt = SHOWNEXTLOCDELAY * TICRATE;
777
778 WI_initAnimatedBack();
779 }
780
WI_updateShowNextLoc(void)781 void WI_updateShowNextLoc(void)
782 {
783 WI_updateAnimatedBack();
784
785 if (!--cnt || acceleratestage)
786 WI_initNoState();
787 else
788 snl_pointeron = (cnt & 31) < 20;
789 }
790
WI_drawShowNextLoc(void)791 void WI_drawShowNextLoc(void)
792 {
793
794 int i;
795 int last;
796
797 WI_slamBackground();
798
799 // draw animated background
800 WI_drawAnimatedBack();
801
802 if ( gamemode != commercial)
803 {
804 if (wbs->epsd > 2)
805 {
806 WI_drawEL();
807 return;
808 }
809
810 last = (wbs->last == 8) ? wbs->next - 1 : wbs->last;
811
812 // draw a splat on taken cities.
813 for (i=0 ; i<=last ; i++)
814 WI_drawOnLnode(i, splat);
815
816 // splat the secret level?
817 if (wbs->didsecret)
818 WI_drawOnLnode(8, splat);
819
820 // draw flashing ptr
821 if (snl_pointeron)
822 WI_drawOnLnode(wbs->next, yah);
823 }
824
825 // draws which level you are entering..
826 if ( (gamemode != commercial)
827 || wbs->next != 30)
828 WI_drawEL();
829
830 }
831
WI_drawNoState(void)832 void WI_drawNoState(void)
833 {
834 snl_pointeron = true;
835 WI_drawShowNextLoc();
836 }
837
WI_fragSum(int playernum)838 int WI_fragSum(int playernum)
839 {
840 int i;
841 int frags = 0;
842
843 for (i=0 ; i<MAXPLAYERS ; i++)
844 {
845 if (playeringame[i]
846 && i!=playernum)
847 {
848 frags += plrs[playernum].frags[i];
849 }
850 }
851
852
853 // JDC hack - negative frags.
854 frags -= plrs[playernum].frags[playernum];
855 // UNUSED if (frags < 0)
856 // frags = 0;
857
858 return frags;
859 }
860
861
862
863 static int dm_state;
864 static int dm_frags[MAXPLAYERS][MAXPLAYERS];
865 static int dm_totals[MAXPLAYERS];
866
867
868
WI_initDeathmatchStats(void)869 void WI_initDeathmatchStats(void)
870 {
871
872 int i;
873 int j;
874
875 state = StatCount;
876 acceleratestage = 0;
877 dm_state = 1;
878
879 cnt_pause = TICRATE;
880
881 for (i=0 ; i<MAXPLAYERS ; i++)
882 {
883 if (playeringame[i])
884 {
885 for (j=0 ; j<MAXPLAYERS ; j++)
886 if (playeringame[j])
887 dm_frags[i][j] = 0;
888
889 dm_totals[i] = 0;
890 }
891 }
892
893 WI_initAnimatedBack();
894 }
895
896
897
WI_updateDeathmatchStats(void)898 void WI_updateDeathmatchStats(void)
899 {
900
901 int i;
902 int j;
903
904 boolean stillticking;
905
906 WI_updateAnimatedBack();
907
908 if (acceleratestage && dm_state != 4)
909 {
910 acceleratestage = 0;
911
912 for (i=0 ; i<MAXPLAYERS ; i++)
913 {
914 if (playeringame[i])
915 {
916 for (j=0 ; j<MAXPLAYERS ; j++)
917 if (playeringame[j])
918 dm_frags[i][j] = plrs[i].frags[j];
919
920 dm_totals[i] = WI_fragSum(i);
921 }
922 }
923
924
925 S_StartSound(0, sfx_barexp);
926 dm_state = 4;
927 }
928
929
930 if (dm_state == 2)
931 {
932 if (!(bcnt&3))
933 S_StartSound(0, sfx_pistol);
934
935 stillticking = false;
936
937 for (i=0 ; i<MAXPLAYERS ; i++)
938 {
939 if (playeringame[i])
940 {
941 for (j=0 ; j<MAXPLAYERS ; j++)
942 {
943 if (playeringame[j]
944 && dm_frags[i][j] != plrs[i].frags[j])
945 {
946 if (plrs[i].frags[j] < 0)
947 dm_frags[i][j]--;
948 else
949 dm_frags[i][j]++;
950
951 if (dm_frags[i][j] > 99)
952 dm_frags[i][j] = 99;
953
954 if (dm_frags[i][j] < -99)
955 dm_frags[i][j] = -99;
956
957 stillticking = true;
958 }
959 }
960 dm_totals[i] = WI_fragSum(i);
961
962 if (dm_totals[i] > 99)
963 dm_totals[i] = 99;
964
965 if (dm_totals[i] < -99)
966 dm_totals[i] = -99;
967 }
968
969 }
970 if (!stillticking)
971 {
972 S_StartSound(0, sfx_barexp);
973 dm_state++;
974 }
975
976 }
977 else if (dm_state == 4)
978 {
979 if (acceleratestage)
980 {
981 S_StartSound(0, sfx_slop);
982
983 if ( gamemode == commercial)
984 WI_initNoState();
985 else
986 WI_initShowNextLoc();
987 }
988 }
989 else if (dm_state & 1)
990 {
991 if (!--cnt_pause)
992 {
993 dm_state++;
994 cnt_pause = TICRATE;
995 }
996 }
997 }
998
999
1000
WI_drawDeathmatchStats(void)1001 void WI_drawDeathmatchStats(void)
1002 {
1003
1004 int i;
1005 int j;
1006 int x;
1007 int y;
1008 int w;
1009
1010 WI_slamBackground();
1011
1012 // draw animated background
1013 WI_drawAnimatedBack();
1014 WI_drawLF();
1015
1016 // draw stat titles (top line)
1017 V_DrawPatch(DM_TOTALSX-SHORT(total->width)/2,
1018 DM_MATRIXY-WI_SPACINGY+10,
1019 total);
1020
1021 V_DrawPatch(DM_KILLERSX, DM_KILLERSY, killers);
1022 V_DrawPatch(DM_VICTIMSX, DM_VICTIMSY, victims);
1023
1024 // draw P?
1025 x = DM_MATRIXX + DM_SPACINGX;
1026 y = DM_MATRIXY;
1027
1028 for (i=0 ; i<MAXPLAYERS ; i++)
1029 {
1030 if (playeringame[i])
1031 {
1032 V_DrawPatch(x-SHORT(p[i]->width)/2,
1033 DM_MATRIXY - WI_SPACINGY,
1034 p[i]);
1035
1036 V_DrawPatch(DM_MATRIXX-SHORT(p[i]->width)/2,
1037 y,
1038 p[i]);
1039
1040 if (i == me)
1041 {
1042 V_DrawPatch(x-SHORT(p[i]->width)/2,
1043 DM_MATRIXY - WI_SPACINGY,
1044 bstar);
1045
1046 V_DrawPatch(DM_MATRIXX-SHORT(p[i]->width)/2,
1047 y,
1048 star);
1049 }
1050 }
1051 else
1052 {
1053 // V_DrawPatch(x-SHORT(bp[i]->width)/2,
1054 // DM_MATRIXY - WI_SPACINGY, bp[i]);
1055 // V_DrawPatch(DM_MATRIXX-SHORT(bp[i]->width)/2,
1056 // y, bp[i]);
1057 }
1058 x += DM_SPACINGX;
1059 y += WI_SPACINGY;
1060 }
1061
1062 // draw stats
1063 y = DM_MATRIXY+10;
1064 w = SHORT(num[0]->width);
1065
1066 for (i=0 ; i<MAXPLAYERS ; i++)
1067 {
1068 x = DM_MATRIXX + DM_SPACINGX;
1069
1070 if (playeringame[i])
1071 {
1072 for (j=0 ; j<MAXPLAYERS ; j++)
1073 {
1074 if (playeringame[j])
1075 WI_drawNum(x+w, y, dm_frags[i][j], 2);
1076
1077 x += DM_SPACINGX;
1078 }
1079 WI_drawNum(DM_TOTALSX+w, y, dm_totals[i], 2);
1080 }
1081 y += WI_SPACINGY;
1082 }
1083 }
1084
1085 static int cnt_frags[MAXPLAYERS];
1086 static int dofrags;
1087 static int ng_state;
1088
WI_initNetgameStats(void)1089 void WI_initNetgameStats(void)
1090 {
1091
1092 int i;
1093
1094 state = StatCount;
1095 acceleratestage = 0;
1096 ng_state = 1;
1097
1098 cnt_pause = TICRATE;
1099
1100 for (i=0 ; i<MAXPLAYERS ; i++)
1101 {
1102 if (!playeringame[i])
1103 continue;
1104
1105 cnt_kills[i] = cnt_items[i] = cnt_secret[i] = cnt_frags[i] = 0;
1106
1107 dofrags += WI_fragSum(i);
1108 }
1109
1110 dofrags = !!dofrags;
1111
1112 WI_initAnimatedBack();
1113 }
1114
1115
1116
WI_updateNetgameStats(void)1117 void WI_updateNetgameStats(void)
1118 {
1119
1120 int i;
1121 int fsum;
1122
1123 boolean stillticking;
1124
1125 WI_updateAnimatedBack();
1126
1127 if (acceleratestage && ng_state != 10)
1128 {
1129 acceleratestage = 0;
1130
1131 for (i=0 ; i<MAXPLAYERS ; i++)
1132 {
1133 if (!playeringame[i])
1134 continue;
1135
1136 cnt_kills[i] = (plrs[i].skills * 100) / wbs->maxkills;
1137 cnt_items[i] = (plrs[i].sitems * 100) / wbs->maxitems;
1138 cnt_secret[i] = (plrs[i].ssecret * 100) / wbs->maxsecret;
1139
1140 if (dofrags)
1141 cnt_frags[i] = WI_fragSum(i);
1142 }
1143 S_StartSound(0, sfx_barexp);
1144 ng_state = 10;
1145 }
1146
1147 if (ng_state == 2)
1148 {
1149 if (!(bcnt&3))
1150 S_StartSound(0, sfx_pistol);
1151
1152 stillticking = false;
1153
1154 for (i=0 ; i<MAXPLAYERS ; i++)
1155 {
1156 if (!playeringame[i])
1157 continue;
1158
1159 cnt_kills[i] += 2;
1160
1161 if (cnt_kills[i] >= (plrs[i].skills * 100) / wbs->maxkills)
1162 cnt_kills[i] = (plrs[i].skills * 100) / wbs->maxkills;
1163 else
1164 stillticking = true;
1165 }
1166
1167 if (!stillticking)
1168 {
1169 S_StartSound(0, sfx_barexp);
1170 ng_state++;
1171 }
1172 }
1173 else if (ng_state == 4)
1174 {
1175 if (!(bcnt&3))
1176 S_StartSound(0, sfx_pistol);
1177
1178 stillticking = false;
1179
1180 for (i=0 ; i<MAXPLAYERS ; i++)
1181 {
1182 if (!playeringame[i])
1183 continue;
1184
1185 cnt_items[i] += 2;
1186 if (cnt_items[i] >= (plrs[i].sitems * 100) / wbs->maxitems)
1187 cnt_items[i] = (plrs[i].sitems * 100) / wbs->maxitems;
1188 else
1189 stillticking = true;
1190 }
1191 if (!stillticking)
1192 {
1193 S_StartSound(0, sfx_barexp);
1194 ng_state++;
1195 }
1196 }
1197 else if (ng_state == 6)
1198 {
1199 if (!(bcnt&3))
1200 S_StartSound(0, sfx_pistol);
1201
1202 stillticking = false;
1203
1204 for (i=0 ; i<MAXPLAYERS ; i++)
1205 {
1206 if (!playeringame[i])
1207 continue;
1208
1209 cnt_secret[i] += 2;
1210
1211 if (cnt_secret[i] >= (plrs[i].ssecret * 100) / wbs->maxsecret)
1212 cnt_secret[i] = (plrs[i].ssecret * 100) / wbs->maxsecret;
1213 else
1214 stillticking = true;
1215 }
1216
1217 if (!stillticking)
1218 {
1219 S_StartSound(0, sfx_barexp);
1220 ng_state += 1 + 2*!dofrags;
1221 }
1222 }
1223 else if (ng_state == 8)
1224 {
1225 if (!(bcnt&3))
1226 S_StartSound(0, sfx_pistol);
1227
1228 stillticking = false;
1229
1230 for (i=0 ; i<MAXPLAYERS ; i++)
1231 {
1232 if (!playeringame[i])
1233 continue;
1234
1235 cnt_frags[i] += 1;
1236
1237 if (cnt_frags[i] >= (fsum = WI_fragSum(i)))
1238 cnt_frags[i] = fsum;
1239 else
1240 stillticking = true;
1241 }
1242
1243 if (!stillticking)
1244 {
1245 S_StartSound(0, sfx_pldeth);
1246 ng_state++;
1247 }
1248 }
1249 else if (ng_state == 10)
1250 {
1251 if (acceleratestage)
1252 {
1253 S_StartSound(0, sfx_sgcock);
1254 if ( gamemode == commercial )
1255 WI_initNoState();
1256 else
1257 WI_initShowNextLoc();
1258 }
1259 }
1260 else if (ng_state & 1)
1261 {
1262 if (!--cnt_pause)
1263 {
1264 ng_state++;
1265 cnt_pause = TICRATE;
1266 }
1267 }
1268 }
1269
1270
1271
WI_drawNetgameStats(void)1272 void WI_drawNetgameStats(void)
1273 {
1274 int i;
1275 int x;
1276 int y;
1277 int pwidth = SHORT(percent->width);
1278
1279 WI_slamBackground();
1280
1281 // draw animated background
1282 WI_drawAnimatedBack();
1283
1284 WI_drawLF();
1285
1286 // draw stat titles (top line)
1287 V_DrawPatch(NG_STATSX+NG_SPACINGX-SHORT(kills->width),
1288 NG_STATSY, kills);
1289
1290 V_DrawPatch(NG_STATSX+2*NG_SPACINGX-SHORT(items->width),
1291 NG_STATSY, items);
1292
1293 V_DrawPatch(NG_STATSX+3*NG_SPACINGX-SHORT(secret->width),
1294 NG_STATSY, secret);
1295
1296 if (dofrags)
1297 V_DrawPatch(NG_STATSX+4*NG_SPACINGX-SHORT(frags->width),
1298 NG_STATSY, frags);
1299
1300 // draw stats
1301 y = NG_STATSY + SHORT(kills->height);
1302
1303 for (i=0 ; i<MAXPLAYERS ; i++)
1304 {
1305 if (!playeringame[i])
1306 continue;
1307
1308 x = NG_STATSX;
1309 V_DrawPatch(x-SHORT(p[i]->width), y, p[i]);
1310
1311 if (i == me)
1312 V_DrawPatch(x-SHORT(p[i]->width), y, star);
1313
1314 x += NG_SPACINGX;
1315 WI_drawPercent(x-pwidth, y+10, cnt_kills[i]); x += NG_SPACINGX;
1316 WI_drawPercent(x-pwidth, y+10, cnt_items[i]); x += NG_SPACINGX;
1317 WI_drawPercent(x-pwidth, y+10, cnt_secret[i]); x += NG_SPACINGX;
1318
1319 if (dofrags)
1320 WI_drawNum(x, y+10, cnt_frags[i], -1);
1321
1322 y += WI_SPACINGY;
1323 }
1324
1325 }
1326
1327 static int sp_state;
1328
WI_initStats(void)1329 void WI_initStats(void)
1330 {
1331 state = StatCount;
1332 acceleratestage = 0;
1333 sp_state = 1;
1334 cnt_kills[0] = cnt_items[0] = cnt_secret[0] = -1;
1335 cnt_time = cnt_par = -1;
1336 cnt_pause = TICRATE;
1337
1338 WI_initAnimatedBack();
1339 }
1340
WI_updateStats(void)1341 void WI_updateStats(void)
1342 {
1343
1344 WI_updateAnimatedBack();
1345
1346 if (acceleratestage && sp_state != 10)
1347 {
1348 acceleratestage = 0;
1349 cnt_kills[0] = (plrs[me].skills * 100) / wbs->maxkills;
1350 cnt_items[0] = (plrs[me].sitems * 100) / wbs->maxitems;
1351 cnt_secret[0] = (plrs[me].ssecret * 100) / wbs->maxsecret;
1352 cnt_time = plrs[me].stime / TICRATE;
1353 cnt_par = wbs->partime / TICRATE;
1354 S_StartSound(0, sfx_barexp);
1355 sp_state = 10;
1356 }
1357
1358 if (sp_state == 2)
1359 {
1360 cnt_kills[0] += 2;
1361
1362 if (!(bcnt&3))
1363 S_StartSound(0, sfx_pistol);
1364
1365 if (cnt_kills[0] >= (plrs[me].skills * 100) / wbs->maxkills)
1366 {
1367 cnt_kills[0] = (plrs[me].skills * 100) / wbs->maxkills;
1368 S_StartSound(0, sfx_barexp);
1369 sp_state++;
1370 }
1371 }
1372 else if (sp_state == 4)
1373 {
1374 cnt_items[0] += 2;
1375
1376 if (!(bcnt&3))
1377 S_StartSound(0, sfx_pistol);
1378
1379 if (cnt_items[0] >= (plrs[me].sitems * 100) / wbs->maxitems)
1380 {
1381 cnt_items[0] = (plrs[me].sitems * 100) / wbs->maxitems;
1382 S_StartSound(0, sfx_barexp);
1383 sp_state++;
1384 }
1385 }
1386 else if (sp_state == 6)
1387 {
1388 cnt_secret[0] += 2;
1389
1390 if (!(bcnt&3))
1391 S_StartSound(0, sfx_pistol);
1392
1393 if (cnt_secret[0] >= (plrs[me].ssecret * 100) / wbs->maxsecret)
1394 {
1395 cnt_secret[0] = (plrs[me].ssecret * 100) / wbs->maxsecret;
1396 S_StartSound(0, sfx_barexp);
1397 sp_state++;
1398 }
1399 }
1400
1401 else if (sp_state == 8)
1402 {
1403 if (!(bcnt&3))
1404 S_StartSound(0, sfx_pistol);
1405
1406 cnt_time += 3;
1407
1408 if (cnt_time >= plrs[me].stime / TICRATE)
1409 cnt_time = plrs[me].stime / TICRATE;
1410
1411 cnt_par += 3;
1412
1413 if (cnt_par >= wbs->partime / TICRATE)
1414 {
1415 cnt_par = wbs->partime / TICRATE;
1416
1417 if (cnt_time >= plrs[me].stime / TICRATE)
1418 {
1419 S_StartSound(0, sfx_barexp);
1420 sp_state++;
1421 }
1422 }
1423 }
1424 else if (sp_state == 10)
1425 {
1426 if (acceleratestage)
1427 {
1428 S_StartSound(0, sfx_sgcock);
1429
1430 if (gamemode == commercial)
1431 WI_initNoState();
1432 else
1433 WI_initShowNextLoc();
1434 }
1435 }
1436 else if (sp_state & 1)
1437 {
1438 if (!--cnt_pause)
1439 {
1440 sp_state++;
1441 cnt_pause = TICRATE;
1442 }
1443 }
1444
1445 }
1446
WI_drawStats(void)1447 void WI_drawStats(void)
1448 {
1449 // line height
1450 int lh;
1451
1452 lh = (3*SHORT(num[0]->height))/2;
1453
1454 WI_slamBackground();
1455
1456 // draw animated background
1457 WI_drawAnimatedBack();
1458
1459 WI_drawLF();
1460
1461 V_DrawPatch(SP_STATSX, SP_STATSY, kills);
1462 WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY, cnt_kills[0]);
1463
1464 V_DrawPatch(SP_STATSX, SP_STATSY+lh, items);
1465 WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY+lh, cnt_items[0]);
1466
1467 V_DrawPatch(SP_STATSX, SP_STATSY+2*lh, sp_secret);
1468 WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY+2*lh, cnt_secret[0]);
1469
1470 V_DrawPatch(SP_TIMEX, SP_TIMEY, timepatch);
1471 WI_drawTime(SCREENWIDTH/2 - SP_TIMEX, SP_TIMEY, cnt_time);
1472
1473 if (wbs->epsd < 3)
1474 {
1475 V_DrawPatch(SCREENWIDTH/2 + SP_TIMEX, SP_TIMEY, par);
1476 WI_drawTime(SCREENWIDTH - SP_TIMEX, SP_TIMEY, cnt_par);
1477 }
1478
1479 }
1480
WI_checkForAccelerate(void)1481 void WI_checkForAccelerate(void)
1482 {
1483 int i;
1484 player_t *player;
1485
1486 // check for button presses to skip delays
1487 for (i=0, player = players ; i<MAXPLAYERS ; i++, player++)
1488 {
1489 if (playeringame[i])
1490 {
1491 if (player->cmd.buttons & BT_ATTACK)
1492 {
1493 if (!player->attackdown)
1494 acceleratestage = 1;
1495 player->attackdown = true;
1496 }
1497 else
1498 player->attackdown = false;
1499 if (player->cmd.buttons & BT_USE)
1500 {
1501 if (!player->usedown)
1502 acceleratestage = 1;
1503 player->usedown = true;
1504 }
1505 else
1506 player->usedown = false;
1507 }
1508 }
1509 }
1510
1511
1512
1513 // Updates stuff each tick
WI_Ticker(void)1514 void WI_Ticker(void)
1515 {
1516 // counter for general background animation
1517 bcnt++;
1518
1519 if (bcnt == 1)
1520 {
1521 // intermission music
1522 if ( gamemode == commercial )
1523 S_ChangeMusic(mus_dm2int, true);
1524 else
1525 S_ChangeMusic(mus_inter, true);
1526 }
1527
1528 WI_checkForAccelerate();
1529
1530 switch (state)
1531 {
1532 case StatCount:
1533 if (deathmatch) WI_updateDeathmatchStats();
1534 else if (netgame) WI_updateNetgameStats();
1535 else WI_updateStats();
1536 break;
1537
1538 case ShowNextLoc:
1539 WI_updateShowNextLoc();
1540 break;
1541
1542 case NoState:
1543 WI_updateNoState();
1544 break;
1545 }
1546
1547 }
1548
1549 typedef void (*load_callback_t)(char *lumpname, patch_t **variable);
1550
1551 // Common load/unload function. Iterates over all the graphics
1552 // lumps to be loaded/unloaded into memory.
1553
WI_loadUnloadData(load_callback_t callback)1554 static void WI_loadUnloadData(load_callback_t callback)
1555 {
1556 int i, j;
1557 char name[9];
1558 anim_t *a;
1559
1560 if (gamemode == commercial)
1561 {
1562 for (i=0 ; i<NUMCMAPS ; i++)
1563 {
1564 DEH_snprintf(name, 9, "CWILV%2.2d", i);
1565 callback(name, &lnames[i]);
1566 }
1567 }
1568 else
1569 {
1570 for (i=0 ; i<NUMMAPS ; i++)
1571 {
1572 DEH_snprintf(name, 9, "WILV%d%d", wbs->epsd, i);
1573 callback(name, &lnames[i]);
1574 }
1575
1576 // you are here
1577 callback(DEH_String("WIURH0"), &yah[0]);
1578
1579 // you are here (alt.)
1580 callback(DEH_String("WIURH1"), &yah[1]);
1581
1582 // splat
1583 callback(DEH_String("WISPLAT"), &splat[0]);
1584
1585 if (wbs->epsd < 3)
1586 {
1587 for (j=0;j<NUMANIMS[wbs->epsd];j++)
1588 {
1589 a = &anims[wbs->epsd][j];
1590 for (i=0;i<a->nanims;i++)
1591 {
1592 // MONDO HACK!
1593 if (wbs->epsd != 1 || j != 8)
1594 {
1595 // animations
1596 DEH_snprintf(name, 9, "WIA%d%.2d%.2d", wbs->epsd, j, i);
1597 callback(name, &a->p[i]);
1598 }
1599 else
1600 {
1601 // HACK ALERT!
1602 a->p[i] = anims[1][4].p[i];
1603 }
1604 }
1605 }
1606 }
1607 }
1608
1609 // More hacks on minus sign.
1610 callback(DEH_String("WIMINUS"), &wiminus);
1611
1612 for (i=0;i<10;i++)
1613 {
1614 // numbers 0-9
1615 DEH_snprintf(name, 9, "WINUM%d", i);
1616 callback(name, &num[i]);
1617 }
1618
1619 // percent sign
1620 callback(DEH_String("WIPCNT"), &percent);
1621
1622 // "finished"
1623 callback(DEH_String("WIF"), &finished);
1624
1625 // "entering"
1626 callback(DEH_String("WIENTER"), &entering);
1627
1628 // "kills"
1629 callback(DEH_String("WIOSTK"), &kills);
1630
1631 // "scrt"
1632 callback(DEH_String("WIOSTS"), &secret);
1633
1634 // "secret"
1635 callback(DEH_String("WISCRT2"), &sp_secret);
1636
1637 // french wad uses WIOBJ (?)
1638 if (W_CheckNumForName(DEH_String("WIOBJ")) >= 0)
1639 {
1640 // "items"
1641 if (netgame && !deathmatch)
1642 callback(DEH_String("WIOBJ"), &items);
1643 else
1644 callback(DEH_String("WIOSTI"), &items);
1645 } else {
1646 callback(DEH_String("WIOSTI"), &items);
1647 }
1648
1649 // "frgs"
1650 callback(DEH_String("WIFRGS"), &frags);
1651
1652 // ":"
1653 callback(DEH_String("WICOLON"), &colon);
1654
1655 // "time"
1656 callback(DEH_String("WITIME"), &timepatch);
1657
1658 // "sucks"
1659 callback(DEH_String("WISUCKS"), &sucks);
1660
1661 // "par"
1662 callback(DEH_String("WIPAR"), &par);
1663
1664 // "killers" (vertical)
1665 callback(DEH_String("WIKILRS"), &killers);
1666
1667 // "victims" (horiz)
1668 callback(DEH_String("WIVCTMS"), &victims);
1669
1670 // "total"
1671 callback(DEH_String("WIMSTT"), &total);
1672
1673 for (i=0 ; i<MAXPLAYERS ; i++)
1674 {
1675 // "1,2,3,4"
1676 DEH_snprintf(name, 9, "STPB%d", i);
1677 callback(name, &p[i]);
1678
1679 // "1,2,3,4"
1680 DEH_snprintf(name, 9, "WIBP%d", i+1);
1681 callback(name, &bp[i]);
1682 }
1683
1684 // Background image
1685
1686 if (gamemode == commercial)
1687 {
1688 M_StringCopy(name, DEH_String("INTERPIC"), sizeof(name));
1689 }
1690 else if (gameversion >= exe_ultimate && wbs->epsd == 3)
1691 {
1692 M_StringCopy(name, DEH_String("INTERPIC"), sizeof(name));
1693 }
1694 else
1695 {
1696 DEH_snprintf(name, sizeof(name), "WIMAP%d", wbs->epsd);
1697 }
1698
1699 // Draw backdrop and save to a temporary buffer
1700
1701 callback(name, &background);
1702 }
1703
WI_loadCallback(char * name,patch_t ** variable)1704 static void WI_loadCallback(char *name, patch_t **variable)
1705 {
1706 *variable = W_CacheLumpName(name, PU_STATIC);
1707 }
1708
WI_loadData(void)1709 void WI_loadData(void)
1710 {
1711 if (gamemode == commercial)
1712 {
1713 NUMCMAPS = 32;
1714 lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMCMAPS,
1715 PU_STATIC, NULL);
1716 }
1717 else
1718 {
1719 lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMMAPS,
1720 PU_STATIC, NULL);
1721 }
1722
1723 WI_loadUnloadData(WI_loadCallback);
1724
1725 // These two graphics are special cased because we're sharing
1726 // them with the status bar code
1727
1728 // your face
1729 star = W_CacheLumpName(DEH_String("STFST01"), PU_STATIC);
1730
1731 // dead face
1732 bstar = W_CacheLumpName(DEH_String("STFDEAD0"), PU_STATIC);
1733 }
1734
WI_unloadCallback(char * name,patch_t ** variable)1735 static void WI_unloadCallback(char *name, patch_t **variable)
1736 {
1737 W_ReleaseLumpName(name);
1738 *variable = NULL;
1739 }
1740
WI_unloadData(void)1741 void WI_unloadData(void)
1742 {
1743 WI_loadUnloadData(WI_unloadCallback);
1744
1745 // We do not free these lumps as they are shared with the status
1746 // bar code.
1747
1748 // W_ReleaseLumpName("STFST01");
1749 // W_ReleaseLumpName("STFDEAD0");
1750 }
1751
WI_Drawer(void)1752 void WI_Drawer (void)
1753 {
1754 switch (state)
1755 {
1756 case StatCount:
1757 if (deathmatch)
1758 WI_drawDeathmatchStats();
1759 else if (netgame)
1760 WI_drawNetgameStats();
1761 else
1762 WI_drawStats();
1763 break;
1764
1765 case ShowNextLoc:
1766 WI_drawShowNextLoc();
1767 break;
1768
1769 case NoState:
1770 WI_drawNoState();
1771 break;
1772 }
1773 }
1774
1775
WI_initVariables(wbstartstruct_t * wbstartstruct)1776 void WI_initVariables(wbstartstruct_t* wbstartstruct)
1777 {
1778
1779 wbs = wbstartstruct;
1780
1781 #ifdef RANGECHECKING
1782 if (gamemode != commercial)
1783 {
1784 if (gameversion >= exe_ultimate)
1785 RNGCHECK(wbs->epsd, 0, 3);
1786 else
1787 RNGCHECK(wbs->epsd, 0, 2);
1788 }
1789 else
1790 {
1791 RNGCHECK(wbs->last, 0, 8);
1792 RNGCHECK(wbs->next, 0, 8);
1793 }
1794 RNGCHECK(wbs->pnum, 0, MAXPLAYERS);
1795 RNGCHECK(wbs->pnum, 0, MAXPLAYERS);
1796 #endif
1797
1798 acceleratestage = 0;
1799 cnt = bcnt = 0;
1800 firstrefresh = 1;
1801 me = wbs->pnum;
1802 plrs = wbs->plyr;
1803
1804 if (!wbs->maxkills)
1805 wbs->maxkills = 1;
1806
1807 if (!wbs->maxitems)
1808 wbs->maxitems = 1;
1809
1810 if (!wbs->maxsecret)
1811 wbs->maxsecret = 1;
1812
1813 if ( gameversion < exe_ultimate )
1814 if (wbs->epsd > 2)
1815 wbs->epsd -= 3;
1816 }
1817
WI_Start(wbstartstruct_t * wbstartstruct)1818 void WI_Start(wbstartstruct_t* wbstartstruct)
1819 {
1820 WI_initVariables(wbstartstruct);
1821 WI_loadData();
1822
1823 if (deathmatch)
1824 WI_initDeathmatchStats();
1825 else if (netgame)
1826 WI_initNetgameStats();
1827 else
1828 WI_initStats();
1829 }
1830