2006-03-20 17:12:09 +00:00
/*
2014-06-01 17:55:23 +00:00
* Portions of this file are copyright Rebirth contributors and licensed as
* described in COPYING . txt .
* Portions of this file are copyright Parallax Software and licensed
* according to the Parallax license below .
* See COPYING . txt for license details .
2006-03-20 17:12:09 +00:00
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 <stdio.h>
# include <string.h>
# include <stdlib.h>
2011-01-22 12:30:20 +00:00
# include "timer.h"
2006-03-20 17:12:09 +00:00
# include "pstypes.h"
# include "console.h"
# include "inferno.h"
2012-07-07 18:35:06 +00:00
# include "dxxerror.h"
2006-03-20 17:12:09 +00:00
# include "gr.h"
# include "palette.h"
# include "bm.h"
# include "player.h"
# include "render.h"
# include "newmenu.h"
# include "screens.h"
2013-12-26 04:18:28 +00:00
# include "config.h"
2012-07-01 02:54:33 +00:00
# include "maths.h"
2006-03-20 17:12:09 +00:00
# include "robot.h"
# include "game.h"
# include "gauges.h"
# include "gamefont.h"
# include "newdemo.h"
# include "text.h"
# include "multi.h"
2015-04-19 04:18:51 +00:00
# include "hudmsg.h"
2006-03-20 17:12:09 +00:00
# include "endlevel.h"
# include "powerup.h"
# include "playsave.h"
# include "automap.h"
# include "mission.h"
# include "gameseq.h"
2013-03-03 19:41:09 +00:00
# include "args.h"
2014-11-23 04:36:58 +00:00
# include "object.h"
2006-03-20 17:12:09 +00:00
2015-02-14 22:48:28 +00:00
# include "compiler-range_for.h"
2020-08-10 03:45:14 +00:00
# include "d_levelstate.h"
2019-05-04 18:27:36 +00:00
# include "d_range.h"
2015-02-14 22:48:28 +00:00
2016-09-24 18:06:11 +00:00
# if DXX_USE_OGL
2006-03-20 17:12:09 +00:00
# include "ogl_init.h"
# endif
2015-12-22 04:18:50 +00:00
namespace dcx {
int netplayerinfo_on ;
2022-02-12 18:57:12 +00:00
cockpit_mode_t last_drawn_cockpit = cockpit_mode_t { UINT8_MAX } ;
2015-12-22 04:18:50 +00:00
}
2007-04-04 17:18:17 +00:00
2015-12-22 04:18:50 +00:00
namespace dsx {
2020-10-12 03:28:26 +00:00
namespace {
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2017-02-11 21:42:45 +00:00
static inline void game_draw_marker_message ( grs_canvas & )
2013-03-03 01:03:33 +00:00
{
}
# elif defined(DXX_BUILD_DESCENT_II)
2017-02-11 21:42:45 +00:00
static void game_draw_marker_message ( grs_canvas & canvas )
2006-03-20 17:12:09 +00:00
{
2018-03-10 22:45:04 +00:00
if ( MarkerState . DefiningMarkerMessage ( ) )
2008-02-24 14:41:27 +00:00
{
2017-02-11 21:42:45 +00:00
gr_set_fontcolor ( canvas , BM_XRGB ( 0 , 63 , 0 ) , - 1 ) ;
2018-05-19 23:21:42 +00:00
auto & game_font = * GAME_FONT ;
gr_printf ( canvas , game_font , 0x8000 , ( LINE_SPACING ( game_font , game_font ) * 5 ) + FSPACY ( 1 ) , " Marker: %s%c " , & Marker_input [ 0 ] , Marker_input [ Marker_input . size ( ) - 2 ] ? 0 : ' _ ' ) ;
2008-02-24 14:41:27 +00:00
}
2006-03-20 17:12:09 +00:00
}
2013-03-03 01:03:33 +00:00
# endif
2020-10-12 03:28:26 +00:00
2021-09-12 16:20:52 +00:00
static void update_cockpits ( grs_canvas & ) ;
2020-10-12 03:28:26 +00:00
}
2015-12-22 04:18:50 +00:00
}
namespace dcx {
2006-03-20 17:12:09 +00:00
2020-10-12 03:28:26 +00:00
namespace {
2017-02-11 21:42:45 +00:00
static void game_draw_multi_message ( grs_canvas & canvas )
2006-03-20 17:12:09 +00:00
{
2015-01-12 00:26:02 +00:00
if ( ! ( Game_mode & GM_MULTI ) )
return ;
2016-07-25 03:48:09 +00:00
const auto sending = multi_sending_message [ Player_num ] ;
int defining ;
2021-11-01 03:37:19 +00:00
if ( sending = = msgsend_state : : none & & ! ( defining = multi_defining_message ) )
2016-07-25 03:48:09 +00:00
return ;
2017-02-11 21:42:45 +00:00
gr_set_fontcolor ( canvas , BM_XRGB ( 0 , 63 , 0 ) , - 1 ) ;
2018-05-19 23:21:42 +00:00
auto & game_font = * GAME_FONT ;
const auto & & y = ( LINE_SPACING ( game_font , game_font ) * 5 ) + FSPACY ( 1 ) ;
2021-11-01 03:37:19 +00:00
if ( sending ! = msgsend_state : : none )
2018-05-19 23:21:42 +00:00
gr_printf ( canvas , game_font , 0x8000 , y , " %s: %s_ " , TXT_MESSAGE , Network_message . data ( ) ) ;
2016-07-25 03:48:09 +00:00
else
2018-05-19 23:21:42 +00:00
gr_printf ( canvas , game_font , 0x8000 , y , " %s #%d: %s_ " , TXT_MACRO , defining , Network_message . data ( ) ) ;
2006-03-20 17:12:09 +00:00
}
2017-02-11 21:42:45 +00:00
static void show_framerate ( grs_canvas & canvas )
2006-03-20 17:12:09 +00:00
{
2011-01-22 17:46:08 +00:00
static int fps_count = 0 , fps_rate = 0 ;
2011-01-22 12:30:20 +00:00
static fix64 fps_time = 0 ;
fps_count + + ;
2018-04-14 21:36:50 +00:00
const auto tq = timer_query ( ) ;
if ( tq > = fps_time + F1_0 )
2011-01-22 12:30:20 +00:00
{
fps_rate = fps_count ;
fps_count = 0 ;
2018-04-23 22:33:43 +00:00
fps_time + = F1_0 ;
2006-03-20 17:12:09 +00:00
}
2018-05-19 23:21:42 +00:00
const auto & & line_spacing = LINE_SPACING ( * canvas . cv_font , * GAME_FONT ) ;
2018-04-14 21:36:50 +00:00
unsigned line_displacement ;
switch ( PlayerCfg . CockpitMode [ 1 ] )
{
2022-02-12 18:57:12 +00:00
case cockpit_mode_t : : full_cockpit :
2018-04-14 21:36:50 +00:00
line_displacement = line_spacing * 2 ;
break ;
2022-02-12 18:57:12 +00:00
case cockpit_mode_t : : status_bar :
2018-04-14 21:36:50 +00:00
line_displacement = line_spacing ;
break ;
2022-02-12 18:57:12 +00:00
case cockpit_mode_t : : full_screen :
2018-04-14 21:36:50 +00:00
switch ( PlayerCfg . HudMode )
{
case HudType : : Standard :
line_displacement = line_spacing * 4 ;
break ;
case HudType : : Alternate1 :
line_displacement = line_spacing * 6 ;
if ( Game_mode & GM_MULTI )
line_displacement - = line_spacing * 4 ;
break ;
case HudType : : Alternate2 :
line_displacement = line_spacing ;
break ;
case HudType : : Hidden :
default :
return ;
}
break ;
2022-02-12 18:57:12 +00:00
case cockpit_mode_t : : letterbox :
case cockpit_mode_t : : rear_view :
2018-04-14 21:36:50 +00:00
default :
return ;
}
const auto & game_font = * GAME_FONT ;
gr_set_fontcolor ( canvas , BM_XRGB ( 0 , 31 , 0 ) , - 1 ) ;
char buf [ 16 ] ;
2015-10-18 21:01:21 +00:00
if ( CGameArg . DbgVerbose )
2018-04-14 21:36:50 +00:00
snprintf ( buf , sizeof ( buf ) , " %iFPS (%.2fms) " , fps_rate , ( FrameTime * 1000. ) / F1_0 ) ;
else
snprintf ( buf , sizeof ( buf ) , " %iFPS " , fps_rate ) ;
2021-09-12 16:20:52 +00:00
const auto & & [ w , h ] = gr_get_string_size ( game_font , buf ) ;
2018-04-14 21:36:50 +00:00
const auto bm_h = canvas . cv_bitmap . bm_h ;
2018-05-19 23:21:42 +00:00
gr_string ( canvas , game_font , FSPACX ( 318 ) - w , bm_h - line_displacement , buf , w , h ) ;
2006-03-20 17:12:09 +00:00
}
2015-12-22 04:18:50 +00:00
}
2020-10-12 03:28:26 +00:00
}
2016-08-25 04:05:32 +00:00
namespace dsx {
2020-10-12 03:28:26 +00:00
namespace {
2021-09-12 16:20:52 +00:00
static void show_netplayerinfo ( grs_canvas & canvas )
2007-09-08 11:11:41 +00:00
{
2019-03-03 00:31:08 +00:00
auto & Objects = LevelUniqueObjectState . Objects ;
auto & vcobjptr = Objects . vcptr ;
2015-12-13 18:00:49 +00:00
int x = 0 , y = 0 ;
2015-03-09 03:33:07 +00:00
static const char * const eff_strings [ ] = { " trashing " , " really hurting " , " seriously affecting " , " hurting " , " affecting " , " tarnishing " } ;
2007-09-08 11:11:41 +00:00
2017-02-11 21:42:46 +00:00
gr_set_fontcolor ( canvas , 255 , - 1 ) ;
2008-02-24 14:41:27 +00:00
2015-06-13 22:42:20 +00:00
const auto & & fspacx = FSPACX ( ) ;
2015-06-13 22:42:20 +00:00
const auto & & fspacx120 = fspacx ( 120 ) ;
const auto & & fspacy84 = FSPACY ( 84 ) ;
x = ( SWIDTH / 2 ) - fspacx120 ;
y = ( SHEIGHT / 2 ) - fspacy84 ;
2007-09-08 11:11:41 +00:00
2021-09-19 10:53:48 +00:00
gr_settransblend ( canvas , gr_fade_level { 14 } , gr_blend : : normal ) ;
2016-05-21 17:24:51 +00:00
const uint8_t color000 = BM_XRGB ( 0 , 0 , 0 ) ;
2017-02-11 21:42:46 +00:00
gr_rect ( canvas , ( SWIDTH / 2 ) - fspacx120 , ( SHEIGHT / 2 ) - fspacy84 , ( SWIDTH / 2 ) + fspacx120 , ( SHEIGHT / 2 ) + fspacy84 , color000 ) ;
2020-07-16 02:31:04 +00:00
gr_settransblend ( canvas , GR_FADE_OFF , gr_blend : : normal ) ;
2007-09-08 11:11:41 +00:00
// general game information
2018-05-19 23:21:42 +00:00
const auto & & line_spacing = LINE_SPACING ( * canvas . cv_font , * GAME_FONT ) ;
2015-06-13 22:42:22 +00:00
y + = line_spacing ;
2018-05-19 23:21:42 +00:00
auto & game_font = * GAME_FONT ;
gr_string ( canvas , game_font , 0x8000 , y , Netgame . game_name . data ( ) ) ;
2015-06-13 22:42:22 +00:00
y + = line_spacing ;
2018-05-19 23:21:42 +00:00
gr_printf ( canvas , game_font , 0x8000 , y , " %s - lvl: %i " , Netgame . mission_title . data ( ) , Netgame . levelnum ) ;
2007-09-08 11:11:41 +00:00
2015-06-13 22:42:20 +00:00
const auto & & fspacx8 = fspacx ( 8 ) ;
x + = fspacx8 ;
2015-06-13 22:42:22 +00:00
y + = line_spacing * 2 ;
2021-11-01 03:37:19 +00:00
const auto gamemode = underlying_value ( Netgame . gamemode ) ;
2018-05-19 23:21:42 +00:00
gr_printf ( canvas , game_font , x , y , " game mode: %s " , gamemode < GMNames . size ( ) ? GMNames [ gamemode ] : " INVALID " ) ;
2015-06-13 22:42:22 +00:00
y + = line_spacing ;
2018-05-19 23:21:42 +00:00
gr_printf ( canvas , game_font , x , y , " difficulty: %s " , MENU_DIFFICULTY_TEXT ( Netgame . difficulty ) ) ;
2015-06-13 22:42:22 +00:00
y + = line_spacing ;
2017-08-13 20:38:31 +00:00
{
auto & plr = get_local_player ( ) ;
2018-05-19 23:21:42 +00:00
gr_printf ( canvas , game_font , x , y , " level time: %i:%02i:%02i " , plr . hours_level , f2i ( plr . time_level ) / 60 % 60 , f2i ( plr . time_level ) % 60 ) ;
2015-06-13 22:42:22 +00:00
y + = line_spacing ;
2018-05-19 23:21:42 +00:00
gr_printf ( canvas , game_font , x , y , " total time: %i:%02i:%02i " , plr . hours_total , f2i ( plr . time_total ) / 60 % 60 , f2i ( plr . time_total ) % 60 ) ;
2017-08-13 20:38:31 +00:00
}
2015-06-13 22:42:22 +00:00
y + = line_spacing ;
2007-09-08 11:11:41 +00:00
if ( Netgame . KillGoal )
2018-05-19 23:21:42 +00:00
gr_printf ( canvas , game_font , x , y , " Kill goal: %d " , Netgame . KillGoal * 5 ) ;
2007-09-08 11:11:41 +00:00
// player information (name, kills, ping, game efficiency)
2015-06-13 22:42:22 +00:00
y + = line_spacing * 2 ;
2018-05-19 23:21:42 +00:00
gr_string ( canvas , game_font , x , y , " player " ) ;
gr_string ( canvas , game_font , x + fspacx8 * 7 , y , ( ( Game_mode & GM_MULTI_COOP )
2016-07-25 03:48:08 +00:00
? " score "
2018-05-19 23:21:42 +00:00
: ( gr_string ( canvas , game_font , x + fspacx8 * 12 , y , " deaths " ) , " kills " )
2016-07-25 03:48:08 +00:00
) ) ;
2018-05-19 23:21:42 +00:00
gr_string ( canvas , game_font , x + fspacx8 * 18 , y , " ping " ) ;
gr_string ( canvas , game_font , x + fspacx8 * 23 , y , " efficiency " ) ;
2007-09-08 11:11:41 +00:00
// process players table
2017-08-13 20:38:31 +00:00
for ( unsigned i = 0 ; i < MAX_PLAYERS ; + + i )
2007-09-08 11:11:41 +00:00
{
2017-08-13 20:38:32 +00:00
auto & plr = * vcplayerptr ( i ) ;
2022-07-16 15:26:12 +00:00
if ( plr . connected = = player_connection_status : : disconnected )
2007-09-08 11:11:41 +00:00
continue ;
2007-09-26 21:57:03 +00:00
2015-06-13 22:42:22 +00:00
y + = line_spacing ;
2007-09-26 21:57:03 +00:00
2015-03-09 03:33:07 +00:00
const auto color = get_player_or_team_color ( i ) ;
2016-05-21 17:24:51 +00:00
auto & prgb = player_rgb [ color ] ;
2017-02-11 21:42:46 +00:00
gr_set_fontcolor ( canvas , BM_XRGB ( prgb . r , prgb . g , prgb . b ) , - 1 ) ;
2019-07-07 22:00:02 +00:00
gr_string ( canvas , game_font , x , y , plr . callsign ) ;
2007-09-08 11:11:41 +00:00
{
2017-08-13 20:38:31 +00:00
auto & plrobj = * vcobjptr ( plr . objnum ) ;
2016-11-12 18:10:07 +00:00
auto & player_info = plrobj . ctype . player_info ;
2016-07-25 03:48:08 +00:00
auto v = ( ( Game_mode & GM_MULTI_COOP )
2016-11-12 18:10:07 +00:00
? player_info . mission . score
2018-05-19 23:21:42 +00:00
: ( gr_printf ( canvas , game_font , x + fspacx8 * 12 , y , " %-6d " , player_info . net_killed_total ) , player_info . net_kills_total )
2016-07-25 03:48:08 +00:00
) ;
2018-05-19 23:21:42 +00:00
gr_printf ( canvas , game_font , x + fspacx8 * 7 , y , " %-6d " , v ) ;
2007-09-08 11:11:41 +00:00
}
2018-05-19 23:21:42 +00:00
gr_printf ( canvas , game_font , x + fspacx8 * 18 , y , " %-6d " , Netgame . players [ i ] . ping ) ;
2008-03-08 22:37:09 +00:00
if ( i ! = Player_num )
2018-05-19 23:21:42 +00:00
gr_printf ( canvas , game_font , x + fspacx8 * 23 , y , " %hu/%hu " , kill_matrix [ Player_num ] [ i ] , kill_matrix [ i ] [ Player_num ] ) ;
2007-09-08 11:11:41 +00:00
}
2015-06-13 22:42:22 +00:00
y + = ( line_spacing * 2 ) + ( line_spacing * ( MAX_PLAYERS - N_players ) ) ;
2007-09-08 11:11:41 +00:00
// printf team scores
if ( Game_mode & GM_TEAM )
{
2017-02-11 21:42:46 +00:00
gr_set_fontcolor ( canvas , 255 , - 1 ) ;
2018-05-19 23:21:42 +00:00
gr_string ( canvas , game_font , x , y , " team " ) ;
gr_string ( canvas , game_font , x + fspacx8 * 8 , y , " score " ) ;
2015-06-13 22:42:22 +00:00
y + = line_spacing ;
2017-02-11 21:42:46 +00:00
gr_set_fontcolor ( canvas , BM_XRGB ( player_rgb [ 0 ] . r , player_rgb [ 0 ] . g , player_rgb [ 0 ] . b ) , - 1 ) ;
2018-05-19 23:21:42 +00:00
gr_printf ( canvas , game_font , x , y , " %s: " , static_cast < const char * > ( Netgame . team_name [ 0 ] ) ) ;
gr_printf ( canvas , game_font , x + fspacx8 * 8 , y , " %i " , team_kills [ 0 ] ) ;
2015-06-13 22:42:22 +00:00
y + = line_spacing ;
2017-02-11 21:42:46 +00:00
gr_set_fontcolor ( canvas , BM_XRGB ( player_rgb [ 1 ] . r , player_rgb [ 1 ] . g , player_rgb [ 1 ] . b ) , - 1 ) ;
2018-05-19 23:21:42 +00:00
gr_printf ( canvas , game_font , x , y , " %s: " , static_cast < const char * > ( Netgame . team_name [ 1 ] ) ) ;
gr_printf ( canvas , game_font , x + fspacx8 * 8 , y , " %i " , team_kills [ 1 ] ) ;
2015-06-13 22:42:22 +00:00
y + = line_spacing * 2 ;
2007-09-08 11:11:41 +00:00
}
else
2015-06-13 22:42:22 +00:00
y + = line_spacing * 4 ;
2007-09-08 11:11:41 +00:00
2017-02-11 21:42:46 +00:00
gr_set_fontcolor ( canvas , 255 , - 1 ) ;
2007-09-08 11:11:41 +00:00
// additional information about game - hoard, ranking
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2013-08-11 16:03:47 +00:00
if ( game_mode_hoard ( ) )
2007-09-08 11:11:41 +00:00
{
2017-08-13 20:38:32 +00:00
if ( hoard_highest_record_stats . player > = Players . size ( ) )
2018-05-19 23:21:42 +00:00
gr_string ( canvas , game_font , 0x8000 , y , " There is no record yet for this level. " ) ;
2007-09-08 11:11:41 +00:00
else
2018-05-19 23:21:42 +00:00
gr_printf ( canvas , game_font , 0x8000 , y , " %s has the record at %d points. " , static_cast < const char * > ( vcplayerptr ( hoard_highest_record_stats . player ) - > callsign ) , hoard_highest_record_stats . points ) ;
2007-09-08 11:11:41 +00:00
}
2013-03-03 01:03:33 +00:00
else
# endif
if ( ! PlayerCfg . NoRankings )
2007-09-08 11:11:41 +00:00
{
2015-12-13 18:00:49 +00:00
const int ieff = ( PlayerCfg . NetlifeKills + PlayerCfg . NetlifeKilled < = 0 )
? 0
: static_cast < int > (
static_cast < float > ( PlayerCfg . NetlifeKills ) / (
static_cast < float > ( PlayerCfg . NetlifeKilled ) + static_cast < float > ( PlayerCfg . NetlifeKills )
) * 100.0
) ;
const unsigned eff = ieff < 0 ? 0 : static_cast < unsigned > ( ieff ) ;
2018-05-19 23:21:42 +00:00
gr_printf ( canvas , game_font , 0x8000 , y , " Your lifetime efficiency of %d%% (%d/%d) " , eff , PlayerCfg . NetlifeKills , PlayerCfg . NetlifeKilled ) ;
2015-06-13 22:42:22 +00:00
y + = line_spacing ;
2007-09-08 11:11:41 +00:00
if ( eff < 60 )
2018-05-19 23:21:42 +00:00
gr_printf ( canvas , game_font , 0x8000 , y , " is %s your ranking. " , eff_strings [ eff / 10 ] ) ;
2007-09-08 11:11:41 +00:00
else
2018-05-19 23:21:42 +00:00
gr_string ( canvas , game_font , 0x8000 , y , " is serving you well. " ) ;
2015-06-13 22:42:22 +00:00
y + = line_spacing ;
2018-05-19 23:21:42 +00:00
gr_printf ( canvas , game_font , 0x8000 , y , " your rank is: %s " , RankStrings [ GetMyNetRanking ( ) ] ) ;
2007-09-08 11:11:41 +00:00
}
}
2020-10-12 03:28:26 +00:00
}
2016-08-25 04:05:32 +00:00
}
2007-09-08 11:11:41 +00:00
2006-03-20 17:12:09 +00:00
# ifndef NDEBUG
fix Show_view_text_timer = - 1 ;
2020-10-12 03:28:26 +00:00
namespace {
2019-03-03 00:31:08 +00:00
static void draw_window_label ( object_array & Objects , grs_canvas & canvas )
2006-03-20 17:12:09 +00:00
{
2019-03-03 00:31:08 +00:00
auto & vcobjptridx = Objects . vcptridx ;
2006-03-20 17:12:09 +00:00
if ( Show_view_text_timer > 0 )
{
2013-09-02 23:21:13 +00:00
const char * viewer_name , * control_name , * viewer_id ;
2006-03-20 17:12:09 +00:00
Show_view_text_timer - = FrameTime ;
viewer_id = " " ;
switch ( Viewer - > type )
{
case OBJ_FIREBALL : viewer_name = " Fireball " ; break ;
case OBJ_ROBOT : viewer_name = " Robot " ;
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2022-07-09 13:39:29 +00:00
viewer_id = Robot_names [ get_robot_id ( * Viewer ) ] . data ( ) ;
2006-03-20 17:12:09 +00:00
# endif
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 " ;
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2022-07-09 13:39:29 +00:00
viewer_id = Powerup_names [ get_powerup_id ( * Viewer ) ] . data ( ) ;
2006-03-20 17:12:09 +00:00
# endif
break ;
case OBJ_DEBRIS : viewer_name = " Debris " ; break ;
case OBJ_CNTRLCEN : viewer_name = " Reactor " ; break ;
default : viewer_name = " Unknown " ; break ;
}
2020-08-10 03:45:13 +00:00
switch ( Viewer - > control_source ) {
2020-08-06 03:47:56 +00:00
case object : : control_type : : None : control_name = " Stopped " ; break ;
case object : : control_type : : ai : control_name = " AI " ; break ;
case object : : control_type : : flying : control_name = " Flying " ; break ;
case object : : control_type : : slew : control_name = " Slew " ; break ;
case object : : control_type : : flythrough : control_name = " Flythrough " ; break ;
case object : : control_type : : morph : control_name = " Morphing " ; break ;
2006-03-20 17:12:09 +00:00
default : control_name = " Unknown " ; break ;
}
2017-02-11 21:42:45 +00:00
gr_set_fontcolor ( canvas , BM_XRGB ( 31 , 0 , 0 ) , - 1 ) ;
2018-05-19 23:21:42 +00:00
auto & game_font = * GAME_FONT ;
2022-07-09 13:39:29 +00:00
gr_printf ( canvas , game_font , 0x8000 , ( SHEIGHT / 10 ) , " %hu: %s [%s] View - %s " , vcobjptridx ( Viewer ) . get_unchecked_index ( ) , viewer_name , viewer_id , control_name ) ;
2006-03-20 17:12:09 +00:00
}
}
2020-10-12 03:28:26 +00:00
}
2006-03-20 17:12:09 +00:00
# endif
2016-08-25 04:05:32 +00:00
namespace dsx {
2020-10-12 03:28:26 +00:00
namespace {
2017-02-11 21:42:45 +00:00
static void render_countdown_gauge ( grs_canvas & canvas )
2006-03-20 17:12:09 +00:00
{
2019-08-15 01:34:22 +00:00
auto & LevelUniqueControlCenterState = LevelUniqueObjectState . ControlCenterState ;
2019-08-15 01:34:22 +00:00
int Countdown_seconds_left ;
if ( ! Endlevel_sequence & & LevelUniqueControlCenterState . Control_center_destroyed & & ( Countdown_seconds_left = LevelUniqueControlCenterState . Countdown_seconds_left ) > - 1 )
2019-08-15 01:34:22 +00:00
{ // && (Countdown_seconds_left<127))
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
if ( ! is_D2_OEM & & ! is_MAC_SHARE & & ! is_SHAREWARE ) // no countdown on registered only
{
// On last level, we don't want a countdown.
2021-11-01 03:37:19 +00:00
if ( PLAYING_BUILTIN_MISSION & & Current_level_num = = Current_mission - > last_level )
2006-03-20 17:12:09 +00:00
{
if ( ! ( Game_mode & GM_MULTI ) )
return ;
if ( Game_mode & GM_MULTI_ROBOTS )
return ;
}
}
2013-03-03 01:03:33 +00:00
# endif
2017-02-11 21:42:45 +00:00
gr_set_fontcolor ( canvas , BM_XRGB ( 0 , 63 , 0 ) , - 1 ) ;
2018-05-19 23:21:42 +00:00
auto & game_font = * GAME_FONT ;
gr_printf ( canvas , game_font , 0x8000 , ( LINE_SPACING ( game_font , game_font ) * 6 ) + FSPACY ( 1 ) , " T-%d s " , Countdown_seconds_left ) ;
2006-03-20 17:12:09 +00:00
}
}
2022-07-09 13:39:29 +00:00
static void game_draw_hud_stuff ( const d_robot_info_array & Robot_info , grs_canvas & canvas , const control_info & Controls )
2006-03-20 17:12:09 +00:00
{
2019-03-03 00:31:08 +00:00
auto & Objects = LevelUniqueObjectState . Objects ;
auto & vmobjptr = Objects . vmptr ;
2013-02-21 00:20:26 +00:00
# ifndef NDEBUG
2019-03-03 00:31:08 +00:00
draw_window_label ( Objects , canvas ) ;
2013-02-21 00:20:26 +00:00
# endif
2006-03-20 17:12:09 +00:00
2017-03-11 19:56:22 +00:00
game_draw_multi_message ( canvas ) ;
2006-03-20 17:12:09 +00:00
2017-03-11 19:56:22 +00:00
game_draw_marker_message ( canvas ) ;
2006-03-20 17:12:09 +00:00
2022-02-12 18:57:12 +00:00
if ( ( Newdemo_state = = ND_STATE_PLAYBACK | | Newdemo_state = = ND_STATE_RECORDING ) & & PlayerCfg . CockpitMode [ 1 ] ! = cockpit_mode_t : : rear_view )
{
2008-02-24 14:41:27 +00:00
int y ;
2006-03-20 17:12:09 +00:00
2018-05-19 23:21:42 +00:00
auto & game_font = * GAME_FONT ;
2020-12-27 22:03:09 +00:00
gr_set_curfont ( canvas , game_font ) ;
2017-03-11 19:56:22 +00:00
gr_set_fontcolor ( canvas , BM_XRGB ( 27 , 0 , 0 ) , - 1 ) ;
2006-10-08 15:57:11 +00:00
2018-05-19 23:21:42 +00:00
y = canvas . cv_bitmap . bm_h - ( LINE_SPACING ( * canvas . cv_font , * GAME_FONT ) * 2 ) ;
2006-10-08 15:57:11 +00:00
2022-02-12 18:57:12 +00:00
if ( PlayerCfg . CockpitMode [ 1 ] = = cockpit_mode_t : : full_cockpit )
2017-03-11 19:56:22 +00:00
y = canvas . cv_bitmap . bm_h / 1.2 ;
2013-08-07 22:01:01 +00:00
if ( Newdemo_state = = ND_STATE_PLAYBACK ) {
if ( Newdemo_show_percentage ) {
2018-05-19 23:21:42 +00:00
gr_printf ( canvas , game_font , 0x8000 , y , " %s (%d%% %s) " , TXT_DEMO_PLAYBACK , newdemo_get_percent_done ( ) , TXT_DONE ) ;
2013-08-07 22:01:01 +00:00
}
} else {
2018-05-19 23:21:42 +00:00
gr_printf ( canvas , game_font , 0x8000 , y , " %s (%dK) " , TXT_DEMO_RECORDING , ( Newdemo_num_written / 1024 ) ) ;
2013-08-07 22:01:01 +00:00
}
2006-03-20 17:12:09 +00:00
}
2017-03-11 19:56:22 +00:00
render_countdown_gauge ( canvas ) ;
2006-03-20 17:12:09 +00:00
2022-02-12 18:57:12 +00:00
if ( CGameCfg . FPSIndicator & & PlayerCfg . CockpitMode [ 1 ] ! = cockpit_mode_t : : rear_view )
2017-03-11 19:56:22 +00:00
show_framerate ( canvas ) ;
2006-03-20 17:12:09 +00:00
2021-09-12 16:20:52 +00:00
auto previous_game_mode = Game_mode ;
2009-11-30 14:59:37 +00:00
if ( Newdemo_state = = ND_STATE_PLAYBACK )
Game_mode = Newdemo_game_mode ;
2016-12-10 17:51:10 +00:00
auto & plrobj = get_local_plrobj ( ) ;
2022-07-09 13:39:29 +00:00
draw_hud ( Robot_info , canvas , plrobj , Controls , Game_mode ) ;
2006-03-20 17:12:09 +00:00
2009-11-30 14:59:37 +00:00
if ( Newdemo_state = = ND_STATE_PLAYBACK )
2021-09-12 16:20:52 +00:00
Game_mode = previous_game_mode ;
2009-11-30 14:59:37 +00:00
2015-12-15 04:09:35 +00:00
if ( Player_dead_state ! = player_dead_state : : no )
2017-03-11 19:56:22 +00:00
player_dead_message ( canvas ) ;
2006-03-20 17:12:09 +00:00
}
2020-10-12 03:28:26 +00:00
}
2015-12-22 04:18:50 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
ubyte RenderingType = 0 ;
ubyte DemoDoingRight = 0 , DemoDoingLeft = 0 ;
2020-10-12 03:28:26 +00:00
namespace {
2021-01-17 22:23:23 +00:00
constexpr weapon_box_user DemoWBUType [ ] = { weapon_box_user : : weapon , weapon_box_user : : guided , weapon_box_user : : missile , weapon_box_user : : rear , weapon_box_user : : escort , weapon_box_user : : marker , weapon_box_user : : weapon } ;
2016-12-20 05:17:33 +00:00
constexpr char DemoRearCheck [ ] = { 0 , 0 , 0 , 1 , 0 , 0 , 0 } ;
2016-07-16 16:52:04 +00:00
constexpr char DemoExtraMessage [ ] [ 10 ] = {
2013-11-28 00:21:36 +00:00
" PLAYER " ,
" GUIDED " ,
" MISSILE " ,
" REAR " ,
" GUIDE-BOT " ,
" MARKER " ,
" SHIP "
} ;
2006-03-20 17:12:09 +00:00
2012-07-08 20:23:01 +00:00
static const char * get_missile_name ( const unsigned laser_type )
{
switch ( laser_type )
{
2015-12-03 03:26:49 +00:00
case weapon_id_type : : CONCUSSION_ID :
2012-07-08 20:23:01 +00:00
return " CONCUSSION " ;
2015-12-03 03:26:49 +00:00
case weapon_id_type : : HOMING_ID :
2012-07-08 20:23:01 +00:00
return " HOMING " ;
2015-12-03 03:26:49 +00:00
case weapon_id_type : : SMART_ID :
2012-07-08 20:23:01 +00:00
return " SMART " ;
2015-12-03 03:26:49 +00:00
case weapon_id_type : : MEGA_ID :
2012-07-08 20:23:01 +00:00
return " MEGA " ;
2015-12-03 03:26:49 +00:00
case weapon_id_type : : FLASH_ID :
2012-07-08 20:23:01 +00:00
return " FLASH " ;
2015-12-03 03:26:49 +00:00
case weapon_id_type : : MERCURY_ID :
2012-07-08 20:23:01 +00:00
return " MERCURY " ;
2015-12-03 03:26:49 +00:00
case weapon_id_type : : EARTHSHAKER_ID :
2012-07-08 20:23:01 +00:00
return " SHAKER " ;
default :
return " MISSILE " ; // Bad!
}
}
2016-07-06 01:54:25 +00:00
static void set_missile_viewer ( object & o )
2015-02-14 22:48:28 +00:00
{
2016-07-06 01:54:25 +00:00
Missile_viewer = & o ;
Missile_viewer_sig = o . signature ;
2015-02-14 22:48:28 +00:00
}
2016-07-04 12:31:30 +00:00
static int clear_missile_viewer ( )
2015-02-14 22:48:28 +00:00
{
2016-07-04 12:31:30 +00:00
if ( ! Missile_viewer )
return 0 ;
Missile_viewer = nullptr ;
return 1 ;
2015-02-14 22:48:28 +00:00
}
2021-06-28 03:37:51 +00:00
[[nodiscard]]
2015-12-03 03:26:48 +00:00
static bool is_viewable_missile ( weapon_id_type laser_type )
2015-02-14 22:48:28 +00:00
{
2015-12-03 03:26:49 +00:00
return laser_type = = weapon_id_type : : CONCUSSION_ID | |
laser_type = = weapon_id_type : : HOMING_ID | |
laser_type = = weapon_id_type : : SMART_ID | |
laser_type = = weapon_id_type : : MEGA_ID | |
laser_type = = weapon_id_type : : FLASH_ID | |
laser_type = = weapon_id_type : : GUIDEDMISS_ID | |
laser_type = = weapon_id_type : : MERCURY_ID | |
laser_type = = weapon_id_type : : EARTHSHAKER_ID ;
2015-02-14 22:48:28 +00:00
}
static bool choose_missile_viewer ( )
{
2019-03-03 00:31:08 +00:00
auto & Objects = LevelUniqueObjectState . Objects ;
auto & vcobjptr = Objects . vcptr ;
auto & vmobjptr = Objects . vmptr ;
2016-07-06 01:54:25 +00:00
const auto MissileViewEnabled = PlayerCfg . MissileViewEnabled ;
if ( unlikely ( MissileViewEnabled = = MissileViewMode : : None ) )
2015-02-14 22:48:28 +00:00
return false ;
const auto need_new_missile_viewer = [ ] {
if ( ! Missile_viewer )
return true ;
if ( Missile_viewer - > type ! = OBJ_WEAPON )
return true ;
if ( Missile_viewer - > signature ! = Missile_viewer_sig )
return true ;
/* No check on parent here. Missile_viewer is cleared if needed
* when a missile is fired .
*/
return false ;
} ;
if ( likely ( ! need_new_missile_viewer ( ) ) )
/* Valid viewer already set */
return true ;
2016-07-06 01:54:25 +00:00
const auto better_match = [ ] ( object * const a , object & b ) {
if ( ! a )
2015-02-14 22:48:28 +00:00
return true ;
2016-07-06 01:54:25 +00:00
return a - > lifeleft < b . lifeleft ;
2015-02-14 22:48:28 +00:00
} ;
/* Find new missile */
2016-07-06 01:54:25 +00:00
object * local_player_missile = nullptr , * other_player_missile = nullptr ;
2015-02-14 22:48:28 +00:00
const auto game_mode = Game_mode ;
2016-07-06 01:54:25 +00:00
const auto local_player_objnum = get_local_player ( ) . objnum ;
2017-06-10 03:31:02 +00:00
range_for ( object & o , vmobjptr )
2015-02-14 22:48:28 +00:00
{
2016-07-06 01:54:25 +00:00
if ( o . type ! = OBJ_WEAPON )
2015-02-14 22:48:28 +00:00
continue ;
2016-07-06 01:54:25 +00:00
if ( o . ctype . laser_info . parent_type ! = OBJ_PLAYER )
2015-02-14 22:48:28 +00:00
continue ;
const auto laser_type = get_weapon_id ( o ) ;
if ( ! is_viewable_missile ( laser_type ) )
continue ;
2016-07-06 01:54:25 +00:00
if ( o . ctype . laser_info . parent_num = = local_player_objnum )
2015-02-14 22:48:28 +00:00
{
if ( ! better_match ( local_player_missile , o ) )
continue ;
2016-07-06 01:54:25 +00:00
local_player_missile = & o ;
2015-02-14 22:48:28 +00:00
}
else
{
2016-07-06 01:54:25 +00:00
if ( MissileViewEnabled ! = MissileViewMode : : EnabledSelfAndAllies )
continue ;
2015-02-14 22:48:28 +00:00
if ( ! better_match ( other_player_missile , o ) )
continue ;
2015-09-26 18:28:49 +00:00
else if ( game_mode & GM_MULTI_COOP )
2015-02-14 22:48:28 +00:00
{
/* Always allow missiles of other players */
}
else if ( game_mode & GM_TEAM )
{
/* Allow missiles from same team */
2016-07-06 01:54:25 +00:00
if ( get_team ( Player_num ) ! = get_team ( get_player_id ( vcobjptr ( o . ctype . laser_info . parent_num ) ) ) )
2015-02-14 22:48:28 +00:00
continue ;
}
else
continue ;
2016-07-06 01:54:25 +00:00
other_player_missile = & o ;
2015-02-14 22:48:28 +00:00
}
}
2016-07-06 01:54:25 +00:00
object * o ;
if ( ( o = local_player_missile ) ! = nullptr | |
( o = other_player_missile ) ! = nullptr )
set_missile_viewer ( * o ) ;
2015-02-14 22:48:28 +00:00
else
return false ;
return true ;
}
2021-09-12 16:20:52 +00:00
static void show_one_extra_view ( grs_canvas & canvas , const gauge_inset_window_view w ) ;
static void show_extra_views ( grs_canvas & canvas )
2006-03-20 17:12:09 +00:00
{
2019-03-03 00:31:08 +00:00
auto & Objects = LevelUniqueObjectState . Objects ;
auto & vmobjptr = Objects . vmptr ;
2006-03-20 17:12:09 +00:00
int did_missile_view = 0 ;
int save_newdemo_state = Newdemo_state ;
2008-03-08 22:37:09 +00:00
if ( Newdemo_state = = ND_STATE_PLAYBACK )
{
if ( DemoDoLeft )
{
DemoDoingLeft = DemoDoLeft ;
2006-03-20 17:12:09 +00:00
2008-03-08 22:37:09 +00:00
if ( DemoDoLeft = = 3 )
2021-09-12 16:20:52 +00:00
do_cockpit_window_view ( canvas , gauge_inset_window_view : : primary , * ConsoleObject , 1 , weapon_box_user : : rear , " REAR " ) ;
2008-03-08 22:37:09 +00:00
else
2021-09-12 16:20:52 +00:00
do_cockpit_window_view ( canvas , gauge_inset_window_view : : primary , DemoLeftExtra , DemoRearCheck [ DemoDoLeft ] , DemoWBUType [ DemoDoLeft ] , DemoExtraMessage [ DemoDoLeft ] , DemoDoLeft = = 1 ? & get_local_plrobj ( ) . ctype . player_info : nullptr ) ;
2008-03-08 22:37:09 +00:00
}
else
2021-01-17 22:23:23 +00:00
do_cockpit_window_view ( gauge_inset_window_view : : primary , weapon_box_user : : weapon ) ;
2008-03-08 22:37:09 +00:00
if ( DemoDoRight )
2006-03-20 17:12:09 +00:00
{
2008-03-08 22:37:09 +00:00
DemoDoingRight = DemoDoRight ;
if ( DemoDoRight = = 3 )
2021-09-12 16:20:52 +00:00
do_cockpit_window_view ( canvas , gauge_inset_window_view : : secondary , * ConsoleObject , 1 , weapon_box_user : : rear , " REAR " ) ;
2008-03-08 22:37:09 +00:00
else
2021-09-12 16:20:52 +00:00
do_cockpit_window_view ( canvas , gauge_inset_window_view : : secondary , DemoRightExtra , DemoRearCheck [ DemoDoRight ] , DemoWBUType [ DemoDoRight ] , DemoExtraMessage [ DemoDoRight ] , DemoDoLeft = = 1 ? & get_local_plrobj ( ) . ctype . player_info : nullptr ) ;
2008-03-08 22:37:09 +00:00
}
else
2021-01-17 22:23:23 +00:00
do_cockpit_window_view ( gauge_inset_window_view : : secondary , weapon_box_user : : weapon ) ;
2006-03-20 17:12:09 +00:00
2008-03-08 22:37:09 +00:00
DemoDoLeft = DemoDoRight = 0 ;
2006-03-20 17:12:09 +00:00
DemoDoingLeft = DemoDoingRight = 0 ;
2008-03-08 22:37:09 +00:00
return ;
}
2006-03-20 17:12:09 +00:00
2018-12-30 00:43:57 +00:00
const auto & & gimobj = LevelUniqueObjectState . Guided_missile . get_player_active_guided_missile ( vmobjptr , Player_num ) ;
2018-10-08 03:58:48 +00:00
if ( gimobj ! = nullptr )
2008-03-08 22:37:09 +00:00
{
2008-04-13 00:28:36 +00:00
if ( PlayerCfg . GuidedInBigWindow )
2008-03-08 22:37:09 +00:00
{
2006-03-20 17:12:09 +00:00
RenderingType = 6 + ( 1 < < 4 ) ;
2021-09-12 16:20:52 +00:00
do_cockpit_window_view ( canvas , gauge_inset_window_view : : secondary , * Viewer , 0 , weapon_box_user : : missile , " SHIP " ) ;
2008-03-08 22:37:09 +00:00
}
2006-03-20 17:12:09 +00:00
else
2008-03-08 22:37:09 +00:00
{
2006-03-20 17:12:09 +00:00
RenderingType = 1 + ( 1 < < 4 ) ;
2017-02-11 21:42:31 +00:00
auto & player_info = get_local_plrobj ( ) . ctype . player_info ;
2021-09-12 16:20:52 +00:00
do_cockpit_window_view ( canvas , gauge_inset_window_view : : secondary , * gimobj , 0 , weapon_box_user : : guided , " GUIDED " , & player_info ) ;
2008-03-08 22:37:09 +00:00
}
2006-03-20 17:12:09 +00:00
did_missile_view = 1 ;
}
else {
2015-02-14 22:48:28 +00:00
if ( choose_missile_viewer ( ) )
//do missile view
{
2006-03-20 17:12:09 +00:00
RenderingType = 2 + ( 1 < < 4 ) ;
2021-09-12 16:20:52 +00:00
do_cockpit_window_view ( canvas , gauge_inset_window_view : : secondary , * Missile_viewer , 0 , weapon_box_user : : missile , get_missile_name ( get_weapon_id ( * Missile_viewer ) ) ) ;
2006-03-20 17:12:09 +00:00
did_missile_view = 1 ;
}
else {
2016-07-04 12:31:30 +00:00
if ( clear_missile_viewer ( ) )
2021-01-17 22:23:23 +00:00
do_cockpit_window_view ( gauge_inset_window_view : : secondary , weapon_box_user : : post_missile_static ) ;
2016-07-04 12:31:30 +00:00
RenderingType = 255 ;
2006-03-20 17:12:09 +00:00
}
}
2021-09-12 16:20:52 +00:00
show_one_extra_view ( canvas , gauge_inset_window_view : : primary ) ;
2020-08-10 03:45:13 +00:00
if ( ! did_missile_view ) //if showing missile view in right window, can't show anything else
2021-09-12 16:20:52 +00:00
show_one_extra_view ( canvas , gauge_inset_window_view : : secondary ) ;
2012-07-15 21:55:33 +00:00
RenderingType = 0 ;
Newdemo_state = save_newdemo_state ;
}
2021-09-12 16:20:52 +00:00
static void show_one_extra_view ( grs_canvas & canvas , const gauge_inset_window_view w )
2012-07-15 21:55:33 +00:00
{
2019-03-03 00:31:08 +00:00
auto & Objects = LevelUniqueObjectState . Objects ;
auto & vcobjptr = Objects . vcptr ;
auto & vmobjptridx = Objects . vmptridx ;
2018-12-30 00:43:59 +00:00
auto & Robot_info = LevelSharedRobotInfoState . Robot_info ;
2006-03-20 17:12:09 +00:00
//show special views if selected
2008-04-13 00:28:36 +00:00
switch ( PlayerCfg . Cockpit3DView [ w ] ) {
2021-01-25 00:45:07 +00:00
case cockpit_3d_view : : None :
2006-03-20 17:12:09 +00:00
RenderingType = 255 ;
2021-01-17 22:23:23 +00:00
do_cockpit_window_view ( w , weapon_box_user : : weapon ) ;
2006-03-20 17:12:09 +00:00
break ;
2021-01-25 00:45:07 +00:00
case cockpit_3d_view : : Rear :
2020-08-10 03:45:13 +00:00
RenderingType = 3 + ( static_cast < unsigned > ( w ) < < 4 ) ;
2016-07-25 03:48:09 +00:00
{
int rear_view_flag ;
const char * label ;
if ( Rear_view ) //if big window is rear view, show front here
{
rear_view_flag = 0 ;
label = " FRONT " ;
}
else //show normal rear view
{
rear_view_flag = 1 ;
label = " REAR " ;
}
2021-09-12 16:20:52 +00:00
do_cockpit_window_view ( canvas , w , * ConsoleObject , rear_view_flag , weapon_box_user : : rear , label ) ;
2006-03-20 17:12:09 +00:00
}
break ;
2021-01-25 00:45:07 +00:00
case cockpit_3d_view : : Escort : {
2018-09-19 02:13:29 +00:00
const auto & & buddy = find_escort ( vmobjptridx , Robot_info ) ;
2014-10-25 15:19:20 +00:00
if ( buddy = = object_none ) {
2021-01-17 22:23:23 +00:00
do_cockpit_window_view ( w , weapon_box_user : : weapon ) ;
2021-01-25 00:45:07 +00:00
PlayerCfg . Cockpit3DView [ w ] = cockpit_3d_view : : None ;
2006-03-20 17:12:09 +00:00
}
else {
2020-08-10 03:45:13 +00:00
RenderingType = 4 + ( static_cast < unsigned > ( w ) < < 4 ) ;
2021-09-12 16:20:52 +00:00
do_cockpit_window_view ( canvas , w , * buddy , 0 , weapon_box_user : : escort , PlayerCfg . GuidebotName ) ;
2006-03-20 17:12:09 +00:00
}
break ;
}
2021-01-25 00:45:07 +00:00
case cockpit_3d_view : : Coop : {
2017-08-13 20:38:31 +00:00
const auto player = Coop_view_player [ w ] ;
2006-03-20 17:12:09 +00:00
RenderingType = 255 ; // don't handle coop stuff
2022-07-16 15:26:12 +00:00
if ( player < Players . size ( ) & & vcplayerptr ( player ) - > connected ! = player_connection_status : : disconnected & & ( ( Game_mode & GM_MULTI_COOP ) | | ( ( Game_mode & GM_TEAM ) & & ( get_team ( player ) = = get_team ( Player_num ) ) ) ) )
2017-08-13 20:38:32 +00:00
{
auto & p = * vcplayerptr ( player ) ;
2021-09-12 16:20:52 +00:00
do_cockpit_window_view ( canvas , w , * vcobjptr ( p . objnum ) , 0 , weapon_box_user : : coop , p . callsign ) ;
2017-08-13 20:38:32 +00:00
}
2006-03-20 17:12:09 +00:00
else {
2021-01-17 22:23:23 +00:00
do_cockpit_window_view ( w , weapon_box_user : : weapon ) ;
2021-01-25 00:45:07 +00:00
PlayerCfg . Cockpit3DView [ w ] = cockpit_3d_view : : None ;
2006-03-20 17:12:09 +00:00
}
break ;
}
2021-01-25 00:45:07 +00:00
case cockpit_3d_view : : Marker : {
2006-03-20 17:12:09 +00:00
char label [ 10 ] ;
2020-08-10 03:45:13 +00:00
RenderingType = 5 + ( static_cast < unsigned > ( w ) < < 4 ) ;
2017-06-10 03:31:03 +00:00
const auto mvn = Marker_viewer_num [ w ] ;
2020-07-22 03:11:18 +00:00
if ( ! MarkerState . imobjidx . valid_index ( mvn ) )
2017-06-10 03:31:03 +00:00
{
2021-01-25 00:45:07 +00:00
PlayerCfg . Cockpit3DView [ w ] = cockpit_3d_view : : None ;
2017-06-10 03:31:03 +00:00
break ;
}
2018-03-10 18:32:02 +00:00
const auto mo = MarkerState . imobjidx [ mvn ] ;
2017-06-10 03:31:03 +00:00
if ( mo = = object_none )
{
2021-01-25 00:45:07 +00:00
PlayerCfg . Cockpit3DView [ w ] = cockpit_3d_view : : None ;
2006-03-20 17:12:09 +00:00
break ;
}
2020-07-22 03:11:18 +00:00
const auto displayed_marker_id = static_cast < unsigned > ( mvn ) + 1 ;
snprintf ( label , sizeof ( label ) , " Marker %u " , displayed_marker_id ) ;
2021-09-12 16:20:52 +00:00
do_cockpit_window_view ( canvas , w , * vcobjptr ( mo ) , 0 , weapon_box_user : : marker , label ) ;
2006-03-20 17:12:09 +00:00
break ;
}
default :
Int3 ( ) ; //invalid window type
}
}
2020-10-12 03:28:26 +00:00
}
2006-03-20 17:12:09 +00:00
int BigWindowSwitch = 0 ;
2013-03-03 01:03:33 +00:00
# endif
2015-12-22 04:18:50 +00:00
2006-03-20 17:12:09 +00:00
//render a frame for the game
2022-07-09 13:39:29 +00:00
void game_render_frame_mono ( const d_robot_info_array & Robot_info , const control_info & Controls )
2006-03-20 17:12:09 +00:00
{
2021-03-18 01:01:03 +00:00
int no_draw_hud = 0 ;
2013-02-21 00:20:26 +00:00
2017-11-05 20:49:08 +00:00
gr_set_current_canvas ( Screen_3d_window ) ;
2021-09-12 16:20:52 +00:00
{
auto & canvas = * grd_curcanv ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2019-03-03 00:31:08 +00:00
auto & Objects = LevelUniqueObjectState . Objects ;
auto & vmobjptr = Objects . vmptr ;
2018-10-08 03:58:48 +00:00
if ( const auto & & gimobj = (
PlayerCfg . GuidedInBigWindow
2018-12-30 00:43:57 +00:00
? LevelUniqueObjectState . Guided_missile . get_player_active_guided_missile ( LevelUniqueObjectState . get_objects ( ) . vmptr , Player_num )
2018-10-08 03:58:48 +00:00
: nullptr ) )
2015-11-27 03:56:13 +00:00
{
2018-09-25 03:44:09 +00:00
const auto viewer_save = Viewer ;
2006-03-20 17:12:09 +00:00
2022-02-12 18:57:12 +00:00
if ( PlayerCfg . CockpitMode [ 1 ] = = cockpit_mode_t : : full_cockpit | | PlayerCfg . CockpitMode [ 1 ] = = cockpit_mode_t : : rear_view )
2008-03-08 22:37:09 +00:00
{
2006-03-20 17:12:09 +00:00
BigWindowSwitch = 1 ;
force_cockpit_redraw = 1 ;
2022-02-12 18:57:12 +00:00
PlayerCfg . CockpitMode [ 1 ] = cockpit_mode_t : : status_bar ;
2006-03-20 17:12:09 +00:00
return ;
2008-03-08 22:37:09 +00:00
}
2018-10-08 03:58:48 +00:00
Viewer = gimobj ;
2006-03-20 17:12:09 +00:00
2014-12-18 04:12:38 +00:00
window_rendered_data window ;
2022-10-09 23:15:20 +00:00
# if DXX_USE_STEREOSCOPIC_RENDER
2021-09-12 16:20:52 +00:00
if ( VR_stereo ! = StereoFormat : : None )
{
2021-09-12 16:20:52 +00:00
render_frame ( canvas , - VR_eye_width , window ) ;
render_frame ( canvas , + VR_eye_width , window ) ;
2021-03-10 18:51:32 +00:00
}
else
2022-10-09 23:15:20 +00:00
# endif
{
2021-09-12 16:20:52 +00:00
render_frame ( canvas , 0 , window ) ;
2022-10-09 23:15:20 +00:00
}
2006-03-20 17:12:09 +00:00
2018-09-25 03:44:09 +00:00
wake_up_rendered_objects ( * Viewer , window ) ;
2022-07-09 13:39:29 +00:00
show_HUD_names ( Robot_info , canvas , Game_mode ) ;
2011-07-09 11:25:11 +00:00
2008-03-08 22:37:09 +00:00
Viewer = viewer_save ;
2006-03-20 17:12:09 +00:00
2018-05-19 23:21:42 +00:00
auto & game_font = * GAME_FONT ;
2021-09-12 16:20:52 +00:00
gr_set_fontcolor ( canvas , BM_XRGB ( 27 , 0 , 0 ) , - 1 ) ;
2006-03-20 17:12:09 +00:00
2021-09-12 16:20:52 +00:00
gr_string ( canvas , game_font , 0x8000 , FSPACY ( 1 ) , " Guided Missile View " ) ;
2008-03-08 22:37:09 +00:00
2016-12-11 01:56:43 +00:00
auto & player_info = get_local_plrobj ( ) . ctype . player_info ;
2021-09-12 16:20:52 +00:00
show_reticle ( canvas , player_info , RET_TYPE_CROSS_V1 , 0 ) ;
2006-03-20 17:12:09 +00:00
2021-09-12 16:20:52 +00:00
HUD_render_message_frame ( canvas ) ;
2006-03-20 17:12:09 +00:00
no_draw_hud = 1 ;
}
else
2013-03-03 01:03:33 +00:00
# endif
2008-03-08 22:37:09 +00:00
{
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
if ( BigWindowSwitch )
2008-03-08 22:37:09 +00:00
{
force_cockpit_redraw = 1 ;
2022-02-12 18:57:12 +00:00
PlayerCfg . CockpitMode [ 1 ] = ( Rear_view ? cockpit_mode_t : : rear_view : cockpit_mode_t : : full_cockpit ) ;
2008-03-08 22:37:09 +00:00
BigWindowSwitch = 0 ;
2006-03-20 17:12:09 +00:00
return ;
2008-03-08 22:37:09 +00:00
}
2013-03-03 01:03:33 +00:00
# endif
2014-12-18 04:12:38 +00:00
window_rendered_data window ;
2022-10-09 23:15:20 +00:00
# if DXX_USE_STEREOSCOPIC_RENDER
2021-09-12 16:20:52 +00:00
if ( VR_stereo ! = StereoFormat : : None )
{
2021-09-12 16:20:52 +00:00
render_frame ( canvas , - VR_eye_width , window ) ;
render_frame ( canvas , + VR_eye_width , window ) ;
2021-03-10 18:51:32 +00:00
}
else
2022-10-09 23:15:20 +00:00
# endif
{
2021-09-12 16:20:52 +00:00
render_frame ( canvas , 0 , window ) ;
2022-10-09 23:15:20 +00:00
}
2021-09-12 16:20:52 +00:00
}
2008-03-08 22:37:09 +00:00
}
2021-09-12 16:20:52 +00:00
gr_set_default_canvas ( ) ;
2021-09-12 16:20:52 +00:00
{
auto & canvas = * grd_curcanv ;
update_cockpits ( canvas ) ;
2006-03-20 17:12:09 +00:00
2022-02-12 18:57:12 +00:00
if ( PlayerCfg . CockpitMode [ 1 ] = = cockpit_mode_t : : full_cockpit | | PlayerCfg . CockpitMode [ 1 ] = = cockpit_mode_t : : status_bar )
2021-09-12 16:20:52 +00:00
render_gauges ( canvas , Newdemo_state = = ND_STATE_PLAYBACK ? Newdemo_game_mode : Game_mode ) ;
}
2013-02-21 00:20:26 +00:00
2021-03-17 23:30:31 +00:00
if ( ! no_draw_hud ) {
2022-10-09 23:15:20 +00:00
# if DXX_USE_STEREOSCOPIC_RENDER
2021-09-12 16:20:52 +00:00
if ( VR_stereo ! = StereoFormat : : None )
{
2022-07-09 13:39:29 +00:00
game_draw_hud_stuff ( Robot_info , VR_hud_left , Controls ) ;
game_draw_hud_stuff ( Robot_info , VR_hud_right , Controls ) ;
2021-03-17 23:30:31 +00:00
}
else
2022-10-09 23:15:20 +00:00
# endif
{
2022-07-09 13:39:29 +00:00
game_draw_hud_stuff ( Robot_info , Screen_3d_window , Controls ) ;
2022-10-09 23:15:20 +00:00
}
2021-03-17 23:30:31 +00:00
}
2008-02-24 14:41:27 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2017-11-05 20:49:08 +00:00
gr_set_default_canvas ( ) ;
2021-09-12 16:20:52 +00:00
show_extra_views ( * grd_curcanv ) ; //missile view, buddy bot, etc.
2013-03-03 01:03:33 +00:00
# endif
2011-05-26 13:57:02 +00:00
2013-02-21 00:20:26 +00:00
if ( netplayerinfo_on & & Game_mode & GM_MULTI )
2021-09-12 16:20:52 +00:00
{
gr_set_default_canvas ( ) ;
show_netplayerinfo ( * grd_curcanv ) ;
}
2006-03-20 17:12:09 +00:00
}
2015-12-22 04:18:50 +00:00
}
2006-03-20 17:12:09 +00:00
void toggle_cockpit ( )
{
2022-10-09 23:15:20 +00:00
if ( Rear_view | | Player_dead_state ! = player_dead_state : : no )
2008-02-24 14:41:27 +00:00
return ;
2022-10-09 23:15:20 +00:00
# if DXX_USE_STEREOSCOPIC_RENDER
if ( VR_stereo ! = StereoFormat : : None )
return ;
# endif
2008-02-24 14:41:27 +00:00
2022-02-12 18:57:12 +00:00
auto new_mode = cockpit_mode_t : : full_screen ;
2010-01-28 00:04:29 +00:00
switch ( PlayerCfg . CockpitMode [ 1 ] )
2007-06-14 20:52:14 +00:00
{
2022-02-12 18:57:12 +00:00
case cockpit_mode_t : : full_cockpit :
new_mode = cockpit_mode_t : : status_bar ;
2006-03-20 17:12:09 +00:00
break ;
2022-02-12 18:57:12 +00:00
case cockpit_mode_t : : status_bar :
new_mode = cockpit_mode_t : : full_screen ;
2007-06-14 20:52:14 +00:00
break ;
2022-02-12 18:57:12 +00:00
case cockpit_mode_t : : full_screen :
new_mode = cockpit_mode_t : : full_cockpit ;
2006-03-20 17:12:09 +00:00
break ;
2022-02-12 18:57:12 +00:00
case cockpit_mode_t : : rear_view :
case cockpit_mode_t : : letterbox :
2012-07-15 03:51:54 +00:00
break ;
2006-03-20 17:12:09 +00:00
}
select_cockpit ( new_mode ) ;
HUD_clear_messages ( ) ;
2010-01-28 00:04:29 +00:00
PlayerCfg . CockpitMode [ 0 ] = new_mode ;
2006-03-20 17:12:09 +00:00
write_player_file ( ) ;
}
2015-12-22 04:18:50 +00:00
namespace dsx {
2020-10-12 03:28:26 +00:00
namespace {
2008-10-28 13:28:10 +00:00
2006-03-20 17:12:09 +00:00
// This actually renders the new cockpit onto the screen.
2021-09-12 16:20:52 +00:00
static void update_cockpits ( grs_canvas & canvas )
2006-03-20 17:12:09 +00:00
{
2007-06-10 16:21:53 +00:00
grs_bitmap * bm ;
2022-02-12 18:57:12 +00:00
const auto raw_cockpit_mode = PlayerCfg . CockpitMode [ 1 ] ;
auto mode =
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2022-02-12 18:57:12 +00:00
HIRESMODE
? static_cast < cockpit_mode_t > ( underlying_value ( raw_cockpit_mode ) + ( Num_cockpits / 2 ) )
:
2013-03-03 01:03:33 +00:00
# endif
2022-02-12 18:57:12 +00:00
raw_cockpit_mode ;
2007-06-10 16:21:53 +00:00
2010-01-28 00:04:29 +00:00
switch ( PlayerCfg . CockpitMode [ 1 ] ) {
2022-02-12 18:57:12 +00:00
case cockpit_mode_t : : full_cockpit :
case cockpit_mode_t : : rear_view :
2013-08-16 23:07:08 +00:00
PIGGY_PAGE_IN ( cockpit_bitmap [ mode ] ) ;
bm = & GameBitmaps [ cockpit_bitmap [ mode ] . index ] ;
2016-09-24 18:06:11 +00:00
# if DXX_USE_OGL
2021-11-01 03:37:18 +00:00
ogl_ubitmapm_cs ( canvas , 0 , 0 , opengl_bitmap_use_dst_canvas , opengl_bitmap_use_dst_canvas , * bm , 255 ) ;
2007-10-05 23:47:16 +00:00
# else
2021-09-12 16:20:52 +00:00
gr_ubitmapm ( canvas , 0 , 0 , * bm ) ;
2006-03-20 17:12:09 +00:00
# endif
2007-06-10 16:21:53 +00:00
break ;
2022-02-12 18:57:12 +00:00
case cockpit_mode_t : : full_screen :
2007-06-10 16:21:53 +00:00
break ;
2022-02-12 18:57:12 +00:00
case cockpit_mode_t : : status_bar :
2013-08-16 23:07:08 +00:00
PIGGY_PAGE_IN ( cockpit_bitmap [ mode ] ) ;
bm = & GameBitmaps [ cockpit_bitmap [ mode ] . index ] ;
2016-09-24 18:06:11 +00:00
# if DXX_USE_OGL
2021-11-01 03:37:18 +00:00
ogl_ubitmapm_cs ( canvas , 0 , ( HIRESMODE ? ( SHEIGHT * 2 ) / 2.6 : ( SHEIGHT * 2 ) / 2.72 ) , opengl_bitmap_use_dst_canvas , ( static_cast < int > ( static_cast < double > ( bm - > bm_h ) * ( HIRESMODE ? static_cast < double > ( SHEIGHT ) / 480 : static_cast < double > ( SHEIGHT ) / 200 ) + 0.5 ) ) , * bm , 255 ) ;
2006-03-20 17:12:09 +00:00
# else
2021-09-12 16:20:52 +00:00
gr_ubitmapm ( canvas , 0 , SHEIGHT - bm - > bm_h , * bm ) ;
2006-03-20 17:12:09 +00:00
# endif
2007-06-10 16:21:53 +00:00
break ;
2022-02-12 18:57:12 +00:00
case cockpit_mode_t : : letterbox :
2007-06-10 16:21:53 +00:00
break ;
2006-03-20 17:12:09 +00:00
}
2010-01-28 00:04:29 +00:00
if ( PlayerCfg . CockpitMode [ 1 ] ! = last_drawn_cockpit )
last_drawn_cockpit = PlayerCfg . CockpitMode [ 1 ] ;
2006-03-20 17:12:09 +00:00
else
return ;
2022-02-12 18:57:12 +00:00
if ( PlayerCfg . CockpitMode [ 1 ] = = cockpit_mode_t : : full_cockpit | | PlayerCfg . CockpitMode [ 1 ] = = cockpit_mode_t : : status_bar )
2006-03-20 17:12:09 +00:00
init_gauges ( ) ;
}
2015-12-22 04:18:50 +00:00
}
2022-07-09 13:39:29 +00:00
void game_render_frame ( const d_robot_info_array & Robot_info , const control_info & Controls )
2006-03-20 17:12:09 +00:00
{
2019-03-03 00:31:08 +00:00
auto & Objects = LevelUniqueObjectState . Objects ;
auto & vmobjptr = Objects . vmptr ;
2006-03-20 17:12:09 +00:00
set_screen_mode ( SCREEN_GAME ) ;
2016-12-11 01:56:43 +00:00
auto & player_info = get_local_plrobj ( ) . ctype . player_info ;
play_homing_warning ( player_info ) ;
2021-09-12 16:20:52 +00:00
gr_set_default_canvas ( ) ;
2022-07-09 13:39:29 +00:00
game_render_frame_mono ( Robot_info , Controls ) ;
2020-10-12 03:28:26 +00:00
}
2006-03-20 17:12:09 +00:00
}
//show a message in a nice little box
2021-09-12 16:20:52 +00:00
void show_boxed_message ( grs_canvas & canvas , const char * msg )
2006-09-29 00:57:57 +00:00
{
2006-03-20 17:12:09 +00:00
int x , y ;
2010-01-09 09:19:26 +00:00
2017-03-10 01:22:28 +00:00
gr_set_fontcolor ( canvas , BM_XRGB ( 31 , 31 , 31 ) , - 1 ) ;
2018-05-19 23:21:42 +00:00
auto & medium1_font = * MEDIUM1_FONT ;
2021-09-12 16:20:52 +00:00
const auto & & [ w , h ] = gr_get_string_size ( medium1_font , msg ) ;
2010-01-09 09:19:26 +00:00
2008-02-24 14:41:27 +00:00
x = ( SWIDTH - w ) / 2 ;
y = ( SHEIGHT - h ) / 2 ;
2010-01-09 09:19:26 +00:00
2017-04-08 16:48:20 +00:00
nm_draw_background ( canvas , x - BORDERX , y - BORDERY , x + w + BORDERX , y + h + BORDERY ) ;
2010-01-09 09:19:26 +00:00
2018-05-19 23:21:42 +00:00
gr_string ( canvas , medium1_font , 0x8000 , y , msg , w , h ) ;
2006-03-20 17:12:09 +00:00
}