1 /*
2 Copyright (C) 1994-1995 Apogee Software, Ltd.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21 #ifdef DOS
22 #include <dos.h>
23 #include <io.h>
24 #include <conio.h>
25 #endif
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdio.h>
30 #include <ctype.h>
31
32 #include "rt_def.h"
33 #include "rt_main.h"
34 #include "rt_game.h"
35 #include "_rt_game.h"
36 #include "rt_menu.h"
37 #include "z_zone.h"
38 #include "w_wad.h"
39 #include "lumpy.h"
40 #include "rt_playr.h"
41 #include "rt_util.h"
42 #include "rt_ted.h"
43 #include "rt_draw.h"
44 #include "rt_view.h"
45 #include "rt_vid.h"
46 #include "rt_door.h"
47 #include "rt_in.h"
48 #include "rt_str.h"
49 #include "isr.h"
50 #include "rt_build.h"
51 #include "rt_rand.h"
52 #include "rt_cfg.h"
53 #include "rt_sound.h"
54 #include "version.h"
55 #include "rt_crc.h"
56 #include "modexlib.h"
57 #include "engine.h"
58 #include "gmove.h"
59 #include "rt_com.h"
60 #include "rt_net.h"
61 #include "watcom.h"
62 #include "rt_floor.h"
63 #include "rt_msg.h"
64 #include "rt_scale.h"
65 #include "develop.h"
66 //MED
67 #include "memcheck.h"
68
69 #if (SHAREWARE == 1)
70 #define NUMAMMOGRAPHICS 10
71 #else
72 #define NUMAMMOGRAPHICS 20
73 #endif
74
75 //******************************************************************************
76 //
77 // GLOBALS
78 //
79 //******************************************************************************
80
81 int PlayerSnds[5] = {SD_PLAYERTCSND, SD_PLAYERTBSND, SD_PLAYERDWSND,
82 SD_PLAYERLNSND, SD_PLAYERIPFSND};
83
84
85 int SHAKETICS = 0xFFFF;
86 int damagecount = 0;
87 HighScore Scores[MaxScores] =
88 {
89 {"Tom",70000,7,1},
90 {"Chuck",60000,6,1},
91 {"Mark",50000,5,1},
92 {"The Joes",40000,4,1},
93 {"William",30000,3,1},
94 {"Jim",20000,2,1},
95 {"Steve",10000,1,1},
96 };
97
98
99 //******************************************************************************
100 //
101 // LOCALS
102 //
103 //******************************************************************************
104
105 static int KeyX[4] = {KEY1_X, KEY2_X, KEY3_X, KEY4_X};
106
107 static char *Names[ 5 ] =
108 {
109 "Taradino", "Thi", "Doug", "Lorelei", "Ian Paul"
110 };
111
112 static char *LastNames[ 5 ] =
113 {
114 "Cassatt", "Barrett", "Wendt", "Ni", "Freeley"
115 };
116
117 static STR ScoreStr;
118 static STR LivesStr;
119 static STR TriadStr;
120 static STR KillStr;
121
122 static pic_t *lifeptnums[10];
123 static pic_t *lifenums[10];
124 static pic_t *timenums[10];
125 static pic_t *scorenums[10];
126 static pic_t *keys[4];
127 static pic_t *men[5];
128
129 static pic_t *health[6];
130 static pic_t *ammo[26];
131 static pic_t *erase;
132 static pic_t *eraseb;
133 static pic_t *fragpic[ 5 ];
134 static pic_t *frag100pic[ 5 ];
135 static pic_t *negfragpic[ 5 ];
136 static pic_t *menneg[ 5 ];
137 static pic_t *blankfragpic;
138
139 static int powerpics;
140 static int poweradjust;
141
142 static int poweruptime;
143 static int powerupheight;
144 static int protectiontime;
145 static int protectionheight;
146
147
148 static boolean EndLevelStuff = false;
149 static boolean borderset = false;
150 static int oldsec = -1;
151
152 static pic_t *BkPic;
153 int SaveTime = 0;
154 int oldhealth;
155
156 static int oldplayerhealth;
157 static int oldpercenthealth;
158
159 static int playeruniformcolor;
160
161 #define NUMBONUSES 11
162 #define BONUSBONUS 100000
163
164 void DrawPPic (int xpos, int ypos, int width, int height, byte *src, int num, boolean up, boolean bufferofsonly);
165
166 //******************************************************************************
167 //
168 // V_ReDrawBkgnd ()
169 //
170 //******************************************************************************
171
V_ReDrawBkgnd(int x,int y,int width,int height,boolean shade)172 void V_ReDrawBkgnd (int x, int y, int width, int height, boolean shade)
173 {
174 byte *src;
175 byte *dest;
176 byte *origdest;
177 int j,
178 k,
179 planes,
180 mask,
181 m;
182
183 m = (x&3);
184 mask = (1 << m);
185
186 #ifdef DOS
187 origdest = (byte *)(bufferofs+ylookup[y]+(x>>2));
188 #else
189 origdest = (byte *)(bufferofs+ylookup[y]+x);
190 #endif
191
192 if (VW_MarkUpdateBlock (x, y, x+width-1, y+height-1))
193 {
194 for (planes = 0; planes < 4; planes++)
195 {
196 src = (&(BkPic->data)+((80*200)*m)+(80*y)+(x>>2));
197 dest = origdest;
198
199 #ifdef DOS
200 VGAMAPMASK (mask);
201 #else
202 dest += planes;
203 #endif
204
205 for (j = 0; j < height; j++)
206 {
207 for (k = 0; k < (width/4); k++) {
208 if (shade) {
209 *dest = *(colormap + ((MENUSHADELEVEL>>2)<<8) + *src++);
210 } else {
211 *dest = *src++;
212 }
213 #ifdef DOS
214 dest++;
215 #else
216 dest += 4;
217 #endif
218 }
219
220 #ifndef DOS
221 // draw the remainder. did the DOS version even bother? - SBF
222 if ((width & 3) > planes) {
223 if (shade) {
224 *dest = *(colormap + ((MENUSHADELEVEL>>2)<<8) + *src);
225 } else {
226 *dest = *src;
227 }
228 }
229 #endif
230
231 src += (80-(width/4));
232 #ifdef DOS
233 dest += (linewidth-(width/4));
234 #else
235 dest += (linewidth-(width&~3));
236 #endif
237 }
238
239 m++;
240
241 mask <<= 1;
242
243 if (mask == 16)
244 {
245 x+=4;
246 mask = 1;
247 m = 0;
248 #ifdef DOS
249 origdest++;
250 #endif
251 }
252 }
253 }
254 }
255
256
257 //******************************************************************************
258 //
259 // CacheLumpGroup ()
260 //
261 //******************************************************************************
CacheLumpGroup(char * startlump,pic_t ** lumparray,int numberoflumps)262 void CacheLumpGroup
263 (
264 char *startlump,
265 pic_t **lumparray,
266 int numberoflumps
267 )
268
269 {
270 int lumpnum;
271 int i;
272
273 lumpnum = W_GetNumForName( startlump );
274
275 for( i = 0; i < numberoflumps; i++ )
276 {
277 lumparray[ i ] = ( pic_t * )W_CacheLumpNum( lumpnum + i, PU_LEVEL, Cvt_pic_t, 1 );
278 }
279 }
280
281 //******************************************************************************
282 //
283 // SetupPlayScreen ()
284 //
285 //******************************************************************************
SetupPlayScreen(void)286 void SetupPlayScreen
287 (
288 void
289 )
290
291 {
292 int i;
293 int j;
294 int num;
295
296 erase = ( pic_t * )W_CacheLumpName( "erase", PU_LEVEL, Cvt_pic_t, 1 );
297 eraseb = ( pic_t * )W_CacheLumpName( "eraseb", PU_LEVEL, Cvt_pic_t, 1 );
298
299 CacheLumpGroup( "tmnum0", timenums, 10 );
300 CacheLumpGroup( "lfnum0", lifeptnums, 10 );
301 CacheLumpGroup( "lvnum0", lifenums, 10 );
302 CacheLumpGroup( "health1b", health, 6 );
303 CacheLumpGroup( "key1", keys, 4 );
304
305 if ( !BATTLEMODE )
306 {
307 CacheLumpGroup( "scnum0", scorenums, 10 );
308
309 num = locplayerstate->player;
310 men[ num ] = ( pic_t * )W_CacheLumpNum( W_GetNumForName( "MAN1" ) +
311 num, PU_LEVEL, Cvt_pic_t, 1 );
312 }
313 else
314 {
315 int man;
316 int num100;
317 int negnum;
318 int negman;
319
320 CacheLumpGroup( "kilnum0", scorenums, 10 );
321
322 negnum = W_GetNumForName( "botnpic1" );
323 num = W_GetNumForName( "botpic0" );
324 num100 = W_GetNumForName( "botopic1" );
325 negman = W_GetNumForName( "negman1" );
326 man = W_GetNumForName( "man1" );
327
328 blankfragpic = ( pic_t * )W_CacheLumpNum( num, PU_LEVEL, Cvt_pic_t, 1 );
329 num++;
330
331 for( i = 0; i < numplayers; i++ )
332 {
333 j = PLAYERSTATE[ i ].player;
334 if ( !gamestate.teamplay )
335 {
336 fragpic[ j ] = ( pic_t * )W_CacheLumpNum( num + j, PU_LEVEL, Cvt_pic_t, 1 );
337 frag100pic[ j ] = ( pic_t * )W_CacheLumpNum( num100 + j, PU_LEVEL, Cvt_pic_t, 1 );
338 negfragpic[ j ] = ( pic_t * )W_CacheLumpNum( negnum + j, PU_LEVEL, Cvt_pic_t, 1 );
339 }
340 else
341 {
342 negfragpic[ j ] = ( pic_t * )W_CacheLumpName( "teamnpic", PU_LEVEL, Cvt_pic_t, 1 );
343 fragpic[ j ] = ( pic_t * )W_CacheLumpName( "teampic", PU_LEVEL, Cvt_pic_t, 1 );
344 frag100pic[ j ] = fragpic[ j ];
345 }
346
347 menneg[ j ] = ( pic_t * )W_CacheLumpNum( negman + j, PU_LEVEL, Cvt_pic_t, 1 );
348 men[ j ] = ( pic_t * )W_CacheLumpNum( man + j, PU_LEVEL, Cvt_pic_t, 1 );
349 }
350 }
351
352 powerpics = W_GetNumForName( "GDMODEP" );
353 poweradjust = POWERUPTICS / 16;
354
355 num = W_GetNumForName( "INF_B" );
356
357 // bullet weapons
358 ammo[0] = ( pic_t * )W_CacheLumpNum( num, PU_LEVEL, Cvt_pic_t, 1 );
359 ammo[1] = ( pic_t * )W_CacheLumpNum( num, PU_LEVEL, Cvt_pic_t, 1 );
360 ammo[2] = ( pic_t * )W_CacheLumpNum( num++, PU_LEVEL, Cvt_pic_t, 1 );
361
362
363 for(i=3;i < 13; i++ )
364 {
365 ammo[ i ] = ( pic_t * )W_CacheLumpNum( num++, PU_LEVEL, Cvt_pic_t, 1 );
366 }
367
368 ammo[13] = ( pic_t * )W_CacheLumpNum( num, PU_LEVEL, Cvt_pic_t, 1 );
369 ammo[14] = ( pic_t * )W_CacheLumpNum( num, PU_LEVEL, Cvt_pic_t, 1 );
370 ammo[15] = ( pic_t * )W_CacheLumpNum( num++, PU_LEVEL, Cvt_pic_t, 1 );
371
372
373 for(i=16;i < 26; i++ )
374 {
375 ammo[ i ] = ( pic_t * )W_CacheLumpNum( num++, PU_LEVEL, Cvt_pic_t, 1 );
376 }
377
378
379 oldplayerhealth = -1;
380 oldpercenthealth = -1;
381 }
382
383
384
385 //******************************************************************************
386 //
387 // GameMemToScreen()
388 //
389 //******************************************************************************
390
GameMemToScreen(pic_t * source,int x,int y,int bufferofsonly)391 void GameMemToScreen
392 (
393 pic_t *source,
394 int x,
395 int y,
396 int bufferofsonly
397 )
398
399 {
400 if ( bufferofsonly )
401 {
402 VL_MemToScreen( ( byte * )&source->data, source->width,
403 source->height, x, y );
404 }
405 else
406 {
407 GM_MemToScreen( ( byte * )&source->data, source->width,
408 source->height, x, y );
409 }
410 }
411
412
413 //******************************************************************************
414 //
415 // DrawPlayScreen ()
416 //
417 //******************************************************************************
DrawPlayScreen(boolean bufferofsonly)418 void DrawPlayScreen
419 (
420 boolean bufferofsonly
421 )
422
423 {
424 pic_t *shape;
425 int shapenum;
426
427 if ( SHOW_TOP_STATUS_BAR() )
428 {
429 shape = W_CacheLumpName( "stat_bar", PU_CACHE, Cvt_pic_t, 1 );
430 GameMemToScreen( shape, 0, 0, bufferofsonly );
431 }
432
433 if ( BATTLEMODE )
434 {
435 DrawKills( bufferofsonly );
436 }
437
438 if ( SHOW_BOTTOM_STATUS_BAR() )
439 {
440 shape = ( pic_t * ) W_CacheLumpName( "bottbar", PU_CACHE, Cvt_pic_t, 1 );
441
442 if ( SHOW_KILLS() )
443 {
444 GameMemToScreen( shape, 0, 160, bufferofsonly );
445 }
446 else
447 {
448 GameMemToScreen( shape, 0, 184, bufferofsonly );
449 }
450
451 DrawBarAmmo( bufferofsonly );
452 DrawBarHealth( bufferofsonly );
453
454 if ( demoplayback )
455 {
456 shape = ( pic_t * )W_CacheLumpName( "demo", PU_CACHE, Cvt_pic_t, 1 );
457 DrawPPic( 148, 185, shape->width, shape->height,
458 ( byte * )&shape->data, 1, true, bufferofsonly );
459 }
460 }
461
462 if ( !SHOW_TOP_STATUS_BAR() )
463 {
464 return;
465 }
466
467
468 oldsec = -1;
469
470 DrawTime( bufferofsonly );
471
472 if ( !BATTLEMODE )
473 {
474 int character;
475 int width;
476 int height;
477
478 character = locplayerstate->player;
479 GameMemToScreen( men[ character ], MEN_X, MEN_Y,
480 bufferofsonly );
481
482 CurrentFont = tinyfont;
483
484 // Draw player's name
485 DrawGameString ( MEN_X + 3, MEN_Y + 2, Names[ character ], bufferofsonly );
486
487 VW_MeasurePropString( LastNames[ character ], &width, &height );
488
489 DrawGameString ( MEN_X + 44 - width, MEN_Y + 8,
490 Names[ character + 5 ], bufferofsonly );
491
492 UpdateLives( locplayerstate->lives );
493 UpdateScore( gamestate.score );
494 DrawTriads( bufferofsonly );
495 DrawLives( bufferofsonly );
496 DrawScore( bufferofsonly );
497 }
498
499 DrawKeys( bufferofsonly );
500
501 if ( locplayerstate->poweruptime )
502 {
503 if ( player->flags & FL_GODMODE )
504 {
505 shapenum = powerpics;
506 }
507 else if ( player->flags & FL_DOGMODE )
508 {
509 shapenum = powerpics + 1;
510 }
511 else if ( player->flags & FL_FLEET )
512 {
513 shapenum = powerpics + 2;
514 }
515 else if ( player->flags & FL_ELASTO )
516 {
517 shapenum = powerpics + 3;
518 }
519 else if ( player->flags & FL_SHROOMS )
520 {
521 shapenum = powerpics + 4;
522 }
523
524 shape = ( pic_t * )W_CacheLumpNum ( shapenum, PU_CACHE, Cvt_pic_t, 1 );
525
526 GameMemToScreen( eraseb, POWERUP1X, POWERUPY, bufferofsonly );
527
528 DrawMPPic( POWERUP1X, POWERUPY + powerupheight, shape->width,
529 shape->height - powerupheight, powerupheight,
530 ( byte * )&shape->data, bufferofsonly );
531 }
532
533
534 if ( locplayerstate->protectiontime )
535 {
536 if ( player->flags & FL_BPV )
537 {
538 shapenum = powerpics + 6;
539 }
540 else if ( player->flags & FL_GASMASK )
541 {
542 shapenum = powerpics + 5;
543 }
544 else if ( player->flags & FL_AV )
545 {
546 shapenum = powerpics + 7;
547 }
548
549 shape = ( pic_t * )W_CacheLumpNum( shapenum, PU_CACHE, Cvt_pic_t, 1 );
550
551 GameMemToScreen( eraseb, POWERUP2X, POWERUPY, bufferofsonly );
552
553 DrawMPPic( POWERUP2X, POWERUPY + protectionheight, shape->width,
554 shape->height - protectionheight, protectionheight,
555 ( byte * )&shape->data, bufferofsonly );
556 }
557 }
558
559
560 //******************************************************************************
561 //
562 // ShortenCodeName()
563 //
564 //******************************************************************************
GetShortCodeName(char * dest,char * source,int maxwidth)565 void GetShortCodeName
566 (
567 char *dest,
568 char *source,
569 int maxwidth
570 )
571
572 {
573 int width;
574 int height;
575 int length;
576
577 strcpy( dest, source );
578
579 // Shorten name to fit
580 length = strlen( dest );
581 VW_MeasurePropString( dest, &width, &height );
582 while( width > maxwidth )
583 {
584 dest[ length ] = 0;
585 length--;
586 VW_MeasurePropString( dest, &width, &height );
587 }
588 }
589
590
591 //******************************************************************************
592 //
593 // DrawKills ()
594 //
595 //******************************************************************************
DrawKills(boolean bufferofsonly)596 void DrawKills
597 (
598 boolean bufferofsonly
599 )
600 {
601 int rank;
602 int xpos;
603 char codename[ MAXCODENAMELENGTH ];
604 int width;
605 int playernum;
606 int playerimage;
607 int temp;
608 pic_t *pic;
609
610 CurrentFont = tinyfont;
611
612 if ( SHOW_TOP_STATUS_BAR() )
613 {
614 playernum = BATTLE_Team[ consoleplayer ];
615 playerimage = BATTLE_TeamLeader[ playernum ];
616
617 // Set uniformcolor
618 playeruniformcolor = PLAYERSTATE[ playerimage ].uniformcolor;
619
620 // Draw player's point box
621 pic = men[ PLAYERSTATE[ playerimage ].player ];
622 if ( ( gamestate.ShowScores ) && ( BATTLE_Points[ playernum ] < 0 ) )
623 {
624 pic = menneg[ PLAYERSTATE[ playerimage ].player ];
625 }
626
627 DrawPPic( MEN_X, MEN_Y, pic->width, pic->height,
628 ( byte * )&pic->data, 1, true, bufferofsonly );
629
630 // Draw player's name
631 if ( gamestate.teamplay )
632 {
633 GetShortCodeName( codename, colorname[ playeruniformcolor ],
634 42 );
635 }
636 else
637 {
638 GetShortCodeName( codename, PLAYERSTATE[ playerimage ].codename,
639 42 );
640 }
641
642 DrawGameString ( MEN_X + 2, MEN_Y + 2, codename, bufferofsonly );
643 // Draw "It" if player is 'it'
644 if ( ( ( gamestate.battlemode == battle_Tag ) ||
645 ( gamestate.battlemode == battle_Hunter ) ) &&
646 ( BATTLE_It == BATTLE_Team[ consoleplayer ] ) )
647 {
648 DrawGameString ( MEN_X + 22, MEN_Y + 8,
649 "It", bufferofsonly);
650 }
651
652 // Draw triad if player is 'it' or has caught a triad
653 if ( PLAYER[ consoleplayer ]->flags & FL_DESIGNATED )
654 {
655 pic = W_CacheLumpName( "smalltri", PU_CACHE, Cvt_pic_t, 1 );
656 DrawPPic( TRIAD_X - 1, TRIAD_Y - 2, pic->width, pic->height,
657 ( byte * )&pic->data, 1, true, bufferofsonly );
658 }
659 else if ( ( gamestate.ShowScores ) &&
660 ( DisplayPoints != bo_kills_infinite ) )
661 {
662 // Draw Kill goal
663 if ( ( gamestate.battlemode == battle_Collector ) ||
664 ( gamestate.battlemode == battle_StandAloneGame ) )
665 {
666 temp = BATTLE_NumCollectorItems;
667 }
668 else
669 {
670 temp = DisplayPoints;
671 }
672
673 ltoa ( temp % 1000, KillStr.str, 10);
674 KillStr.length = strlen (KillStr.str);
675 DrawNumber (TRIAD_X - 6, TRIAD_Y, 3, 5, bufferofsonly);
676 }
677
678 // Set uniformcolor
679 playeruniformcolor = PLAYERSTATE[ consoleplayer ].uniformcolor;
680
681 if ( gamestate.ShowScores )
682 {
683 // Draw local player's points
684 temp = BATTLE_Points[ playernum ] % 1000;
685 if ( temp < 0 )
686 {
687 temp = -temp;
688 }
689 ltoa ( temp, KillStr.str, 10);
690 KillStr.length = strlen (KillStr.str);
691
692 DrawNumber( LIVES_X - 12, LIVES_Y, 3, 4, bufferofsonly);
693 }
694 else
695 {
696 pic = W_CacheLumpName( "minus", PU_CACHE, Cvt_pic_t, 1 );
697 StatusDrawColoredPic( LIVES_X - 12, LIVES_Y, pic, bufferofsonly, playeruniformcolor );
698 StatusDrawColoredPic( LIVES_X - 4, LIVES_Y, pic, bufferofsonly, playeruniformcolor );
699 }
700
701 // Draw whoever is 'It'
702 playernum = BATTLE_It;
703 playerimage = BATTLE_TeamLeader[ playernum ];
704
705 // Set uniformcolor
706 playeruniformcolor = PLAYERSTATE[ playerimage ].uniformcolor;
707
708 // Draw player's point box
709 pic = men[ PLAYERSTATE[ playerimage ].player ];
710 if ( ( gamestate.ShowScores ) && ( BATTLE_Points[ playernum ] < 0 ) )
711 {
712 pic = menneg[ PLAYERSTATE[ playerimage ].player ];
713 }
714
715 DrawPPic( LEADER_X, LEADER_Y, pic->width, pic->height,
716 (byte *)&pic->data, 1, true, bufferofsonly );
717
718 if ( ( gamestate.battlemode == battle_Tag ) ||
719 ( gamestate.battlemode == battle_Hunter ) )
720 {
721 DrawGameString ( LEADER_X + 22, LEADER_Y + 8,
722 "It", bufferofsonly);
723 }
724
725 if ( gamestate.ShowScores )
726 {
727 // Draw number of points
728 temp = BATTLE_Points[ playernum ] % 1000;
729 if ( temp < 0 )
730 {
731 temp = -temp;
732 }
733 ltoa ( temp, KillStr.str, 10);
734 KillStr.length = strlen (KillStr.str);
735 DrawNumber ( LEADER_NUM_X, LEADER_NUM_Y, 3, 4, bufferofsonly);
736 }
737 else
738 {
739 pic = W_CacheLumpName( "minus", PU_CACHE, Cvt_pic_t, 1 );
740 StatusDrawColoredPic( LEADER_NUM_X, LEADER_NUM_Y, pic, bufferofsonly, playeruniformcolor );
741 StatusDrawColoredPic( LEADER_NUM_X + 8, LEADER_NUM_Y, pic, bufferofsonly, playeruniformcolor );
742 }
743
744 // Draw name
745 if ( gamestate.teamplay )
746 {
747 DrawGameString ( LEADER_NAME_X, LEADER_NAME_Y - 1,
748 colorname[ playeruniformcolor ], bufferofsonly);
749 }
750 else
751 {
752 GetShortCodeName( codename, PLAYERSTATE[ playerimage ].codename,
753 42 );
754 DrawGameString ( LEADER_NAME_X - 1, LEADER_NAME_Y,
755 codename, bufferofsonly);
756 }
757 }
758
759 // Only draw the rest of the rifraff when the kill count is selected
760 if ( !SHOW_KILLS() )
761 {
762 return;
763 }
764
765 // Draw all the other losers
766 xpos = KILLS_X;
767 for( rank = 0; rank < BATTLE_NumberOfTeams; rank++ )
768 {
769 playernum = BATTLE_PlayerOrder[ rank ];
770 playerimage = BATTLE_TeamLeader[ playernum ];
771
772 if ( ( playernum == BATTLE_It ) && SHOW_TOP_STATUS_BAR() )
773 {
774 continue;
775 }
776
777 // Set uniformcolor
778 playeruniformcolor = PLAYERSTATE[ playerimage ].uniformcolor;
779
780 // Draw player's point box
781 pic = fragpic[ PLAYERSTATE[ playerimage ].player ];
782 if ( gamestate.ShowScores )
783 {
784 if ( BATTLE_Points[ playernum ] < 0 )
785 {
786 pic = negfragpic[ PLAYERSTATE[ playerimage ].player ];
787 }
788 else if ( BATTLE_Points[ playernum ] >= 100 )
789 {
790 pic = frag100pic[ PLAYERSTATE[ playerimage ].player ];
791 }
792 }
793 DrawPPic( xpos, KILLS_Y, pic->width, pic->height,
794 (byte *)&pic->data, 1, true, bufferofsonly );
795
796 // Draw number of points
797 if ( gamestate.ShowScores )
798 {
799 temp = BATTLE_Points[ playernum ] % 1000;
800 if ( temp < 0 )
801 {
802 temp = -temp;
803 }
804 ltoa ( temp, KillStr.str, 10);
805 KillStr.length = strlen (KillStr.str);
806 width = 2;
807 if ( temp > 99 )
808 {
809 width = 3;
810 }
811 DrawNumber( xpos + KILLS_OFFSET + 16 - ( 8 * width ), KILLS_Y, width, 4, bufferofsonly);
812 }
813 else
814 {
815 pic = W_CacheLumpName( "minus", PU_CACHE, Cvt_pic_t, 1 );
816 StatusDrawColoredPic( ( xpos + KILLS_OFFSET ), KILLS_Y, pic, bufferofsonly, playeruniformcolor );
817 StatusDrawColoredPic( ( xpos + KILLS_OFFSET + 8 ), KILLS_Y, pic, bufferofsonly, playeruniformcolor );
818 }
819
820 // Get codename
821 if ( gamestate.teamplay )
822 {
823 GetShortCodeName( codename, colorname[ playeruniformcolor ],
824 KILLS_WIDTH - 2 );
825 }
826 else
827 {
828 GetShortCodeName( codename, PLAYERSTATE[ playerimage ].codename,
829 KILLS_WIDTH - 2 );
830 }
831
832 // Draw name
833 DrawGameString (xpos + 1, KILLS_NAME_Y, codename, bufferofsonly);
834
835 // Advance to next position
836 xpos += KILLS_WIDTH;
837
838 if ( xpos >= 320 )
839 {
840 break;
841 }
842 }
843
844 for( rank = BATTLE_NumberOfTeams; rank <= MAXKILLBOXES; rank++ )
845 {
846 if ( xpos >= 320 )
847 {
848 break;
849 }
850
851 pic = blankfragpic;
852 DrawPPic( xpos, KILLS_Y, pic->width, pic->height,
853 (byte *)&pic->data, 1, true, bufferofsonly );
854
855 // Advance to next position
856 xpos += KILLS_WIDTH;
857 }
858 }
859
860
861 //******************************************************************************
862 //
863 // DrawPlayers ()
864 //
865 //******************************************************************************
DrawPlayers(void)866 void DrawPlayers
867 (
868 void
869 )
870
871 {
872 int num;
873 int xpos;
874 char codename[ MAXCODENAMELENGTH ];
875 int length;
876 int width;
877 int height;
878 int team;
879 int player;
880 int character;
881 pic_t *pic;
882 pic_t *enemy;
883 pic_t *friend;
884
885 num = W_GetNumForName( "botpic1" );
886
887 scorenums[ 0 ]= ( pic_t * )W_CacheLumpName( "kilnum0", PU_CACHE, Cvt_pic_t, 1 );
888 friend = ( pic_t * )W_CacheLumpName( "t_friend", PU_CACHE, Cvt_pic_t, 1 );
889 enemy = ( pic_t * )W_CacheLumpName( "t_enemy", PU_CACHE, Cvt_pic_t, 1 );
890
891 // Draw all the losers
892 CurrentFont = tinyfont;
893
894 xpos = ( 320 - min( numplayers, MAXKILLBOXES ) * KILLS_WIDTH ) / 2;
895
896 for( team = 0; team < BATTLE_NumberOfTeams; team++ )
897 {
898 for( player = 0; player < numplayers; player++ )
899 {
900 if ( BATTLE_Team[ player ] == team )
901 {
902 character = PLAYERSTATE[ player ].player;
903
904 fragpic[ character ] = ( pic_t * )W_CacheLumpNum( num +
905 character, PU_CACHE, Cvt_pic_t, 1 );
906
907 if ( ( numplayers <= MAXKILLBOXES ) ||
908 ( player != consoleplayer ) )
909 {
910 // Set uniformcolor
911 playeruniformcolor = PLAYERSTATE[ player ].uniformcolor;
912
913 // Draw player's point box
914 pic = fragpic[ PLAYERSTATE[ player ].player ];
915
916 VWB_DrawPic ( xpos, PLAYERS_Y, pic );
917 if ( gamestate.teamplay )
918 {
919 if ( BATTLE_Team[ player ] == BATTLE_Team[ consoleplayer ] )
920 {
921 VWB_DrawPic ( xpos, PLAYERS_TEAM_Y, friend );
922 }
923 else
924 {
925 VWB_DrawPic ( xpos, PLAYERS_TEAM_Y, enemy );
926 }
927 }
928
929 strcpy( KillStr.str, "00" );
930 KillStr.length = strlen ( KillStr.str );
931 DrawNumber( xpos + KILLS_OFFSET, PLAYERS_Y, 2, 4, true );
932
933 // Get codename
934 strcpy( codename, PLAYERSTATE[ player ].codename );
935
936 // Shorten name to fit into point count
937 length = strlen( codename );
938 US_MeasureStr( &width, &height, codename );
939 while( width > KILLS_WIDTH )
940 {
941 codename[ length ] = 0;
942 length--;
943 US_MeasureStr( &width, &height, codename );
944 }
945
946 // Draw name
947 PrintX = xpos;
948 PrintY = PLAYERS_NAME_Y;
949 US_Print( codename );
950
951 // Advance to next position
952 xpos += KILLS_WIDTH;
953 }
954 }
955 if ( xpos >= 320 )
956 {
957 break;
958 }
959 }
960 if ( xpos >= 320 )
961 {
962 break;
963 }
964 }
965 }
966
967 //******************************************************************************
968 //
969 // StatusDrawPic ()
970 //
971 //******************************************************************************
972
StatusDrawPic(unsigned x,unsigned y,pic_t * nums,boolean bufferofsonly)973 void StatusDrawPic (unsigned x, unsigned y, pic_t *nums, boolean bufferofsonly)
974 {
975 DrawMPPic (x, y, nums->width, nums->height, 0,
976 (byte *)&nums->data, bufferofsonly);
977 }
978
979 //******************************************************************************
980 //
981 // StatusDrawColoredPic ()
982 //
983 //******************************************************************************
984
StatusDrawColoredPic(unsigned x,unsigned y,pic_t * nums,boolean bufferofsonly,int color)985 void StatusDrawColoredPic (unsigned x, unsigned y, pic_t *nums, boolean bufferofsonly, int color)
986 {
987 DrawColoredMPPic (x, y, nums->width, nums->height, 0,
988 (byte *)&nums->data, bufferofsonly, color);
989 }
990
991 //******************************************************************************
992 //
993 // DrawGameString ()
994 //
995 // draw string to game screen at x,y
996 //
997 //******************************************************************************
998
DrawGameString(int x,int y,char * str,boolean bufferofsonly)999 void DrawGameString (int x, int y, char * str, boolean bufferofsonly)
1000 {
1001 unsigned tempbuf;
1002
1003 px=x;
1004 py=y;
1005
1006 if (bufferofsonly==true)
1007 VW_DrawPropString (str);
1008 else
1009 {
1010 tempbuf=bufferofs;
1011 bufferofs=page1start;
1012 VW_DrawPropString (str);
1013 px=x;
1014 py=y;
1015 bufferofs=page2start;
1016 VW_DrawPropString (str);
1017 px=x;
1018 py=y;
1019 bufferofs=page3start;
1020 VW_DrawPropString (str);
1021 bufferofs=tempbuf;
1022 }
1023 }
1024
1025
1026 //******************************************************************************
1027 //
1028 // DrawNumber ()
1029 //
1030 // right justifies and pads with zeros
1031 //
1032 //******************************************************************************
1033
DrawNumber(int x,int y,int width,int which,boolean bufferofsonly)1034 void DrawNumber (int x, int y, int width, int which, boolean bufferofsonly)
1035 {
1036 unsigned length,c;
1037 char *str;
1038 byte z;
1039
1040 switch (which)
1041 {
1042 case 1:
1043 str = ScoreStr.str;
1044 length = ScoreStr.length;
1045 break;
1046
1047 case 2:
1048 str = LivesStr.str;
1049 length = LivesStr.length;
1050 break;
1051
1052 case 3:
1053 str = TriadStr.str;
1054 length = TriadStr.length;
1055 break;
1056
1057 case 4:
1058 case 5:
1059 case 6:
1060 str = KillStr.str;
1061 length = KillStr.length;
1062 break;
1063 }
1064
1065 z = width - length; // Num zeros
1066
1067 while (z)
1068 {
1069 switch (which)
1070 {
1071 case 1: StatusDrawPic (x, y, scorenums[0], bufferofsonly); x+=8; break;
1072 case 2: StatusDrawPic (x, y, lifenums[0], bufferofsonly); x+=8; break;
1073 case 3: StatusDrawPic (x, y, lifeptnums[0], bufferofsonly); x+=6; break;
1074 case 4: StatusDrawColoredPic (x, y, scorenums[0], bufferofsonly, playeruniformcolor); x+=8; break;
1075 case 5: StatusDrawPic (x, y, lifeptnums[0], bufferofsonly); x+=6; break;
1076 case 6: StatusDrawPic (x, y, lifenums[0], bufferofsonly); x+=8; break;
1077 }
1078 z--;
1079 }
1080
1081 c = length <= (unsigned)width ? 0 : length-width;
1082 while (c < length)
1083 {
1084 switch (which)
1085 {
1086 case 1: StatusDrawPic (x, y, scorenums[str[c]-'0'], bufferofsonly); x+=8; break;
1087 case 2: StatusDrawPic (x, y, lifenums[str[c]-'0'], bufferofsonly); x+=8; break;
1088 case 3: StatusDrawPic (x, y, lifeptnums[str[c]-'0'], bufferofsonly); x+=6; break;
1089 case 4: StatusDrawColoredPic (x, y, scorenums[str[c]-'0'], bufferofsonly, playeruniformcolor); x+=8; break;
1090 case 5: StatusDrawPic (x, y, lifeptnums[str[c]-'0'], bufferofsonly); x+=6; break;
1091 case 6: StatusDrawPic (x, y, lifenums[str[c]-'0'], bufferofsonly); x+=8; break;
1092 }
1093 c++;
1094 }
1095 }
1096
1097
1098
1099 //******************************************************************************
1100 //
1101 // HealPlayer ()
1102 //
1103 //******************************************************************************
1104
HealPlayer(int points,objtype * ob)1105 void HealPlayer
1106 (
1107 int points,
1108 objtype *ob
1109 )
1110
1111 {
1112 playertype *pstate;
1113 int maxhitpoints;
1114
1115 M_LINKSTATE( ob, pstate );
1116
1117 pstate->health += points;
1118 maxhitpoints = MaxHitpointsForCharacter( pstate );
1119 if ( pstate->health > maxhitpoints )
1120 {
1121 pstate->health = maxhitpoints;
1122 }
1123
1124 if ( ( SHOW_BOTTOM_STATUS_BAR() ) && ( ob == player ) )
1125 {
1126 DrawBarHealth( false );
1127 }
1128 }
1129
1130 //******************************************************************************
1131 //
1132 // DrawLives ()
1133 //
1134 //******************************************************************************
1135
DrawLives(boolean bufferofsonly)1136 void DrawLives
1137 (
1138 boolean bufferofsonly
1139 )
1140
1141 {
1142 if ( !SHOW_TOP_STATUS_BAR() )
1143 {
1144 return;
1145 }
1146
1147 if ( !EndLevelStuff )
1148 {
1149 DrawNumber( LIVES_X, LIVES_Y, 2, 2, bufferofsonly );
1150 }
1151 }
1152
1153
1154 //******************************************************************************
1155 //
1156 // GiveExtraMan ()
1157 //
1158 //******************************************************************************
1159
GiveExtraMan(void)1160 void GiveExtraMan (void)
1161 {
1162 if (locplayerstate->lives < 99)
1163 locplayerstate->lives++;
1164 UpdateLives (locplayerstate->lives);
1165 DrawLives (false);
1166 // SD_PlaySound (BONUS1UPSND);
1167 }
1168
1169
1170
1171 //******************************************************************************
1172 //
1173 // DrawScore ()
1174 //
1175 //******************************************************************************
1176
DrawScore(boolean bufferofsonly)1177 void DrawScore
1178 (
1179 boolean bufferofsonly
1180 )
1181
1182 {
1183 if ( !SHOW_TOP_STATUS_BAR() )
1184 {
1185 return;
1186 }
1187
1188 if ( !BATTLEMODE )
1189 {
1190 DrawNumber( SCORE_X, SCORE_Y, 10, 1, bufferofsonly );
1191 }
1192 }
1193
1194
1195 //******************************************************************************
1196 //
1197 // GivePoints ()
1198 //
1199 //******************************************************************************
1200
GivePoints(long points)1201 void GivePoints (long points)
1202 {
1203 gamestate.score += points;
1204
1205 UpdateScore (gamestate.score);
1206
1207 if (!EndLevelStuff)
1208 DrawScore (false);
1209 }
1210
1211
1212 //******************************************************************************
1213 //
1214 // GiveKey ()
1215 //
1216 //******************************************************************************
1217
GiveKey(int key)1218 void GiveKey (int key)
1219 {
1220 locplayerstate->keys |= (1<<key);
1221 DrawKeys (false);
1222 }
1223
1224
1225 //******************************************************************************
1226 //
1227 // GiveLives ()
1228 //
1229 //******************************************************************************
1230
GiveLives(int newlives)1231 void GiveLives (int newlives)
1232 {
1233 if ((locplayerstate->lives + newlives) <= 99)
1234 locplayerstate->lives += newlives;
1235 else
1236 locplayerstate->lives = 99;
1237 UpdateLives (locplayerstate->lives);
1238 DrawLives (false);
1239 }
1240
1241
1242 #define EnableOldWeapon(pstate) \
1243 { \
1244 LASTSTAT->flags |= FL_ABP; \
1245 LASTSTAT->flags &= ~FL_RESPAWN; \
1246 MakeStatActive(LASTSTAT); \
1247 pstate->weaponx = ob->tilex; \
1248 pstate->weapony = ob->tiley; \
1249 }
1250
1251
1252 //******************************************************************************
1253 //
1254 // GiveWeapon ()
1255 //
1256 //******************************************************************************
1257
GiveWeapon(objtype * ob,int weapon)1258 void GiveWeapon
1259 (
1260 objtype *ob,
1261 int weapon
1262 )
1263
1264 {
1265 playertype *pstate;
1266
1267 M_LINKSTATE( ob, pstate );
1268
1269 if ( pstate->weapon == weapon )
1270 {
1271 return;
1272 }
1273
1274 pstate->HASBULLETWEAPON[ weapon ] = 1;
1275 if ( ( pstate->weapon == pstate->bulletweapon ) &&
1276 ( pstate->weapon < weapon ) )
1277 {
1278 pstate->new_weapon = weapon;
1279 pstate->weapondowntics = WEAPONS[ pstate->weapon ].screenheight / GMOVE;
1280 if ( ( ob == player ) && ( SHOW_BOTTOM_STATUS_BAR() ) )
1281 {
1282 DrawBarAmmo( false );
1283 }
1284 }
1285
1286 if ( gamestate.BattleOptions.WeaponPersistence )
1287 {
1288 SpawnStatic(ob->tilex,ob->tiley,GetItemForWeapon(weapon),9);
1289 EnableOldWeapon(pstate);
1290 }
1291
1292 if ( weapon > pstate->bulletweapon )
1293 {
1294 pstate->bulletweapon = weapon;
1295 }
1296 }
1297
1298
1299 //******************************************************************************
1300 //
1301 // GiveMissileWeapon ()
1302 //
1303 //******************************************************************************
1304
GiveMissileWeapon(objtype * ob,int which)1305 void GiveMissileWeapon(objtype * ob, int which)
1306 {
1307 playertype * pstate;
1308
1309
1310 //pstate = (ob==player)?(&playerstate):(&remoteplayerstate);
1311 M_LINKSTATE(ob,pstate);
1312
1313 if (!gamestate.BattleOptions.WeaponPersistence)
1314 {
1315 if (pstate->ammo &&
1316 (pstate->missileweapon != -1) &&
1317 (!(WEAPON_IS_MAGICAL(which))) &&
1318 (!(WEAPON_IS_MAGICAL(pstate->missileweapon)))
1319 )
1320 {
1321 int nx,ny;
1322
1323
1324 nx = ob->tilex;
1325 ny = ob->tiley;
1326 //FindEmptyTile(&nx,&ny);
1327
1328 if (IsPlatform(nx,ny))
1329 SpawnStatic(nx,ny,GetItemForWeapon(pstate->missileweapon),9);
1330 else
1331 {
1332 int newz = sprites[ob->tilex][ob->tiley]->z;
1333 SpawnStatic(nx,ny,GetItemForWeapon(pstate->missileweapon),-1);
1334 LASTSTAT->z = newz;
1335 }
1336 LASTSTAT->ammo = pstate->ammo;
1337 EnableOldWeapon(pstate);
1338
1339 }
1340 }
1341
1342 else if (!WEAPON_IS_MAGICAL(which))
1343 {
1344 int newz = sprites[ob->tilex][ob->tiley]->z;
1345 SpawnStatic(ob->tilex,ob->tiley,GetItemForWeapon(which),9);
1346 LASTSTAT->z = newz;
1347 EnableOldWeapon(pstate);
1348
1349 }
1350 pstate->new_weapon = pstate->missileweapon = which;
1351 pstate->weapondowntics = WEAPONS[pstate->weapon].screenheight/GMOVE;
1352
1353
1354 }
1355
1356
1357 //******************************************************************************
1358 //
1359 // DrawKeys ()
1360 //
1361 //******************************************************************************
1362
DrawKeys(boolean bufferofsonly)1363 void DrawKeys
1364 (
1365 boolean bufferofsonly
1366 )
1367
1368 {
1369 if ( !SHOW_TOP_STATUS_BAR() )
1370 {
1371 return;
1372 }
1373
1374 if ( locplayerstate->keys & 1 )
1375 {
1376 GameMemToScreen( keys[ 0 ], KeyX[ 0 ], KEY_Y, bufferofsonly );
1377 }
1378
1379 if ( locplayerstate->keys & 2 )
1380 {
1381 GameMemToScreen( keys[ 1 ], KeyX[ 1 ], KEY_Y, bufferofsonly );
1382 }
1383
1384 if ( locplayerstate->keys & 4 )
1385 {
1386 GameMemToScreen( keys[ 2 ], KeyX[ 2 ], KEY_Y, bufferofsonly );
1387 }
1388
1389 if ( locplayerstate->keys & 8 )
1390 {
1391 GameMemToScreen( keys[ 3 ], KeyX[ 3 ], KEY_Y, bufferofsonly );
1392 }
1393 }
1394
1395
1396 //******************************************************************************
1397 //
1398 // StatusDrawTime ()
1399 //
1400 //******************************************************************************
1401
StatusDrawTime(unsigned x,unsigned y,unsigned num,boolean bufferofsonly)1402 void StatusDrawTime
1403 (
1404 unsigned x,
1405 unsigned y,
1406 unsigned num,
1407 boolean bufferofsonly
1408 )
1409
1410 {
1411 DrawMPPic( x, y, timenums[ num ]->width, timenums[ num ]->height, 0,
1412 ( byte * )&timenums[ num ]->data, bufferofsonly );
1413 }
1414
1415
1416 //******************************************************************************
1417 //
1418 // DrawTimeNumber ()
1419 //
1420 // right justifies and pads with blanks
1421 //
1422 //******************************************************************************
1423
DrawTimeNumber(int x,int y,int number,boolean seconds,boolean bufferofsonly)1424 void DrawTimeNumber (int x, int y, int number, boolean seconds, boolean bufferofsonly)
1425 {
1426 char str[20];
1427
1428 ltoa (number,str,10);
1429
1430 if (seconds)
1431 {
1432 if (number < 10)
1433 {
1434 StatusDrawTime (x, y, 0, bufferofsonly);
1435 StatusDrawTime (x+8, y, str[0]-'0', bufferofsonly);
1436 }
1437 else
1438 {
1439 StatusDrawTime (x, y, str[0]-'0', bufferofsonly);
1440 StatusDrawTime (x+8, y, str[1]-'0', bufferofsonly);
1441 }
1442 }
1443 else
1444 {
1445 if (number < 10)
1446 StatusDrawTime (x+8, y, str[0]-'0', bufferofsonly);
1447 else
1448 {
1449 StatusDrawTime (x, y, str[0]-'0', bufferofsonly);
1450 StatusDrawTime (x+8, y, str[1]-'0', bufferofsonly);
1451 }
1452 }
1453 }
1454
1455
1456 //******************************************************************************
1457 //
1458 // DrawTimeXY ()
1459 //
1460 //******************************************************************************
1461
DrawTimeXY(int x,int y,int sec,boolean bufferofsonly)1462 void DrawTimeXY
1463 (
1464 int x,
1465 int y,
1466 int sec,
1467 boolean bufferofsonly
1468 )
1469
1470 {
1471 int min;
1472 int hour;
1473
1474 while (sec > ( ( 9 * 3600 ) + 3599 ) )
1475 {
1476 sec -= ( ( 9 * 3600 ) + 3599 );
1477 }
1478
1479 hour = sec / 3600;
1480 min = ( sec / 60 ) - ( hour * 60 );
1481 sec %= 60;
1482
1483 DrawTimeNumber ( x + HOUR_X, y, hour, false, bufferofsonly );
1484 DrawTimeNumber ( x + MIN_X, y, min, true, bufferofsonly );
1485 DrawTimeNumber ( x + SEC_X, y, sec, true, bufferofsonly );
1486 }
1487
1488
1489 //******************************************************************************
1490 //
1491 // DrawTime ()
1492 //
1493 //******************************************************************************
1494
DrawTime(boolean bufferofsonly)1495 void DrawTime
1496 (
1497 boolean bufferofsonly
1498 )
1499
1500 {
1501 int sec;
1502
1503 if ( !SHOW_TOP_STATUS_BAR() )
1504 {
1505 return;
1506 }
1507
1508 if (timelimitenabled == true)
1509 {
1510 sec = (timelimit-gamestate.TimeCount) / VBLCOUNTER;
1511 }
1512 else
1513 {
1514 sec = gamestate.TimeCount / VBLCOUNTER;
1515 }
1516
1517 if ( oldsec != sec )
1518 {
1519 oldsec = sec;
1520 DrawTimeXY( GAMETIME_X, GAMETIME_Y, sec, bufferofsonly) ;
1521 }
1522 }
1523
1524
1525 //******************************************************************************
1526 //
1527 // DrawMPPic ()
1528 //
1529 // Purpose
1530 // Draws a masked, planer pic at xpos, ypos.
1531 //
1532 // Parms
1533 // xpos - x position.
1534 // ypos - y position.
1535 // width - width of pic : should be << 2.
1536 // height - height of pic.
1537 // src - data to draw.
1538 //
1539 // Returns
1540 // Nothing.
1541 //
1542 //******************************************************************************
1543
DrawMPPic(int xpos,int ypos,int width,int height,int heightmod,byte * src,boolean bufferofsonly)1544 void DrawMPPic (int xpos, int ypos, int width, int height, int heightmod, byte *src, boolean bufferofsonly)
1545 {
1546 byte *olddest;
1547 byte *dest;
1548 int x;
1549 int y;
1550 int planes;
1551 byte mask;
1552 byte pixel;
1553
1554 mask = 1 << (xpos&3);
1555
1556 #ifdef DOS
1557 olddest = (byte *)(ylookup[ypos] + (xpos>>2));
1558 #else
1559 olddest = (byte *)(ylookup[ypos] + xpos);
1560 #endif
1561
1562 for (planes = 0; planes < 4; planes++)
1563 {
1564 VGAMAPMASK (mask);
1565
1566 dest = olddest;
1567
1568 #ifndef DOS
1569 dest += planes;
1570 #endif
1571
1572 for (y = 0; y < height; y++)
1573 {
1574 for (x = 0; x < width; x++)
1575 {
1576 pixel = *src++;
1577
1578 if (pixel != 255)
1579 {
1580 if (bufferofsonly)
1581 *(dest+bufferofs) = pixel;
1582 else
1583 {
1584 *(dest+page1start) = pixel;
1585 *(dest+page2start) = pixel;
1586 *(dest+page3start) = pixel;
1587 }
1588 }
1589
1590 #ifdef DOS
1591 dest++;
1592 #else
1593 dest += 4;
1594 #endif
1595 }
1596
1597 #ifdef DOS
1598 dest += (linewidth-width);
1599 #else
1600 dest += (linewidth-width*4);
1601 #endif
1602 }
1603
1604 if (heightmod)
1605 src += (heightmod*width);
1606
1607 #ifdef DOS
1608 mask <<= 1;
1609 if (mask == 16)
1610 {
1611 mask = 1;
1612 olddest++;
1613 }
1614 #endif
1615 }
1616 }
1617
1618
1619 //******************************************************************************
1620 //
1621 // DrawColoredMPPic ()
1622 //
1623 // Purpose
1624 // Draws a masked, planer pic at xpos, ypos.
1625 //
1626 // Parms
1627 // xpos - x position.
1628 // ypos - y position.
1629 // width - width of pic : should be << 2.
1630 // height - height of pic.
1631 // src - data to draw.
1632 //
1633 // Returns
1634 // Nothing.
1635 //
1636 //******************************************************************************
1637
DrawColoredMPPic(int xpos,int ypos,int width,int height,int heightmod,byte * src,boolean bufferofsonly,int color)1638 void DrawColoredMPPic (int xpos, int ypos, int width, int height, int heightmod, byte *src, boolean bufferofsonly, int color)
1639 {
1640 byte *olddest;
1641 byte *dest;
1642 int x;
1643 int y;
1644 int planes;
1645 byte mask;
1646 byte pixel;
1647 byte * cmap;
1648
1649 cmap=playermaps[color]+(1<<12);
1650
1651 mask = 1 << (xpos&3);
1652
1653 #ifdef DOS
1654 olddest = (byte *)(ylookup[ypos] + (xpos>>2));
1655 #else
1656 olddest = (byte *)(ylookup[ypos] + xpos);
1657 #endif
1658
1659 for (planes = 0; planes < 4; planes++)
1660 {
1661 VGAMAPMASK (mask);
1662
1663 dest = olddest;
1664
1665 #ifndef DOS
1666 dest += planes;
1667 #endif
1668
1669 for (y = 0; y < height; y++)
1670 {
1671 for (x = 0; x < width; x++)
1672 {
1673 pixel = *src++;
1674
1675 pixel = *(cmap+pixel);
1676
1677 if (pixel != 255)
1678 {
1679 if (bufferofsonly)
1680 *(dest+bufferofs) = pixel;
1681 else
1682 {
1683 *(dest+page1start) = pixel;
1684 *(dest+page2start) = pixel;
1685 *(dest+page3start) = pixel;
1686 }
1687 }
1688
1689 #ifdef DOS
1690 dest++;
1691 #else
1692 dest += 4;
1693 #endif
1694 }
1695
1696 #ifdef DOS
1697 dest += (linewidth-width);
1698 #else
1699 dest += (linewidth-width*4);
1700 #endif
1701 }
1702
1703 if (heightmod)
1704 src += (heightmod*width);
1705
1706 #ifdef DOS
1707 mask <<= 1;
1708 if (mask == 16)
1709 {
1710 mask = 1;
1711 olddest++;
1712 }
1713 #endif
1714 }
1715 }
1716
1717
1718 //******************************************************************************
1719 //
1720 // UpdateScore ()
1721 //
1722 //******************************************************************************
1723
UpdateScore(unsigned int num)1724 void UpdateScore (unsigned int num)
1725 {
1726 if (num > 999999999)
1727 {
1728 num = 999999999;
1729 gamestate.score = 999999999;
1730 }
1731
1732 ltoa (num, ScoreStr.str, 10);
1733 ScoreStr.length = strlen (ScoreStr.str);
1734 }
1735
1736
1737 //******************************************************************************
1738 //
1739 // UpdateLives ()
1740 //
1741 //******************************************************************************
1742
UpdateLives(int num)1743 void UpdateLives (int num)
1744 {
1745 ltoa (num, LivesStr.str, 10);
1746 LivesStr.length = strlen (LivesStr.str);
1747 }
1748
1749 //****************************************************************************
1750 //
1751 // ClearTriads ()
1752 //
1753 //****************************************************************************
ClearTriads(playertype * pstate)1754 void ClearTriads (playertype * pstate)
1755 {
1756 pstate->triads = 0;
1757 ltoa (pstate->triads, TriadStr.str, 10);
1758 TriadStr.length = strlen (TriadStr.str);
1759 }
1760
1761 //****************************************************************************
1762 //
1763 // UpdateTriads ()
1764 //
1765 //****************************************************************************
1766
UpdateTriads(objtype * ob,int num)1767 void UpdateTriads (objtype * ob, int num)
1768 {
1769 playertype * pstate;
1770
1771 M_LINKSTATE(ob,pstate);
1772
1773 pstate->triads += num;
1774
1775 if (pstate->triads >= 100)
1776 {
1777 GiveLives(1);
1778 if (ob==player)
1779 {
1780 AddMessage("100 Life Item Points! Extra Life!\n",MSG_BONUS);
1781 SD_PlaySoundRTP (SD_GET1UPSND, player->x, player->y);
1782 }
1783 pstate->triads -= 100;
1784 }
1785
1786 if (ob==player)
1787 {
1788 ltoa (pstate->triads, TriadStr.str, 10);
1789 TriadStr.length = strlen (TriadStr.str);
1790 }
1791 }
1792
1793 //****************************************************************************
1794 //
1795 // DrawTriads ()
1796 //
1797 //****************************************************************************
1798
DrawTriads(boolean bufferofsonly)1799 void DrawTriads
1800 (
1801 boolean bufferofsonly
1802 )
1803
1804 {
1805 if ( !SHOW_TOP_STATUS_BAR() )
1806 {
1807 return;
1808 }
1809
1810 if ( !EndLevelStuff )
1811 {
1812 DrawNumber( TRIAD_X, TRIAD_Y, 2, 3, bufferofsonly );
1813 }
1814 }
1815
1816
1817 //******************************************************************************
1818 //
1819 // DrawPPic ()
1820 //
1821 //******************************************************************************
1822
DrawPPic(int xpos,int ypos,int width,int height,byte * src,int num,boolean up,boolean bufferofsonly)1823 void DrawPPic (int xpos, int ypos, int width, int height, byte *src, int num, boolean up, boolean bufferofsonly)
1824 {
1825 byte *olddest;
1826 byte *dest;
1827 int x;
1828 int y;
1829 int planes;
1830 byte mask;
1831 byte pixel;
1832 int k;
1833 int amt;
1834
1835 #ifdef DOS
1836 if (up)
1837 amt = 2;
1838 else
1839 amt = -2;
1840 #else
1841 if (up)
1842 amt = 8;
1843 else
1844 amt = -8;
1845 #endif
1846
1847 mask = 1;
1848
1849 #ifdef DOS
1850 olddest = (byte *)(ylookup[ypos] + (xpos>>2));
1851 #else
1852 olddest = (byte *)(ylookup[ypos] + xpos);
1853 #endif
1854
1855 for (planes = 0; planes < 4; planes++)
1856 {
1857 VGAMAPMASK (mask);
1858
1859 dest = olddest;
1860
1861 #ifndef DOS
1862 dest += planes;
1863 #endif
1864
1865 for (y = 0; y < height; y++)
1866 {
1867 for (x = 0; x < width; x++)
1868 {
1869 pixel = *src++;
1870
1871 if (pixel != 255)
1872 {
1873 for (k = 0; k < num; k++)
1874 {
1875 if (bufferofsonly)
1876 *(dest+bufferofs+(amt*k)) = pixel;
1877 else
1878 {
1879 *(dest+page1start+(amt*k)) = pixel;
1880 *(dest+page2start+(amt*k)) = pixel;
1881 *(dest+page3start+(amt*k)) = pixel;
1882 }
1883 }
1884 }
1885
1886 #ifdef DOS
1887 dest++;
1888 #else
1889 dest += 4;
1890 #endif
1891 }
1892
1893 #ifdef DOS
1894 dest += (linewidth-width);
1895 #else
1896 dest += (linewidth-width*4);
1897 #endif
1898 }
1899
1900 mask <<= 1;
1901 }
1902 }
1903
1904
1905 //****************************************************************************
1906 //
1907 // DrawBarHealth ()
1908 //
1909 //****************************************************************************
1910
DrawBarHealth(boolean bufferofsonly)1911 void DrawBarHealth
1912 (
1913 boolean bufferofsonly
1914 )
1915
1916 {
1917 int percenthealth;
1918 int health_y;
1919
1920 if ( !SHOW_BOTTOM_STATUS_BAR() )
1921 {
1922 return;
1923 }
1924
1925 health_y = HEALTH_Y;
1926 if ( SHOW_KILLS() )
1927 {
1928 health_y -= KILLS_HEIGHT;
1929 }
1930
1931 percenthealth = ( locplayerstate->health * 10 ) /
1932 MaxHitpointsForCharacter( locplayerstate );
1933
1934 oldpercenthealth = percenthealth + 1;
1935
1936 if ( playstate == ex_died )
1937 {
1938 DrawPPic( HEALTH_X, health_y, 8 >> 2, 16, ( byte * )&erase->data,
1939 10, true, bufferofsonly );
1940
1941 return;
1942 }
1943
1944 if ( locplayerstate->health <= 0 )
1945 {
1946 oldpercenthealth = 0;
1947 }
1948
1949 if ( oldpercenthealth >= 11 )
1950 {
1951 oldpercenthealth = 10;
1952 }
1953
1954 if ( oldpercenthealth < 4 )
1955 {
1956 DrawPPic( HEALTH_X, health_y, 8 >> 2, 16,
1957 ( byte * )&health[ 0 ]->data, oldpercenthealth,
1958 true, bufferofsonly );
1959 }
1960 else if ( oldpercenthealth < 5 )
1961 {
1962 DrawPPic( HEALTH_X, health_y, 8 >> 2, 16,
1963 (byte *)&health[ 1 ]->data, oldpercenthealth,
1964 true, bufferofsonly );
1965 }
1966 else
1967 {
1968 DrawPPic( HEALTH_X, health_y, 8 >> 2, 16,
1969 ( byte * )&health[ 2 ]->data, oldpercenthealth,
1970 true, bufferofsonly );
1971 }
1972
1973 if ( oldpercenthealth < 10 )
1974 {
1975 DrawPPic( HEALTH_X + ( 8 * oldpercenthealth ), health_y,
1976 8 >> 2, 16, ( byte * )&erase->data, 10 - oldpercenthealth,
1977 true, bufferofsonly );
1978 }
1979 }
1980
1981
1982 //****************************************************************************
1983 //
1984 // DrawBarAmmo ()
1985 //
1986 //****************************************************************************
1987
DrawBarAmmo(boolean bufferofsonly)1988 void DrawBarAmmo
1989 (
1990 boolean bufferofsonly
1991 )
1992
1993 {
1994 int ammo_y;
1995
1996 if ( ( !SHOW_BOTTOM_STATUS_BAR() ) || ( playstate == ex_died ) )
1997 {
1998 return;
1999 }
2000
2001 ammo_y = AMMO_Y;
2002 if ( SHOW_KILLS() )
2003 {
2004 ammo_y -= KILLS_HEIGHT;
2005 }
2006
2007 DrawPPic ( AMMO_X, ammo_y + 1, 8 >> 2, 16, ( byte * )&erase->data,
2008 10, false, bufferofsonly );
2009
2010 if ( !ARMED( player->dirchoosetime ) )
2011 {
2012 return;
2013 }
2014 if ((locplayerstate->new_weapon < wp_bazooka) ||
2015 (locplayerstate->new_weapon == wp_godhand) ||
2016 ( gamestate.BattleOptions.Ammo == bo_infinite_shots )
2017 )
2018 {
2019 DrawPPic( AMMO_X - 16, ammo_y, 24 >> 2, 16,
2020 ( byte * )&ammo[ 0 ]->data, 1, true, bufferofsonly);
2021
2022 DrawPPic( AMMO_X - 32, ammo_y + 1, 8 >> 2, 16,
2023 ( byte * )&erase->data, 2, true, bufferofsonly );
2024 }
2025 #if (SHAREWARE == 0)
2026 else if ( locplayerstate->new_weapon == wp_dog )
2027 {
2028 DrawPPic( AMMO_X - 16, ammo_y, 24 >> 2, 16,
2029 ( byte * )&ammo[12]->data, 1, true, bufferofsonly );
2030
2031 DrawPPic( AMMO_X - 32, ammo_y + 1, 8 >> 2, 16,
2032 ( byte * )&erase->data, 2, true, bufferofsonly );
2033 }
2034 #endif
2035 else
2036 {
2037 DrawPPic( AMMO_X, ammo_y + 1, 8 >> 2, 16,
2038 ( byte * )&ammo[ locplayerstate->new_weapon]->data,
2039 locplayerstate->ammo, false, bufferofsonly );
2040 }
2041 }
2042
2043
2044 //******************************************************************************
2045 //
2046 // SingleDrawPPic ()
2047 //
2048 //******************************************************************************
2049
SingleDrawPPic(int xpos,int ypos,int width,int height,byte * src,int num,boolean up)2050 void SingleDrawPPic (int xpos, int ypos, int width, int height, byte *src, int num, boolean up)
2051 {
2052 byte *olddest;
2053 byte *dest;
2054 int x;
2055 int y;
2056 int planes;
2057 byte mask;
2058 byte pixel;
2059 int k;
2060 int amt;
2061
2062 #ifdef DOS
2063 if (up)
2064 amt = 2;
2065 else
2066 amt = -2;
2067 #else
2068 if (up)
2069 amt = 8;
2070 else
2071 amt = -8;
2072 #endif
2073
2074 mask = 1;
2075
2076 #ifdef DOS
2077 olddest = (byte *)(bufferofs - screenofs + ylookup[ypos] + (xpos>>2));
2078 #else
2079 olddest = (byte *)(bufferofs - screenofs + ylookup[ypos] + xpos);
2080 #endif
2081
2082 for (planes = 0; planes < 4; planes++)
2083 {
2084 VGAMAPMASK (mask);
2085
2086 dest = olddest;
2087
2088 #ifndef DOS
2089 dest += planes;
2090 #endif
2091
2092 for (y = 0; y < height; y++)
2093 {
2094 for (x = 0; x < width; x++)
2095 {
2096 pixel = *src++;
2097
2098 if (pixel != 255)
2099 {
2100 for (k = 0; k < num; k++)
2101 {
2102 *(dest+(amt*k)) = pixel;
2103 }
2104 }
2105
2106 #ifdef DOS
2107 dest++;
2108 #else
2109 dest += 4;
2110 #endif
2111 }
2112
2113 #ifdef DOS
2114 dest += (linewidth-width);
2115 #else
2116 dest += (linewidth-width*4);
2117 #endif
2118 }
2119
2120 mask <<= 1;
2121 }
2122 }
2123
2124
2125
2126 //****************************************************************************
2127 //
2128 // DrawStats ()
2129 //
2130 //****************************************************************************
2131
DrawStats(void)2132 void DrawStats
2133 (
2134 void
2135 )
2136
2137 {
2138 int percenthealth;
2139 int health_y;
2140 int ammo_y;
2141
2142 if ( ( !SHOW_PLAYER_STATS() ) || ( playstate == ex_died ) ||
2143 ( locplayerstate->health <= 0 ) )
2144 {
2145 return;
2146 }
2147
2148 // Uncomment this if we want transparent health only on sizes < 16
2149 // if ( viewsize < 16 )
2150 // {
2151 // pic_t *shape;
2152 //
2153 // shape = W_CacheLumpName( "backtile", PU_CACHE );
2154 // DrawTiledRegion( 0, 160, 320, 24, shape );
2155 // }
2156
2157 health_y = HEALTH_Y;
2158 ammo_y = AMMO_Y;
2159
2160 if ( SHOW_KILLS() )
2161 {
2162 health_y -= KILLS_HEIGHT;
2163 ammo_y -= KILLS_HEIGHT;
2164 }
2165
2166 if ( oldplayerhealth != locplayerstate->health )
2167 {
2168 oldplayerhealth = locplayerstate->health;
2169
2170 percenthealth = ( locplayerstate->health * 10 ) /
2171 MaxHitpointsForCharacter( locplayerstate );
2172
2173 oldpercenthealth = percenthealth + 1;
2174 }
2175
2176 if ( oldpercenthealth > 10 )
2177 {
2178 oldpercenthealth = 10;
2179 }
2180
2181 if ( oldpercenthealth < 4 )
2182 {
2183 SingleDrawPPic( HEALTH_X - 16, health_y, 8 >> 2, 16,
2184 ( byte * )&health[ 3 ]->data, oldpercenthealth, true);
2185 }
2186 else if ( oldpercenthealth < 5 )
2187 {
2188 SingleDrawPPic( HEALTH_X - 16, health_y, 8 >> 2, 16,
2189 ( byte * )&health[ 4 ]->data, oldpercenthealth, true );
2190 }
2191 else
2192 {
2193 SingleDrawPPic( HEALTH_X - 16, health_y, 8 >> 2, 16,
2194 ( byte * )&health[ 5 ]->data, oldpercenthealth, true );
2195 }
2196
2197 if ( ARMED( consoleplayer ) )
2198 {
2199 if ((locplayerstate->new_weapon < wp_bazooka) ||
2200 (locplayerstate->new_weapon == wp_godhand) ||
2201 (gamestate.BattleOptions.Ammo == bo_infinite_shots )
2202 )
2203
2204 {
2205 SingleDrawPPic( AMMO_X - 16, ammo_y, 24 >> 2, 16,
2206 ( byte * )&ammo[13]->data, 1, true );
2207 }
2208 #if (SHAREWARE == 0)
2209 else if ( locplayerstate->new_weapon == wp_dog )
2210 {
2211 SingleDrawPPic( AMMO_X - 16, ammo_y + 1, 24 >> 2, 16,
2212 ( byte * )&ammo[25]->data, 1, true );
2213 }
2214 #endif
2215 else
2216 {
2217 SingleDrawPPic( AMMO_X, ammo_y + 1, 8 >> 2, 16,
2218 ( byte * )&ammo[13 + locplayerstate->new_weapon]->data,
2219 locplayerstate->ammo, false );
2220 }
2221 }
2222 }
2223
2224
2225 //****************************************************************************
2226 //
2227 // DrawPauseXY ()
2228 //
2229 //****************************************************************************
2230
DrawPauseXY(int x,int y)2231 void DrawPauseXY (int x, int y)
2232 {
2233 pic_t *p;
2234
2235 if (GamePaused == true)
2236 {
2237 p = (pic_t *) W_CacheLumpNum (W_GetNumForName ("paused"), PU_CACHE, Cvt_pic_t, 1);
2238 VWB_DrawPic (x, y, p);
2239 DrawEpisodeLevel (x,y);
2240 }
2241 else
2242 {
2243 p = (pic_t *) W_CacheLumpNum (W_GetNumForName ("wait"), PU_CACHE, Cvt_pic_t, 1);
2244 VWB_DrawPic (x, y, p);
2245 }
2246 }
2247
2248 //****************************************************************************
2249 //
2250 // DrawPause ()
2251 //
2252 //****************************************************************************
2253
DrawPause(void)2254 void DrawPause (void)
2255 {
2256 pic_t *p;
2257 int bufftemp = bufferofs;
2258
2259 bufferofs -= screenofs;
2260
2261 if (GamePaused == true)
2262 {
2263 p = (pic_t *) W_CacheLumpNum (W_GetNumForName ("paused"), PU_CACHE, Cvt_pic_t, 1);
2264 DrawPauseXY( (320-(p->width<<2) ) >>1, (200-p->height)>>1);
2265 }
2266 else
2267 {
2268 p = (pic_t *) W_CacheLumpNum (W_GetNumForName ("wait"), PU_CACHE, Cvt_pic_t, 1);
2269 DrawPauseXY( (320-(p->width<<2) ) >>1, (200-p->height)>>1);
2270 }
2271
2272 bufferofs = bufftemp;
2273 }
2274
2275 //****************************************************************************
2276 //
2277 // GM_DrawBonus ()
2278 //
2279 //****************************************************************************
2280
GM_DrawBonus(int which)2281 void GM_DrawBonus
2282 (
2283 int which
2284 )
2285
2286 {
2287 int x;
2288
2289 if ( which < stat_gasmask )
2290 {
2291 x = POWERUP1X;
2292 poweruptime = GetBonusTimeForItem(which);
2293 poweradjust = (poweruptime >> 4);
2294 powerupheight = 0;
2295 GM_UpdateBonus(poweruptime-poweradjust - 1,true);
2296
2297 }
2298 else
2299 {
2300 x = POWERUP2X;
2301 protectiontime = GetBonusTimeForItem(which);
2302 poweradjust = (protectiontime >> 4);
2303 protectionheight = 0;
2304 GM_UpdateBonus(protectiontime-poweradjust-1,false);
2305
2306 }
2307
2308 }
2309
2310
2311 //******************************************************************************
2312 //
2313 // GM_UpdateBonus ()
2314 //
2315 //******************************************************************************
2316
GM_UpdateBonus(int time,int powerup)2317 void GM_UpdateBonus
2318 (
2319 int time,
2320 int powerup
2321 )
2322
2323 {
2324 pic_t *shape;
2325 int shapenum;
2326
2327 if ( powerup )
2328 {
2329 if ( time < ( poweruptime - poweradjust ) )
2330 {
2331 powerupheight++;
2332 if ( !SHOW_TOP_STATUS_BAR() )
2333 {
2334 poweruptime = time;
2335 }
2336 }
2337 }
2338 else
2339 {
2340 if ( time < ( protectiontime - poweradjust ) )
2341 {
2342 protectionheight++;
2343 if ( !SHOW_TOP_STATUS_BAR() )
2344 {
2345 protectiontime = time;
2346 }
2347 }
2348 }
2349
2350
2351 if ( !SHOW_TOP_STATUS_BAR() )
2352 {
2353 return;
2354 }
2355
2356 if ( !time )
2357 {
2358 if ( powerup == 1 )
2359 {
2360 shapenum = POWERUP1X;
2361 }
2362 else
2363 {
2364 shapenum = POWERUP2X;
2365 }
2366
2367 GM_MemToScreen( ( byte * )&eraseb->data, eraseb->width,
2368 eraseb->height, shapenum, POWERUPY );
2369
2370 return;
2371 }
2372
2373 if ( powerup )
2374 {
2375 if ( time < ( poweruptime - poweradjust ) )
2376 {
2377 if ( player->flags & FL_GODMODE )
2378 {
2379 shapenum = powerpics;
2380 }
2381 else if ( player->flags & FL_DOGMODE )
2382 {
2383 shapenum = powerpics + 1;
2384 }
2385 else if ( player->flags & FL_FLEET )
2386 {
2387 shapenum = powerpics + 2;
2388 }
2389 else if ( player->flags & FL_ELASTO )
2390 {
2391 shapenum = powerpics + 3;
2392 }
2393 else if ( player->flags & FL_SHROOMS )
2394 {
2395 shapenum = powerpics + 4;
2396 }
2397 else
2398 {
2399 GM_MemToScreen( ( byte * )&eraseb->data,
2400 eraseb->width, eraseb->height, POWERUP1X, POWERUPY );
2401
2402 return;
2403 }
2404
2405 poweruptime = time;
2406
2407 shape = ( pic_t * )W_CacheLumpNum( shapenum, PU_CACHE, Cvt_pic_t, 1 );
2408
2409 GM_MemToScreen( ( byte * )&eraseb->data, eraseb->width,
2410 eraseb->height, POWERUP1X, POWERUPY );
2411
2412 DrawMPPic( POWERUP1X, POWERUPY + powerupheight, shape->width,
2413 shape->height - powerupheight, powerupheight,
2414 ( byte * )&shape->data, false );
2415 }
2416 }
2417 else
2418 {
2419 if ( time < ( protectiontime - poweradjust ) )
2420 {
2421 if ( player->flags & FL_BPV )
2422 {
2423 shapenum = powerpics + 6;
2424 }
2425 else if ( player->flags & FL_GASMASK )
2426 {
2427 shapenum = powerpics + 5;
2428 }
2429 else if ( player->flags & FL_AV )
2430 {
2431 shapenum = powerpics + 7;
2432 }
2433
2434 protectiontime = time;
2435
2436 shape = ( pic_t * )W_CacheLumpNum( shapenum, PU_CACHE, Cvt_pic_t, 1 );
2437
2438 GM_MemToScreen( ( byte * )&eraseb->data, eraseb->width,
2439 eraseb->height, POWERUP2X, POWERUPY );
2440
2441 DrawMPPic( POWERUP2X, POWERUPY + protectionheight,
2442 shape->width, shape->height - protectionheight,
2443 protectionheight, ( byte * )&shape->data, false );
2444 }
2445 }
2446 }
2447
2448
2449 //******************************************************************************
2450 //
2451 // Drawpic ()
2452 //
2453 // Purpose
2454 // Draws a masked, planer pic at xpos, ypos.
2455 //
2456 // Parms
2457 // xpos - x position.
2458 // ypos - y position.
2459 // width - width of pic : should be << 2.
2460 // height - height of pic.
2461 // src - data to draw.
2462 //
2463 // Returns
2464 // Nothing.
2465 //
2466 //******************************************************************************
2467
Drawpic(int xpos,int ypos,int width,int height,byte * src)2468 void Drawpic (int xpos, int ypos, int width, int height, byte *src)
2469 {
2470 byte *olddest;
2471 byte *dest;
2472 int x;
2473 int y;
2474 int planes;
2475 byte mask;
2476 byte pixel;
2477
2478
2479 mask = 1 << (xpos&3);
2480
2481 #ifdef DOS
2482 olddest = (byte *)(bufferofs + ylookup[ypos] + (xpos>>2));
2483 #else
2484 olddest = (byte *)(bufferofs + ylookup[ypos] + xpos);
2485 #endif
2486 for (planes = 0; planes < 4; planes++)
2487 {
2488 VGAMAPMASK (mask);
2489
2490 dest = olddest;
2491
2492 #ifdef DOS
2493 dest += planes;
2494 #endif
2495
2496 for (y = 0; y < height; y++)
2497 {
2498 for (x = 0; x < width; x++)
2499 {
2500 pixel = *src++;
2501
2502 if (pixel != 255)
2503 *(dest) = pixel;
2504
2505 #ifdef DOS
2506 dest++;
2507 #else
2508 dest += 4;
2509 #endif
2510 }
2511
2512 #ifdef DOS
2513 dest += (linewidth-width);
2514 #else
2515 dest += (linewidth-width*4);
2516 #endif
2517 }
2518
2519 #ifdef DOS
2520 mask <<= 1;
2521 if (mask == 16)
2522 {
2523 mask = 1;
2524 olddest++;
2525 }
2526 #endif
2527 }
2528 }
2529
2530
2531 //******************************************************************************
2532 //
2533 // DrawEpisodeLevel ()
2534 //
2535 // right justifies and pads with blanks
2536 //
2537 //******************************************************************************
2538
DrawEpisodeLevel(int x,int y)2539 void DrawEpisodeLevel (int x, int y)
2540 {
2541 int level;
2542 char str[20];
2543 pic_t *p;
2544
2545 if (!BATTLEMODE)
2546 {
2547 ltoa (gamestate.episode, str, 10);
2548
2549 Drawpic (x+29, y+16, 8>>2, 16, (byte *)&timenums[str[0]-'0']->data);
2550
2551 if ((gamestate.mapon == 6) || (gamestate.mapon == 14) ||
2552 (gamestate.mapon == 22) || (gamestate.mapon == 32) ||
2553 (gamestate.mapon == 33))
2554 {
2555 p = (pic_t *) W_CacheLumpName ("tnumb", PU_CACHE, Cvt_pic_t, 1);
2556 Drawpic (x+40, y+16, 8>>2, 16, (byte *)&p->data);
2557
2558 if (gamestate.mapon == 6)
2559 level = 1;
2560 else
2561 if (gamestate.mapon == 14)
2562 level = 2;
2563 else
2564 if (gamestate.mapon == 22)
2565 level = 3;
2566 else
2567 if (gamestate.mapon == 32)
2568 level = 4;
2569 else
2570 level = 5;
2571 }
2572 else
2573 level = GetLevel (gamestate.episode, gamestate.mapon);
2574
2575 level = abs(level);
2576 ltoa (level, str, 10);
2577
2578 if (level < 10)
2579 Drawpic (x+49, y+16, 8>>2, 16, (byte *)&timenums[str[0]-'0']->data);
2580 else
2581 {
2582 Drawpic (x+49, y+16, 8>>2, 16, (byte *)&timenums[str[0]-'0']->data);
2583 Drawpic (x+57, y+16, 8>>2, 16, (byte *)&timenums[str[1]-'0']->data);
2584 }
2585 }
2586 else
2587 {
2588 p = (pic_t *) W_CacheLumpName ("battp", PU_CACHE, Cvt_pic_t, 1);
2589 Drawpic (x+16, y+15, 32>>2, 16, (byte *)&p->data);
2590
2591 level = abs(gamestate.mapon + 1);
2592 ltoa (level, str, 10);
2593
2594 if (level < 10)
2595 Drawpic (x+49, y+16, 8>>2, 16, (byte *)&timenums[str[0]-'0']->data);
2596 else
2597 {
2598 Drawpic (x+49, y+16, 8>>2, 16, (byte *)&timenums[str[0]-'0']->data);
2599 Drawpic (x+57, y+16, 8>>2, 16, (byte *)&timenums[str[1]-'0']->data);
2600 }
2601 }
2602 }
2603
2604
2605 //******************************************************************************
2606 //
2607 // GM_MemToScreen ()
2608 //
2609 //******************************************************************************
2610
GM_MemToScreen(byte * source,int width,int height,int x,int y)2611 void GM_MemToScreen (byte *source, int width, int height, int x, int y)
2612 {
2613 byte *dest, *dest1, *dest2, *dest3, mask;
2614 byte *screen1, *screen2, *screen3;
2615 int plane;
2616 int w;
2617
2618 #ifdef DOS
2619 dest = (byte *)(ylookup[y]+(x>>2));
2620 #else
2621 dest = (byte *)(ylookup[y]+x);
2622 #endif
2623 mask = 1 << (x&3);
2624
2625 dest1 = (byte *)(dest+page1start);
2626 dest2 = (byte *)(dest+page2start);
2627 dest3 = (byte *)(dest+page3start);
2628
2629 for (plane = 0; plane<4; plane++)
2630 {
2631 VGAMAPMASK (mask);
2632
2633 screen1 = dest1;
2634 screen2 = dest2;
2635 screen3 = dest3;
2636 for (y = 0; y < height; y++, screen1 += linewidth,
2637 screen2 += linewidth,
2638 screen3 += linewidth, source+=width)
2639 {
2640 #ifdef DOS
2641 memcpy (screen1, source, width);
2642 memcpy (screen2, source, width);
2643 memcpy (screen3, source, width);
2644 #else
2645 for (x = 0; x < width; x++) {
2646 screen1[x*4+plane] = source[x];
2647 screen2[x*4+plane] = source[x];
2648 screen3[x*4+plane] = source[x];
2649 }
2650 #endif
2651 }
2652
2653 #ifdef DOS
2654 mask <<= 1;
2655
2656 if (mask == 16)
2657 {
2658 mask = 1;
2659 dest1++;
2660 dest2++;
2661 dest3++;
2662 }
2663 #endif
2664 }
2665 }
2666
2667
2668 //==========================================================================
2669
2670 /*
2671 ==================
2672 =
2673 = ScreenShake
2674 =
2675 ==================
2676 */
2677
ScreenShake(void)2678 void ScreenShake (void)
2679 {
2680 static int which = 0;
2681
2682 if (SHAKETICS != 0xFFFF)
2683 {
2684 SHAKETICS -= tics;
2685
2686 which = (RandomNumber ("ScreenShake",0) & 3);
2687
2688 switch (which)
2689 {
2690 case 0:
2691 displayofs += 1;
2692 break;
2693
2694 case 1:
2695 displayofs -= 1;
2696 break;
2697
2698 case 2:
2699 displayofs += 3*SCREENBWIDE;
2700 break;
2701
2702 case 3:
2703 displayofs -= 3*SCREENBWIDE;
2704 break;
2705 }
2706 }
2707 }
2708
2709 //******************************************************************************
2710 //
2711 // DoBorderShifts ()
2712 //
2713 //******************************************************************************
2714
DoBorderShifts(void)2715 void DoBorderShifts (void)
2716 {
2717 if (damagecount)
2718 {
2719 if (damagecount > 100)
2720 damagecount = 100;
2721
2722 damagecount -= 6;
2723
2724 if (damagecount < 0)
2725 damagecount = 0;
2726
2727 SetBorderColor (*(colormap+(((100-damagecount)>>2)<<8)+48));
2728
2729 borderset = true;
2730 }
2731 else
2732 if (borderset)
2733 {
2734 SetBorderColor (0);
2735 borderset = false;
2736 }
2737 }
2738
2739
2740 //******************************************************************************
2741 //
2742 // DrawHighScores ()
2743 //
2744 //******************************************************************************
2745
DrawHighScores(void)2746 void DrawHighScores (void)
2747 {
2748 char buffer[16];
2749 #if (SHAREWARE == 0)
2750 char buffer1[5];
2751 #endif
2752 int i,
2753 w,
2754 h;
2755 HighScore *s;
2756
2757 for (i = 0, s = Scores; i < MaxScores; i++, s++)
2758 {
2759 PrintY = 25 + (16 * i);
2760
2761 //
2762 // name
2763 //
2764 PrintX = 3*8;
2765 DrawMenuBufPropString (PrintX, PrintY, s->name);
2766
2767 //
2768 // level
2769 //
2770 ultoa (s->completed, buffer, 10);
2771
2772 PrintX = (17 * 8)-10;
2773 #if (SHAREWARE == 0)
2774 itoa (s->episode, buffer1, 10);
2775
2776 DrawMenuBufPropString (PrintX, PrintY, buffer1);
2777 #else
2778 DrawMenuBufPropString (PrintX, PrintY, "S");
2779 #endif
2780
2781 DrawMenuBufPropString (PrintX, PrintY, "-");
2782
2783 #if (SHAREWARE == 0)
2784 if (s->completed == 7)
2785 DrawMenuBufPropString (PrintX, PrintY, "B");
2786 else if (s->completed == 8)
2787 DrawMenuBufPropString (PrintX, PrintY, "S");
2788 else if (s->completed == 9)
2789 DrawMenuBufPropString (PrintX, PrintY, "C");
2790 else if (s->completed == 10)
2791 DrawMenuBufPropString (PrintX, PrintY, "D");
2792 else
2793 DrawMenuBufPropString (PrintX, PrintY, buffer);
2794 #else
2795 DrawMenuBufPropString (PrintX, PrintY, buffer);
2796 #endif
2797
2798 //
2799 // score
2800 //
2801 ultoa(s->score,buffer,10);
2802
2803 VW_MeasurePropString (buffer, &w, &h);
2804 PrintX = (33 * 8) - w;
2805 DrawMenuBufPropString (PrintX, PrintY, buffer);
2806 }
2807 }
2808
2809
2810
2811 //******************************************************************************
2812 //
2813 // CheckHighScore ()
2814 //
2815 //******************************************************************************
2816
CheckHighScore(long score,word other,boolean INMENU)2817 void CheckHighScore (long score, word other, boolean INMENU)
2818 {
2819 word i,j;
2820 int n;
2821 HighScore myscore;
2822 int level;
2823
2824 MenuFadeIn();
2825 if (!INMENU)
2826 SetupMenuBuf ();
2827
2828 strcpy (myscore.name,"");
2829 myscore.score = score;
2830
2831 level = GetLevel (gamestate.episode, other-1);
2832
2833 myscore.episode = gamestate.episode;
2834 myscore.completed = level;
2835
2836 CurrentFont = smallfont;
2837
2838 for (i = 0, n = -1; i < MaxScores; i++)
2839 {
2840 if ((myscore.score > Scores[i].score) ||
2841 ((myscore.score == Scores[i].score) &&
2842 (myscore.completed > Scores[i].completed)))
2843 {
2844 for (j = MaxScores; --j > i;)
2845 Scores[j] = Scores[j - 1];
2846 Scores[i] = myscore;
2847 n = i;
2848 break;
2849 }
2850 }
2851
2852 if (INMENU)
2853 {
2854 SetAlternateMenuBuf();
2855 SetMenuTitle ("High Scores");
2856 ClearMenuBuf();
2857 DrawHighScores ();
2858 if (n != -1)
2859 DisplayInfo (6);
2860 else
2861 DisplayInfo (5);
2862 FlipMenuBuf ();
2863 }
2864 else
2865 {
2866 ClearMenuBuf ();
2867 SetMenuTitle ("High Scores");
2868 DrawHighScores ();
2869 if (n != -1)
2870 DisplayInfo (6);
2871 else
2872 DisplayInfo (5);
2873 RefreshMenuBuf (0);
2874 }
2875
2876 if (n != -1)
2877 {
2878 PrintY = 25 + (16 * n);
2879 PrintX = 3*8;
2880 US_LineInput (PrintX, PrintY, Scores[n].name, NULL,
2881 true, 10, 98, 0);
2882 }
2883 else
2884 {
2885 IN_ClearKeysDown ();
2886 if ( INMENU )
2887 {
2888 while( !IN_CheckAck () )
2889 {
2890 RefreshMenuBuf (0);
2891 }
2892 }
2893 else
2894 {
2895 for( i = 0; i <= 150; i += tics )
2896 {
2897 RefreshMenuBuf (0);
2898 if (IN_CheckAck ())
2899 {
2900 break;
2901 }
2902 }
2903 }
2904 }
2905
2906 if (INMENU)
2907 {
2908 SD_Play (SD_ESCPRESSEDSND);
2909 }
2910 else
2911 {
2912 ShutdownMenuBuf ();
2913 }
2914 }
2915
2916
2917 //===========================================================================
2918
2919 //#define HEADERX 140
2920 //#define BONERNAMEX 170
2921 #define HEADERX 152
2922 #define BONERNAMEX 166
2923
2924
2925 /*
2926 ==================
2927 =
2928 = DrawEOLHeader ()
2929 =
2930 ==================
2931 */
DrawEOLHeader(int playstate)2932 void DrawEOLHeader
2933 (
2934 int playstate
2935 )
2936
2937 {
2938 int health;
2939 char tempstr[ 15 ];
2940 char *string;
2941 int level;
2942 int w;
2943 int h;
2944
2945 VWB_TBar( 30, 5, 250, 75 );
2946
2947 switch( playstate )
2948 {
2949 case ex_skiplevel :
2950 if ( ( gamestate.violence >= vl_high ) &&
2951 ( gamestate.difficulty >= gd_hard ) )
2952 {
2953 string = "LEVEL WUSSED OUT ON!";
2954 }
2955 else
2956 {
2957 string = "LEVEL SKIPPED.";
2958 }
2959 break;
2960
2961 case ex_secretdone :
2962 string = "SECRET LEVEL COMPLETED!";
2963 break;
2964
2965 case ex_secretlevel :
2966 string = "SECRET EXIT TAKEN!";
2967 break;
2968
2969 case ex_gameover :
2970 string = "GAME COMPLETED!";
2971 break;
2972
2973 case ex_bossdied :
2974 string = "BOSS DEFEATED!";
2975 break;
2976
2977 default :
2978 string = "LEVEL COMPLETED!";
2979 break;
2980 }
2981
2982 VW_MeasurePropString( string, &w, &h );
2983
2984 px = ( 320 - w ) / 2;
2985 py = 10;
2986 VWB_DrawPropString( string );
2987
2988 // draw episode number
2989 string = "EPISODE";
2990 VW_MeasurePropString( string, &w, &h );
2991 px = HEADERX - w;
2992 py = 25;
2993 VWB_DrawPropString( string );
2994
2995 itoa( gamestate.episode, tempstr, 10 );
2996 px = BONERNAMEX;
2997 VWB_DrawPropString( tempstr );
2998
2999 // draw area number
3000 level = GetLevel( gamestate.episode, gamestate.mapon );
3001 itoa( level, tempstr, 10 );
3002
3003 py = 35;
3004
3005 if ( playstate == ex_secretdone )
3006 {
3007 string = "SECRET AREA";
3008 }
3009 else if ( playstate == ex_bossdied )
3010 {
3011 string = "BOSS AREA";
3012 }
3013 else if ( gamestate.mapon == 32 )
3014 {
3015 string = "CHASE AREA";
3016 }
3017 else
3018 {
3019 string = "AREA";
3020 }
3021
3022 VW_MeasurePropString( string, &w, &h);
3023 px = HEADERX - w;
3024 VWB_DrawPropString( string );
3025
3026 if ( gamestate.mapon != 33 )
3027 {
3028 px = BONERNAMEX;
3029 VWB_DrawPropString( tempstr );
3030 }
3031
3032 string = "SCORE";
3033 VW_MeasurePropString( string, &w, &h);
3034 px = HEADERX - w;
3035 py = 45;
3036 VWB_DrawPropString( string );
3037
3038 px = BONERNAMEX;
3039 itoa( gamestate.score, tempstr, 10 );
3040 VWB_DrawPropString( tempstr );
3041
3042 string = "HEALTH";
3043 VW_MeasurePropString( string, &w, &h );
3044 px = HEADERX - w;
3045 py = 55;
3046 VWB_DrawPropString( string );
3047
3048 px = BONERNAMEX;
3049 health = ( ( locplayerstate->health * 100 ) /
3050 MaxHitpointsForCharacter( locplayerstate ) );
3051
3052 itoa( health, tempstr, 10 );
3053 VWB_DrawPropString( tempstr );
3054 VWB_DrawPropString( "%" );
3055
3056 //
3057 // Secret count
3058 //
3059
3060 {
3061 char str1[10];
3062 char str2[10];
3063
3064 itoa(gamestate.secretcount,&(str1[0]),10);
3065 strcat(str1," / ");
3066 itoa(gamestate.secrettotal,&(str2[0]),10);
3067 strcat(str1,str2);
3068 string = "SECRET WALLS";
3069 VW_MeasurePropString( string, &w, &h );
3070 px = HEADERX - w;
3071 py = 65;
3072 VWB_DrawPropString( string );
3073
3074 px = BONERNAMEX;
3075 VWB_DrawPropString( str1 );
3076 }
3077
3078 VW_UpdateScreen ();
3079 }
3080
3081 boolean EndBonusFirst;
3082 boolean EndBonusSkip;
3083 int EndBonusNumBonuses;
3084 int EndBonusVoice;
3085 int EndBonusStartY;
3086
DrawEndBonus(char * string,char * bonusstring,int type)3087 void DrawEndBonus
3088 (
3089 char *string,
3090 char *bonusstring,
3091 int type
3092 )
3093
3094 {
3095 int w;
3096 int h;
3097 int health;
3098 char tempstr[ 15 ];
3099
3100 if ( EndBonusFirst )
3101 {
3102 VWB_TBar( 5, EndBonusStartY - 2, 310, 4 );
3103 EndBonusFirst = false;
3104 }
3105
3106 VWB_TBar( 5, EndBonusStartY + 2, 310, 10 );
3107 VW_MeasurePropString( string, &w, &h );
3108
3109 py = EndBonusStartY;
3110 if ( bonusstring == NULL )
3111 {
3112 px = ( 320 - w ) / 2;
3113 VWB_DrawPropString( string );
3114 }
3115 else
3116 {
3117 px = BONERNAMEX - w;
3118 VWB_DrawPropString( string );
3119
3120 EndBonusNumBonuses++;
3121 VW_MeasurePropString( bonusstring, &w, &h );
3122 px = 310 - w;
3123 py = EndBonusStartY;
3124 VWB_DrawPropString( bonusstring );
3125 }
3126
3127 // Update Score
3128 py = 45;
3129 px = BONERNAMEX;
3130 V_ReDrawBkgnd( px, py, 107, 11, false );
3131 VWB_TBar( px, py, 107, 11 );
3132 itoa( gamestate.score, tempstr, 10 );
3133 VWB_DrawPropString( tempstr );
3134
3135 // Update Health
3136 py = 55;
3137 px = BONERNAMEX;
3138 V_ReDrawBkgnd( px, py, 107, 11, false );
3139 VWB_TBar( px, py, 107, 11 );
3140 health = ( ( locplayerstate->health * 100 ) /
3141 MaxHitpointsForCharacter( locplayerstate ) );
3142 itoa( health, tempstr, 10 );
3143 VWB_DrawPropString( tempstr );
3144 VWB_DrawPropString( "%" );
3145
3146 switch( type )
3147 {
3148 case 0 :
3149 EndBonusVoice = SD_Play( SD_ENDBONUS1SND );
3150 break;
3151
3152 case 1 :
3153 EndBonusVoice = SD_Play( SD_NOBONUSSND );
3154 break;
3155
3156 case 2 :
3157 VL_FillPalette(255,255,255);
3158 VW_UpdateScreen();
3159 VL_FadeIn(0,255,origpal,10);
3160 EndBonusVoice = SD_Play( SD_LIGHTNINGSND );
3161 break;
3162 }
3163
3164 EndBonusStartY += 10;
3165
3166 VW_UpdateScreen();
3167 while( SD_SoundActive( EndBonusVoice ) && !EndBonusSkip )
3168 {
3169 if ( IN_CheckAck() )
3170 {
3171 EndBonusSkip = true;
3172 }
3173 }
3174 }
3175
3176
3177
3178 /*
3179 ==================
3180 =
3181 = LevelCompleted
3182 =
3183 = Exit with the screen faded out
3184 =
3185 ==================
3186 */
3187
3188 extern int OLDLMWEAPON;
3189 extern int OLDLWEAPON;
3190
LevelCompleted(exit_t playstate)3191 void LevelCompleted
3192 (
3193 exit_t playstate
3194 )
3195
3196 {
3197 objtype *obj;
3198 boolean dobonus;
3199 int i;
3200 int kr;
3201 int sr;
3202 int tr;
3203 int missileratio;
3204 int superratio;
3205 int healthratio;
3206 int democraticratio;
3207 int plantratio;
3208 int cnt;
3209
3210 EndBonusNumBonuses = 0;
3211 EndBonusFirst = true;
3212 EndBonusSkip = false;
3213 EndBonusStartY = 90;
3214
3215 IN_StartAck();
3216 EndBonusVoice = 0;
3217 if ( playstate != ex_bossdied )
3218 {
3219 EndBonusVoice = SD_Play( SD_LEVELDONESND );
3220 VL_FillPalette( 255, 255, 255 );
3221 VL_FadeIn( 0, 255, origpal, 10 );
3222 if ( player->flags & FL_DOGMODE )
3223 {
3224 MU_StartSong( song_dogend );
3225 }
3226 else
3227 {
3228 MU_StartSong( song_endlevel );
3229 }
3230 }
3231
3232 BkPic = ( pic_t * )W_CacheLumpName( "mmbk", PU_CACHE, Cvt_pic_t, 1 );
3233 VWB_DrawPic( 0, 0, BkPic );
3234
3235 CheckHolidays();
3236 CurrentFont = smallfont;
3237
3238 // Kill powerups
3239 if ( player->flags & FL_ELASTO )
3240 {
3241 player->flags &= ~FL_NOFRICTION;
3242 }
3243
3244 player->flags &= ~( FL_FLEET | FL_SHROOMS | FL_ELASTO | FL_GODMODE |
3245 FL_DOGMODE | FL_BPV | FL_AV | FL_GASMASK );
3246
3247 // Turn off quickload for next level
3248 pickquick = false;
3249
3250 //
3251 // FIGURE RATIOS OUT BEFOREHAND
3252 //
3253 kr = 0;
3254 tr = 0;
3255 tr = 0;
3256 superratio = 0;
3257 missileratio = 0;
3258 healthratio = 0;
3259 democraticratio = 0;
3260 plantratio = 0;
3261
3262 if ( gamestate.killtotal )
3263 {
3264 kr = ( int )( ( ( int )gamestate.killcount ) * 100 ) /
3265 ( ( int )gamestate.killtotal );
3266 }
3267
3268 if ( gamestate.secrettotal )
3269 {
3270 sr = ( int )( ( ( int )gamestate.secretcount ) * 100 ) /
3271 ( ( int )gamestate.secrettotal );
3272 }
3273
3274 if ( gamestate.treasuretotal )
3275 {
3276 tr = ( int )( ( ( int )gamestate.treasurecount ) * 100 ) /
3277 ( ( int )gamestate.treasuretotal );
3278 }
3279
3280 if ( gamestate.supertotal )
3281 {
3282 superratio = ( int )( ( ( int )gamestate.supercount ) * 100 ) /
3283 ( ( int )gamestate.supertotal );
3284 }
3285
3286 if ( gamestate.missiletotal )
3287 {
3288 missileratio = ( int )( ( ( int )gamestate.missilecount ) * 100 ) /
3289 ( ( int )gamestate.missiletotal );
3290 }
3291
3292 if ( gamestate.healthtotal )
3293 {
3294 healthratio = ( int )( ( ( int )gamestate.healthcount ) * 100 ) /
3295 ( ( int )gamestate.healthtotal );
3296 }
3297
3298 if ( gamestate.democratictotal )
3299 {
3300 democraticratio = ( int )( ( ( int )gamestate.democraticcount ) *
3301 100 ) / ( ( int )gamestate.democratictotal );
3302 }
3303
3304 if ( gamestate.planttotal )
3305 {
3306 plantratio = ( int )( ( ( int )gamestate.plantcount ) * 100 ) /
3307 ( ( int )gamestate.planttotal );
3308 }
3309
3310 DrawEOLHeader( playstate );
3311
3312 while( SD_SoundActive( EndBonusVoice ) && !EndBonusSkip )
3313 {
3314 VW_UpdateScreen();
3315 if ( IN_CheckAck() )
3316 {
3317 EndBonusSkip = true;
3318 }
3319 }
3320
3321 if ( GetNextMap(player->tilex,player->tiley) == -1)
3322 {
3323 if ( gamestate.dipballs == 3 )
3324 {
3325 gamestate.score += 100000;
3326 DrawEndBonus( "DIP BONUS", "100000 POINTS", 0 );
3327 EndBonusStartY += 10;
3328 }
3329
3330 if ( locplayerstate->lives > 0 )
3331 {
3332 char str[20];
3333 char str2[60];
3334
3335 DrawEndBonus( "EXTRA LIVES BONUS", "\0", 0 );
3336 itoa(locplayerstate->lives,str,10);
3337 strcpy(str2,str);
3338 strcat(str2," EXTRA LIVES =");
3339 DrawEndBonus( "\0", str2, 0 );
3340 itoa(locplayerstate->lives,str,10);
3341 strcpy(str2,str);
3342 strcat(str2," X 10000 = ");
3343 itoa(locplayerstate->lives*10000,str,10);
3344 strcat(str2,str);
3345 strcat(str2," POINTS");
3346 gamestate.score += 10000*locplayerstate->lives;
3347 DrawEndBonus( "\0", str2, 0 );
3348 }
3349 }
3350 else
3351 {
3352 //
3353 // Check for SKIN OF YO TEETH
3354 //
3355 if ( locplayerstate->health <= 10 )
3356 {
3357 locplayerstate->health = MaxHitpointsForCharacter( locplayerstate );
3358 DrawEndBonus( "SKIN OF YOUR TEETH", "100% HEALTH", 0 );
3359 }
3360
3361 // BULL IN CHINA SHOP BONUS
3362 if ( tr == 100 )
3363 {
3364 gamestate.score += 10000;
3365 DrawEndBonus( "BULL IN CHINA SHOP", "10000 POINTS", 0 );
3366 }
3367
3368 // SUPERCHARE BONUS
3369 if ( superratio == 100 )
3370 {
3371 gamestate.score += 10000;
3372 DrawEndBonus( "SUPERCHARGE BONUS", "10000 POINTS", 0 );
3373 }
3374
3375 // BLEEDER BONUS
3376 if ( healthratio == 100 )
3377 {
3378 gamestate.score += 10000;
3379 DrawEndBonus( "BLEEDER BONUS", "10000 POINTS", 0 );
3380 }
3381
3382 // ADRENALINE BONUS
3383 if ( kr == 100 )
3384 {
3385 gamestate.score += 10000;
3386 DrawEndBonus( "ADRENALINE BONUS", "10000 POINTS", 0 );
3387 }
3388
3389 // CURIOSITY BONUS
3390 dobonus = true;
3391
3392 //
3393 // Check switches
3394 cnt = lastswitch - &switches[ 0 ];
3395 if ( cnt != 0 )
3396 {
3397 for ( i = 0; i < cnt; i++ )
3398 {
3399 if ( ( switches[ i ].flags & FL_S_FLIPPED ) == 0 )
3400 {
3401 dobonus = false;
3402 break;
3403 }
3404 }
3405 }
3406
3407 //
3408 // Check pillars
3409 for ( obj = FIRSTACTOR; obj != NULL; obj = obj->next )
3410 {
3411 if ( ( obj->obclass == pillarobj ) &&
3412 ( ( obj->flags & FL_FLIPPED ) == 0 ) )
3413 {
3414 dobonus = false;
3415 }
3416 }
3417
3418 if ( ( gamestate.secrettotal ) && ( sr != 100 ) )
3419 {
3420 dobonus = false;
3421 }
3422
3423 if ( dobonus )
3424 {
3425 gamestate.score += 10000;
3426 DrawEndBonus( "CURIOSITY BONUS", "10000 POINTS", 0 );
3427 }
3428
3429 // GROUND ZERO BONUS
3430 if ( gamestate.DOGROUNDZEROBONUS )
3431 {
3432 gamestate.score += 10000;
3433 DrawEndBonus( "GROUND ZERO BONUS", "10000 POINTS", 0 );
3434 }
3435
3436 // REPUBLICAN BONUS 1
3437 if ( missileratio == 100 )
3438 {
3439 gamestate.score += 5000;
3440 DrawEndBonus( "REPUBLICAN BONUS 1", " 5000 POINTS", 0 );
3441 }
3442
3443 // REPUBLICAN BONUS 2
3444 if (plantratio == 100)
3445 {
3446 gamestate.score += 5000;
3447 DrawEndBonus( "REPUBLICAN BONUS 2", " 5000 POINTS", 0 );
3448 }
3449
3450 // DEMOCRATIC BONUS 1
3451 if ( gamestate.DODEMOCRATICBONUS1 )
3452 {
3453 gamestate.score += 5000;
3454 DrawEndBonus( "DEMOCRATIC BONUS 1", " 5000 POINTS", 0 );
3455 }
3456
3457 // DEMOCRATIC BONUS 2
3458 if (democraticratio == 100)
3459 {
3460 gamestate.score += 5000;
3461 DrawEndBonus( "DEMOCRATIC BONUS 2", " 5000 POINTS", 0 );
3462 }
3463 }
3464
3465 if ( EndBonusNumBonuses == 0 )
3466 {
3467 DrawEndBonus( "NO BONUS!", NULL, 1 );
3468 }
3469
3470 if ( ( EndBonusNumBonuses != 0 ) || ( playstate == ex_gameover ) )
3471 {
3472 SD_Play( PlayerSnds[ locplayerstate->player ] );
3473
3474 // DO BONUS BONUS
3475 if ( EndBonusNumBonuses == NUMBONUSES )
3476 {
3477 IN_StartAck();
3478 while( !IN_CheckAck() )
3479 {
3480 ;
3481 }
3482
3483 BkPic = ( pic_t * )W_CacheLumpName( "mmbk", PU_CACHE, Cvt_pic_t, 1 );
3484 VWB_DrawPic( 0, 0, BkPic );
3485
3486 gamestate.score += BONUSBONUS;
3487 DrawEOLHeader( playstate );
3488 EndBonusFirst = true;
3489 EndBonusStartY = 110;
3490 EndBonusSkip = true;
3491 DrawEndBonus( "BONUS BONUS! 1,000,000 POINTS!", NULL, 2 );
3492 }
3493 else if ( ( kr == 100 ) && ( dobonus ) )
3494 {
3495 IN_StartAck();
3496 while( !IN_CheckAck() )
3497 {
3498 ;
3499 }
3500
3501 BkPic = ( pic_t * )W_CacheLumpName( "mmbk", PU_CACHE, Cvt_pic_t, 1 );
3502 VWB_DrawPic( 0, 0, BkPic );
3503
3504 DrawEOLHeader( playstate );
3505 EndBonusFirst = true;
3506 EndBonusStartY = 110;
3507 DrawEndBonus( "You have done well.", NULL, 3 );
3508 #if (SHAREWARE==1)
3509 EndBonusVoice = SD_Play( SD_RICOCHET3SND );
3510 #else
3511 EndBonusVoice = SD_Play( SD_PERCENT100SND );
3512 #endif
3513 EndBonusSkip = false;
3514 DrawEndBonus( "This level is toast.", NULL, 3 );
3515 }
3516 }
3517
3518 IN_StartAck();
3519 while( !IN_CheckAck() )
3520 {
3521 ;
3522 }
3523
3524 EndLevelStuff = false;
3525 CurrentFont = smallfont;
3526 }
3527
3528
DrawTallyHeader(int which)3529 void DrawTallyHeader
3530 (
3531 int which
3532 )
3533
3534 {
3535 pic_t *Name;
3536 pic_t *KillCount;
3537 pic_t *TimesYouKilledPerson;
3538 pic_t *TimesPersonKilledYou;
3539 pic_t *Suicides;
3540 pic_t *Score;
3541 pic_t *Blank;
3542 pic_t *TopBar;
3543
3544 Name = ( pic_t * )W_CacheLumpName( "t_name", PU_CACHE, Cvt_pic_t, 1 );
3545 Blank = ( pic_t * )W_CacheLumpName( "t_blnk", PU_CACHE, Cvt_pic_t, 1 );
3546 KillCount = ( pic_t * )W_CacheLumpName( "t_kcount", PU_CACHE, Cvt_pic_t, 1 );
3547 TimesYouKilledPerson = ( pic_t * )W_CacheLumpName( "t_kilper", PU_CACHE, Cvt_pic_t, 1 );
3548 TimesPersonKilledYou = ( pic_t * )W_CacheLumpName( "t_perkil" , PU_CACHE, Cvt_pic_t, 1 );
3549 Suicides = ( pic_t * )W_CacheLumpName( "t_suicid", PU_CACHE, Cvt_pic_t, 1 );
3550 Score = ( pic_t * )W_CacheLumpName( "t_score", PU_CACHE, Cvt_pic_t, 1 );
3551 TopBar = ( pic_t * )W_CacheLumpName( "t_bar", PU_CACHE, Cvt_pic_t, 1 );
3552
3553 IFont = ( cfont_t * )W_CacheLumpName( "sifont", PU_CACHE, Cvt_cfont_t, 1 );
3554
3555 switch( which )
3556 {
3557 case 0 :
3558 VWB_DrawPic ( 8, 8, TopBar );
3559 DrawIntensityString( 12, 11, "FINAL SCORE", 20 );
3560 VWB_DrawPic ( 8, 24, Name );
3561 VWB_DrawPic ( 136, 24, KillCount );
3562 VWB_DrawPic ( 184, 24, Suicides );
3563 VWB_DrawPic ( 272, 24, Score );
3564 break;
3565
3566 case 1 :
3567 VWB_DrawPic ( 8, 8, TopBar );
3568 DrawIntensityString( 12, 11, "FINAL SCORE", 20 );
3569 VWB_DrawPic ( 8, 24, Name );
3570 VWB_DrawPic ( 136, 24, Blank );
3571 VWB_DrawPic ( 272, 24, Score );
3572 break;
3573
3574 case 2 :
3575 VWB_DrawPic ( 8, 8, TopBar );
3576 DrawIntensityString( 12, 11, "YOUR KILLS", 20 );
3577 VWB_DrawPic ( 8, 24, Name );
3578 VWB_DrawPic ( 136, 24, KillCount );
3579 VWB_DrawPic ( 184, 24, TimesYouKilledPerson );
3580 break;
3581
3582 case 3 :
3583 VWB_DrawPic ( 8, 8, TopBar );
3584 DrawIntensityString( 12, 11, "YOUR DEATHS", 20 );
3585 VWB_DrawPic ( 8, 24, Name );
3586 VWB_DrawPic ( 136, 24, TimesPersonKilledYou );
3587 break;
3588 }
3589
3590 DrawTimeXY( TALLYTIME_X, TALLYTIME_Y, gamestate.TimeCount / VBLCOUNTER,
3591 true );
3592 }
3593
3594
3595 #define BT_RANK_X 23
3596 #define BT_PLAYER_X 30
3597 #define BT_KILLS_X ( 139 + ( ( 40 + 20 ) / 2 ) )
3598 #define BT_DEATHS_X ( 193 + ( ( 56 + 20 ) / 2 ) )
3599 //#define BT_SCORE_X ( 263 + ( ( 46 + 20 ) / 2 ) )
3600 #define BT_SCORE_X ( 273 + ( ( 46 + 20 ) / 2 ) )
3601
3602
ShowKills(int localplayer)3603 void ShowKills( int localplayer )
3604 {
3605 int w;
3606 int h;
3607 int i;
3608 int j;
3609 int temp;
3610 int rank;
3611 int player;
3612 int killer;
3613 int victim;
3614 int color;
3615 char tempstr[15];
3616 int KillCount[ MAXPLAYERS ];
3617 int Order[ MAXPLAYERS ];
3618 int NumPlayers;
3619
3620 // show at the most 11 players
3621 NumPlayers = min( numplayers, 11 );
3622
3623 // Count kills
3624 for( killer = 0; killer < NumPlayers; killer++ )
3625 {
3626 Order[ killer ] = killer;
3627 KillCount[ killer ] = 0;
3628 for( victim = 0; victim < NumPlayers; victim++ )
3629 {
3630 if ( BATTLE_Team[ victim ] != BATTLE_Team[ killer ] )
3631 {
3632 KillCount[ killer ] += WhoKilledWho[ killer ][ victim ];
3633 }
3634 }
3635 }
3636
3637 for( i = 0; i < NumPlayers - 1; i++ )
3638 {
3639 for( j = i + 1; j < NumPlayers; j++ )
3640 {
3641 if ( KillCount[ Order[ i ] ] < KillCount[ Order[ j ] ] )
3642 {
3643 temp = Order[ i ];
3644 Order[ i ] = Order[ j ];
3645 Order[ j ] = temp;
3646 }
3647 }
3648 }
3649
3650 DrawTallyHeader( 2 );
3651
3652 IFont = (cfont_t * )W_CacheLumpNum (W_GetNumForName ("sifont"), PU_CACHE, Cvt_cfont_t, 1);
3653 CurrentFont = smallfont;
3654 py = 43;
3655
3656 for( rank = 0; rank < NumPlayers; rank++ )
3657 {
3658 player = Order[ rank ];
3659
3660 color = 21;
3661
3662 // Highlight the your score
3663 if ( player == localplayer )
3664 {
3665 // Change to Intensity
3666 color = 241;
3667 }
3668
3669 // Draw rank if not tied with previous rank
3670 if ( ( rank == 0 ) || ( KillCount[ player ] !=
3671 KillCount[ Order[ rank - 1 ] ] ) )
3672 {
3673 itoa( rank + 1, tempstr, 10 );
3674 }
3675 else
3676 {
3677 strcpy( tempstr, "Tie" );
3678 }
3679
3680 VW_MeasureIntensityPropString ( tempstr, &w, &h);
3681 DrawIntensityString( BT_RANK_X - w, py, tempstr, color );
3682
3683 // Draw name
3684 DrawIntensityString( BT_PLAYER_X, py, PLAYERSTATE[ player ].codename, color );
3685
3686 // Draw kills
3687 itoa( KillCount[ player ], tempstr, 10 );
3688 VW_MeasureIntensityPropString ( tempstr, &w, &h);
3689 DrawIntensityString( BT_KILLS_X - w, py, tempstr, color );
3690
3691 // Draw times you killed that person
3692 if ( player != localplayer )
3693 {
3694 itoa( WhoKilledWho[ localplayer ][ player ], tempstr, 10 );
3695 }
3696 else
3697 {
3698 strcpy( tempstr, "-" );
3699 }
3700
3701 VW_MeasureIntensityPropString ( tempstr, &w, &h);
3702 DrawIntensityString( BT_DEATHS_X - w, py, tempstr, color );
3703
3704 if ( gamestate.teamplay )
3705 {
3706 DrawIntensityString( BT_DEATHS_X + 16, py,
3707 colorname[ PLAYERSTATE[ player ].uniformcolor ], color );
3708 }
3709
3710 py += h;
3711 }
3712 }
3713
3714
ShowDeaths(int localplayer)3715 void ShowDeaths( int localplayer )
3716 {
3717 int w;
3718 int h;
3719 int i;
3720 int j;
3721 int temp;
3722 int rank;
3723 int player;
3724 int killer;
3725 int victim;
3726 int color;
3727 char tempstr[15];
3728 int DeathCount[ MAXPLAYERS ];
3729 int Order[ MAXPLAYERS ];
3730 int NumPlayers;
3731
3732 // show at the most 11 players
3733 NumPlayers = min( numplayers, 11 );
3734
3735 // Count Deaths
3736 for( victim = 0; victim < NumPlayers; victim++ )
3737 {
3738 Order[ victim ] = victim;
3739 DeathCount[ victim ] = 0;
3740 for( killer = 0; killer < NumPlayers; killer++ )
3741 {
3742 DeathCount[ victim ] += WhoKilledWho[ killer ][ victim ];
3743 }
3744 }
3745
3746 for( i = 0; i < NumPlayers - 1; i++ )
3747 {
3748 for( j = i + 1; j < NumPlayers; j++ )
3749 {
3750 if ( DeathCount[ Order[ i ] ] < DeathCount[ Order[ j ] ] )
3751 {
3752 temp = Order[ i ];
3753 Order[ i ] = Order[ j ];
3754 Order[ j ] = temp;
3755 }
3756 }
3757 }
3758
3759 DrawTallyHeader( 3 );
3760
3761 IFont = (cfont_t * )W_CacheLumpNum (W_GetNumForName ("sifont"), PU_CACHE, Cvt_cfont_t, 1);
3762 CurrentFont = smallfont;
3763 py = 43;
3764
3765 for( rank = 0; rank < NumPlayers; rank++ )
3766 {
3767 player = Order[ rank ];
3768 color = 21;
3769
3770 // Highlight the your score
3771 if ( player == localplayer )
3772 {
3773 // Change to Intensity
3774 color = 241;
3775 }
3776
3777 // Draw rank if not tied with previous rank
3778 if ( ( rank == 0 ) || ( DeathCount[ player ] !=
3779 DeathCount[ Order[ rank - 1 ] ] ) )
3780 {
3781 itoa( rank + 1, tempstr, 10 );
3782 }
3783 else
3784 {
3785 strcpy( tempstr, "Tie" );
3786 }
3787
3788 VW_MeasureIntensityPropString ( tempstr, &w, &h);
3789 DrawIntensityString( BT_RANK_X - w, py, tempstr, color );
3790
3791 // Draw name
3792 DrawIntensityString( BT_PLAYER_X, py, PLAYERSTATE[ player ].codename, color );
3793
3794 // Draw deaths
3795 itoa( DeathCount[ player ], tempstr, 10 );
3796 VW_MeasureIntensityPropString ( tempstr, &w, &h);
3797 DrawIntensityString( BT_KILLS_X - w, py, tempstr, color );
3798
3799 // Draw times you were killed by that person
3800 itoa( WhoKilledWho[ player ][ localplayer ], tempstr, 10 );
3801 VW_MeasureIntensityPropString ( tempstr, &w, &h);
3802 DrawIntensityString( BT_DEATHS_X - w, py, tempstr, color );
3803
3804 if ( gamestate.teamplay )
3805 {
3806 DrawIntensityString( BT_DEATHS_X + 16, py,
3807 colorname[ PLAYERSTATE[ player ].uniformcolor ], color );
3808 }
3809
3810 py += h;
3811 }
3812 }
3813
3814
ShowEndScore(int localplayer)3815 void ShowEndScore( int localplayer )
3816 {
3817 int w;
3818 int h;
3819 int rank;
3820 int leader;
3821 int team;
3822 int color;
3823 int killer;
3824 int victim;
3825 int killcount;
3826 int suicidecount;
3827 char tempstr[15];
3828 boolean dofullstats;
3829 int NumPlayers;
3830
3831 // show at the most 11 players
3832 NumPlayers = min( numplayers, 11 );
3833
3834 dofullstats = false;
3835 switch( gamestate.battlemode )
3836 {
3837 case battle_Normal :
3838 case battle_ScoreMore :
3839 case battle_Hunter :
3840 dofullstats = true;
3841 DrawTallyHeader( 0 );
3842 break;
3843
3844 case battle_Collector :
3845 case battle_Scavenger :
3846 case battle_Tag :
3847 case battle_Eluder :
3848 case battle_Deluder :
3849 case battle_CaptureTheTriad :
3850 dofullstats = false;
3851 DrawTallyHeader( 1 );
3852 break;
3853 }
3854
3855 IFont = (cfont_t * )W_CacheLumpNum (W_GetNumForName ("sifont"), PU_CACHE, Cvt_cfont_t, 1);
3856 CurrentFont = smallfont;
3857 py = 43;
3858
3859 for( rank = 0; rank < BATTLE_NumberOfTeams; rank++ )
3860 {
3861 team = BATTLE_PlayerOrder[ rank ];
3862
3863 color = 21;
3864 if ( team == BATTLE_Team[ localplayer ] )
3865 {
3866 // Change to Intensity
3867 color = 241;
3868 }
3869
3870 // Draw rank if not tied with previous rank
3871 if ( ( rank == 0 ) || ( BATTLE_Points[ team ] !=
3872 BATTLE_Points[ BATTLE_PlayerOrder[ rank - 1 ] ] ) )
3873 {
3874 itoa( rank + 1, tempstr, 10 );
3875 }
3876 else
3877 {
3878 strcpy( tempstr, "Tie" );
3879 }
3880
3881 VW_MeasureIntensityPropString ( tempstr, &w, &h);
3882 DrawIntensityString( BT_RANK_X - w, py, tempstr, color );
3883
3884 // Draw name of team leader
3885 leader = BATTLE_TeamLeader[ team ];
3886 if ( gamestate.teamplay )
3887 {
3888 DrawIntensityString( BT_PLAYER_X, py,
3889 colorname[ PLAYERSTATE[ leader ].uniformcolor ], color );
3890 }
3891 else
3892 {
3893 DrawIntensityString( BT_PLAYER_X, py,
3894 PLAYERSTATE[ leader ].codename, color );
3895 }
3896
3897 if ( dofullstats )
3898 {
3899 // Count how many kills each person on the team got
3900 killcount = 0;
3901 suicidecount = 0;
3902 for( killer = 0; killer < NumPlayers; killer++ )
3903 {
3904 if ( BATTLE_Team[ killer ] == team )
3905 {
3906 for( victim = 0; victim < NumPlayers; victim++ )
3907 {
3908 if ( BATTLE_Team[ victim ] != team )
3909 {
3910 killcount += WhoKilledWho[ killer ][ victim ];
3911 }
3912 else
3913 {
3914 suicidecount += WhoKilledWho[ killer ][ victim ];
3915 }
3916 }
3917 }
3918 }
3919
3920 // Draw kills
3921 itoa( killcount, tempstr, 10 );
3922 VW_MeasureIntensityPropString ( tempstr, &w, &h);
3923 DrawIntensityString( BT_KILLS_X - w, py, tempstr, color );
3924
3925 // Draw suicides
3926 itoa( suicidecount, tempstr, 10 );
3927 VW_MeasureIntensityPropString ( tempstr, &w, &h);
3928 DrawIntensityString( BT_DEATHS_X - w, py, tempstr, color );
3929 }
3930
3931 // Draw Score
3932 itoa( BATTLE_Points[ team ], tempstr, 10 );
3933 VW_MeasureIntensityPropString ( tempstr, &w, &h);
3934 DrawIntensityString( BT_SCORE_X - w, py, tempstr, color );
3935
3936 py += h;
3937 }
3938 }
3939
3940
BattleLevelCompleted(int localplayer)3941 void BattleLevelCompleted ( int localplayer )
3942 {
3943 ControlInfo ci;
3944 int w;
3945 int h;
3946 int key;
3947 int Screen;
3948 int LastScreen;
3949 int Player;
3950 char text[80];
3951
3952 IN_ClearKeysDown ();
3953
3954 Player = localplayer;
3955 Screen = 1;
3956 LastScreen = 0;
3957 key = -1;
3958 while( 1 )
3959 {
3960 if ( Screen != LastScreen )
3961 {
3962 VL_DrawPostPic (W_GetNumForName("trilogo"));
3963
3964 switch( Screen )
3965 {
3966 case 1 :
3967 ShowEndScore( Player );
3968 break;
3969
3970 case 2 :
3971 ShowKills( Player );
3972 break;
3973
3974 case 3 :
3975 ShowDeaths( Player );
3976 break;
3977 }
3978
3979 CurrentFont = tinyfont;
3980
3981 sprintf ( text, "Page %d of 3. Use arrows to switch stats. "
3982 "Press Esc to quit.", Screen );
3983 VW_MeasurePropString ( text, &w, &h);
3984 py = 192;
3985 px = ( 320 - w ) / 2;
3986 VWB_DrawPropString ( text );
3987 VW_UpdateScreen ();
3988
3989 do
3990 {
3991 ReadAnyControl (&ci);
3992 }
3993 while( ci.dir == (dirtype)key );
3994 }
3995
3996 LastScreen = Screen;
3997 ReadAnyControl ( &ci );
3998 key = ci.dir;
3999 if ( ( Screen > 1 ) && ( key == dir_West ) )
4000 {
4001 Screen--;
4002 MN_PlayMenuSnd (SD_MOVECURSORSND);
4003 }
4004 else if ( ( Screen < 3 ) && ( key == dir_East ) )
4005 {
4006 Screen++;
4007 MN_PlayMenuSnd (SD_MOVECURSORSND);
4008 }
4009 // Allow us to select which player to view
4010 if ( Keyboard[ sc_RShift ] && ( key == dir_South ) )
4011 {
4012 Player++;
4013 if ( Player >= numplayers )
4014 {
4015 Player = 0;
4016 }
4017 LastScreen = 0;
4018 MN_PlayMenuSnd (SD_SELECTSND);
4019 }
4020
4021 if ( Keyboard[ sc_RShift ] && ( key == dir_North ) )
4022 {
4023 Player--;
4024 if ( Player < 0 )
4025 {
4026 Player = numplayers - 1;
4027 }
4028 LastScreen = 0;
4029 MN_PlayMenuSnd (SD_SELECTSND);
4030 }
4031
4032 if ( Keyboard[sc_Escape] )
4033 {
4034 break;
4035 }
4036 }
4037
4038 while ( Keyboard[sc_Escape] )
4039 {
4040 IN_UpdateKeyboard ();
4041 }
4042
4043 MN_PlayMenuSnd (SD_ESCPRESSEDSND);
4044
4045 CurrentFont = smallfont;
4046 }
4047
4048 //==========================================================================
4049
4050 /*
4051 ==================
4052 =
4053 = FindAngleToWindow
4054 =
4055 ==================
4056 */
FindAngleToWindow(int tx,int ty)4057 int FindAngleToWindow ( int tx, int ty )
4058 {
4059 if (!IsWindow(tx+1,ty))
4060 return ANG180;
4061 else if (!IsWindow(tx-1,ty))
4062 return 0;
4063 else if (!IsWindow(tx,ty+1))
4064 return ANG90;
4065 else
4066 return ANG270;
4067 }
4068
4069 #define STARTRADIUS (0xa000)
4070 #define STOPRADIUS (0x14000)
4071 #define DEATHRADIUS (STOPRADIUS-STARTRADIUS)
4072 #define ROTRATE (5)
4073 #define TOTALDEATHROT (FINEANGLES<<1)
4074 #define RADIUSINC ((DEATHRADIUS)/(TOTALDEATHROT))
4075
4076 /*
4077 ==================
4078 =
4079 = ZoomDeathOkay
4080 =
4081 ==================
4082 */
ZoomDeathOkay(void)4083 boolean ZoomDeathOkay ( void )
4084 {
4085 int x,y;
4086 int radius;
4087
4088 if (
4089 !(
4090 (player->state==&s_ashwait) ||
4091 ((player->flags & FL_HBM) && (gamestate.violence >= vl_high))
4092 )
4093 )
4094 return false;
4095
4096 radius=STOPRADIUS;
4097 x=player->x;
4098 y=player->y;
4099 while (radius>0)
4100 {
4101 if (tilemap[x>>16][(y+radius)>>16])
4102 return false;
4103 if (tilemap[x>>16][(y-radius)>>16])
4104 return false;
4105 if (tilemap[(x-radius)>>16][y>>16])
4106 return false;
4107 if (tilemap[(x+radius)>>16][y>>16])
4108 return false;
4109 if (tilemap[(x+radius)>>16][(y+radius)>>16])
4110 return false;
4111 if (tilemap[(x+radius)>>16][(y-radius)>>16])
4112 return false;
4113 if (tilemap[(x-radius)>>16][(y+radius)>>16])
4114 return false;
4115 if (tilemap[(x-radius)>>16][(y-radius)>>16])
4116 return false;
4117 radius-=0x10000;
4118 }
4119 return true;
4120 }
4121
4122 /*
4123 ==================
4124 =
4125 = Died
4126 =
4127 ==================
4128 */
4129
4130 #define DEATHROTATE 6
4131
4132 extern boolean dopefish;
Died(void)4133 void Died (void)
4134 {
4135 long dx,dy;
4136 int iangle,curangle,clockwise,change;
4137 int da;
4138 int rate;
4139 lbm_t *LBM;
4140 int slowrate;
4141 playertype *pstate;
4142 objtype * killerobj=(objtype *)player->target;
4143
4144
4145 if (killerobj == NULL)
4146 killerobj = player;
4147
4148 if (CheckParm("slowdeath"))
4149 slowrate=3;
4150 else
4151 slowrate=0;
4152
4153 M_LINKSTATE (player, pstate);
4154
4155 if ( (ZoomDeathOkay()==true) && (pstate->falling==false))
4156 {
4157 int x,y,z,radius,heightoffset;
4158 int endangle,startangle,killangle;
4159 boolean deadflagset;
4160 objtype * dummy;
4161
4162 x=player->x;
4163 y=player->y;
4164 z=player->z;
4165 dummy=player;
4166 SpawnPlayerobj (x>>16, y>>16, 0, 0);
4167 player=dummy;
4168 dummy=new;
4169 dummy->x=x;
4170 dummy->drawx=x;
4171 dummy->y=y;
4172 dummy->z=z;
4173 dummy->drawy=y;
4174 dummy->flags=player->flags;
4175 player->momentumx=0;
4176 player->momentumy=0;
4177 player->speed=0;
4178 radius=STARTRADIUS;
4179 heightoffset=pstate->heightoffset;
4180 deadflagset=false;
4181 startangle=(player->angle+ANG180)&(FINEANGLES-1);
4182 endangle=startangle+TOTALDEATHROT;
4183 killangle=startangle+(TOTALDEATHROT>>1);
4184 if (dopefish==true)
4185 {
4186 AddMessage("Dopefish Death Cam\n",MSG_SYSTEM);
4187 }
4188 for (iangle=startangle;;)
4189 {
4190 if ( iangle > killangle )
4191 {
4192 if ( deadflagset==false )
4193 {
4194 dummy->hitpoints=0;
4195 pstate->health=0;
4196 dummy->flags &= ~FL_DYING;
4197 dummy->flags |= FL_SHOOTABLE;
4198 if (player->state==&s_ashwait)
4199 dummy->flags |= FL_SKELETON;
4200 Collision(dummy,(objtype*)NULL,0,0);
4201 deadflagset=true;
4202 if ( ( killerobj==player ) && ( gamestate.violence >=
4203 vl_high ) && ( gamestate.difficulty >= gd_hard ) )
4204 {
4205 SD_Play( SD_YOUSUCKSND );
4206 }
4207 else
4208 {
4209 SD_Play (SD_PLAYERTCDEATHSND+(pstate->player));
4210 }
4211 }
4212 }
4213 else
4214 {
4215 dummy->flags &= ~FL_DYING;
4216 }
4217 if (dopefish==true)
4218 {
4219 dummy->momentumx+=(RandomNumber("Died",0)<<6)-(256<<5);
4220 dummy->momentumy+=(RandomNumber("Died",0)<<6)-(256<<5);
4221 }
4222 player->x=x+FixedMul(radius,costable[iangle&(FINEANGLES-1)]);
4223 player->y=y-FixedMul(radius,sintable[iangle&(FINEANGLES-1)]);
4224 player->z=dummy->z;
4225 player->angle=(iangle+ANG180)&(FINEANGLES-1);
4226 if (dopefish==true)
4227 {
4228 int dx,dy;
4229
4230 dx = dummy->x - player->x;
4231 dy = player->y - dummy->y;
4232
4233 if (dx && dy)
4234 player->angle = atan2_appx (dx,dy);
4235 }
4236 pstate->heightoffset=heightoffset;
4237 player->yzangle=0;
4238 UpdateGameObjects();
4239 player->momentumx=0;
4240 player->momentumy=0;
4241 player->speed=0;
4242 ThreeDRefresh ();
4243 AnimateWalls();
4244 DoSprites();
4245 DoAnimatedMaskedWalls();
4246 UpdatePlayers();
4247 UpdateLightLevel(player->areanumber);
4248
4249 if (iangle<endangle)
4250 {
4251 iangle+=(tics<<ROTRATE);
4252 radius+=tics*(RADIUSINC<<ROTRATE);
4253 }
4254 if ( (dummy->state==dummy->state->next) && (iangle>=endangle) )
4255 break;
4256 }
4257 }
4258 else if (pstate->falling==false)
4259 {
4260
4261 //
4262 // swing around to face attacker
4263 //
4264
4265 rate=DEATHROTATE-slowrate;
4266 {
4267 if (killerobj==player)
4268 {
4269 iangle=player->angle;
4270 if ( ( gamestate.violence >= vl_high ) &&
4271 ( gamestate.difficulty >= gd_hard ) )
4272 {
4273 SD_Play( SD_YOUSUCKSND );
4274 }
4275 }
4276 else
4277 {
4278 SD_Play (SD_PLAYERTCDEATHSND+(pstate->player));
4279 if (killerobj->which==PWALL)
4280 {
4281 dx = ((pwallobj_t *)killerobj)->x - player->x;
4282 dy = player->y - ((pwallobj_t *)killerobj)->y;
4283 }
4284 else
4285 {
4286 dx = killerobj->x - player->x;
4287 dy = player->y - killerobj->y;
4288 }
4289
4290 iangle = atan2_appx (dx,dy); // returns -pi to pi
4291 }
4292 }
4293
4294 da = iangle-player->angle;
4295
4296 if (da>0)
4297 clockwise=1;
4298 else
4299 clockwise=0;
4300 da=abs(da);
4301 if (da>ANG180)
4302 {
4303 clockwise^=1;
4304 da=ANGLES-da;
4305 }
4306
4307 curangle = player->angle;
4308
4309 do
4310 {
4311 DoBorderShifts ();
4312 change = tics<<rate;
4313 if (clockwise==1)
4314 curangle+=change;
4315 else
4316 curangle-=change;
4317 da-=change;
4318 if (curangle >= ANGLES)
4319 curangle -= ANGLES;
4320 if (curangle < 0)
4321 curangle += ANGLES;
4322 player->angle = (curangle & (FINEANGLES-1));
4323 ThreeDRefresh ();
4324 CalcTics ();
4325 } while (da>0);
4326 }
4327 else
4328 {
4329 DrawFullSky();
4330 FlipPage();
4331 }
4332
4333 while (damagecount)
4334 DoBorderShifts ();
4335 DoBorderShifts ();
4336
4337 locplayerstate->weapon = -1; // take away weapon
4338
4339 if (
4340 (tedlevel == false) && // SO'S YA DON'T GET KILLED WHILE LAUNCHING!
4341 (timelimitenabled == false)
4342 )
4343 locplayerstate->lives--;
4344
4345 if (pstate->falling==false)
4346 {
4347 ThreeDRefresh ();
4348 }
4349
4350 FlipPage();
4351 FlipPage();
4352
4353 if (locplayerstate->lives > -1)
4354 {
4355 int rng;
4356
4357 rng = RandomNumber ("Died",0);
4358
4359 if (pstate->falling==true)
4360 {
4361 RotateBuffer (0, 0, (FINEANGLES), (FINEANGLES>>6), (VBLCOUNTER*(1+slowrate)));
4362 SD_Play (SD_PLAYERTCDEATHSND+(pstate->player));
4363 pstate->falling=false;
4364 }
4365
4366 else if (rng < 64)
4367 RotateBuffer (0, 0, (FINEANGLES), (FINEANGLES*64), (VBLCOUNTER*(2+slowrate)));
4368 else if (rng < 128)
4369 {
4370 RotateBuffer (0, 0, (FINEANGLES), (FINEANGLES>>6), (VBLCOUNTER*(1+slowrate)));
4371 }
4372 else if (rng < 192)
4373 RotateBuffer(0, (FINEANGLES*4), (FINEANGLES), (FINEANGLES*64), (VBLCOUNTER*(3+slowrate)));
4374 else
4375 VL_FadeToColor (VBLCOUNTER*2, 100, 0, 0);
4376
4377 screenfaded=false;
4378
4379 VL_FadeOut (0, 255, 0,0,0,VBLCOUNTER>>1);
4380 gamestate.episode = 1;
4381 player->flags &= ~FL_DONE;
4382
4383 InitializeWeapons (locplayerstate);
4384 ResetPlayerstate(locplayerstate);
4385
4386 UpdateLives (locplayerstate->lives);
4387 UpdateScore (gamestate.score);
4388
4389 DrawTriads(true);
4390 DrawLives (true);
4391 DrawKeys (true);
4392 DrawScore (true);
4393 }
4394 else
4395 {
4396 int rng;
4397
4398 SD_Play (SD_GAMEOVERSND);
4399 rng=RandomNumber("Died",0);
4400 if (rng<64)
4401 RotateBuffer(0,(FINEANGLES>>1),(FINEANGLES),(FINEANGLES*64),(VBLCOUNTER*(3+slowrate)));
4402 else if (rng<128)
4403 VL_FadeToColor (VBLCOUNTER*3, 255, 255, 255);
4404 else if (rng<192)
4405 RotateBuffer(0,(FINEANGLES*2),(FINEANGLES),(FINEANGLES*64),(VBLCOUNTER*(3+slowrate)));
4406 else
4407 RotateBuffer(0,(FINEANGLES*2),(FINEANGLES),(FINEANGLES*64),(VBLCOUNTER*(3+slowrate)));
4408
4409 screenfaded=false;
4410
4411 VL_FadeOut (0, 255, 0,0,0,VBLCOUNTER>>1);
4412
4413 MU_StartSong(song_gameover);
4414
4415 #if (SHAREWARE==0)
4416 if (gamestate.violence==vl_excessive)
4417 LBM = (lbm_t *) W_CacheLumpNum (W_GetNumForName ("bootblod"), PU_CACHE, Cvt_lbm_t, 1);
4418 else
4419 LBM = (lbm_t *) W_CacheLumpNum (W_GetNumForName ("bootnorm"), PU_CACHE, Cvt_lbm_t, 1);
4420 #else
4421 LBM = (lbm_t *) W_CacheLumpNum (W_GetNumForName ("bootblod"), PU_CACHE, Cvt_lbm_t, 1);
4422 #endif
4423 VL_DecompressLBM (LBM,true);
4424
4425 StopWind();
4426
4427 IN_UserInput (VBLCOUNTER*60);
4428
4429 MainMenu[savegame].active = 0;
4430 MainMenu[viewscores].routine = (void *)CP_ViewScores;
4431 MainMenu[viewscores].texture[6] = '7';
4432 MainMenu[viewscores].texture[7] = '\0';
4433 MainMenu[viewscores].letter = 'V';
4434 }
4435 ClearGraphicsScreen();
4436
4437 VL_FadeIn (0, 255, origpal, 15);
4438 }
4439
4440
4441 //******************************************************************************
4442 //
4443 // DoLoadGameAction ()
4444 //
4445 //******************************************************************************
4446
4447 static byte whichstr = 0;
4448
DoLoadGameAction(void)4449 void DoLoadGameAction (void)
4450 {
4451 if ((SaveTime+1) < GetTicCount())
4452 {
4453 int temp = bufferofs;
4454
4455 bufferofs = displayofs;
4456 SaveTime = GetTicCount();
4457
4458 CurrentFont=tinyfont;
4459
4460 px = 92;
4461 py = 152;
4462 if (whichstr)
4463 {
4464 // VW_DrawPropString ("�");
4465 VW_DrawPropString (".");
4466 whichstr = 0;
4467 }
4468 else
4469 {
4470 // VW_DrawPropString ("�");
4471 VW_DrawPropString (".");
4472 whichstr = 1;
4473 }
4474 bufferofs = temp;
4475 }
4476 }
4477
4478 //******************************************************************************
4479 //
4480 // DoCheckSum ()
4481 //
4482 //******************************************************************************
4483
DoCheckSum(byte * source,int size,long csum)4484 long DoCheckSum (byte *source, int size, long csum)
4485 {
4486 int i;
4487 long checksum;
4488
4489 checksum = csum;
4490
4491 for (i = 0; i < size; i++)
4492 checksum=updatecrc(checksum,*(source+i));
4493
4494 return checksum;
4495 }
4496
4497 //******************************************************************************
4498 //
4499 // CaculateSaveGameCheckSum ()
4500 //
4501 //******************************************************************************
4502
4503 #define SAVECHECKSUMSIZE (10000)
CalculateSaveGameCheckSum(char * filename)4504 long CalculateSaveGameCheckSum (char * filename)
4505 {
4506 int handle;
4507 int lengthleft;
4508 int length;
4509 byte * altbuffer;
4510 long checksum;
4511
4512 altbuffer=SafeMalloc(SAVECHECKSUMSIZE);
4513
4514 checksum = 0;
4515
4516 // Open the savegame file
4517
4518 handle = SafeOpenRead (filename);
4519 lengthleft = filelength (handle);
4520
4521 while (lengthleft>0)
4522 {
4523 length=SAVECHECKSUMSIZE;
4524 if (length>lengthleft)
4525 length=lengthleft;
4526
4527 SafeRead(handle,altbuffer,length);
4528 checksum = DoCheckSum (altbuffer, length, checksum);
4529
4530 lengthleft-=length;
4531 }
4532
4533 SafeFree(altbuffer);
4534
4535 close (handle);
4536
4537 return checksum;
4538 }
4539
4540 //******************************************************************************
4541 //
4542 // StoreBuffer
4543 //
4544 //******************************************************************************
StoreBuffer(int handle,byte * src,int size)4545 void StoreBuffer (int handle, byte * src, int size)
4546 {
4547 SafeWrite(handle,&size,sizeof(size));
4548 SafeWrite(handle,src,size);
4549 }
4550
4551 //******************************************************************************
4552 //
4553 // SaveTag
4554 //
4555 //******************************************************************************
SaveTag(int handle,char * tag,int size)4556 void SaveTag (int handle, char * tag, int size)
4557 {
4558 SafeWrite(handle,tag,size);
4559 }
4560
4561
4562 //******************************************************************************
4563 //
4564 // SaveTheGame ()
4565 //
4566 // Expects game to be premalloced
4567 //
4568 //******************************************************************************
4569
SaveTheGame(int num,gamestorage_t * game)4570 boolean SaveTheGame (int num, gamestorage_t * game)
4571 {
4572 char loadname[MAX_PATH]="rottgam0.rot";
4573 char filename[MAX_PATH];
4574 byte * altbuffer;
4575 int size;
4576 int avail;
4577 int savehandle;
4578 int crc;
4579 int i;
4580 char letter;
4581 int myticcount;
4582
4583 if (num > 15 || num < 0)
4584 Error("Illegal Saved game value=%ld\n",num);
4585
4586 //
4587 // Save Alternate Game Level information for reloading game
4588 //
4589 memset (&game->info, 0, sizeof (game->info));
4590 if (GameLevels.avail == true)
4591 {
4592 memcpy (&game->info.path[0], &GameLevels.path[0], sizeof (GameLevels.path));
4593 memcpy (&game->info.file[0], &GameLevels.file[0], sizeof (GameLevels.file));
4594 game->info.avail = true;
4595 }
4596
4597 game->mapcrc=GetMapCRC (gamestate.mapon);
4598
4599 // Create the proper file name
4600
4601 itoa(num,&loadname[7],16);
4602 loadname[8]='.';
4603
4604
4605 GetPathFromEnvironment( filename, ApogeePath, loadname );
4606
4607 #if PLATFORM_DOS
4608 {
4609 struct diskfree_t dfree;
4610 // Determine available disk space
4611 letter = toupper(filename[0]);
4612 if (
4613 (letter >= 'A') &&
4614 (letter <= 'Q')
4615 )
4616 {
4617 if (_dos_getdiskfree ((letter-'A'+1), &dfree))
4618 Error ("Error in _dos_getdiskfree call\n");
4619 }
4620 else
4621 {
4622 if (_dos_getdiskfree (0, &dfree))
4623 Error ("Error in _dos_getdiskfree call\n");
4624 }
4625
4626 avail = (int) dfree.avail_clusters *
4627 dfree.bytes_per_sector *
4628 dfree.sectors_per_cluster;
4629 avail -= 8192;
4630
4631 // Check to see if we have enough
4632
4633 if (avail < MAXSAVEDGAMESIZE)
4634 {
4635 CP_DisplayMsg ("There is not enough\nspace on your disk\nto Save Game!\nPress any key to continue", 13);
4636 return (false);
4637 }
4638 }
4639 #endif
4640
4641 // Open the savegame file
4642
4643 savehandle = SafeOpenWrite (filename);
4644
4645 // Save out file tag
4646
4647 size=4;
4648 SaveTag(savehandle,"ROTT",size);
4649
4650 // Save out header
4651
4652 size=sizeof(*game);
4653
4654 SafeWrite(savehandle,game,size);
4655
4656 /////////////////////////////////////////////////////////////////////////////
4657 // Save out rest of save game file beyond this point
4658 /////////////////////////////////////////////////////////////////////////////
4659
4660 // Door Tag
4661
4662 size=4;
4663 SaveTag(savehandle,"DOOR",size);
4664
4665 // Doors
4666
4667 SaveDoors(&altbuffer,&size);
4668 StoreBuffer(savehandle,altbuffer,size);
4669 SafeFree(altbuffer);
4670
4671 // Elevator Tag
4672
4673 size = 9;
4674 SaveTag(savehandle,"ELEVATORS",size);
4675
4676 // Elevators
4677
4678 SaveElevators(&altbuffer,&size);
4679 StoreBuffer(savehandle,altbuffer,size);
4680 SafeFree(altbuffer);
4681
4682 // Pushwall Tag
4683
4684 size=5;
4685 SaveTag(savehandle,"PWALL",size);
4686
4687 // PushWalls
4688
4689 SavePushWalls(&altbuffer,&size);
4690 StoreBuffer(savehandle,altbuffer,size);
4691 SafeFree(altbuffer);
4692
4693 // MaskedWalls Tag
4694
4695 size=5;
4696 SaveTag(savehandle,"MWALL",size);
4697
4698 // Masked Walls
4699
4700 SaveMaskedWalls(&altbuffer,&size);
4701 StoreBuffer(savehandle,altbuffer,size);
4702 SafeFree(altbuffer);
4703
4704 // Switches Tag
4705
4706 size=6;
4707 SaveTag(savehandle,"SWITCH",size);
4708
4709 // Switches
4710
4711 SaveSwitches(&altbuffer,&size);
4712 StoreBuffer(savehandle,altbuffer,size);
4713 SafeFree(altbuffer);
4714
4715 // Statics Tag
4716
4717 size=6;
4718 SaveTag(savehandle,"STATIC",size);
4719
4720 // Statics
4721
4722 SaveStatics(&altbuffer,&size);
4723 StoreBuffer(savehandle,altbuffer,size);
4724 SafeFree(altbuffer);
4725
4726 // Actors Tag
4727
4728 size=5;
4729 SaveTag(savehandle,"ACTOR",size);
4730
4731 // Actors
4732
4733 SaveActors(&altbuffer,&size);
4734 StoreBuffer(savehandle,altbuffer,size);
4735 SafeFree(altbuffer);
4736
4737 // TouchPlates Tag
4738
4739 size=5;
4740 SaveTag(savehandle,"TOUCH",size);
4741
4742 // TouchPlates
4743
4744 SaveTouchPlates(&altbuffer,&size);
4745 StoreBuffer(savehandle,altbuffer,size);
4746 SafeFree(altbuffer);
4747
4748 // GameState Tag
4749
4750 size=9;
4751 SaveTag(savehandle,"GAMESTATE",size);
4752
4753 // GameState
4754
4755 size=sizeof(gamestate);
4756 SafeWrite(savehandle,&gamestate,size);
4757
4758 // PlayerState Tag
4759
4760 size=12;
4761 SaveTag(savehandle,"PLAYERSTATES",size);
4762
4763 // PlayerStates
4764 size=sizeof(playertype);
4765 for(i=0;i<numplayers;i++)
4766 {
4767 SafeWrite(savehandle,&PLAYERSTATE[i],size);
4768 }
4769
4770 // Mapseen Tag
4771
4772 size=7;
4773 SaveTag(savehandle,"MAPSEEN",size);
4774
4775 // MapSeen
4776
4777 size=sizeof(mapseen);
4778 SafeWrite(savehandle,&mapseen,size);
4779
4780 // Song Tag
4781
4782 size=4;
4783 SaveTag(savehandle,"SONG",size);
4784
4785 // Song info
4786
4787 MU_SaveMusic(&altbuffer,&size);
4788 StoreBuffer(savehandle,altbuffer,size);
4789 SafeFree(altbuffer);
4790
4791 // Misc Tag
4792
4793 size=4;
4794 SaveTag(savehandle,"MISC",size);
4795
4796 // Misc
4797
4798 // ticcount
4799 myticcount = GetTicCount();
4800 size=sizeof(myticcount);
4801 SafeWrite(savehandle,&myticcount,size);
4802
4803 // shaketics
4804 size=sizeof(SHAKETICS);
4805 SafeWrite(savehandle,&SHAKETICS,size);
4806
4807 // damagecount
4808 size=sizeof(damagecount);
4809 SafeWrite(savehandle,&damagecount,size);
4810
4811 // viewsize
4812 size=sizeof(viewsize);
4813 SafeWrite(savehandle,&viewsize,size);
4814
4815 // poweruptimes
4816 size = sizeof (poweruptime);
4817 SafeWrite(savehandle,&poweruptime,size);
4818
4819 size = sizeof (protectiontime);
4820 SafeWrite(savehandle,&protectiontime,size);
4821
4822 size = sizeof (powerupheight);
4823 SafeWrite(savehandle,&powerupheight,size);
4824
4825 size = sizeof (protectionheight);
4826 SafeWrite(savehandle,&protectionheight,size);
4827
4828 size = sizeof (poweradjust);
4829 SafeWrite(savehandle,&poweradjust,size);
4830
4831 close (savehandle);
4832
4833 // Calculate CRC
4834
4835 crc = CalculateSaveGameCheckSum (filename);
4836
4837 // Append the crc
4838
4839 savehandle = SafeOpenAppend (filename);
4840
4841 size=sizeof(crc);
4842 SafeWrite(savehandle,&crc,size);
4843
4844 close (savehandle);
4845
4846 pickquick = true;
4847 return (true);
4848 }
4849
4850
4851 //******************************************************************************
4852 //
4853 // LoadTag
4854 //
4855 //******************************************************************************
4856
LoadTag(byte ** src,char * tag,int size)4857 void LoadTag (byte ** src, char * tag, int size)
4858 {
4859 if (StringsNotEqual((char *)*src,(char *)tag,size)==true)
4860 Error("Could not locate %s header in saved game file\n",tag);
4861 *src+=size;
4862 }
4863
4864 //******************************************************************************
4865 //
4866 // LoadBuffer
4867 //
4868 //******************************************************************************
LoadBuffer(byte ** dest,byte ** src)4869 int LoadBuffer (byte ** dest, byte ** src)
4870 {
4871 int size;
4872
4873 memcpy(&size,*src,sizeof(size));
4874 *src+=sizeof(size);
4875 *dest=SafeMalloc(size);
4876 memcpy(*dest,*src,size);
4877 *src+=size;
4878 return size;
4879 }
4880
4881
4882 //******************************************************************************
4883 //
4884 // LoadTheGame ()
4885 //
4886 // Expects game to be premalloced
4887 //
4888 //******************************************************************************
4889
LoadTheGame(int num,gamestorage_t * game)4890 boolean LoadTheGame (int num, gamestorage_t * game)
4891 {
4892 char loadname[45]="rottgam0.rot";
4893 char filename[128];
4894 byte * loadbuffer;
4895 byte * bufptr;
4896 byte * altbuffer;
4897 int size;
4898 int totalsize;
4899 int checksum;
4900 int savedchecksum;
4901 int i;
4902 word mapcrc;
4903 int myticcount;
4904
4905 if (num>15 || num<0)
4906 Error("Illegal Load game value=%ld\n",num);
4907
4908 // Create the proper file name
4909
4910 itoa(num,&loadname[7],16);
4911 loadname[8]='.';
4912
4913 GetPathFromEnvironment( filename, ApogeePath, loadname );
4914
4915 // Load the file
4916
4917 totalsize=LoadFile(filename,(void **)&loadbuffer);
4918 bufptr=loadbuffer;
4919
4920 // Calculate checksum
4921
4922 checksum = DoCheckSum (loadbuffer, totalsize-sizeof(checksum), 0);
4923
4924 // Retrieve saved checksum
4925
4926 memcpy (&savedchecksum,loadbuffer+(totalsize-sizeof(savedchecksum)),sizeof(savedchecksum));
4927
4928 // Compare the two checksums;
4929
4930 if (checksum!=savedchecksum)
4931 {
4932 if (CP_DisplayMsg ("Your Saved Game file is\n"
4933 "shall we say, \"corrupted\".\n"
4934 "Would you like to\n"
4935 "continue anyway (Y/N)?\n", 12)==false)
4936 {
4937 return false;
4938 }
4939 }
4940
4941 // Load in file tag
4942
4943 size=4;
4944 LoadTag(&bufptr,"ROTT",size);
4945
4946 // Load in header
4947
4948 size=sizeof(*game);
4949 memcpy(game,bufptr,size);
4950 bufptr+=size;
4951
4952 if (game->version!=ROTTVERSION)
4953 return false;
4954
4955 memcpy (&GameLevels, &game->info, sizeof (GameLevels));
4956
4957 gamestate.episode=game->episode;
4958 gamestate.mapon=game->area;
4959
4960 mapcrc=GetMapCRC (gamestate.mapon);
4961
4962 if (mapcrc!=game->mapcrc)
4963 return false;
4964
4965 /////////////////////////////////////////////////////////////////////////////
4966 // Load in rest of saved game file beyond this point
4967 /////////////////////////////////////////////////////////////////////////////
4968
4969 // Free up the current level
4970 Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level
4971
4972 gamestate.battlemode = battle_StandAloneGame;
4973 BATTLE_SetOptions( &BATTLE_Options[ battle_StandAloneGame ] );
4974 BATTLE_Init( gamestate.battlemode, 1 );
4975
4976 DoLoadGameAction ();
4977 SetupGameLevel();
4978
4979 // Door Tag
4980
4981 size=4;
4982 LoadTag(&bufptr,"DOOR",size);
4983
4984 // Doors
4985
4986 DoLoadGameAction ();
4987 size=LoadBuffer(&altbuffer,&bufptr);
4988 LoadDoors(altbuffer,size);
4989 SafeFree(altbuffer);
4990
4991 // Elevator Tag
4992
4993 size = 9;
4994 LoadTag(&bufptr,"ELEVATORS",size);
4995
4996
4997 // Elevators
4998
4999 DoLoadGameAction ();
5000 size=LoadBuffer(&altbuffer,&bufptr);
5001 LoadElevators(altbuffer,size);
5002 SafeFree(altbuffer);
5003
5004 // Pushwall Tag
5005
5006 size=5;
5007 LoadTag(&bufptr,"PWALL",size);
5008
5009 // PushWalls
5010
5011 DoLoadGameAction ();
5012 size=LoadBuffer(&altbuffer,&bufptr);
5013 LoadPushWalls(altbuffer,size);
5014 SafeFree(altbuffer);
5015 #if 0
5016 // Animated Walls Tag
5017
5018 size=5;
5019 LoadTag(&bufptr,"AWALL",size);
5020
5021 // Animated Walls
5022 size=LoadBuffer(&altbuffer,&bufptr);
5023 LoadAnimWalls(altbuffer,size);
5024 SafeFree(altbuffer);
5025 #endif
5026
5027 // MaskedWalls Tag
5028
5029 size=5;
5030 LoadTag(&bufptr,"MWALL",size);
5031
5032 // Masked Walls
5033
5034 DoLoadGameAction ();
5035 size=LoadBuffer(&altbuffer,&bufptr);
5036 LoadMaskedWalls(altbuffer,size);
5037 SafeFree(altbuffer);
5038
5039 // Switches Tag
5040
5041 size=6;
5042 LoadTag(&bufptr,"SWITCH",size);
5043
5044 // Switches
5045
5046 DoLoadGameAction ();
5047 size=LoadBuffer(&altbuffer,&bufptr);
5048 LoadSwitches(altbuffer,size);
5049 SafeFree(altbuffer);
5050
5051
5052 // Statics Tag
5053
5054 size=6;
5055 LoadTag(&bufptr,"STATIC",size);
5056
5057 // Statics
5058
5059 DoLoadGameAction ();
5060 size=LoadBuffer(&altbuffer,&bufptr);
5061 LoadStatics(altbuffer,size);
5062 SafeFree(altbuffer);
5063
5064 // Actors Tag
5065
5066 size=5;
5067 LoadTag(&bufptr,"ACTOR",size);
5068
5069 // Actors
5070
5071 DoLoadGameAction ();
5072 size=LoadBuffer(&altbuffer,&bufptr);
5073 LoadActors(altbuffer,size);
5074 SafeFree(altbuffer);
5075
5076 // TouchPlates Tag
5077
5078 size=5;
5079 LoadTag(&bufptr,"TOUCH",size);
5080
5081 // TouchPlates
5082
5083 DoLoadGameAction ();
5084 size=LoadBuffer(&altbuffer,&bufptr);
5085 LoadTouchPlates(altbuffer,size);
5086 SafeFree(altbuffer);
5087
5088 // SetupWindows
5089
5090 SetupWindows();
5091
5092 // GameState Tag
5093
5094 size=9;
5095 LoadTag(&bufptr,"GAMESTATE",size);
5096
5097 // GameState
5098
5099 DoLoadGameAction ();
5100 size=sizeof(gamestate);
5101 memcpy(&gamestate,bufptr,size);
5102 bufptr+=size;
5103
5104 // PlayerState Tag
5105
5106 size=12;
5107 LoadTag(&bufptr,"PLAYERSTATES",size);
5108
5109 // PlayerState
5110
5111 DoLoadGameAction ();
5112 size=sizeof(playertype);
5113 for(i=0;i<numplayers;i++)
5114 {memcpy(&PLAYERSTATE[i],bufptr,size);
5115 bufptr+=size;
5116 }
5117
5118 // Zero out player targets
5119
5120 locplayerstate->guntarget=0;
5121 locplayerstate->targettime=0;
5122
5123 // Mapseen Tag
5124
5125 size=7;
5126 LoadTag(&bufptr,"MAPSEEN",size);
5127
5128 // MapSeen
5129
5130 DoLoadGameAction ();
5131 size=sizeof(mapseen);
5132 memcpy(&mapseen,bufptr,size);
5133 bufptr+=size;
5134
5135 // Song Tag
5136
5137 size=4;
5138 LoadTag(&bufptr,"SONG",size);
5139
5140 // Song info
5141
5142 DoLoadGameAction ();
5143 size=LoadBuffer(&altbuffer,&bufptr);
5144 MU_LoadMusic(altbuffer,size);
5145 SafeFree(altbuffer);
5146
5147 // Misc Tag
5148
5149 size=4;
5150 LoadTag(&bufptr,"MISC",size);
5151
5152 // Misc
5153
5154 // ticcount
5155 DoLoadGameAction ();
5156 size=sizeof(myticcount);
5157 memcpy((void *)&myticcount,bufptr,size);
5158 bufptr+=size;
5159 SaveTime = myticcount;
5160 ISR_SetTime(myticcount);
5161
5162 // shaketics
5163 DoLoadGameAction ();
5164 size=sizeof(SHAKETICS);
5165 memcpy(&SHAKETICS,bufptr,size);
5166 bufptr+=size;
5167
5168 // damagecount
5169 DoLoadGameAction ();
5170 size=sizeof(damagecount);
5171 memcpy(&damagecount,bufptr,size);
5172 bufptr+=size;
5173
5174 // viewsize
5175 DoLoadGameAction ();
5176 size=sizeof(viewsize);
5177 memcpy(&viewsize,bufptr,size);
5178 bufptr+=size;
5179
5180 // powerup times
5181 DoLoadGameAction ();
5182 size = sizeof (poweruptime);
5183 memcpy (&poweruptime, bufptr, size);
5184 bufptr += size;
5185 size = sizeof (protectiontime);
5186 memcpy (&protectiontime, bufptr, size);
5187 bufptr += size;
5188 size = sizeof (powerupheight);
5189 memcpy (&powerupheight, bufptr, size);
5190 bufptr += size;
5191 size = sizeof (protectionheight);
5192 memcpy (&protectionheight, bufptr, size);
5193 bufptr += size;
5194 size = sizeof (poweradjust);
5195 memcpy (&poweradjust, bufptr, size);
5196 bufptr += size;
5197
5198 // Set the viewsize
5199
5200 SetViewSize(viewsize);
5201 DoLoadGameAction ();
5202
5203 // Connect areas
5204
5205 ConnectAreas ();
5206 DoLoadGameAction ();
5207
5208 // Free up the loadbuffer
5209
5210 SafeFree (loadbuffer);
5211 DoLoadGameAction ();
5212
5213 Illuminate();
5214
5215 IN_UpdateKeyboard ();
5216 LoadPlayer ();
5217 DoLoadGameAction ();
5218 SetupPlayScreen();
5219 UpdateScore (gamestate.score);
5220 UpdateLives (locplayerstate->lives);
5221 UpdateTriads (player, 0);
5222 PreCache ();
5223 InitializeMessages();
5224
5225 for (i=0;i<100;i++)
5226 UpdateLightLevel(player->areanumber);
5227
5228 CalcTics();
5229 CalcTics();
5230
5231 pickquick = true;
5232
5233 return (true);
5234 }
5235
5236
5237 //******************************************************************************
5238 //
5239 // GetSavedMessage ()
5240 //
5241 // Expects message to be premalloced
5242 //
5243 //******************************************************************************
5244
GetSavedMessage(int num,char * message)5245 void GetSavedMessage (int num, char * message)
5246 {
5247 gamestorage_t game;
5248 char loadname[45]="rottgam0.rot";
5249 char filename[128];
5250 byte * loadbuffer;
5251 byte * bufptr;
5252 int size;
5253
5254 if (num>15 || num<0)
5255 Error("Illegal Load game value=%ld\n",num);
5256
5257 // Create the proper file name
5258
5259 itoa(num,&loadname[7],16);
5260 loadname[8]='.';
5261
5262 GetPathFromEnvironment( filename, ApogeePath, loadname );
5263
5264 // Load the file
5265
5266 size=LoadFile(filename,(void **)&loadbuffer);
5267 bufptr=loadbuffer;
5268
5269 size=4;
5270 LoadTag(&bufptr,"ROTT",size);
5271
5272 // Load in header
5273
5274 size=sizeof(game);
5275 memcpy(&game,bufptr,size);
5276 strcpy(message,game.message);
5277 SafeFree(loadbuffer);
5278 }
5279
5280 //******************************************************************************
5281 //
5282 // GetSavedHeader ()
5283 //
5284 // Expects game to be premalloced
5285 //
5286 //******************************************************************************
5287
GetSavedHeader(int num,gamestorage_t * game)5288 void GetSavedHeader (int num, gamestorage_t * game)
5289 {
5290 char loadname[45]="rottgam0.rot";
5291 char filename[128];
5292 byte * loadbuffer;
5293 byte * bufptr;
5294 int size;
5295
5296 if (num>15 || num<0)
5297 Error("Illegal Load game value=%ld\n",num);
5298
5299 // Create the proper file name
5300
5301 itoa(num,&loadname[7],16);
5302 loadname[8]='.';
5303
5304 GetPathFromEnvironment( filename, ApogeePath, loadname );
5305
5306 // Load the file
5307
5308 size=LoadFile(filename, (void **)&loadbuffer);
5309 bufptr=loadbuffer;
5310
5311 size=4;
5312 LoadTag(&bufptr,"ROTT",size);
5313
5314 // Load in header
5315
5316 size=sizeof(*game);
5317 memcpy(game,bufptr,size);
5318 SafeFree(loadbuffer);
5319 }
5320
5321
5322
5323 //******************************************************************************
5324 //
5325 // GetLevel ()
5326 //
5327 //******************************************************************************
5328
GetLevel(int episode,int mapon)5329 int GetLevel (int episode, int mapon)
5330 {
5331 int level;
5332
5333 level = (mapon+1) - ((episode-1) << 3);
5334
5335 return (level);
5336 }
5337