/* 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. */ /* * * Stuff for rendering the HUD * */ #include #include #include #include "pstypes.h" #include "console.h" #include "inferno.h" #include "error.h" #include "gr.h" #include "palette.h" #include "bm.h" #include "player.h" #include "render.h" #include "menu.h" #include "newmenu.h" #include "screens.h" #include "fix.h" #include "robot.h" #include "game.h" #include "gauges.h" #include "gamefont.h" #include "newdemo.h" #include "text.h" #include "multi.h" #include "endlevel.h" #include "cntrlcen.h" #include "fuelcen.h" #include "powerup.h" #include "laser.h" #include "playsave.h" #include "automap.h" #include "mission.h" #include "gameseq.h" #ifdef OGL #include "ogl_init.h" #endif extern fix Cruise_speed; int netplayerinfo_on=0; #ifdef NETWORK void game_draw_multi_message() { char temp_string[MAX_MULTI_MESSAGE_LEN+25]; if ( (Game_mode&GM_MULTI) && (multi_sending_message)) { gr_set_curfont(GAME_FONT); gr_set_fontcolor(BM_XRGB(0,63,0),-1); sprintf( temp_string, "%s: %s_", TXT_MESSAGE, Network_message ); gr_printf(0x8000, (SHEIGHT/5.555), temp_string ); } if ( (Game_mode&GM_MULTI) && (multi_defining_message)) { gr_set_curfont(GAME_FONT); gr_set_fontcolor(BM_XRGB(0,63,0),-1); sprintf( temp_string, "%s #%d: %s_", TXT_MACRO, multi_defining_message, Network_message ); gr_printf(0x8000, (SHEIGHT/5.555), temp_string ); } } #endif fix frame_time_list[8] = {0,0,0,0,0,0,0,0}; fix frame_time_total=0; int frame_time_cntr=0; void ftoa(char *string, fix f) { int decimal, fractional; decimal = f2i(f); fractional = ((f & 0xffff)*100)/65536; if (fractional < 0 ) fractional *= -1; if (fractional > 99 ) fractional = 99; sprintf( string, "FPS: %d.%02d", decimal, fractional ); } void show_framerate() { char temp[13]; fix rate; int aw,w,h; frame_time_total += FrameTime - frame_time_list[frame_time_cntr]; frame_time_list[frame_time_cntr] = FrameTime; frame_time_cntr = (frame_time_cntr+1)%8; if (frame_time_total) { int y=GHEIGHT; if (PlayerCfg.CockpitMode[1]==CM_FULL_SCREEN) { if ((Game_mode & GM_MULTI) || (Newdemo_state == ND_STATE_PLAYBACK && Newdemo_game_mode && GM_MULTI)) y -= LINE_SPACING * 10; else y -= LINE_SPACING * 4; } else if (PlayerCfg.CockpitMode[1] == CM_STATUS_BAR) { if ((Game_mode & GM_MULTI) || (Newdemo_state == ND_STATE_PLAYBACK && Newdemo_game_mode && GM_MULTI)) y -= LINE_SPACING * 6; else y -= LINE_SPACING * 1; } else { if ((Game_mode & GM_MULTI) || (Newdemo_state == ND_STATE_PLAYBACK && Newdemo_game_mode && GM_MULTI)) y -= LINE_SPACING * 7; else y -= LINE_SPACING * 2; } rate = fixdiv(f1_0*8,frame_time_total); gr_set_curfont(GAME_FONT); gr_set_fontcolor(BM_XRGB(0,31,0),-1); ftoa( temp, rate ); gr_get_string_size("FPS: 000.00",&w,&h,&aw); gr_printf(SWIDTH-w-FSPACX(1),y,"%s", temp ); } } #ifdef NETWORK void show_netplayerinfo() { int x=0, y=0, i=0, color=0; char *NetworkModeNames[]={"Anarchy","Team Anarchy","Robo Anarchy","Cooperative","Capture the Flag","Hoard","Team Hoard","Unknown"}; gr_set_current_canvas(NULL); gr_set_curfont(GAME_FONT); gr_set_fontcolor(255,-1); x=(SWIDTH/2)-FSPACX(120); y=(SHEIGHT/2)-FSPACY(84); Gr_scanline_darkening_level = 2*7; gr_setcolor( BM_XRGB(0,0,0) ); gr_rect((SWIDTH/2)-FSPACX(120),(SHEIGHT/2)-FSPACY(84),(SWIDTH/2)+FSPACX(120),(SHEIGHT/2)+FSPACY(84)); Gr_scanline_darkening_level = GR_FADE_LEVELS; // general game information y+=LINE_SPACING; gr_printf(0x8000,y,"%s",Netgame.game_name); #ifndef SHAREWARE y+=LINE_SPACING; gr_printf(0x8000,y,"%s - lvl: %i",Netgame.mission_title,Netgame.levelnum); #endif x+=FSPACX(8); y+=LINE_SPACING*2; gr_printf(x,y,"game mode: %s",NetworkModeNames[Netgame.gamemode]); y+=LINE_SPACING; gr_printf(x,y,"difficulty: %s",MENU_DIFFICULTY_TEXT(Netgame.difficulty)); y+=LINE_SPACING; gr_printf(x,y,"level time: %i:%02i:%02i",Players[Player_num].hours_level,f2i(Players[Player_num].time_level) / 60 % 60,f2i(Players[Player_num].time_level) % 60); y+=LINE_SPACING; gr_printf(x,y,"total time: %i:%02i:%02i",Players[Player_num].hours_total,f2i(Players[Player_num].time_total) / 60 % 60,f2i(Players[Player_num].time_total) % 60); y+=LINE_SPACING; // player information (name, kills, ping, game efficiency) y+=LINE_SPACING*2; gr_printf(x,y,"player"); if (Game_mode & GM_MULTI_COOP) gr_printf(x+FSPACX(8)*7,y,"score"); else { gr_printf(x+FSPACX(8)*7,y,"kills"); gr_printf(x+FSPACX(8)*12,y,"deaths"); } gr_printf(x+FSPACX(8)*18,y,"ping"); gr_printf(x+FSPACX(8)*23,y,"efficiency"); // process players table for (i=0; i 0 ) { char *viewer_name,*control_name; Show_view_text_timer -= FrameTime; switch( Viewer->type ) { case OBJ_FIREBALL: viewer_name = "Fireball"; break; case OBJ_ROBOT: viewer_name = "Robot"; break; case OBJ_HOSTAGE: viewer_name = "Hostage"; break; case OBJ_PLAYER: viewer_name = "Player"; break; case OBJ_WEAPON: viewer_name = "Weapon"; break; case OBJ_CAMERA: viewer_name = "Camera"; break; case OBJ_POWERUP: viewer_name = "Powerup"; break; case OBJ_DEBRIS: viewer_name = "Debris"; break; case OBJ_CNTRLCEN: viewer_name = "Control Center"; break; default: viewer_name = "Unknown"; break; } switch ( Viewer->control_type) { case CT_NONE: control_name = "Stopped"; break; case CT_AI: control_name = "AI"; break; case CT_FLYING: control_name = "Flying"; break; case CT_SLEW: control_name = "Slew"; break; case CT_FLYTHROUGH: control_name = "Flythrough"; break; case CT_MORPH: control_name = "Morphing"; break; default: control_name = "Unknown"; break; } gr_set_curfont( GAME_FONT ); gr_set_fontcolor( BM_XRGB(31, 0, 0), -1 ); gr_printf( 0x8000, (SHEIGHT/10), "%s View - %s",viewer_name,control_name ); } } #endif void render_countdown_gauge() { if (!Endlevel_sequence && Control_center_destroyed && (Fuelcen_seconds_left>-1) && (Fuelcen_seconds_left<127)) { gr_set_curfont(GAME_FONT); gr_set_fontcolor(BM_XRGB(0,63,0),-1); gr_printf(0x8000, (SHEIGHT/6.666), "T-%d s", Fuelcen_seconds_left ); } } void game_draw_hud_stuff() { #ifdef CROSSHAIR if ( Viewer->type == OBJ_PLAYER ) laser_do_crosshair(Viewer); #endif #ifndef NDEBUG draw_window_label(); #endif #ifdef NETWORK game_draw_multi_message(); #endif if ((Newdemo_state == ND_STATE_PLAYBACK) || (Newdemo_state == ND_STATE_RECORDING)) { char message[128]; int y; if (Newdemo_state == ND_STATE_PLAYBACK) { if (Newdemo_show_percentage) { sprintf(message, "%s (%d%%%% %s)", TXT_DEMO_PLAYBACK, newdemo_get_percent_done(), TXT_DONE); } else { sprintf (message, " "); } } else { extern int Newdemo_num_written; sprintf (message, "%s (%dK)", TXT_DEMO_RECORDING, (Newdemo_num_written / 1024)); } gr_set_curfont( GAME_FONT ); gr_set_fontcolor( BM_XRGB(27,0,0), -1 ); y = GHEIGHT-(LINE_SPACING*2); if (PlayerCfg.CockpitMode[1] == CM_FULL_COCKPIT) y = grd_curcanv->cv_bitmap.bm_h / 1.2 ; if (PlayerCfg.CockpitMode[1] != CM_REAR_VIEW) gr_printf(0x8000, y, message ); } render_countdown_gauge(); // this should be made part of hud code some day if ( Player_num > -1 && Viewer->type==OBJ_PLAYER && Viewer->id==Player_num && PlayerCfg.CockpitMode[1] != CM_REAR_VIEW) { int x = FSPACX(1); int y = grd_curcanv->cv_bitmap.bm_h; gr_set_curfont( GAME_FONT ); gr_set_fontcolor( BM_XRGB(0, 31, 0), -1 ); if (Cruise_speed > 0) { if (PlayerCfg.CockpitMode[1]==CM_FULL_SCREEN) { if (Game_mode & GM_MULTI) y -= LINE_SPACING * 10; else y -= LINE_SPACING * 5; } else if (PlayerCfg.CockpitMode[1] == CM_STATUS_BAR) { if (Game_mode & GM_MULTI) y -= LINE_SPACING * 6; else y -= LINE_SPACING * 1; } else { if (Game_mode & GM_MULTI) y -= LINE_SPACING * 7; else y -= LINE_SPACING * 2; } gr_printf( x, y, "%s %2d%%", TXT_CRUISE, f2i(Cruise_speed) ); } } if (GameArg.SysFPSIndicator && PlayerCfg.CockpitMode[1] != CM_REAR_VIEW) show_framerate(); if (Newdemo_state == ND_STATE_PLAYBACK) Game_mode = Newdemo_game_mode; draw_hud(); if (Newdemo_state == ND_STATE_PLAYBACK) Game_mode = GM_NORMAL; if ( Player_is_dead ) player_dead_message(); } extern int gr_bitblt_dest_step_shift; extern int gr_bitblt_double; extern int force_cockpit_redraw; void update_cockpits(); //render a frame for the game void game_do_render_frame(int flip) { gr_set_current_canvas(&Screen_3d_window); render_frame(0); update_cockpits(); if (Newdemo_state == ND_STATE_PLAYBACK) Game_mode = Newdemo_game_mode; if (PlayerCfg.CockpitMode[1]==CM_FULL_COCKPIT || PlayerCfg.CockpitMode[1]==CM_STATUS_BAR) render_gauges(); if (Newdemo_state == ND_STATE_PLAYBACK) Game_mode = GM_NORMAL; gr_set_current_canvas(&Screen_3d_window); game_draw_hud_stuff(); #ifdef NETWORK if (netplayerinfo_on) show_netplayerinfo(); #endif con_show(); } void toggle_cockpit() { int new_mode=CM_FULL_SCREEN; if (Rear_view || Player_is_dead) return; switch (PlayerCfg.CockpitMode[1]) { case CM_FULL_COCKPIT: new_mode = CM_STATUS_BAR; break; case CM_STATUS_BAR: new_mode = CM_FULL_SCREEN; break; case CM_FULL_SCREEN: new_mode = CM_FULL_COCKPIT; break; } select_cockpit(new_mode); HUD_clear_messages(); PlayerCfg.CockpitMode[0] = new_mode; write_player_file(); } int last_drawn_cockpit = -1; extern void ogl_loadbmtexture(grs_bitmap *bm); // This actually renders the new cockpit onto the screen. void update_cockpits() { grs_bitmap * bm; PIGGY_PAGE_IN(cockpit_bitmap[PlayerCfg.CockpitMode[1]]); bm = &GameBitmaps[cockpit_bitmap[PlayerCfg.CockpitMode[1]].index]; //Redraw the on-screen cockpit bitmaps if (VR_render_mode != VR_NONE ) return; switch( PlayerCfg.CockpitMode[1] ) { case CM_FULL_COCKPIT: gr_set_current_canvas(NULL); #ifdef OGL ogl_ubitmapm_cs (0, 0, -1, grd_curcanv->cv_bitmap.bm_h, bm,255, F1_0); #else gr_ubitmapm(0,0, bm); #endif break; case CM_REAR_VIEW: gr_set_current_canvas(NULL); #ifdef OGL ogl_ubitmapm_cs (0, 0, -1, grd_curcanv->cv_bitmap.bm_h, bm,255, F1_0); #else gr_ubitmapm(0,0, bm); #endif break; case CM_FULL_SCREEN: break; case CM_STATUS_BAR: gr_set_current_canvas(NULL); #ifdef OGL ogl_ubitmapm_cs (0, (HIRESMODE?(SHEIGHT*2)/2.6:(SHEIGHT*2)/2.72), -1, ((int) ((double) (bm->bm_h) * (HIRESMODE?(double)SHEIGHT/480:(double)SHEIGHT/200) + 0.5)), bm,255, F1_0); #else gr_ubitmapm(0,SHEIGHT-bm->bm_h,bm); #endif break; case CM_LETTERBOX: gr_set_current_canvas(NULL); break; } gr_set_current_canvas(NULL); if (PlayerCfg.CockpitMode[1] != last_drawn_cockpit) last_drawn_cockpit = PlayerCfg.CockpitMode[1]; else return; if (PlayerCfg.CockpitMode[1]==CM_FULL_COCKPIT || PlayerCfg.CockpitMode[1]==CM_STATUS_BAR) init_gauges(); } void game_render_frame() { set_screen_mode(SCREEN_GAME); play_homing_warning(); game_do_render_frame(GameArg.DbgUseDoubleBuffer); FrameCount++; } //show a message in a nice little box void show_boxed_message(char *msg, int RenderFlag) { int w,h,aw; int x,y; gr_set_current_canvas(NULL); gr_set_curfont( MEDIUM1_FONT ); gr_set_fontcolor(BM_XRGB(31, 31, 31), -1); gr_get_string_size(msg,&w,&h,&aw); x = (SWIDTH-w)/2; y = (SHEIGHT-h)/2; nm_draw_background(x-BORDERX,y-BORDERY,x+w+BORDERX,y+h+BORDERY); gr_printf( 0x8000, y, msg ); // If we haven't drawn behind it, need to flip if (!RenderFlag) gr_flip(); }