1
2 #include "Maelstrom_Globals.h"
3 #include "object.h"
4 #include "player.h"
5 #include "netplay.h"
6 #include "make.h"
7 #include "load.h"
8
9
10 #ifdef MOVIE_SUPPORT
11 extern int gMovie;
12 static SDL_Rect gMovieRect;
SelectMovieRect(void)13 int SelectMovieRect(void)
14 {
15 SDL_Event event;
16 SDL_Surface *saved;
17 Uint32 white;
18 int center_x, center_y;
19 int width, height;
20
21 /* Wait for initial button press */
22 screen->ShowCursor();
23 center_x = 0;
24 center_y = 0;
25 while ( ! center_x && ! center_y ) {
26 screen->WaitEvent(&event);
27
28 /* Check for escape key */
29 if ( (event.type == SDL_KEYEVENT) &&
30 (event.key.state == SDL_PRESSED) &&
31 (event.key.keysym.sym == SDL_ESCAPE) ) {
32 screen->HideCursor();
33 return(0);
34 }
35
36 /* Wait for button press */
37 if ( (event.type == SDL_MOUSEBUTTONEVENT) &&
38 (event.button.state == SDL_PRESSED) ) {
39 center_x = event.button.x;
40 center_y = event.button.y;
41 break;
42 }
43 }
44
45 /* Save the screen */
46 white = screen->MapRGB(0xFFFF, 0xFFFF, 0xFFFF);
47 saved = screen->GrabArea(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
48
49 /* As the box moves... */
50 width = height = 0;
51 while ( 1 ) {
52 win->GetEvent(&event);
53
54 /* Check for escape key */
55 if ( (event.type == SDL_KEYEVENT) &&
56 (event.key.state == SDL_PRESSED) &&
57 (event.key.keysym.sym == SDL_ESCAPE) ) {
58 screen->QueueBlit(0, 0, saved, NOCLIP);
59 screen->Update();
60 screen->FreeImage(saved);
61 win->HideCursor();
62 return(0);
63 }
64
65 /* Check for ending button press */
66 if ( event.type == ButtonPress ) {
67 gMovieRect.x = center_x - width;
68 gMovieRect.y = center_y - height;
69 gMovieRect.w = 2*width;
70 gMovieRect.h = 2*height;
71 screen->QueueBlit(0, 0, saved, NOCLIP);
72 screen->Update();
73 screen->FreeImage(saved);
74 win->HideCursor();
75 return(1);
76 }
77
78 if ( event.type == MotionNotify ) {
79 screen->QueueBlit(0, 0, saved, NOCLIP);
80 screen->Update();
81 width = abs(event.motion.x - center_x);
82 height = abs(event.motion.y - center_y);
83 screen->DrawRect(center_x-width, center_y-height,
84 2*width, 2*height, white);
85 screen->Update();
86 }
87 }
88 /* NEVERREACHED */
89
90 }
91 #endif
92 extern int RunFrame(void); /* The heart of blit.cc */
93
94 // Global variables set in this file...
95 int gGameOn;
96 int gPaused;
97 int gWave;
98 int gBoomDelay;
99 int gNextBoom;
100 int gBoomPhase;
101 int gNumRocks;
102 int gLastStar;
103 int gWhenDone;
104 int gDisplayed;
105
106 int gMultiplierShown;
107 int gPrizeShown;
108 int gBonusShown;
109 int gWhenHoming;
110 int gWhenGrav;
111 int gWhenDamaged;
112 int gWhenNova;
113 int gShakeTime;
114 int gFreezeTime;
115 Object *gEnemySprite;
116 int gWhenEnemy;
117
118 // Local global variables;
119 static MFont *geneva=NULL;
120 static Uint32 ourGrey, ourWhite, ourBlack;
121 static int text_height;
122
123 // Local functions used in the game module of Maelstrom
124 static void DoHouseKeeping(void);
125 static void NextWave(void);
126 static void DoGameOver(void);
127 static void DoBonus(void);
128 static void TwinkleStars(void);
129
130 /* ----------------------------------------------------------------- */
131 /* -- Draw the status display */
132
DrawStatus(Bool first,Bool ForceDraw)133 void DrawStatus(Bool first, Bool ForceDraw)
134 {
135 static int nextDraw;
136 static int lastDisplayed;
137 int Score;
138 static int lastScore, lastScores[MAX_PLAYERS];
139 static int lastWave;
140 int Lives;
141 static int lastLives;
142 static int lastLife[MAX_PLAYERS];
143 int Bonus;
144 static int lastBonus;
145 int Frags;
146 static int lastFrags;
147 int AutoFire;
148 static int lastGun;
149 int AirBrakes;
150 static int lastBrakes;
151 int ShieldLevel;
152 static int lastShield;
153 int MultFactor;
154 static int lastMult;
155 int LongFire;
156 static int lastLong;
157 int TripleFire;
158 static int lastTriple;
159 int LuckOfTheIrish;
160 static int lastLuck;
161 static int fragoff;
162 static int score_width, wave_width;
163 static int lives_width, bonus_width;
164 static int frags_width;
165 int i;
166 char numbuf[128];
167
168 if (first) {
169 int x;
170
171 nextDraw = 1;
172 lastDisplayed = -1;
173 OBJ_LOOP(i, gNumPlayers)
174 lastScores[i] = -1;
175 lastScore = -1;
176 lastWave = -1;
177 lastShield = -1;
178 lastLives = -1;
179 lastBonus = -1;
180 lastFrags = -1;
181 lastGun = -1;
182 lastBrakes = -1;
183 lastMult = -1;
184 lastLuck = -1;
185 if (gWave == 1) {
186 OBJ_LOOP(i, gNumPlayers)
187 lastLife[i] = 0;
188 }
189 lastLong = -1;
190 lastTriple = -1;
191
192 score_width = 0;
193 wave_width = 0;
194 lives_width = 0;
195 bonus_width = 0;
196 frags_width = 0;
197
198 /* -- Draw the status display */
199
200 screen->DrawLine(0, gStatusLine, SCREEN_WIDTH-1,
201 gStatusLine, ourWhite);
202 x = 3;
203 i = DrawText(x, gStatusLine+11, "Score:", geneva, STYLE_BOLD,
204 30000>>8, 30000>>8, 0xFF);
205 x += (i+70);
206 i = DrawText(x, gStatusLine+11, "Shield:", geneva, STYLE_BOLD,
207 30000>>8, 30000>>8, 0xFF);
208 x += (i+70);
209 i = DrawText(x, gStatusLine+11, "Wave:", geneva, STYLE_BOLD,
210 30000>>8, 30000>>8, 0xFF);
211 x += (i+30);
212 i = DrawText(x, gStatusLine+11, "Lives:", geneva, STYLE_BOLD,
213 30000>>8, 30000>>8, 0xFF);
214 x += (i+30);
215 DrawText(x, gStatusLine+11, "Bonus:", geneva, STYLE_BOLD,
216 30000>>8, 30000>>8, 0xFF);
217 /* Heh, DOOM style frag count */
218 if ( gNumPlayers > 1 ) {
219 x = 530;
220 i = DrawText(x, gStatusLine+11, "Frags:", geneva,
221 STYLE_BOLD, 30000>>8, 30000>>8, 0xFF);
222 fragoff = x+i+4;
223 }
224 }
225
226 if ( ForceDraw || (--nextDraw == 0) ) {
227 nextDraw = DISPLAY_DELAY+1;
228 /* -- Do incremental updates */
229
230 if ( (gNumPlayers > 1) && (lastDisplayed != gDisplayed) ) {
231 char caption[BUFSIZ];
232
233 lastDisplayed = gDisplayed;
234 screen->FillRect(0, 0, SCREEN_WIDTH, 12, ourBlack);
235 snprintf(caption, sizeof(caption),
236 "You are player %d --- displaying player %d",
237 gOurPlayer+1, gDisplayed+1);
238 DrawText(SPRITES_WIDTH, 11, caption, geneva,
239 STYLE_BOLD, 30000>>8, 30000>>8, 0xFF);
240
241 /* Fill in the color by the frag count */
242 screen->FillRect(518, gStatusLine+4, 4, 8,
243 TheShip->Color());
244 }
245
246 ShieldLevel = TheShip->GetShieldLevel();
247 if (lastShield != ShieldLevel) {
248 int fact;
249
250 lastShield = ShieldLevel;
251 screen->DrawRect(152, gStatusLine+4, SHIELD_WIDTH,
252 8, ourWhite);
253 fact = ((SHIELD_WIDTH - 2) * ShieldLevel) / MAX_SHIELD;
254 screen->FillRect(152+1,gStatusLine+4+1, fact, 6,
255 ourGrey);
256 screen->FillRect(152+1+fact, gStatusLine+4+1,
257 SHIELD_WIDTH-2-fact, 6, ourBlack);
258 }
259
260 MultFactor = TheShip->GetBonusMult();
261 if (lastMult != MultFactor) {
262 lastMult = MultFactor;
263
264 switch (MultFactor) {
265 case 1: screen->FillRect(424,
266 gStatusLine+4, 8, 8, ourBlack);
267 break;
268 case 2: screen->QueueBlit(424, gStatusLine+4,
269 gMult2Icon, NOCLIP);
270 break;
271 case 3: screen->QueueBlit(424, gStatusLine+4,
272 gMult3Icon, NOCLIP);
273 break;
274 case 4: screen->QueueBlit(424, gStatusLine+4,
275 gMult4Icon, NOCLIP);
276 break;
277 case 5: screen->QueueBlit(424, gStatusLine+4,
278 gMult5Icon, NOCLIP);
279 break;
280 default: /* WHAT? */
281 break;
282 }
283 }
284
285 /* -- Do incremental updates */
286
287 AutoFire = TheShip->GetSpecial(MACHINE_GUNS);
288 if (lastGun != AutoFire) {
289 lastGun = AutoFire;
290
291 if ( AutoFire > 0 ) {
292 screen->QueueBlit(438, gStatusLine+4,
293 gAutoFireIcon, NOCLIP);
294 } else {
295 screen->FillRect(438, gStatusLine+4, 8, 8,
296 ourBlack);
297 }
298 }
299
300 AirBrakes = TheShip->GetSpecial(AIR_BRAKES);
301 if (lastBrakes != AirBrakes) {
302 lastBrakes = AirBrakes;
303
304 if ( AirBrakes > 0 ) {
305 screen->QueueBlit(454, gStatusLine+4,
306 gAirBrakesIcon, NOCLIP);
307 } else {
308 screen->FillRect(454, gStatusLine+4, 8, 8,
309 ourBlack);
310 }
311 }
312
313 LuckOfTheIrish = TheShip->GetSpecial(LUCKY_IRISH);
314 if (lastLuck != LuckOfTheIrish) {
315 lastLuck = LuckOfTheIrish;
316
317 if ( LuckOfTheIrish > 0 ) {
318 screen->QueueBlit(470, gStatusLine+4,
319 gLuckOfTheIrishIcon, NOCLIP);
320 } else {
321 screen->FillRect(470, gStatusLine+4, 8, 8,
322 ourBlack);
323 }
324 }
325
326 TripleFire = TheShip->GetSpecial(TRIPLE_FIRE);
327 if (lastTriple != TripleFire) {
328 lastTriple = TripleFire;
329
330 if ( TripleFire > 0 ) {
331 screen->QueueBlit(486, gStatusLine+4,
332 gTripleFireIcon, NOCLIP);
333 } else {
334 screen->FillRect(486, gStatusLine+4, 8, 8,
335 ourBlack);
336 }
337 }
338
339 LongFire = TheShip->GetSpecial(LONG_RANGE);
340 if (lastLong != LongFire) {
341 lastLong = LongFire;
342
343 if ( LongFire > 0 ) {
344 screen->QueueBlit(502, gStatusLine+4,
345 gLongFireIcon, NOCLIP);
346 } else {
347 screen->FillRect(502, gStatusLine+4, 8, 8,
348 ourBlack);
349 }
350 }
351
352 /* Check for everyone else's new lives */
353 OBJ_LOOP(i, gNumPlayers) {
354 Score = gPlayers[i]->GetScore();
355
356 if ( (i == gDisplayed) && (Score != lastScore) ) {
357 /* -- Erase old and draw new score */
358 screen->FillRect(45, gStatusLine+1,
359 score_width, text_height, ourBlack);
360 snprintf(numbuf, sizeof(numbuf), "%d", Score);
361 score_width = DrawText(45, gStatusLine+11,
362 numbuf, geneva, STYLE_BOLD,
363 0xFF, 0xFF, 0xFF);
364 lastScore = Score;
365 }
366
367 if (lastScores[i] == Score)
368 continue;
369
370 /* -- See if they got a new life */
371 lastScores[i] = Score;
372 if ((Score - lastLife[i]) >= NEW_LIFE) {
373 gPlayers[i]->IncrLives(1);
374 lastLife[i] = (Score / NEW_LIFE) * NEW_LIFE;
375 if ( i == gOurPlayer )
376 sound->PlaySound(gNewLife, 5);
377 }
378 }
379
380 if (lastWave != gWave) {
381 screen->FillRect(255, gStatusLine+1,
382 wave_width, text_height, ourBlack);
383 snprintf(numbuf, sizeof(numbuf), "%d", gWave);
384 wave_width = DrawText(255, gStatusLine+11,
385 numbuf, geneva, STYLE_BOLD,
386 0xFF, 0xFF, 0xFF);
387 lastWave = gWave;
388 }
389
390 Lives = TheShip->GetLives();
391 if (lastLives != Lives) {
392 screen->FillRect(319, gStatusLine+1,
393 lives_width, text_height, ourBlack);
394 snprintf(numbuf, sizeof(numbuf), "%-3.1d", Lives);
395 lives_width = DrawText(319, gStatusLine+11,
396 numbuf, geneva, STYLE_BOLD,
397 0xFF, 0xFF, 0xFF);
398 lastLives = Lives;
399 }
400
401 Bonus = TheShip->GetBonus();
402 if (lastBonus != Bonus) {
403 screen->FillRect(384, gStatusLine+1,
404 bonus_width, text_height, ourBlack);
405 snprintf(numbuf, sizeof(numbuf), "%-7.1d", Bonus);
406 bonus_width = DrawText(384, gStatusLine+11,
407 numbuf, geneva, STYLE_BOLD,
408 0xFF, 0xFF, 0xFF);
409 lastBonus = Bonus;
410 }
411
412 if ( gNumPlayers > 1 ) {
413 Frags = TheShip->GetFrags();
414 if (lastFrags != Frags) {
415 screen->FillRect(fragoff, gStatusLine+1,
416 frags_width, text_height, ourBlack);
417 snprintf(numbuf, sizeof(numbuf), "%-3.1d", Frags);
418 frags_width = DrawText(fragoff, gStatusLine+11,
419 numbuf, geneva, STYLE_BOLD,
420 0xFF, 0xFF, 0xFF);
421 lastFrags = Frags;
422 }
423 }
424 }
425 } /* -- DrawStatus */
426
427
428 /* ----------------------------------------------------------------- */
429 /* -- Start a new game */
430
NewGame(void)431 void NewGame(void)
432 {
433 int i;
434
435 /* Send a "NEW_GAME" packet onto the network */
436 if ( gNumPlayers > 1 ) {
437 if ( gOurPlayer == 0 ) {
438 if ( Send_NewGame(&gStartLevel,&gStartLives,&gNoDelay)
439 < 0)
440 return;
441 } else {
442 if ( Await_NewGame(&gStartLevel,&gStartLives,&gNoDelay)
443 < 0 )
444 return;
445 }
446 }
447
448 /* Load the font and colors we use everywhere */
449 if ( (geneva = fontserv->NewFont("Geneva", 9)) == NULL ) {
450 error("Can't use Geneva font! -- Exiting.\n");
451 exit(255);
452 }
453 text_height = fontserv->TextHeight(geneva);
454 ourGrey = screen->MapRGB(30000>>8, 30000>>8, 0xFF);
455 ourWhite = screen->MapRGB(0xFF, 0xFF, 0xFF);
456 ourBlack = screen->MapRGB(0x00, 0x00, 0x00);
457
458 /* Fade into game mode */
459 screen->Fade();
460 screen->HideCursor();
461
462 /* Initialize some game variables */
463 gGameOn = 1;
464 gPaused = 0;
465 gWave = gStartLevel - 1;
466 for ( i=gNumPlayers; i--; )
467 gPlayers[i]->NewGame(gStartLives);
468 gLastStar = STAR_DELAY;
469 gLastDrawn = 0L;
470 gNumSprites = 0;
471
472 NextWave();
473
474 /* Play the game, dammit! */
475 while ( (RunFrame() > 0) && gGameOn )
476 DoHouseKeeping();
477
478 /* -- Do the game over stuff */
479
480 DoGameOver();
481 screen->ShowCursor();
482 delete geneva;
483 } /* -- NewGame */
484
485
486 /* ----------------------------------------------------------------- */
487 /* -- Do some housekeeping! */
488
DoHouseKeeping(void)489 static void DoHouseKeeping(void)
490 {
491 /* Don't do anything if we're paused */
492 if ( gPaused ) {
493 /* Give up the CPU for a frame duration */
494 Delay(FRAME_DELAY);
495 return;
496 }
497
498 #ifdef MOVIE_SUPPORT
499 if ( gMovie )
500 win->ScreenDump("MovieFrame", &gMovieRect);
501 #endif
502 /* -- Maybe throw a multiplier up on the screen */
503 if (gMultiplierShown && (--gMultiplierShown == 0) )
504 MakeMultiplier();
505
506 /* -- Maybe throw a prize(!) up on the screen */
507 if (gPrizeShown && (--gPrizeShown == 0) )
508 MakePrize();
509
510 /* -- Maybe throw a bonus up on the screen */
511 if (gBonusShown && (--gBonusShown == 0) )
512 MakeBonus();
513
514 /* -- Maybe make a nasty enemy fighter? */
515 if (gWhenEnemy && (--gWhenEnemy == 0) )
516 MakeEnemy();
517
518 /* -- Maybe create a transcenfugal vortex */
519 if (gWhenGrav && (--gWhenGrav == 0) )
520 MakeGravity();
521
522 /* -- Maybe create a recified space vehicle */
523 if (gWhenDamaged && (--gWhenDamaged == 0) )
524 MakeDamagedShip();
525
526 /* -- Maybe create a autonominous tracking device */
527 if (gWhenHoming && (--gWhenHoming == 0) )
528 MakeHoming();
529
530 /* -- Maybe make a supercranial destruction thang */
531 if (gWhenNova && (--gWhenNova == 0) )
532 MakeNova();
533
534 /* -- Maybe create a new star ? */
535 if ( --gLastStar == 0 ) {
536 gLastStar = STAR_DELAY;
537 TwinkleStars();
538 }
539
540 /* -- Time for the next wave? */
541 if (gNumRocks == 0) {
542 if ( gWhenDone == 0 )
543 gWhenDone = DEAD_DELAY;
544 else if ( --gWhenDone == 0 )
545 NextWave();
546 }
547
548 /* -- Housekeping */
549 DrawStatus(false, false);
550 } /* -- DoHouseKeeping */
551
552
553 /* ----------------------------------------------------------------- */
554 /* -- Start the next wave! */
555
NextWave(void)556 static void NextWave(void)
557 {
558 int index, x, y;
559 int NewRoids;
560 short temp;
561
562 gEnemySprite = NULL;
563
564 /* -- Initialize some variables */
565 gDisplayed = gOurPlayer;
566 gNumRocks = 0;
567 gShakeTime = 0;
568 gFreezeTime = 0;
569
570 if (gWave != (gStartLevel - 1))
571 DoBonus();
572
573 gWave++;
574
575 /* See about the Multiplier */
576 if ( FastRandom(2) )
577 gMultiplierShown = ((FastRandom(30) * 60)/FRAME_DELAY);
578 else
579 gMultiplierShown = 0;
580
581 /* See about the Prize */
582 if ( FastRandom(2) )
583 gPrizeShown = ((FastRandom(30) * 60)/FRAME_DELAY);
584 else
585 gPrizeShown = 0;
586
587 /* See about the Bonus */
588 if ( FastRandom(2) )
589 gBonusShown = ((FastRandom(30) * 60)/FRAME_DELAY);
590 else
591 gBonusShown = 0;
592
593 /* See about the Gravity */
594 if (FastRandom(10 + gWave) > 11)
595 gWhenGrav = ((FastRandom(30) * 60)/FRAME_DELAY);
596 else
597 gWhenGrav = 0;
598
599 /* See about the Nova */
600 if (FastRandom(10 + gWave) > 13)
601 gWhenNova = ((FastRandom(30) * 60)/FRAME_DELAY);
602 else
603 gWhenNova = 0;
604
605 /* See about the Enemy */
606 if (FastRandom(3) == 0)
607 gWhenEnemy = ((FastRandom(30) * 60)/FRAME_DELAY);
608 else
609 gWhenEnemy = 0;
610
611 /* See about the Damaged Ship */
612 if (FastRandom(10) == 0)
613 gWhenDamaged = ((FastRandom(60) * 60L)/FRAME_DELAY);
614 else
615 gWhenDamaged = 0;
616
617 /* See about the Homing Mine */
618 if (FastRandom(10 + gWave) > 12)
619 gWhenHoming = ((FastRandom(60) * 60L)/FRAME_DELAY);
620 else
621 gWhenHoming = 0;
622
623 temp = gWave / 4;
624 if (temp < 1)
625 temp = 1;
626
627 NewRoids = FastRandom(temp) + (gWave / 5) + 3;
628
629 /* -- Black the screen out and draw the wave */
630 screen->Clear();
631
632 /* -- Kill any existing sprites */
633 while (gNumSprites > 0)
634 delete gSprites[gNumSprites-1];
635
636 /* -- Initialize some variables */
637 gLastDrawn = 0L;
638 gBoomDelay = (60/FRAME_DELAY);
639 gNextBoom = gBoomDelay;
640 gBoomPhase = 0;
641 gWhenDone = 0;
642
643 /* -- Create the ship's sprite */
644 for ( index=gNumPlayers; index--; )
645 gPlayers[index]->NewWave();
646 DrawStatus(true, false);
647 screen->Update();
648
649 /* -- Create some asteroids */
650 for (index = 0; index < NewRoids; index++) {
651 int randval;
652
653 x = FastRandom(SCREEN_WIDTH) * SCALE_FACTOR;
654 y = 0;
655
656 randval = FastRandom(10);
657
658 /* -- See what kind of asteroid to make */
659 if (randval == 0)
660 MakeSteelRoid(x, y);
661 else
662 MakeLargeRock(x, y);
663 }
664
665 /* -- Create the star field */
666 screen->FocusBG();
667 for ( index=0; index<MAX_STARS; ++index ) {
668 screen->DrawPoint(gTheStars[index]->xCoord,
669 gTheStars[index]->yCoord, gTheStars[index]->color);
670 }
671 screen->Update(1);
672 screen->FocusFG();
673 screen->Fade();
674 } /* -- NextWave */
675
676 /* ----------------------------------------------------------------- */
677 /* -- Do the game over display */
678
679 struct FinalScore {
680 int Player;
681 int Score;
682 int Frags;
683 };
684
cmp_byscore(const void * A,const void * B)685 static int cmp_byscore(const void *A, const void *B)
686 {
687 return(((struct FinalScore *)B)->Score-((struct FinalScore *)A)->Score);
688 }
cmp_byfrags(const void * A,const void * B)689 static int cmp_byfrags(const void *A, const void *B)
690 {
691 return(((struct FinalScore *)B)->Frags-((struct FinalScore *)A)->Frags);
692 }
693
DoGameOver(void)694 static void DoGameOver(void)
695 {
696 SDL_Event event;
697 SDL_Surface *gameover;
698 MFont *newyork;
699 int newyork_height, w, x;
700 int which = -1, i;
701 char handle[20];
702 Uint8 key;
703 int chars_in_handle = 0;
704 Bool done = false;
705
706 /* Get the final scoring */
707 struct FinalScore *final = new struct FinalScore[gNumPlayers];
708 for ( i=0; i<gNumPlayers; ++i ) {
709 final[i].Player = i+1;
710 final[i].Score = gPlayers[i]->GetScore();
711 final[i].Frags = gPlayers[i]->GetFrags();
712 }
713 #ifndef macintosh
714 if ( gDeathMatch )
715 qsort(final,gNumPlayers,sizeof(struct FinalScore),cmp_byfrags);
716 else
717 qsort(final,gNumPlayers,sizeof(struct FinalScore),cmp_byscore);
718 #endif
719
720 screen->Fade();
721 sound->HaltSound();
722
723 /* -- Kill any existing sprites */
724 while (gNumSprites > 0)
725 delete gSprites[gNumSprites-1];
726
727 /* -- Clear the screen */
728 screen->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ourBlack);
729
730 /* -- Draw the game over picture */
731 gameover = Load_Title(screen, 128);
732 if ( gameover == NULL ) {
733 error("Can't load 'gameover' title!\n");
734 exit(255);
735 }
736 screen->QueueBlit((SCREEN_WIDTH-gameover->w)/2,
737 ((SCREEN_HEIGHT-gameover->h)/2)-80, gameover, NOCLIP);
738 screen->FreeImage(gameover);
739
740 /* Show the player ranking */
741 if ( gNumPlayers > 1 ) {
742 if ( (newyork = fontserv->NewFont("New York", 18)) == NULL ) {
743 error("Can't use New York font! -- Exiting.\n");
744 exit(255);
745 }
746 newyork_height = fontserv->TextHeight(newyork);
747 for ( i=0; i<gNumPlayers; ++i ) {
748 char buffer[BUFSIZ], num1[12], num2[12];
749
750 snprintf(num1, sizeof(num1), "%7.1d", final[i].Score);
751 snprintf(num2, sizeof(num2), "%3.1d", final[i].Frags);
752 snprintf(buffer, sizeof(buffer),
753 "Player %d: %-.7s Points, %-.3s Frags",
754 final[i].Player, num1, num2);
755 DrawText(160, 380+i*newyork_height, buffer,
756 newyork, STYLE_NORM, 30000>>8, 30000>>8, 0xFF);
757 }
758 delete newyork;
759 }
760 screen->Update();
761
762 /* -- Play the game over sound */
763 sound->PlaySound(gGameOver, 5);
764 screen->Fade();
765
766 while( sound->Playing() )
767 Delay(SOUND_DELAY);
768
769 /* -- See if they got a high score */
770 LoadScores();
771 for ( i = 0; i<10; ++i ) {
772 if ( OurShip->GetScore() > hScores[i].score ) {
773 which = i;
774 break;
775 }
776 }
777
778 /* -- They got a high score! */
779 gLastHigh = which;
780
781 if ((which != -1) && (gStartLevel == 1) && (gStartLives == 3) &&
782 (gNumPlayers == 1) && !gDeathMatch ) {
783 sound->PlaySound(gBonusShot, 5);
784 for ( i = 8; i >= which ; --i ) {
785 hScores[i + 1].score = hScores[i].score;
786 hScores[i + 1].wave = hScores[i].wave;
787 strcpy(hScores[i+1].name, hScores[i].name);
788 }
789
790 /* -- Draw the "Enter your name" string */
791 if ( (newyork = fontserv->NewFont("New York", 18)) == NULL ) {
792 error("Can't use New York font! -- Exiting.\n");
793 exit(255);
794 }
795 newyork_height = fontserv->TextHeight(newyork);
796 x = (SCREEN_WIDTH-(fontserv->TextWidth("Enter your name: ",
797 newyork, STYLE_NORM)*2))/2;
798 x += DrawText(x, 300, "Enter your name: ",
799 newyork, STYLE_NORM, 30000>>8, 30000>>8, 0xFF);
800 screen->Update();
801
802 /* -- Let them enter their name */
803 w = 0;
804 chars_in_handle = 0;
805
806 while ( screen->PollEvent(&event) ) /* Loop, flushing events */;
807 SDL_EnableUNICODE(1);
808 while ( !done ) {
809 screen->WaitEvent(&event);
810
811 /* -- Handle key down's (no UNICODE support) */
812 if ( event.type == SDL_KEYDOWN ) {
813 key = (Uint8)event.key.keysym.unicode;
814 switch ( key ) {
815 case '\0': // Ignore NUL char
816 case '\033': // Ignore ESC char
817 case '\t': // Ignore TAB too.
818 continue;
819 case '\003':
820 case '\r':
821 case '\n':
822 done = true;
823 continue;
824 case 127:
825 case '\b':
826 if ( chars_in_handle ) {
827 sound->PlaySound(gExplosionSound, 5);
828 --chars_in_handle;
829 }
830 break;
831 default:
832 if ( chars_in_handle < 15 ) {
833 sound->PlaySound(gShotSound, 5);
834 handle[chars_in_handle++] = (char)key;
835 } else
836 sound->PlaySound(gBonk, 5);
837 break;
838 }
839 screen->FillRect(x, 300-newyork_height+2,
840 w, newyork_height, ourBlack);
841
842 handle[chars_in_handle] = '\0';
843 w = DrawText(x, 300, handle,
844 newyork, STYLE_NORM, 0xFF, 0xFF, 0xFF);
845 screen->Update();
846 }
847 }
848 delete newyork;
849 SDL_EnableUNICODE(0);
850
851 /* In case the user just pressed <Return> */
852 handle[chars_in_handle] = '\0';
853
854 hScores[which].wave = gWave;
855 hScores[which].score = OurShip->GetScore();
856 strcpy(hScores[which].name, handle);
857
858 sound->HaltSound();
859 sound->PlaySound(gGotPrize, 6);
860 if ( gNetScores ) // All time high!
861 RegisterHighScore(hScores[which]);
862 else
863 SaveScores();
864 } else
865 if ( gNumPlayers > 1 ) /* Let them watch their ranking */
866 SDL_Delay(3000);
867
868 while ( sound->Playing() )
869 Delay(SOUND_DELAY);
870 HandleEvents(0);
871
872 screen->Fade();
873 gUpdateBuffer = true;
874 } /* -- DoGameOver */
875
876
877 /* ----------------------------------------------------------------- */
878 /* -- Do the bonus display */
879
DoBonus(void)880 static void DoBonus(void)
881 {
882 int i, x, sw, xs, xt;
883 int bonus_width;
884 int score_width;
885 char numbuf[128];
886
887 DrawStatus(false, true);
888 screen->Update();
889
890 /* -- Now do the bonus */
891 sound->HaltSound();
892 sound->PlaySound(gRiff, 6);
893
894 /* Fade out */
895 screen->Fade();
896
897 /* -- Clear the screen */
898 screen->FillRect(0, 0, SCREEN_WIDTH, gStatusLine-1, ourBlack);
899
900
901 /* -- Draw the wave completed message */
902 snprintf(numbuf, sizeof(numbuf), "Wave %d completed.", gWave);
903 sw = fontserv->TextWidth(numbuf, geneva, STYLE_BOLD);
904 x = (SCREEN_WIDTH - sw) / 2;
905 DrawText(x, 150, numbuf, geneva, STYLE_BOLD, 0xFF, 0xFF, 0x00);
906
907 /* -- Draw the bonus */
908 sw = fontserv->TextWidth("Bonus Score: ", geneva, STYLE_BOLD);
909 x = ((SCREEN_WIDTH - sw) / 2) - 20;
910 DrawText(x, 200, "Bonus Score: ", geneva, STYLE_BOLD,
911 30000>>8, 30000>>8, 0xFF);
912 xt = x+sw;
913
914 /* -- Draw the score */
915 sw = fontserv->TextWidth("Score: ", geneva, STYLE_BOLD);
916 x = ((SCREEN_WIDTH - sw) / 2) - 3;
917 DrawText(x, 220, "Score: ", geneva, STYLE_BOLD,
918 30000>>8, 30000>>8, 0xFF);
919 xs = x+sw;
920 screen->Update();
921
922 /* Fade in */
923 screen->Fade();
924 while ( sound->Playing() )
925 Delay(SOUND_DELAY);
926
927 /* -- Count the score down */
928 x = xs;
929
930 OBJ_LOOP(i, gNumPlayers) {
931 if ( i != gOurPlayer ) {
932 gPlayers[i]->MultBonus();
933 continue;
934 }
935
936 if (OurShip->GetBonusMult() != 1) {
937 SDL_Surface *sprite;
938
939 snprintf(numbuf, sizeof(numbuf), "%-5.1d", OurShip->GetBonus());
940 DrawText(x, 200, numbuf, geneva, STYLE_BOLD,
941 0xFF, 0xFF, 0xFF);
942 x += 75;
943 OurShip->MultBonus();
944 Delay(SOUND_DELAY);
945 sound->PlaySound(gMultiplier, 5);
946 sprite = gMult[OurShip->GetBonusMult()-2]->sprite[0];
947 screen->QueueBlit(xs+34, 180, sprite);
948 screen->Update();
949 Delay(60);
950 }
951 }
952 Delay(SOUND_DELAY);
953 sound->PlaySound(gFunk, 5);
954
955 snprintf(numbuf, sizeof(numbuf), "%-5.1d", OurShip->GetBonus());
956 bonus_width = DrawText(x, 200, numbuf, geneva, STYLE_BOLD,
957 0xFF, 0xFF, 0xFF);
958 snprintf(numbuf, sizeof(numbuf), "%-5.1d", OurShip->GetScore());
959 score_width = DrawText(xt, 220, numbuf, geneva, STYLE_BOLD,
960 0xFF, 0xFF, 0xFF);
961 screen->Update();
962 Delay(60);
963
964 /* -- Praise them or taunt them as the case may be */
965 if (OurShip->GetBonus() == 0) {
966 Delay(SOUND_DELAY);
967 sound->PlaySound(gNoBonus, 5);
968 }
969 if (OurShip->GetBonus() > 10000) {
970 Delay(SOUND_DELAY);
971 sound->PlaySound(gPrettyGood, 5);
972 }
973 while ( sound->Playing() )
974 Delay(SOUND_DELAY);
975
976 /* -- Count the score down */
977 OBJ_LOOP(i, gNumPlayers) {
978 if ( i != gOurPlayer ) {
979 while ( gPlayers[i]->GetBonus() > 500 ) {
980 gPlayers[i]->IncrScore(500);
981 gPlayers[i]->IncrBonus(-500);
982 }
983 continue;
984 }
985
986 while (OurShip->GetBonus() > 0) {
987 while ( sound->Playing() )
988 Delay(SOUND_DELAY);
989
990 sound->PlaySound(gBonk, 5);
991 if ( OurShip->GetBonus() >= 500 ) {
992 OurShip->IncrScore(500);
993 OurShip->IncrBonus(-500);
994 } else {
995 OurShip->IncrScore(OurShip->GetBonus());
996 OurShip->IncrBonus(-OurShip->GetBonus());
997 }
998
999 screen->FillRect(x, 200-text_height+2,
1000 bonus_width, text_height, ourBlack);
1001 snprintf(numbuf, sizeof(numbuf), "%-5.1d", OurShip->GetBonus());
1002 bonus_width = DrawText(x, 200, numbuf,
1003 geneva, STYLE_BOLD, 0xFF, 0xFF, 0xFF);
1004 screen->FillRect(xt, 220-text_height+2,
1005 score_width, text_height, ourBlack);
1006 snprintf(numbuf, sizeof(numbuf), "%-5.1d", OurShip->GetScore());
1007 score_width = DrawText(xt, 220, numbuf,
1008 geneva, STYLE_BOLD, 0xFF, 0xFF, 0xFF);
1009
1010 DrawStatus(false, true);
1011 screen->Update();
1012 }
1013 }
1014 while ( sound->Playing() )
1015 Delay(SOUND_DELAY);
1016 HandleEvents(10);
1017
1018 /* -- Draw the "next wave" message */
1019 snprintf(numbuf, sizeof(numbuf), "Prepare for Wave %d...", gWave+1);
1020 sw = fontserv->TextWidth(numbuf, geneva, STYLE_BOLD);
1021 x = (SCREEN_WIDTH - sw)/2;
1022 DrawText(x, 259, numbuf, geneva, STYLE_BOLD, 0xFF, 0xFF, 0x00);
1023 screen->Update();
1024 HandleEvents(100);
1025
1026 screen->Fade();
1027 } /* -- DoBonus */
1028
1029
1030 /* ----------------------------------------------------------------- */
1031 /* -- Flash the stars on the screen */
1032
TwinkleStars(void)1033 static void TwinkleStars(void)
1034 {
1035 int theStar;
1036
1037 theStar = FastRandom(MAX_STARS);
1038
1039 /* -- Draw the star */
1040 screen->FocusBG();
1041 screen->DrawPoint(gTheStars[theStar]->xCoord,
1042 gTheStars[theStar]->yCoord, ourBlack);
1043 SetStar(theStar);
1044 screen->DrawPoint(gTheStars[theStar]->xCoord,
1045 gTheStars[theStar]->yCoord, gTheStars[theStar]->color);
1046 screen->Update(1);
1047 screen->FocusFG();
1048 } /* -- TwinkleStars */
1049
1050