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