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