/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Kill matrix displayed at end of level. * This source file contains code for both newer networking protocols and IPX. Pretty much redundant stuff but lets keep a clean cut until IPX dies completly. * */ #include #include #include #include #include #include "error.h" #include "pstypes.h" #include "gr.h" #include "window.h" #include "key.h" #include "palette.h" #include "game.h" #include "window.h" #include "gamefont.h" #include "u_mem.h" #include "newmenu.h" #include "menu.h" #include "player.h" #include "screens.h" #include "gamefont.h" #include "cntrlcen.h" #include "mouse.h" #include "joy.h" #include "timer.h" #include "text.h" #include "rbaudio.h" #include "multi.h" #include "kmatrix.h" #include "gauges.h" #include "pcx.h" #ifdef OGL #include "ogl_init.h" #endif #define CENTERING_OFFSET(x) ((300 - (70 + (x)*25 ))/2) #define CENTERSCREEN (SWIDTH/2) /* IPX CODE - START */ #define MAX_VIEW_TIME F1_0*15 #define ENDLEVEL_IDLE_TIME F1_0*10 fix StartAbortMenuTime; char ConditionLetters[]={' ','P','E','D','E','E','V','W'}; extern void newmenu_close(); void kmatrix_ipx_reactor (char *message); void kmatrix_ipx_phallic (); void kmatrix_ipx_redraw_coop(); void kmatrix_ipx_draw_item( int i, int *sorted ) { int j, x, y; char temp[10]; y = FSPACY(50+i*9); // Print player name. gr_printf( FSPACX(CENTERING_OFFSET(N_players)), y, "%s", Players[sorted[i]].callsign ); gr_printf (FSPACX(CENTERING_OFFSET(N_players)-15),y,"%c",ConditionLetters[Players[sorted[i]].connected]); for (j=0; jcv_font = GAME_FONT; if (oldmessage[0]!=0) { gr_set_fontcolor(gr_find_closest_color(0,0,0),-1); gr_get_string_size(oldmessage, &sw, &sh, &aw); } gr_set_fontcolor(gr_find_closest_color(0,32,63),-1); gr_get_string_size(message, &sw, &sh, &aw); gr_printf( CENTERSCREEN-(sw/2), FSPACY(55+72+12), message); strcpy ((char *)&oldmessage,message); } extern int PhallicLimit,PhallicMan; void kmatrix_ipx_phallic () { int sw, sh, aw; char message[80]; if (!(Game_mode & GM_HOARD)) return; if (PhallicMan==-1) strcpy (message,"There was no record set for this level."); else sprintf (message,"%s had the best record at %d points.",Players[PhallicMan].callsign,PhallicLimit); grd_curcanv->cv_font = GAME_FONT; gr_set_fontcolor(gr_find_closest_color(63,63,63),-1); gr_get_string_size(message, &sw, &sh, &aw); gr_printf( CENTERSCREEN-(sw/2), FSPACY(55+72+3), message); } void kmatrix_ipx_redraw() { int i, pcx_error, color; int sorted[MAX_NUM_NET_PLAYERS]; pcx_error = pcx_read_fullscr(STARS_BACKGROUND, gr_palette); Assert(pcx_error == PCX_ERROR_NONE); if (Game_mode & GM_MULTI_COOP) { kmatrix_ipx_redraw_coop(); return; } multi_sort_kill_list(); gr_set_current_canvas(NULL); grd_curcanv->cv_font = MEDIUM3_FONT; if (Game_mode & GM_CAPTURE) gr_string( 0x8000, FSPACY(10), "CAPTURE THE FLAG SUMMARY"); else if (Game_mode & GM_HOARD) gr_string( 0x8000, FSPACY(10), "HOARD SUMMARY"); else gr_string( 0x8000, FSPACY(10), TXT_KILL_MATRIX_TITLE); grd_curcanv->cv_font = GAME_FONT; multi_get_kill_list(sorted); kmatrix_ipx_draw_names(sorted); for (i=0; icv_font = MEDIUM3_FONT; gr_string( 0x8000, FSPACY(10), "COOPERATIVE SUMMARY"); grd_curcanv->cv_font = GAME_FONT; multi_get_kill_list(sorted); kmatrix_ipx_draw_coop_names(sorted); for (i=0; itype) { case EVENT_KEY_COMMAND: k = ((d_event_keycommand *)event)->keycode; switch( k ) { case KEY_ENTER: case KEY_SPACEBAR: if (is_D2_OEM) { if (Current_level_num==8) { Players[Player_num].connected=CONNECT_DISCONNECTED; if (km->network) multi_send_endlevel_packet(); multi_leave_game(); window_close(wind); if (Game_wind) window_close(Game_wind); return 1; } } Players[Player_num].connected=CONNECT_KMATRIX_WAITING; if (km->network) multi_send_endlevel_packet(); return 1; case KEY_ESC: if (Game_mode & GM_NETWORK) { StartAbortMenuTime=timer_get_fixed_seconds(); choice=nm_messagebox1( NULL,multi_endlevel_poll2, NULL, 2, TXT_YES, TXT_NO, TXT_ABORT_GAME ); } else choice=nm_messagebox( NULL, 2, TXT_YES, TXT_NO, TXT_ABORT_GAME ); if (choice==0) { Players[Player_num].connected=CONNECT_DISCONNECTED; if (km->network) multi_send_endlevel_packet(); multi_leave_game(); window_close(wind); if (Game_wind) window_close(Game_wind); return 1; } return 1; case KEY_PRINT_SCREEN: save_screen_shot(0); return 1; case KEY_BACKSP: Int3(); return 1; default: break; } break; case EVENT_IDLE: timer_delay2(50); //see if redbook song needs to be restarted RBACheckFinishedHook(); if (timer_get_fixed_seconds() >= (km->entry_time+MAX_VIEW_TIME) && Players[Player_num].connected!=CONNECT_KMATRIX_WAITING) { if (is_D2_OEM) { if (Current_level_num==8) { Players[Player_num].connected=CONNECT_DISCONNECTED; if (km->network) multi_send_endlevel_packet(); multi_leave_game(); window_close(wind); if (Game_wind) window_close(Game_wind); return 0; } } Players[Player_num].connected=CONNECT_KMATRIX_WAITING; if (km->network) multi_send_endlevel_packet(); } if (km->network && (Game_mode & GM_NETWORK)) { multi_endlevel_poll1(NULL, event, NULL); for (num_escaped=0,num_ready=0,i=0;i Netgame.players[i].LastPacketTime+ENDLEVEL_IDLE_TIME) { Players[i].connected = CONNECT_DISCONNECTED; } } // HACK: If a player legally exits kmatrix loop he will send the previous connect byte which can invalidate us from setting him to ready and let us stuck here forever... it's stupid to solve it this way, but for now I have no better idea. if ((km->oldstates[i]==CONNECT_END_MENU || km->oldstates[i]==CONNECT_KMATRIX_WAITING) && // player was viewing scores before... (Players[i].connected!=CONNECT_DISCONNECTED || Players[i].connected!=CONNECT_END_MENU || Players[i].connected!=CONNECT_KMATRIX_WAITING)) // ... but now he sends neither disconnect or further waiting signal - so he MUST be out of kmatrix already Players[i].connected=CONNECT_KMATRIX_WAITING; if (Players[i].connected!=km->oldstates[i]) { if (ConditionLetters[Players[i].connected]!=ConditionLetters[km->oldstates[i]]) km->oldstates[i]=Players[i].connected; multi_send_endlevel_packet(); } if (Players[i].connected==CONNECT_DISCONNECTED || Players[i].connected==CONNECT_KMATRIX_WAITING) num_ready++; if (Players[i].connected!=CONNECT_PLAYING) num_escaped++; } if (num_ready>=N_players) { window_close(wind); Players[Player_num].connected=CONNECT_KMATRIX_WAITING; if (km->network) multi_send_endlevel_packet(); // make sure } if (num_escaped>=N_players) Countdown_seconds_left=-1; } break; case EVENT_WINDOW_DRAW: kmatrix_ipx_redraw(); break; case EVENT_WINDOW_CLOSE: game_flush_inputs(); newmenu_close(); d_free(km); break; default: break; } return 0; } void kmatrix_ipx_view(int network) { window *wind; kmatrix_ipx_screen *km; int i; int key; MALLOC(km, kmatrix_ipx_screen, 1); if (!km) return; km->entry_time = timer_get_fixed_seconds(); km->network = network; for (i=0;ioldstates[i]=Players[i].connected; if (km->network) multi_endlevel(&key); wind = window_create(&grd_curscreen->sc_canvas, 0, 0, SWIDTH, SHEIGHT, (int (*)(window *, d_event *, void *))kmatrix_ipx_handler, km); if (!wind) { d_free(km); return; } while (window_exists(wind)) event_process(); } /* IPX CODE - END */ /* NEW CODE - START */ #define KMATRIX_VIEW_SEC 7 // Time after reactor explosion until new level - in seconds void kmatrix_phallic (); void kmatrix_redraw_coop(); void kmatrix_draw_item( int i, int *sorted ) { int j, x, y; char temp[10]; y = FSPACY(50+i*9); gr_printf( FSPACX(CENTERING_OFFSET(N_players)), y, "%s", Players[sorted[i]].callsign ); for (j=0; jcv_font = GAME_FONT; gr_set_fontcolor(gr_find_closest_color(63,63,63),-1); gr_get_string_size(message, &sw, &sh, &aw); gr_printf( CENTERSCREEN-(sw/2), FSPACY(55+72+3), message); } void kmatrix_status_msg (fix time, int reactor) { grd_curcanv->cv_font = GAME_FONT; gr_set_fontcolor(gr_find_closest_color(255,255,255),-1); if (reactor) gr_printf(0x8000, SHEIGHT-LINE_SPACING, "Waiting for players to finish level. Reactor time: T-%d", time); else gr_printf(0x8000, SHEIGHT-LINE_SPACING, "Level finished. Wait (%d) to proceed or ESC to Quit.", time); } void kmatrix_redraw() { int i, pcx_error, color; int sorted[MAX_NUM_NET_PLAYERS]; pcx_error = pcx_read_fullscr(STARS_BACKGROUND, gr_palette); Assert(pcx_error == PCX_ERROR_NONE); if (Game_mode & GM_MULTI_COOP) { kmatrix_redraw_coop(); } else { multi_sort_kill_list(); gr_set_current_canvas(NULL); grd_curcanv->cv_font = MEDIUM3_FONT; if (Game_mode & GM_CAPTURE) gr_string( 0x8000, FSPACY(10), "CAPTURE THE FLAG SUMMARY"); else if (Game_mode & GM_HOARD) gr_string( 0x8000, FSPACY(10), "HOARD SUMMARY"); else gr_string( 0x8000, FSPACY(10), TXT_KILL_MATRIX_TITLE); grd_curcanv->cv_font = GAME_FONT; multi_get_kill_list(sorted); kmatrix_draw_names(sorted); for (i=0; icv_font = MEDIUM3_FONT; gr_string( 0x8000, FSPACY(10), "COOPERATIVE SUMMARY"); grd_curcanv->cv_font = GAME_FONT; multi_get_kill_list(sorted); kmatrix_draw_coop_names(sorted); for (i=0; itype) { case EVENT_KEY_COMMAND: k = ((d_event_keycommand *)event)->keycode; switch( k ) { case KEY_ESC: if (km->network) { StartAbortMenuTime=timer_get_fixed_seconds(); choice=nm_messagebox1( NULL,multi_endlevel_poll2, NULL, 2, TXT_YES, TXT_NO, TXT_ABORT_GAME ); } else choice=nm_messagebox( NULL, 2, TXT_YES, TXT_NO, TXT_ABORT_GAME ); if (choice==0) { Players[Player_num].connected=CONNECT_DISCONNECTED; if (km->network) multi_send_endlevel_packet(); multi_leave_game(); window_close(wind); if (Game_wind) window_close(Game_wind); return 1; } return 1; case KEY_PRINT_SCREEN: save_screen_shot(0); return 1; default: break; } break; case EVENT_IDLE: timer_delay2(50); RBACheckFinishedHook(); //see if redbook song needs to be restarted if (km->network) multi_do_protocol_frame(0, 1); // Check if all connected players are also looking at this screen ... for (i = 0; i < MAX_PLAYERS; i++) if (Players[i].connected) if (Players[i].connected != CONNECT_END_MENU && Players[i].connected != CONNECT_DIED_IN_MINE) km->playing = 1; // ... and let the reactor blow sky high! if (!km->playing) Countdown_seconds_left = -1; // If Reactor is finished and end_time not inited, set the time when we will exit this loop if (km->end_time == -1 && Countdown_seconds_left < 0 && !km->playing) km->end_time = time + (KMATRIX_VIEW_SEC * F1_0); // Check if end_time has been reached and exit loop if (time >= km->end_time && km->end_time != -1) { if (km->network) multi_send_endlevel_packet(); // make sure if (is_D2_OEM) { if (Current_level_num==8) { Players[Player_num].connected=CONNECT_DISCONNECTED; if (km->network) multi_send_endlevel_packet(); multi_leave_game(); window_close(wind); if (Game_wind) window_close(Game_wind); return 0; } } window_close(wind); } break; case EVENT_WINDOW_DRAW: kmatrix_redraw(); if (km->playing) kmatrix_status_msg(Countdown_seconds_left, 1); else kmatrix_status_msg(f2i(time-km->end_time), 0); break; case EVENT_WINDOW_CLOSE: game_flush_inputs(); newmenu_close(); d_free(km); break; default: break; } return 0; } void kmatrix_view(int network) { kmatrix_screen *km; window *wind; int i = 0; MALLOC(km, kmatrix_screen, 1); if (!km) return; km->network = network; km->end_time = -1; km->playing = 0; set_screen_mode( SCREEN_MENU ); game_flush_inputs(); for (i=0;isc_canvas, 0, 0, SWIDTH, SHEIGHT, (int (*)(window *, d_event *, void *))kmatrix_handler, km); if (!wind) { d_free(km); return; } while (window_exists(wind)) event_process(); } /* NEW CODE - END */