]> icculus.org git repositories - btb/d2x.git/blob - main/kmatrix.c
use the orientation parameter of g3_draw_bitmap
[btb/d2x.git] / main / kmatrix.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 /*
15  *
16  * Kill matrix displayed at end of level.
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <conf.h>
22 #endif
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <stdarg.h>
29
30 #include "dxxerror.h"
31 #include "gr.h"
32 #include "mono.h"
33 #include "key.h"
34 #include "inferno.h"
35 #include "u_mem.h"
36 #include "mouse.h"
37 #include "joy.h"
38 #include "timer.h"
39 #include "vid.h"
40
41
42 #define CENTERING_OFFSET(x) ((300 - (70 + (x)*25 ))/2)
43 #define CENTERSCREEN        (SWIDTH/2)
44 #define MARGIN              (CENTERSCREEN - LHX(160))
45
46 int kmatrix_kills_changed = 0;
47 char ConditionLetters[] = { ' ', 'P', 'E', 'D', 'E', 'E', 'V', 'W' };
48 char WaitingForOthers = 0;
49
50 int Kmatrix_nomovie_message = 0;
51
52 extern char MaxPowerupsAllowed[], PowerupsInMine[];
53
54 void kmatrix_reactor(char *message);
55 void kmatrix_phallic(void);
56 void kmatrix_redraw_coop(void);
57
58 #define LHX(x)  ((x)*(MenuHires?2:1))
59 #define LHY(y)  ((y)*(MenuHires?2.4:1))
60
61
62 void kmatrix_draw_item( int  i, int *sorted )
63 {
64         int j, x, y;
65         char temp[10];
66
67         y = LHY(50+i*9);
68
69         // Print player name.
70
71         gr_printf( MARGIN + LHX(CENTERING_OFFSET(N_players)), y, "%s", Players[sorted[i]].callsign );
72
73         if (!((Game_mode & GM_MODEM) || (Game_mode & GM_SERIAL)))
74                 gr_printf( MARGIN + LHX(CENTERING_OFFSET(N_players)-15), y, "%c", ConditionLetters[Players[sorted[i]].connected] );
75    
76         for (j = 0; j < N_players; j++) {
77
78                 x = MARGIN + LHX(70 + CENTERING_OFFSET(N_players) + j*25);
79
80                 if (sorted[i] == sorted[j]) {
81                         if (kill_matrix[sorted[i]][sorted[j]] == 0) {
82                                 gr_set_fontcolor( BM_XRGB(10,10,10), -1 );
83                                 gr_printf( x, y, "%d", kill_matrix[sorted[i]][sorted[j]] );
84                         } else {
85                                 gr_set_fontcolor( BM_XRGB(25,25,25), -1 );
86                                 gr_printf( x, y, "-%d", kill_matrix[sorted[i]][sorted[j]] );
87                         }
88                 } else {
89                         if (kill_matrix[sorted[i]][sorted[j]] <= 0) {
90                                 gr_set_fontcolor( BM_XRGB(10,10,10), -1 );
91                                 gr_printf( x, y, "%d", kill_matrix[sorted[i]][sorted[j]] );
92                         } else {
93                                 gr_set_fontcolor( BM_XRGB(25,25,25), -1 );
94                                 gr_printf( x, y, "%d", kill_matrix[sorted[i]][sorted[j]] );
95                         }
96                 }
97         }
98
99         if (Players[sorted[i]].net_killed_total + Players[sorted[i]].net_kills_total == 0)
100                 sprintf(temp, "NA");
101         else
102                 sprintf(temp, "%d%%", (int)((float)((float)Players[sorted[i]].net_kills_total / ((float)Players[sorted[i]].net_killed_total + (float)Players[sorted[i]].net_kills_total)) * 100.0));
103
104         x = MARGIN + LHX(60 + CENTERING_OFFSET(N_players) + N_players*25);
105         gr_set_fontcolor( BM_XRGB(25,25,25), -1 );
106         gr_printf( x, y, "%4d/%s", Players[sorted[i]].net_kills_total, temp);
107 }
108
109
110 void kmatrix_draw_coop_item( int  i, int *sorted )
111 {
112         int  x, y;
113
114         y = LHY(50+i*9);
115
116         // Print player name.
117
118         gr_printf( MARGIN + LHX(CENTERING_OFFSET(N_players)), y, "%s", Players[sorted[i]].callsign );
119         gr_printf( MARGIN + LHX(CENTERING_OFFSET(N_players)-15), y, "%c", ConditionLetters[Players[sorted[i]].connected] );
120
121         x = CENTERSCREEN;
122
123         gr_set_fontcolor( BM_XRGB(60,40,10), -1 );
124         gr_printf( x, y, "%d", Players[sorted[i]].score );
125
126         x = CENTERSCREEN + LHX(50);
127
128         gr_set_fontcolor( BM_XRGB(60,40,10), -1 );
129         gr_printf( x, y, "%d", Players[sorted[i]].net_killed_total );
130 }
131
132
133 void kmatrix_draw_names(int *sorted)
134 {
135         int j, x;
136         int color;
137
138         if (Kmatrix_nomovie_message) {
139                 gr_set_fontcolor( BM_XRGB(63,0,0), -1 );
140                 gr_printf( CENTERSCREEN - LHX(40), LHY(20), "(Movie not played)" );
141         }
142
143         for (j = 0; j < N_players; j++) {
144                 if (Game_mode & GM_TEAM)
145                         color = get_team(sorted[j]);
146                 else
147                         color = sorted[j];
148
149                 x = MARGIN + LHX(70 + CENTERING_OFFSET(N_players) + j*25);
150
151                 if (Players[sorted[j]].connected == 0)
152                         gr_set_fontcolor(gr_find_closest_color(31,31,31), -1);
153                 else
154                         gr_set_fontcolor(gr_getcolor(player_rgb[color].r, player_rgb[color].g, player_rgb[color].b), -1);
155
156                 gr_printf( x, LHY(40), "%c", Players[sorted[j]].callsign[0] );
157         }
158
159         x = MARGIN + LHX(72 + CENTERING_OFFSET(N_players) + N_players*25);
160         gr_set_fontcolor( BM_XRGB(31,31,31), -1 );
161         gr_printf( x, LHY(40), "K/E" );
162 }
163
164
165 void kmatrix_draw_coop_names(int *sorted)
166 {
167         if (Kmatrix_nomovie_message) {
168                 gr_set_fontcolor( BM_XRGB(63,0,0), -1 );
169                 gr_printf( CENTERSCREEN-LHX(40), LHY(20), "(Movie not played)" );
170         }
171
172         gr_set_fontcolor( BM_XRGB(63,31,31), -1 );
173         gr_printf( CENTERSCREEN, LHY(40), "SCORE");
174
175         gr_set_fontcolor( BM_XRGB(63,31,31), -1 );
176         gr_printf( CENTERSCREEN + LHX(50), LHY(40), "DEATHS");
177 }
178
179
180 void kmatrix_draw_deaths(int *sorted)
181 {
182         int y;
183         int sw, sh, aw;
184         char reactor_message[50];
185
186         y = LHY(55 + 72 + 35);
187
188         gr_set_fontcolor(gr_find_closest_color(63,20,0),-1);
189
190         gr_get_string_size("P-Playing E-Escaped D-Died", &sw, &sh, &aw);
191         if (!((Game_mode & GM_MODEM) || (Game_mode & GM_SERIAL)))
192                 gr_printf( CENTERSCREEN - (sw/2), y, "P-Playing E-Escaped D-Died" );
193
194         y += sh + 5;
195
196         gr_get_string_size("V-Viewing scores W-Waiting", &sw, &sh, &aw);
197         if (!((Game_mode & GM_MODEM) || (Game_mode & GM_SERIAL)))
198                 gr_printf( CENTERSCREEN - (sw/2), y, "V-Viewing scores W-Waiting" );
199
200         y += LHY(20);
201
202         gr_set_fontcolor(gr_find_closest_color(63,63,63),-1);
203
204         if (Players[Player_num].connected == 7) {
205                 gr_get_string_size("Waiting for other players...", &sw, &sh, &aw);
206                 gr_printf( CENTERSCREEN - (sw/2), y,"Waiting for other players...");
207         } else {
208                 gr_get_string_size(TXT_PRESS_ANY_KEY2, &sw, &sh, &aw);
209                 gr_printf( CENTERSCREEN - (sw/2), y, TXT_PRESS_ANY_KEY2 );
210         }
211
212         if (Countdown_seconds_left <= 0)
213                 kmatrix_reactor(TXT_REACTOR_EXPLODED);
214         else {
215                 sprintf((char *)&reactor_message, "%s: %d %s  ", TXT_TIME_REMAINING, Countdown_seconds_left, TXT_SECONDS);
216                 kmatrix_reactor ((char *)&reactor_message);
217         }
218
219         if (Game_mode & GM_HOARD)
220                 kmatrix_phallic();
221 }
222
223
224 void kmatrix_draw_coop_deaths(int *sorted)
225 {
226         int j, x, y;
227         int sw, sh, aw;
228         char reactor_message[50];
229
230         y = LHY(55 + N_players * 9);
231
232 //      gr_set_fontcolor(gr_getcolor(player_rgb[j].r,player_rgb[j].g,player_rgb[j].b), -1);
233         gr_set_fontcolor( BM_XRGB(31,31,31), -1 );
234
235         x = CENTERSCREEN + LHX(50);
236         gr_printf( x, y, TXT_DEATHS );
237
238         for (j = 0; j < N_players; j++) {
239                 x = CENTERSCREEN + LHX(50);
240                 gr_printf( x, y, "%d", Players[sorted[j]].net_killed_total );
241         }
242
243         y = LHY(55 + 72 + 35);
244
245         gr_set_fontcolor(gr_find_closest_color(63,20,0), -1);
246         gr_get_string_size("P-Playing E-Escaped D-Died", &sw, &sh, &aw);
247
248         if (!((Game_mode & GM_MODEM) || (Game_mode & GM_SERIAL)))
249                 gr_printf( CENTERSCREEN-(sw/2), y,"P-Playing E-Escaped D-Died");
250
251         y += sh+5;
252         gr_get_string_size("V-Viewing scores W-Waiting", &sw, &sh, &aw);
253
254         if (!((Game_mode & GM_MODEM) || (Game_mode & GM_SERIAL)))
255                 gr_printf( CENTERSCREEN - (sw/2), y, "V-Viewing scores W-Waiting" );
256
257         y += LHY(20);
258
259         gr_set_fontcolor(gr_find_closest_color(63,63,63), -1);
260
261         if (Players[Player_num].connected == 7) {
262                 gr_get_string_size("Waiting for other players...", &sw, &sh, &aw);
263                 gr_printf( CENTERSCREEN - (sw/2), y, "Waiting for other players..." );
264         } else {
265                 gr_get_string_size(TXT_PRESS_ANY_KEY2, &sw, &sh, &aw);
266                 gr_printf( CENTERSCREEN - (sw/2), y, TXT_PRESS_ANY_KEY2 );
267         }
268
269         if (Countdown_seconds_left <= 0)
270                 kmatrix_reactor(TXT_REACTOR_EXPLODED);
271         else {
272                 sprintf((char *)&reactor_message, "%s: %d %s  ", TXT_TIME_REMAINING, Countdown_seconds_left, TXT_SECONDS);
273                 kmatrix_reactor((char *)&reactor_message);
274         }
275 }
276
277
278 void kmatrix_reactor(char *message)
279 {
280         static char oldmessage[50] = { 0 };
281         int sw, sh, aw;
282
283         if ((Game_mode & GM_MODEM) || (Game_mode & GM_SERIAL))
284                 return;
285
286         grd_curcanv->cv_font = SMALL_FONT;
287
288         if (oldmessage[0] != 0) {
289                 gr_set_fontcolor(gr_find_closest_color(0,0,0), -1);
290                 gr_get_string_size(oldmessage, &sw, &sh, &aw);
291 //              gr_printf( CENTERSCREEN-(sw/2), LHY(55+72+12), oldmessage);
292         }
293         gr_set_fontcolor(gr_find_closest_color(0,32,63), -1);
294         gr_get_string_size(message, &sw, &sh, &aw);
295         gr_printf( CENTERSCREEN - (sw/2), LHY(55+72+12), message );
296
297         strcpy((char *)&oldmessage, message);
298 }
299
300
301 extern int PhallicLimit,PhallicMan;
302
303
304 void kmatrix_phallic(void)
305 {
306         int sw, sh, aw;
307         char message[80];
308
309         if (!(Game_mode & GM_HOARD))
310                 return;
311
312         if ((Game_mode & GM_MODEM) || (Game_mode & GM_SERIAL))
313                 return;
314  
315         if (PhallicMan == -1)
316                 strcpy(message, "There was no record set for this level.");
317         else
318                 sprintf(message,"%s had the best record at %d points.", Players[PhallicMan].callsign, PhallicLimit);
319
320         grd_curcanv->cv_font = SMALL_FONT;
321         gr_set_fontcolor(gr_find_closest_color(63,63,63), -1);
322         gr_get_string_size(message, &sw, &sh, &aw);
323         gr_printf( CENTERSCREEN-(sw/2), LHY(55+72+3), message);
324 }
325
326
327 void load_stars(void);
328
329 grs_canvas *StarBackCanvas;
330
331
332 void kmatrix_redraw(void)
333 {
334         int i, color;
335         int sorted[MAX_NUM_NET_PLAYERS];
336         grs_canvas *tempcanvas;
337
338         if (Game_mode & GM_MULTI_COOP) {
339                 kmatrix_redraw_coop();
340                 return;
341         }
342
343         multi_sort_kill_list();
344
345         tempcanvas = gr_create_canvas( grd_curcanv->cv_bitmap.bm_w, grd_curcanv->cv_bitmap.bm_h );
346
347         gr_set_current_canvas(tempcanvas);
348
349         gr_bitmap(0, 0, &StarBackCanvas->cv_bitmap);
350
351         grd_curcanv->cv_font = MEDIUM3_FONT;
352
353         gr_string( 0x8000, LHY(10), TXT_KILL_MATRIX_TITLE );
354
355         grd_curcanv->cv_font = SMALL_FONT;
356
357         multi_get_kill_list(sorted);
358
359         kmatrix_draw_names(sorted);
360
361         for (i = 0; i < N_players; i++ ) {
362 //              mprintf((0, "Sorted kill list pos %d = %d.\n", i+1, sorted[i]));
363
364                 if (Game_mode & GM_TEAM)
365                         color = get_team(sorted[i]);
366                 else
367                         color = sorted[i];
368
369                 if (Players[sorted[i]].connected == 0)
370                         gr_set_fontcolor(gr_find_closest_color(31,31,31), -1);
371                 else
372                         gr_set_fontcolor(gr_getcolor(player_rgb[color].r, player_rgb[color].g, player_rgb[color].b), -1);
373
374                 kmatrix_draw_item( i, sorted );
375         }
376
377         kmatrix_draw_deaths(sorted);
378
379         gr_set_current_canvas(NULL);
380
381         gr_bitmap(0, 0, &tempcanvas->cv_bitmap);
382
383         gr_palette_load(gr_palette);
384         gr_free_canvas(tempcanvas);
385 }
386
387
388 void kmatrix_redraw_coop(void)
389 {
390         int i, color;
391         int sorted[MAX_NUM_NET_PLAYERS];
392         grs_canvas *tempcanvas;
393
394         multi_sort_kill_list();
395
396         tempcanvas = gr_create_canvas( grd_curcanv->cv_bitmap.bm_w, grd_curcanv->cv_bitmap.bm_h );
397         gr_set_current_canvas(tempcanvas);
398
399         gr_bitmap(0, 0, &StarBackCanvas->cv_bitmap);
400
401         grd_curcanv->cv_font = MEDIUM3_FONT;
402         gr_string( 0x8000, LHY(10), "COOPERATIVE SUMMARY" );
403
404         grd_curcanv->cv_font = SMALL_FONT;
405
406         multi_get_kill_list(sorted);
407
408         kmatrix_draw_coop_names(sorted);
409
410         for (i = 0; i < N_players; i++ ) {
411                 color = sorted[i];
412
413                 if (Players[sorted[i]].connected == 0)
414                         gr_set_fontcolor(gr_find_closest_color(31,31,31), -1);
415                 else
416                         gr_set_fontcolor(gr_getcolor(player_rgb[color].r,player_rgb[color].g,player_rgb[color].b), -1);
417
418                 kmatrix_draw_coop_item( i, sorted );
419         }
420
421         kmatrix_draw_deaths(sorted);
422
423         gr_set_current_canvas(NULL);
424
425         gr_bitmap(0, 0, &tempcanvas->cv_bitmap);
426
427         gr_palette_load(gr_palette);
428         gr_free_canvas(tempcanvas);
429 }
430
431
432 #define MAX_VIEW_TIME       (F1_0*15)
433 #define ENDLEVEL_IDLE_TIME  (F1_0*10)
434
435 fix StartAbortMenuTime;
436
437 #ifdef MACINTOSH
438 extern void load_stars_palette(void);
439 #endif
440
441 extern void network_endlevel_poll3( int nitems, struct newmenu_item *menus, int *key, int citem );
442
443
444 void kmatrix_view(int network)
445 {
446         int i, k, done,choice;
447         fix entry_time = timer_get_approx_seconds();
448         int key;
449         int oldstates[MAX_PLAYERS];
450         int previous_seconds_left = -1;
451         int num_ready, num_escaped;
452
453         network = Game_mode & GM_NETWORK;
454
455         for (i = 0; i < MAX_NUM_NET_PLAYERS; i++)
456                 digi_kill_sound_linked_to_object(Players[i].objnum);
457
458         set_screen_mode( SCREEN_MENU );
459
460         StarBackCanvas = gr_create_canvas( grd_curcanv->cv_bitmap.bm_w, grd_curcanv->cv_bitmap.bm_h );
461         gr_set_current_canvas(StarBackCanvas);
462 #ifdef MACINTOSH
463         if (virtual_memory_on) {
464                 load_stars_palette(); // horrible hack to prevent too much paging when doing endlevel syncing
465                 gr_clear_canvas( BM_XRGB(0, 0, 0) );
466         } else
467 #endif // note link to above if/else pair
468                 load_stars();
469
470         WaitingForOthers = 0;
471         kmatrix_redraw();
472
473         //@@gr_palette_fade_in( gr_palette, 32, 0);
474         game_flush_inputs();
475
476         done = 0;
477
478         for (i = 0; i < N_players; i++)
479                 oldstates[i] = Players[i].connected;
480
481         if (network)
482                 network_endlevel(&key);
483
484         while (!done) {
485                 kmatrix_kills_changed = 0;
486                 for (i = 0; i < 4; i++ )
487                         if (joy_get_button_down_cnt(i) > 0) {
488                                 if (is_D2_OEM && Current_level_num == 8) {
489                                         Players[Player_num].connected = 0;
490                                         if (network)
491                                                 network_send_endlevel_packet();
492                                         gr_free_canvas(StarBackCanvas);
493                                         multi_leave_game();
494                                         Kmatrix_nomovie_message = 0;
495
496                                         longjmp(LeaveGame, 0);
497                                         return;
498                                 }
499
500                                 Players[Player_num].connected = 7;
501                                 if (network)
502                                         network_send_endlevel_packet();
503                                 break;
504                         }
505
506                 for (i = 0; i < 3; i++ )
507                         if (mouse_button_down_count(i) > 0) {
508                                 if (is_D2_OEM && Current_level_num == 8) {
509                                         Players[Player_num].connected = 0;
510                                         if (network)
511                                                 network_send_endlevel_packet();
512                                         gr_free_canvas(StarBackCanvas);
513                                         multi_leave_game();
514                                         Kmatrix_nomovie_message = 0;
515
516                                         longjmp(LeaveGame, 0);
517                                         return;
518                                 }
519                                 Players[Player_num].connected = 7;
520                                 if (network)
521                                         network_send_endlevel_packet();
522                                 break;
523                         }
524
525                 // see if redbook song needs to be restarted
526                 songs_check_redbook_repeat();
527
528                 k = newmenu_inkey();
529                 switch( k ) {
530                 case KEY_ENTER:
531                 case KEY_SPACEBAR:
532                         if ((Game_mode & GM_SERIAL) || (Game_mode & GM_MODEM)) {
533                                 done = 1;
534                                 break;
535                         }
536
537                         if (is_D2_OEM && Current_level_num == 8) {
538                                 Players[Player_num].connected = 0;
539                                 if (network)
540                                         network_send_endlevel_packet();
541                                 gr_free_canvas (StarBackCanvas);
542                                 multi_leave_game();
543                                 Kmatrix_nomovie_message = 0;
544
545                                 longjmp(LeaveGame, 0);
546                                 return;
547                         }
548
549                         Players[Player_num].connected = 7;
550                         if (network)
551                                 network_send_endlevel_packet();
552
553                         break;
554                 case KEY_ESC:
555                         if (Game_mode & GM_NETWORK) {
556                                 StartAbortMenuTime = timer_get_approx_seconds();
557                                 choice = nm_messagebox1( NULL, network_endlevel_poll3, 2, TXT_YES, TXT_NO, TXT_ABORT_GAME );
558                         } else
559                                 choice = nm_messagebox( NULL, 2, TXT_YES, TXT_NO, TXT_ABORT_GAME );
560                         if (choice == 0) {
561                                 Players[Player_num].connected = 0;
562                                 if (network)
563                                         network_send_endlevel_packet();
564                                 gr_free_canvas(StarBackCanvas);
565                                 multi_leave_game();
566                                 Kmatrix_nomovie_message = 0;
567
568                                 longjmp(LeaveGame, 0);
569                 return;
570                         } else
571                                 kmatrix_kills_changed = 1;
572
573                         break;
574                 case KEY_PRINT_SCREEN:
575                         save_screen_shot(0);
576                         break;
577                 case KEY_BACKSP:
578                         Int3();
579                         break;
580                 default:
581                         break;
582                 }
583                 if (timer_get_approx_seconds() >= (entry_time + MAX_VIEW_TIME) && Players[Player_num].connected != 7) {
584                         if (is_D2_OEM && Current_level_num == 8) {
585                                 Players[Player_num].connected = 0;
586                                 if (network)
587                                         network_send_endlevel_packet();
588                                 gr_free_canvas(StarBackCanvas);
589                                 multi_leave_game();
590                                 Kmatrix_nomovie_message = 0;
591
592                                 longjmp(LeaveGame, 0);
593                                 return;
594                         }
595
596                         if ((Game_mode & GM_SERIAL) || (Game_mode & GM_MODEM)) {
597                                 done = 1;
598                                 break;
599                         }
600                         Players[Player_num].connected = 7;
601                         if (network)
602                                 network_send_endlevel_packet();
603                 }
604
605                 if (network && (Game_mode & GM_NETWORK)) {
606                         network_endlevel_poll2(0, NULL, &key, 0);
607
608                         for (num_escaped = 0, num_ready = 0, i = 0; i < N_players; i++) {
609                                 if (Players[i].connected && i != Player_num) {
610                                         // Check timeout for idle players
611                                         if (timer_get_approx_seconds() > LastPacketTime[i] + ENDLEVEL_IDLE_TIME) {
612                                                 mprintf((0, "idle timeout for player %d.\n", i));
613                                                 Players[i].connected = 0;
614                                                 network_send_endlevel_sub(i);
615                                         }
616                                 }
617
618                                 if (Players[i].connected != oldstates[i]) {
619                                         if (ConditionLetters[Players[i].connected] != ConditionLetters[oldstates[i]])
620                                                 kmatrix_kills_changed = 1;
621                                         oldstates[i] = Players[i].connected;
622                                         network_send_endlevel_packet();
623                                 }
624                                 if (Players[i].connected == 0 || Players[i].connected == 7)
625                                         num_ready++;
626
627                                 if (Players[i].connected != 1)
628                                         num_escaped++;
629                         }
630
631                         if (num_ready >= N_players)
632                                 done = 1;
633                         if (num_escaped >= N_players)
634                                 Countdown_seconds_left = -1;
635
636                         if (previous_seconds_left != Countdown_seconds_left) {
637                                 previous_seconds_left = Countdown_seconds_left;
638                                 kmatrix_kills_changed = 1;
639                         }
640
641                         if ( kmatrix_kills_changed ) {
642                                 kmatrix_redraw();
643                                 kmatrix_kills_changed = 0;
644                         }
645                 }
646                 vid_update();
647         }
648
649         Players[Player_num].connected = 7;
650
651         if (network)
652                 network_send_endlevel_packet(); // make sure
653
654         // Restore background and exit
655         gr_palette_fade_out( gr_palette, 32, 0 );
656
657         game_flush_inputs();
658
659         gr_free_canvas(StarBackCanvas);
660
661         Kmatrix_nomovie_message = 0;
662 }