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 .
*/
/*
*
* Routines for displaying the auto - map .
*
*/
2016-09-24 18:06:10 +00:00
# include "dxxsconf.h"
2015-10-03 17:17:49 +00:00
# include <algorithm>
2006-03-20 17:12:09 +00:00
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
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
2012-07-07 18:35:06 +00:00
# include "dxxerror.h"
2006-03-20 17:12:09 +00:00
# include "3d.h"
# include "inferno.h"
# include "u_mem.h"
# include "render.h"
# include "object.h"
# include "vclip.h"
# include "game.h"
# include "polyobj.h"
# include "sounds.h"
# include "player.h"
# include "bm.h"
# include "key.h"
# include "newmenu.h"
# include "menu.h"
# include "screens.h"
# include "textures.h"
2015-04-19 04:18:51 +00:00
# include "hudmsg.h"
2006-03-20 17:12:09 +00:00
# include "mouse.h"
# include "timer.h"
# include "segpoint.h"
# include "joy.h"
# include "iff.h"
# include "pcx.h"
# include "palette.h"
# include "wall.h"
2009-12-02 13:49:54 +00:00
# include "hostage.h"
# include "fuelcen.h"
2014-07-20 01:09:55 +00:00
# include "physfsx.h"
2006-03-20 17:12:09 +00:00
# include "gameseq.h"
# include "gamefont.h"
2013-12-26 04:18:28 +00:00
# include "gameseg.h"
2013-09-24 01:59:09 +00:00
# include "common/3d/globvars.h"
2006-08-07 00:27:18 +00:00
# include "multi.h"
2006-03-20 17:12:09 +00:00
# include "kconfig.h"
# include "endlevel.h"
# include "text.h"
# include "gauges.h"
# include "powerup.h"
# include "switch.h"
# include "automap.h"
# include "cntrlcen.h"
2009-12-02 13:49:54 +00:00
# include "timer.h"
2009-01-15 20:55:35 +00:00
# include "config.h"
2009-12-02 13:49:54 +00:00
# include "playsave.h"
2009-03-03 12:55:27 +00:00
# include "rbaudio.h"
2009-12-02 13:49:54 +00:00
# include "window.h"
2011-01-10 15:12:04 +00:00
# include "playsave.h"
2013-03-03 19:41:09 +00:00
# include "args.h"
2012-11-11 00:14:30 +00:00
# include "physics.h"
2006-03-20 17:12:09 +00:00
2014-10-12 23:05:46 +00:00
# include "compiler-range_for.h"
2020-08-10 03:45:14 +00:00
# include "d_levelstate.h"
2020-07-22 03:11:18 +00:00
# include "d_range.h"
# include "d_zip.h"
2015-10-03 17:17:49 +00:00
# include "partial_range.h"
2020-05-02 21:18:43 +00:00
# include <memory>
2014-08-16 04:15:16 +00:00
2011-02-03 00:05:06 +00:00
# define LEAVE_TIME 0x4000
2006-03-20 17:12:09 +00:00
# define EF_USED 1 // This edge is used
# define EF_DEFINING 2 // A structure defining edge that should always draw.
# define EF_FRONTIER 4 // An edge between the known and the unknown.
# define EF_SECRET 8 // An edge that is part of a secret wall.
# define EF_GRATE 16 // A grate... draw it all the time.
# define EF_NO_FADE 32 // An edge that doesn't fade with distance
# define EF_TOO_FAR 64 // An edge that is too far away
2015-12-13 18:00:49 +00:00
namespace dcx {
2015-12-13 18:00:48 +00:00
2015-08-12 03:11:46 +00:00
namespace {
2013-12-22 22:03:07 +00:00
struct Edge_info
{
2020-05-02 21:18:42 +00:00
std : : array < unsigned , 2 > verts ; // 8 bytes
std : : array < uint8_t , 4 > sides ; // 4 bytes
std : : array < segnum_t , 4 > segnum ; // 16 bytes // This might not need to be stored... If you can access the normals of a side.
2011-06-30 10:23:38 +00:00
ubyte flags ; // 1 bytes // See the EF_??? defines above.
2014-08-08 02:07:47 +00:00
color_t color ; // 1 bytes
2011-06-30 10:23:38 +00:00
ubyte num_faces ; // 1 bytes // 31 bytes...
2013-12-22 22:03:07 +00:00
} ;
2006-03-20 17:12:09 +00:00
2020-08-28 00:18:45 +00:00
struct automap : : : dcx : : window
2009-12-02 13:49:54 +00:00
{
2020-08-28 00:18:45 +00:00
using : : dcx : : window : : window ;
2010-12-10 23:18:17 +00:00
fix64 entry_time ;
fix64 t1 , t2 ;
2020-10-12 03:28:26 +00:00
static_assert ( PF_WIGGLE < UINT8_MAX , " storing PF_WIGGLE into old_wiggle would truncate the value " ) ;
uint8_t old_wiggle ;
2020-10-22 02:26:16 +00:00
uint8_t leave_mode = 0 ;
2020-10-12 03:28:26 +00:00
uint8_t pause_game ;
2011-05-20 10:23:28 +00:00
vms_angvec tangles ;
2020-10-22 02:26:16 +00:00
int max_segments_away = 0 ;
int segment_limit = 1 ;
2020-08-28 00:18:45 +00:00
2009-12-27 12:27:44 +00:00
// Edge list variables
2020-10-22 02:26:16 +00:00
int num_edges = 0 ;
2017-03-10 01:22:33 +00:00
unsigned max_edges ; //set each frame
2020-10-22 02:26:16 +00:00
unsigned end_valid_edges = 0 ;
2014-08-07 03:15:40 +00:00
std : : unique_ptr < Edge_info [ ] > edges ;
2015-10-03 17:17:48 +00:00
std : : unique_ptr < Edge_info * [ ] > drawingListBright ;
2020-08-28 00:18:45 +00:00
2009-12-27 12:27:44 +00:00
// Screen canvas variables
2019-08-18 20:37:29 +00:00
grs_subcanvas automap_view ;
2020-08-28 00:18:45 +00:00
2016-10-29 23:16:15 +00:00
grs_main_bitmap automap_background ;
2020-08-28 00:18:45 +00:00
2009-12-27 12:27:44 +00:00
// Rendering variables
2020-10-22 02:26:16 +00:00
fix zoom = 0x9000 ;
2011-05-20 10:23:28 +00:00
vms_vector view_target ;
vms_vector view_position ;
2020-10-22 02:26:16 +00:00
fix farthest_dist = ( F1_0 * 20 * 50 ) ; // 50 segments away
2011-05-20 10:23:28 +00:00
vms_matrix viewMatrix ;
2020-10-22 02:26:16 +00:00
fix viewDist = 0 ;
2020-08-28 00:18:45 +00:00
segment_depth_array_t depth_array ;
2014-08-08 02:07:47 +00:00
color_t wall_normal_color ;
color_t wall_door_color ;
color_t wall_door_blue ;
color_t wall_door_gold ;
color_t wall_door_red ;
color_t hostage_color ;
color_t green_31 ;
color_t white_63 ;
color_t blue_48 ;
color_t red_48 ;
2020-08-28 00:18:45 +00:00
} ;
}
}
namespace dsx {
namespace {
struct automap : : : dcx : : automap
{
using : : dcx : : automap : : automap ;
# if defined(DXX_BUILD_DESCENT_II)
color_t wall_revealed_color ;
# endif
2011-02-06 13:25:37 +00:00
control_info controls ;
2020-08-28 00:18:45 +00:00
virtual window_event_result event_handler ( const d_event & ) override ;
2013-12-22 22:03:07 +00:00
} ;
2009-12-02 13:49:54 +00:00
2019-08-18 20:37:29 +00:00
static void init_automap_subcanvas ( grs_subcanvas & view , grs_canvas & container )
{
# if defined(DXX_BUILD_DESCENT_I)
if ( MacHog )
gr_init_sub_canvas ( view , container , 38 * ( SWIDTH / 640.0 ) , 77 * ( SHEIGHT / 480.0 ) , 564 * ( SWIDTH / 640.0 ) , 381 * ( SHEIGHT / 480.0 ) ) ;
else
# endif
gr_init_sub_canvas ( view , container , ( SWIDTH / 23 ) , ( SHEIGHT / 6 ) , ( SWIDTH / 1.1 ) , ( SHEIGHT / 1.45 ) ) ;
}
2020-08-28 00:18:45 +00:00
static void automap_build_edge_list ( automap & am , int add_all_edges ) ;
2015-08-12 03:11:46 +00:00
}
2015-12-13 18:00:48 +00:00
}
2015-12-13 18:00:49 +00:00
namespace dcx {
2015-12-13 18:00:48 +00:00
2006-03-20 17:12:09 +00:00
# define MAX_EDGES_FROM_VERTS(v) ((v)*4)
# define K_WALL_NORMAL_COLOR BM_XRGB(29, 29, 29 )
# define K_WALL_DOOR_COLOR BM_XRGB(5, 27, 5 )
# define K_WALL_DOOR_BLUE BM_XRGB(0, 0, 31)
# define K_WALL_DOOR_GOLD BM_XRGB(31, 31, 0)
# define K_WALL_DOOR_RED BM_XRGB(31, 0, 0)
# define K_WALL_REVEALED_COLOR BM_XRGB(0, 0, 25 ) //what you see when you have the full map powerup
# define K_HOSTAGE_COLOR BM_XRGB(0, 31, 0 )
# define K_FONT_COLOR_20 BM_XRGB(20, 20, 20 )
# define K_GREEN_31 BM_XRGB(0, 31, 0)
2010-01-29 03:36:44 +00:00
int Automap_active = 0 ;
2019-08-06 02:59:40 +00:00
2020-08-28 00:18:45 +00:00
namespace {
# ifndef NDEBUG
static uint8_t Automap_debug_show_all_segments ;
# endif
static void automap_clear_visited ( d_level_unique_automap_state & LevelUniqueAutomapState )
2019-08-06 02:59:40 +00:00
{
# ifndef NDEBUG
Automap_debug_show_all_segments = 0 ;
# endif
LevelUniqueAutomapState . Automap_visited = { } ;
}
2020-08-28 00:18:45 +00:00
static void init_automap_colors ( automap & am )
2006-03-20 17:12:09 +00:00
{
2020-08-28 00:18:45 +00:00
am . wall_normal_color = K_WALL_NORMAL_COLOR ;
am . wall_door_color = K_WALL_DOOR_COLOR ;
am . wall_door_blue = K_WALL_DOOR_BLUE ;
am . wall_door_gold = K_WALL_DOOR_GOLD ;
am . wall_door_red = K_WALL_DOOR_RED ;
am . hostage_color = K_HOSTAGE_COLOR ;
am . green_31 = K_GREEN_31 ;
2020-08-28 00:18:45 +00:00
am . white_63 = gr_find_closest_color_current ( 63 , 63 , 63 ) ;
am . blue_48 = gr_find_closest_color_current ( 0 , 0 , 48 ) ;
am . red_48 = gr_find_closest_color_current ( 48 , 0 , 0 ) ;
}
void adjust_segment_limit ( automap & am , const unsigned SegmentLimit )
{
const auto & depth_array = am . depth_array ;
const auto predicate = [ & depth_array , SegmentLimit ] ( const segnum_t & e1 ) {
return depth_array [ e1 ] < = SegmentLimit ;
} ;
for ( auto & i : unchecked_partial_range ( am . edges . get ( ) , am . end_valid_edges ) )
{
// Unchecked for speed
const auto & & range = unchecked_partial_range ( i . segnum . begin ( ) , i . num_faces ) ;
if ( std : : any_of ( range . begin ( ) , range . end ( ) , predicate ) )
i . flags & = ~ EF_TOO_FAR ;
else
i . flags | = EF_TOO_FAR ;
}
}
}
}
namespace dsx {
2009-12-27 12:27:44 +00:00
2020-08-28 00:18:45 +00:00
namespace {
static void recompute_automap_segment_visibility ( const d_level_unique_automap_state & LevelUniqueAutomapState , unsigned compute_depth_all_segments , const segnum_t initial_segnum , automap & am )
{
# ifndef NDEBUG
if ( Automap_debug_show_all_segments )
compute_depth_all_segments = 1 ;
# endif
if ( cheats . fullautomap )
compute_depth_all_segments = 1 ;
automap_build_edge_list ( am , compute_depth_all_segments ) ;
am . max_segments_away = set_segment_depths ( initial_segnum , compute_depth_all_segments ? nullptr : & LevelUniqueAutomapState . Automap_visited , am . depth_array ) ;
am . segment_limit = am . max_segments_away ;
adjust_segment_limit ( am , am . segment_limit ) ;
}
# if defined(DXX_BUILD_DESCENT_II)
void init_automap_colors ( automap & am )
{
: : dcx : : init_automap_colors ( am ) ;
am . wall_revealed_color = K_WALL_REVEALED_COLOR ;
2006-03-20 17:12:09 +00:00
}
2020-08-28 00:18:45 +00:00
# endif
2006-03-20 17:12:09 +00:00
// Map movement defines
# define PITCH_DEFAULT 9000
# define ZOOM_DEFAULT i2f(20*10)
# define ZOOM_MIN_VALUE i2f(20*5)
# define ZOOM_MAX_VALUE i2f(20*100)
2015-12-13 18:00:48 +00:00
}
2006-03-20 17:12:09 +00:00
2018-03-10 22:45:04 +00:00
/* MAX_DROP_MULTI_* must be a power of 2 for LastMarkerDropped to work
* properly .
*/
2020-07-22 03:11:18 +00:00
# define MAX_DROP_MULTI_COOP_0 2
# define MAX_DROP_MULTI_COOP_1 4
# define MAX_DROP_MULTI_COOP_P (max_numplayers > 4)
# define MAX_DROP_MULTI_COOP (MAX_DROP_MULTI_COOP_P ? MAX_DROP_MULTI_COOP_0 : MAX_DROP_MULTI_COOP_1)
2018-03-10 22:45:04 +00:00
# define MAX_DROP_MULTI_COMPETITIVE 2
2006-03-20 17:12:09 +00:00
# define MAX_DROP_SINGLE 9
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2013-12-28 18:56:34 +00:00
marker_message_text_t Marker_input ;
2015-12-03 03:26:49 +00:00
static float MarkerScale = 2.0 ;
2014-08-05 03:10:04 +00:00
2018-03-10 18:32:02 +00:00
d_marker_state MarkerState ;
2018-03-10 22:45:04 +00:00
2020-07-22 03:11:18 +00:00
game_marker_index convert_player_marker_index_to_game_marker_index ( const unsigned game_mode , const unsigned max_numplayers , const unsigned player_num , const player_marker_index player_marker_num )
2018-03-10 22:45:04 +00:00
{
if ( game_mode & GM_MULTI_COOP )
2020-07-22 03:11:18 +00:00
return static_cast < game_marker_index > ( ( player_num * MAX_DROP_MULTI_COOP ) + static_cast < unsigned > ( player_marker_num ) ) ;
2018-03-10 22:45:04 +00:00
if ( game_mode & GM_MULTI )
2020-07-22 03:11:18 +00:00
return static_cast < game_marker_index > ( ( player_num * MAX_DROP_MULTI_COMPETITIVE ) + static_cast < unsigned > ( player_marker_num ) ) ;
return game_marker_index { player_marker_num } ;
2018-03-10 22:45:04 +00:00
}
2020-07-22 03:11:18 +00:00
unsigned d_marker_state : : get_markers_per_player ( const unsigned game_mode , const unsigned max_numplayers )
2018-03-10 22:45:04 +00:00
{
if ( game_mode & GM_MULTI_COOP )
return MAX_DROP_MULTI_COOP ;
if ( game_mode & GM_MULTI )
return MAX_DROP_MULTI_COMPETITIVE ;
return MAX_DROP_SINGLE ;
}
2020-07-22 03:11:18 +00:00
xrange < player_marker_index > get_player_marker_range ( const unsigned maxdrop )
{
const auto base = player_marker_index : : _0 ;
return { base , static_cast < player_marker_index > ( static_cast < unsigned > ( base ) + maxdrop ) } ;
}
playernum_t get_marker_owner ( const unsigned game_mode , const game_marker_index gmi , const unsigned max_numplayers )
{
const auto ugmi = static_cast < unsigned > ( gmi ) ;
if ( game_mode & GM_MULTI_COOP )
{
/* This is split out to encourage the compiler to recognize that
* the divisor is a constant in every path , and in every path ,
* the divisor was chosen to allow use of right shift in place
* of division .
*/
if ( MAX_DROP_MULTI_COOP_P )
return ugmi / MAX_DROP_MULTI_COOP_0 ;
return ugmi / MAX_DROP_MULTI_COOP_1 ;
}
if ( game_mode & GM_MULTI )
return ugmi / MAX_DROP_MULTI_COMPETITIVE ;
return 0 ;
}
namespace {
xrange < game_marker_index > get_game_marker_range ( const unsigned game_mode , const unsigned max_numplayers , const unsigned player_num , const unsigned maxdrop )
{
const auto base = convert_player_marker_index_to_game_marker_index ( game_mode , max_numplayers , player_num , player_marker_index : : _0 ) ;
return { base , static_cast < game_marker_index > ( static_cast < unsigned > ( base ) + maxdrop ) } ;
}
2015-12-13 18:00:48 +00:00
}
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
# define automap_draw_line g3_draw_line
2017-02-11 21:42:44 +00:00
# if DXX_USE_OGL
2020-07-22 03:11:18 +00:00
# define DrawMarkerNumber(C,a,b,c,d) DrawMarkerNumber(a,b,c,d)
2017-03-11 19:56:23 +00:00
# define draw_all_edges(C,a) draw_all_edges(a)
2017-02-11 21:42:44 +00:00
# endif
2006-03-20 17:12:09 +00:00
// -------------------------------------------------------------
2020-08-28 00:18:45 +00:00
namespace {
2020-08-28 00:18:45 +00:00
static void draw_all_edges ( grs_canvas & , automap & am ) ;
# if defined(DXX_BUILD_DESCENT_II)
static void DrawMarkerNumber ( grs_canvas & canvas , const automap & am , const game_marker_index gmi , const player_marker_index pmi , const g3s_point & BasePoint )
2006-08-07 00:27:18 +00:00
{
2015-12-03 03:26:49 +00:00
struct xy
2006-08-07 00:27:18 +00:00
{
2015-12-03 03:26:49 +00:00
float x0 , y0 , x1 , y1 ;
} ;
2020-07-22 03:11:18 +00:00
static constexpr enumerated_array < std : : array < xy , 5 > , 9 , player_marker_index > sArray = { { {
2015-12-03 03:26:49 +00:00
{ {
{ - 0.25 , 0.75 , 0 , 1 } ,
{ 0 , 1 , 0 , - 1 } ,
{ - 1 , - 1 , 1 , - 1 } ,
} } ,
{ {
{ - 1 , 1 , 1 , 1 } ,
{ 1 , 1 , 1 , 0 } ,
{ - 1 , 0 , 1 , 0 } ,
{ - 1 , 0 , - 1 , - 1 } ,
{ - 1 , - 1 , 1 , - 1 }
} } ,
{ {
{ - 1 , 1 , 1 , 1 } ,
{ 1 , 1 , 1 , - 1 } ,
{ - 1 , - 1 , 1 , - 1 } ,
{ 0 , 0 , 1 , 0 } ,
} } ,
{ {
{ - 1 , 1 , - 1 , 0 } ,
{ - 1 , 0 , 1 , 0 } ,
{ 1 , 1 , 1 , - 1 } ,
} } ,
{ {
{ - 1 , 1 , 1 , 1 } ,
{ - 1 , 1 , - 1 , 0 } ,
{ - 1 , 0 , 1 , 0 } ,
{ 1 , 0 , 1 , - 1 } ,
{ - 1 , - 1 , 1 , - 1 }
} } ,
{ {
{ - 1 , 1 , 1 , 1 } ,
{ - 1 , 1 , - 1 , - 1 } ,
{ - 1 , - 1 , 1 , - 1 } ,
{ 1 , - 1 , 1 , 0 } ,
{ - 1 , 0 , 1 , 0 }
} } ,
{ {
{ - 1 , 1 , 1 , 1 } ,
{ 1 , 1 , 1 , - 1 } ,
} } ,
{ {
{ - 1 , 1 , 1 , 1 } ,
{ 1 , 1 , 1 , - 1 } ,
{ - 1 , - 1 , 1 , - 1 } ,
{ - 1 , - 1 , - 1 , 1 } ,
{ - 1 , 0 , 1 , 0 }
} } ,
{ {
{ - 1 , 1 , 1 , 1 } ,
{ 1 , 1 , 1 , - 1 } ,
{ - 1 , 0 , 1 , 0 } ,
{ - 1 , 0 , - 1 , 1 } ,
} }
2020-07-22 03:11:18 +00:00
} } } ;
static constexpr enumerated_array < uint_fast8_t , 9 , player_marker_index > NumOfPoints = { { { 3 , 5 , 4 , 3 , 5 , 5 , 2 , 5 , 4 } } } ;
2015-12-03 03:26:49 +00:00
2020-08-28 00:18:45 +00:00
const auto color = ( gmi = = MarkerState . HighlightMarker ? am . white_63 : am . blue_48 ) ;
2015-12-03 03:26:49 +00:00
const auto scale_x = Matrix_scale . x ;
const auto scale_y = Matrix_scale . y ;
2020-07-22 03:11:18 +00:00
range_for ( const auto & i , unchecked_partial_range ( sArray [ pmi ] . data ( ) , NumOfPoints [ pmi ] ) )
2006-08-07 00:27:18 +00:00
{
2015-12-03 03:26:49 +00:00
const auto ax0 = i . x0 * MarkerScale ;
const auto ay0 = i . y0 * MarkerScale ;
const auto ax1 = i . x1 * MarkerScale ;
const auto ay1 = i . y1 * MarkerScale ;
auto FromPoint = BasePoint ;
auto ToPoint = BasePoint ;
FromPoint . p3_x + = fixmul ( fl2f ( ax0 ) , scale_x ) ;
FromPoint . p3_y + = fixmul ( fl2f ( ay0 ) , scale_y ) ;
ToPoint . p3_x + = fixmul ( fl2f ( ax1 ) , scale_x ) ;
ToPoint . p3_y + = fixmul ( fl2f ( ay1 ) , scale_y ) ;
2014-11-13 03:16:17 +00:00
g3_code_point ( FromPoint ) ;
g3_code_point ( ToPoint ) ;
2015-12-03 03:26:49 +00:00
g3_project_point ( FromPoint ) ;
2014-11-13 03:21:33 +00:00
g3_project_point ( ToPoint ) ;
2017-02-11 21:42:44 +00:00
automap_draw_line ( canvas , FromPoint , ToPoint , color ) ;
2006-08-07 00:27:18 +00:00
}
}
2006-03-20 17:12:09 +00:00
2020-07-22 03:11:18 +00:00
static void DropMarker ( fvmobjptridx & vmobjptridx , fvmsegptridx & vmsegptridx , const object & plrobj , const game_marker_index marker_num , const player_marker_index player_marker_num )
2006-03-20 17:12:09 +00:00
{
2018-03-10 18:32:02 +00:00
auto & marker_objidx = MarkerState . imobjidx [ marker_num ] ;
if ( marker_objidx ! = object_none )
2018-12-30 00:43:57 +00:00
obj_delete ( LevelUniqueObjectState , Segments , vmobjptridx ( marker_objidx ) ) ;
2006-03-20 17:12:09 +00:00
2018-03-10 18:32:02 +00:00
marker_objidx = drop_marker_object ( plrobj . pos , vmsegptridx ( plrobj . segnum ) , plrobj . orient , marker_num ) ;
2006-03-20 17:12:09 +00:00
if ( Game_mode & GM_MULTI )
2018-03-10 18:32:02 +00:00
multi_send_drop_marker ( Player_num , plrobj . pos , player_marker_num , MarkerState . message [ marker_num ] ) ;
2006-03-20 17:12:09 +00:00
}
2020-08-28 00:18:45 +00:00
}
2019-12-22 05:34:08 +00:00
void DropBuddyMarker ( object & objp )
2006-03-20 17:12:09 +00:00
{
2019-03-03 00:31:08 +00:00
auto & Objects = LevelUniqueObjectState . Objects ;
auto & vmobjptridx = Objects . vmptridx ;
2006-03-20 17:12:09 +00:00
2020-07-22 03:11:18 +00:00
constexpr auto marker_num = game_marker_index : : GuidebotDeathSite ;
static_assert ( MarkerState . message . valid_index ( marker_num ) , " not enough markers " ) ;
2006-03-20 17:12:09 +00:00
2018-03-10 18:32:02 +00:00
auto & MarkerMessage = MarkerState . message [ marker_num ] ;
snprintf ( & MarkerMessage [ 0 ] , MarkerMessage . size ( ) , " RIP: %s " , static_cast < const char * > ( PlayerCfg . GuidebotName ) ) ;
2006-03-20 17:12:09 +00:00
2018-03-10 18:32:02 +00:00
auto & marker_objidx = MarkerState . imobjidx [ marker_num ] ;
if ( marker_objidx ! = object_none )
2018-12-30 00:43:57 +00:00
obj_delete ( LevelUniqueObjectState , Segments , vmobjptridx ( marker_objidx ) ) ;
2006-03-20 17:12:09 +00:00
2019-12-22 05:34:08 +00:00
marker_objidx = drop_marker_object ( objp . pos , vmsegptridx ( objp . segnum ) , objp . orient , marker_num ) ;
2006-03-20 17:12:09 +00:00
}
2020-08-28 00:18:45 +00:00
namespace {
2006-03-20 17:12:09 +00:00
# define MARKER_SPHERE_SIZE 0x58000
2020-08-28 00:18:45 +00:00
static void DrawMarkers ( fvcobjptr & vcobjptr , grs_canvas & canvas , automap & am )
2017-02-11 21:42:44 +00:00
{
2006-03-20 17:12:09 +00:00
static int cyc = 10 , cycdir = 1 ;
2018-03-10 22:45:04 +00:00
const auto game_mode = Game_mode ;
2020-07-22 03:11:18 +00:00
const auto max_numplayers = Netgame . max_numplayers ;
const auto maxdrop = MarkerState . get_markers_per_player ( game_mode , max_numplayers ) ;
const auto & & game_marker_range = get_game_marker_range ( game_mode , max_numplayers , Player_num , maxdrop ) ;
const auto & & player_marker_range = get_player_marker_range ( maxdrop ) ;
const auto & & zipped_marker_range = zip ( game_marker_range , player_marker_range , unchecked_partial_range ( & MarkerState . imobjidx [ * game_marker_range . begin ( ) ] , maxdrop ) ) ;
const auto & & mb = zipped_marker_range . begin ( ) ;
const auto & & me = zipped_marker_range . end ( ) ;
auto iter = mb ;
/* Find the first marker object in the player's marker range that is
* not object_none . If every marker object in the range is
* object_none , then there are no markers to draw , so return .
*/
for ( ; ; )
2015-12-03 03:26:49 +00:00
{
2020-07-22 03:11:18 +00:00
auto & & [ gmi , pmi , objidx ] = * iter ;
( void ) gmi ;
( void ) pmi ;
if ( objidx ! = object_none )
2015-12-03 03:26:49 +00:00
break ;
if ( + + iter = = me )
return ;
}
2020-07-22 03:11:18 +00:00
/* A marker was found, so at least one marker will be drawn. Set up
* colors for the markers .
*/
2015-12-03 03:26:49 +00:00
const auto current_cycle_color = cyc ;
2020-05-02 21:18:42 +00:00
const std : : array < color_t , 3 > colors { {
2015-12-03 03:26:49 +00:00
gr_find_closest_color_current ( current_cycle_color , 0 , 0 ) ,
gr_find_closest_color_current ( current_cycle_color + 10 , 0 , 0 ) ,
gr_find_closest_color_current ( current_cycle_color + 20 , 0 , 0 ) ,
} } ;
2020-07-22 03:11:18 +00:00
for ( ; iter ! = me ; + + iter )
{
auto & & [ gmi , pmi , objidx ] = * iter ;
if ( objidx ! = object_none )
2015-12-03 03:26:49 +00:00
{
2020-11-30 05:12:00 +00:00
/* Use cg3s_point so that the type is const for OpenGL and
* mutable for SDL - only .
*/
cg3s_point & & sphere_point = g3_rotate_point ( vcobjptr ( objidx ) - > pos ) ;
2017-02-11 21:42:44 +00:00
g3_draw_sphere ( canvas , sphere_point , MARKER_SPHERE_SIZE , colors [ 0 ] ) ;
g3_draw_sphere ( canvas , sphere_point , MARKER_SPHERE_SIZE / 2 , colors [ 1 ] ) ;
g3_draw_sphere ( canvas , sphere_point , MARKER_SPHERE_SIZE / 4 , colors [ 2 ] ) ;
2020-07-22 03:11:18 +00:00
DrawMarkerNumber ( canvas , am , gmi , pmi , sphere_point ) ;
2006-03-20 17:12:09 +00:00
}
2020-07-22 03:11:18 +00:00
}
2006-03-20 17:12:09 +00:00
if ( cycdir )
cyc + = 2 ;
else
cyc - = 2 ;
if ( cyc > 43 )
2006-08-07 00:27:18 +00:00
{
2006-03-20 17:12:09 +00:00
cyc = 43 ;
cycdir = 0 ;
2006-08-07 00:27:18 +00:00
}
2006-03-20 17:12:09 +00:00
else if ( cyc < 10 )
2006-08-07 00:27:18 +00:00
{
2006-03-20 17:12:09 +00:00
cyc = 10 ;
cycdir = 1 ;
2006-08-07 00:27:18 +00:00
}
}
2006-03-20 17:12:09 +00:00
2013-10-27 22:00:14 +00:00
static void ClearMarkers ( )
2006-08-07 00:27:18 +00:00
{
2018-03-10 18:32:02 +00:00
static_cast < d_marker_object_numbers & > ( MarkerState ) = { } ;
2018-03-10 18:32:02 +00:00
MarkerState . message = { } ;
2006-08-07 00:27:18 +00:00
}
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2020-08-28 00:18:45 +00:00
}
2020-08-28 00:18:45 +00:00
void automap_clear_visited ( d_level_unique_automap_state & LevelUniqueAutomapState )
2006-03-20 17:12:09 +00:00
{
2020-08-28 00:18:45 +00:00
# if defined(DXX_BUILD_DESCENT_II)
ClearMarkers ( ) ;
# endif
: : dcx : : automap_clear_visited ( LevelUniqueAutomapState ) ;
2006-03-20 17:12:09 +00:00
}
2020-10-12 03:28:26 +00:00
namespace {
2017-02-11 21:42:44 +00:00
static void draw_player ( grs_canvas & canvas , const object_base & obj , const uint8_t color )
2006-03-20 17:12:09 +00:00
{
// Draw Console player -- shaped like a ellipse with an arrow.
2016-05-21 17:24:51 +00:00
auto sphere_point = g3_rotate_point ( obj . pos ) ;
const auto obj_size = obj . size ;
2017-02-11 21:42:44 +00:00
g3_draw_sphere ( canvas , sphere_point , obj_size , color ) ;
2006-03-20 17:12:09 +00:00
// Draw shaft of arrow
2016-05-21 17:24:51 +00:00
const auto & & head_pos = vm_vec_scale_add ( obj . pos , obj . orient . fvec , obj_size * 2 ) ;
2016-05-21 17:24:51 +00:00
{
2016-05-21 17:24:51 +00:00
auto & & arrow_point = g3_rotate_point ( vm_vec_scale_add ( obj . pos , obj . orient . fvec , obj_size * 3 ) ) ;
2017-02-11 21:42:44 +00:00
automap_draw_line ( canvas , sphere_point , arrow_point , color ) ;
2006-03-20 17:12:09 +00:00
// Draw right head of arrow
2014-11-02 03:43:57 +00:00
{
2016-05-21 17:24:51 +00:00
const auto & & rhead_pos = vm_vec_scale_add ( head_pos , obj . orient . rvec , obj_size ) ;
2014-11-13 03:41:29 +00:00
auto head_point = g3_rotate_point ( rhead_pos ) ;
2017-02-11 21:42:44 +00:00
automap_draw_line ( canvas , arrow_point , head_point , color ) ;
2014-11-02 03:43:57 +00:00
}
2006-03-20 17:12:09 +00:00
// Draw left head of arrow
2014-11-02 03:43:57 +00:00
{
2016-05-21 17:24:51 +00:00
const auto & & lhead_pos = vm_vec_scale_add ( head_pos , obj . orient . rvec , - obj_size ) ;
2014-11-13 03:41:29 +00:00
auto head_point = g3_rotate_point ( lhead_pos ) ;
2017-02-11 21:42:44 +00:00
automap_draw_line ( canvas , arrow_point , head_point , color ) ;
2014-11-02 03:43:57 +00:00
}
2016-05-21 17:24:51 +00:00
}
2006-03-20 17:12:09 +00:00
// Draw player's up vector
2014-11-02 03:43:57 +00:00
{
2016-05-21 17:24:51 +00:00
const auto & & arrow_pos = vm_vec_scale_add ( obj . pos , obj . orient . uvec , obj_size * 2 ) ;
2014-11-13 03:41:29 +00:00
auto arrow_point = g3_rotate_point ( arrow_pos ) ;
2017-02-11 21:42:44 +00:00
automap_draw_line ( canvas , sphere_point , arrow_point , color ) ;
2014-11-02 03:43:57 +00:00
}
2006-03-20 17:12:09 +00:00
}
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2008-02-24 14:41:27 +00:00
//name for each group. maybe move somewhere else
2016-07-16 16:52:04 +00:00
constexpr char system_name [ ] [ 17 ] = {
2008-02-24 14:41:27 +00:00
" Zeta Aquilae " ,
" Quartzon System " ,
" Brimspark System " ,
" Limefrost Spiral " ,
" Baloris Prime " ,
" Omega System " } ;
2013-03-03 01:03:33 +00:00
# endif
2008-02-24 14:41:27 +00:00
2020-08-28 00:18:45 +00:00
static void name_frame ( grs_canvas & canvas , automap & am )
2008-02-24 14:41:27 +00:00
{
2020-08-28 00:18:45 +00:00
gr_set_fontcolor ( canvas , am . green_31 , - 1 ) ;
2013-10-27 17:07:54 +00:00
char name_level_left [ 128 ] ;
2018-05-19 23:21:42 +00:00
auto & game_font = * GAME_FONT ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2013-10-27 17:07:54 +00:00
const char * name_level ;
2013-03-03 01:03:33 +00:00
if ( Current_level_num > 0 )
2013-10-27 17:07:54 +00:00
{
2014-12-20 04:36:10 +00:00
snprintf ( name_level_left , sizeof ( name_level_left ) , " %s %i: %s " , TXT_LEVEL , Current_level_num , static_cast < const char * > ( Current_level_name ) ) ;
2013-10-27 17:07:54 +00:00
name_level = name_level_left ;
}
2013-03-03 01:03:33 +00:00
else
2013-10-27 17:07:54 +00:00
name_level = Current_level_name ;
2013-03-03 01:03:33 +00:00
2018-05-19 23:21:42 +00:00
gr_string ( canvas , game_font , ( SWIDTH / 64 ) , ( SHEIGHT / 48 ) , name_level ) ;
2013-03-03 01:03:33 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2013-10-27 17:07:54 +00:00
char name_level_right [ 128 ] ;
2008-02-24 14:41:27 +00:00
if ( Current_level_num > 0 )
2013-10-27 17:07:54 +00:00
snprintf ( name_level_left , sizeof ( name_level_left ) , " %s %i " , TXT_LEVEL , Current_level_num ) ;
2008-02-24 14:41:27 +00:00
else
2013-10-27 17:07:54 +00:00
snprintf ( name_level_left , sizeof ( name_level_left ) , " Secret Level %i " , - Current_level_num ) ;
2008-02-24 14:41:27 +00:00
2016-01-03 20:21:36 +00:00
const char * const current_level_name = Current_level_name ;
2008-02-24 14:41:27 +00:00
if ( PLAYING_BUILTIN_MISSION & & Current_level_num > 0 )
2016-01-03 20:21:36 +00:00
snprintf ( name_level_right , sizeof ( name_level_right ) , " %s %d: %s " , system_name [ ( Current_level_num - 1 ) / 4 ] , ( ( Current_level_num - 1 ) % 4 ) + 1 , current_level_name ) ;
2008-02-24 14:41:27 +00:00
else
2016-01-03 20:21:36 +00:00
snprintf ( name_level_right , sizeof ( name_level_right ) , " %s " , current_level_name ) ;
2008-02-24 14:41:27 +00:00
2018-05-19 23:21:42 +00:00
gr_string ( canvas , game_font , ( SWIDTH / 64 ) , ( SHEIGHT / 48 ) , name_level_left ) ;
2015-09-29 02:41:22 +00:00
int wr , h ;
2018-05-19 23:21:42 +00:00
gr_get_string_size ( game_font , name_level_right , & wr , & h , nullptr ) ;
gr_string ( canvas , game_font , canvas . cv_bitmap . bm_w - wr - ( SWIDTH / 64 ) , ( SHEIGHT / 48 ) , name_level_right , wr , h ) ;
2013-03-03 01:03:33 +00:00
# endif
2008-02-24 14:41:27 +00:00
}
2006-12-24 09:15:37 +00:00
2020-08-28 00:18:45 +00:00
static void automap_apply_input ( automap & am , const vms_matrix & plrorient , const vms_vector & plrpos )
2016-05-30 11:17:42 +00:00
{
2018-07-22 04:46:19 +00:00
constexpr int SLIDE_SPEED = 350 ;
constexpr int ZOOM_SPEED_FACTOR = 500 ; //(1500)
constexpr int ROT_SPEED_DIVISOR = 115000 ;
2016-05-30 11:17:42 +00:00
if ( PlayerCfg . AutomapFreeFlight )
{
2020-08-28 00:18:45 +00:00
if ( am . controls . state . fire_primary )
2016-05-30 11:17:42 +00:00
{
// Reset orientation
2020-08-28 00:18:45 +00:00
am . controls . state . fire_primary = 0 ;
am . viewMatrix = plrorient ;
vm_vec_scale_add ( am . view_position , plrpos , am . viewMatrix . fvec , - ZOOM_DEFAULT ) ;
2016-05-30 11:17:42 +00:00
}
2020-08-28 00:18:45 +00:00
if ( am . controls . pitch_time | | am . controls . heading_time | | am . controls . bank_time )
2016-05-30 11:17:42 +00:00
{
vms_angvec tangles ;
2020-08-28 00:18:45 +00:00
tangles . p = fixdiv ( am . controls . pitch_time , ROT_SPEED_DIVISOR ) ;
tangles . h = fixdiv ( am . controls . heading_time , ROT_SPEED_DIVISOR ) ;
tangles . b = fixdiv ( am . controls . bank_time , ROT_SPEED_DIVISOR * 2 ) ;
2016-05-30 11:17:42 +00:00
const auto & & tempm = vm_angles_2_matrix ( tangles ) ;
2020-08-28 00:18:45 +00:00
am . viewMatrix = vm_matrix_x_matrix ( am . viewMatrix , tempm ) ;
check_and_fix_matrix ( am . viewMatrix ) ;
2016-05-30 11:17:42 +00:00
}
2020-08-28 00:18:45 +00:00
if ( am . controls . forward_thrust_time | | am . controls . vertical_thrust_time | | am . controls . sideways_thrust_time )
2016-05-30 11:17:42 +00:00
{
2020-08-28 00:18:45 +00:00
vm_vec_scale_add2 ( am . view_position , am . viewMatrix . fvec , am . controls . forward_thrust_time * ZOOM_SPEED_FACTOR ) ;
vm_vec_scale_add2 ( am . view_position , am . viewMatrix . uvec , am . controls . vertical_thrust_time * SLIDE_SPEED ) ;
vm_vec_scale_add2 ( am . view_position , am . viewMatrix . rvec , am . controls . sideways_thrust_time * SLIDE_SPEED ) ;
2016-05-30 11:17:42 +00:00
// Crude wrapping check
2020-08-28 00:18:45 +00:00
clamp_fix_symmetric ( am . view_position . x , F1_0 * 32000 ) ;
clamp_fix_symmetric ( am . view_position . y , F1_0 * 32000 ) ;
clamp_fix_symmetric ( am . view_position . z , F1_0 * 32000 ) ;
2016-05-30 11:17:42 +00:00
}
}
else
{
2020-08-28 00:18:45 +00:00
if ( am . controls . state . fire_primary )
2016-05-30 11:17:42 +00:00
{
// Reset orientation
2020-08-28 00:18:45 +00:00
am . viewDist = ZOOM_DEFAULT ;
am . tangles . p = PITCH_DEFAULT ;
am . tangles . h = 0 ;
am . tangles . b = 0 ;
am . view_target = plrpos ;
am . controls . state . fire_primary = 0 ;
2016-05-30 11:17:42 +00:00
}
2020-08-28 00:18:45 +00:00
am . viewDist - = am . controls . forward_thrust_time * ZOOM_SPEED_FACTOR ;
am . tangles . p + = fixdiv ( am . controls . pitch_time , ROT_SPEED_DIVISOR ) ;
am . tangles . h + = fixdiv ( am . controls . heading_time , ROT_SPEED_DIVISOR ) ;
am . tangles . b + = fixdiv ( am . controls . bank_time , ROT_SPEED_DIVISOR * 2 ) ;
2016-05-30 11:17:42 +00:00
2020-08-28 00:18:45 +00:00
if ( am . controls . vertical_thrust_time | | am . controls . sideways_thrust_time )
2016-05-30 11:17:42 +00:00
{
vms_angvec tangles1 ;
vms_vector old_vt ;
2020-08-28 00:18:45 +00:00
old_vt = am . view_target ;
tangles1 = am . tangles ;
2016-05-30 11:17:42 +00:00
const auto & & tempm = vm_angles_2_matrix ( tangles1 ) ;
2020-08-28 00:18:45 +00:00
vm_matrix_x_matrix ( am . viewMatrix , plrorient , tempm ) ;
vm_vec_scale_add2 ( am . view_target , am . viewMatrix . uvec , am . controls . vertical_thrust_time * SLIDE_SPEED ) ;
vm_vec_scale_add2 ( am . view_target , am . viewMatrix . rvec , am . controls . sideways_thrust_time * SLIDE_SPEED ) ;
if ( vm_vec_dist_quick ( am . view_target , plrpos ) > i2f ( 1000 ) )
am . view_target = old_vt ;
2016-05-30 11:17:42 +00:00
}
2020-08-28 00:18:45 +00:00
const auto & & tempm = vm_angles_2_matrix ( am . tangles ) ;
vm_matrix_x_matrix ( am . viewMatrix , plrorient , tempm ) ;
2016-05-30 11:17:42 +00:00
2020-08-28 00:18:45 +00:00
clamp_fix_lh ( am . viewDist , ZOOM_MIN_VALUE , ZOOM_MAX_VALUE ) ;
2016-05-30 11:17:42 +00:00
}
}
2020-08-28 00:18:45 +00:00
static void draw_automap ( fvcobjptr & vcobjptr , automap & am )
2006-03-20 17:12:09 +00:00
{
2020-08-28 00:18:45 +00:00
if ( am . leave_mode = = 0 & & am . controls . state . automap & & ( timer_query ( ) - am . entry_time ) > LEAVE_TIME )
am . leave_mode = 1 ;
2011-02-03 00:05:06 +00:00
2017-11-05 20:49:08 +00:00
gr_set_default_canvas ( ) ;
2017-02-11 21:42:46 +00:00
{
auto & canvas = * grd_curcanv ;
2020-08-28 00:18:45 +00:00
if ( am . automap_background . get_bitmap_data ( ) )
show_fullscr ( canvas , am . automap_background ) ;
2017-02-11 21:42:46 +00:00
gr_set_fontcolor ( canvas , BM_XRGB ( 20 , 20 , 20 ) , - 1 ) ;
2016-10-15 00:53:15 +00:00
{
int x , y ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
if ( MacHog )
2016-10-15 00:53:15 +00:00
x = 80 * ( SWIDTH / 640. ) , y = 36 * ( SHEIGHT / 480. ) ;
2013-03-03 01:03:33 +00:00
else
# endif
2016-10-15 00:53:15 +00:00
x = SWIDTH / 8 , y = SHEIGHT / 16 ;
2018-05-19 23:21:42 +00:00
gr_string ( canvas , * HUGE_FONT , x , y , TXT_AUTOMAP ) ;
2016-10-15 00:53:15 +00:00
}
2017-02-11 21:42:46 +00:00
gr_set_fontcolor ( canvas , BM_XRGB ( 20 , 20 , 20 ) , - 1 ) ;
2016-10-15 00:53:15 +00:00
{
int x ;
int y0 , y1 , y2 ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2016-10-15 00:53:15 +00:00
const auto s1 = TXT_SLIDE_UPDOWN ;
const auto & s2 = " F9/F10 Changes viewing distance " ;
2013-03-03 01:03:33 +00:00
if ( ! MacHog )
{
2016-10-15 00:53:15 +00:00
x = SWIDTH / 4.923 ;
y0 = SHEIGHT / 1.126 ;
y1 = SHEIGHT / 1.083 ;
y2 = SHEIGHT / 1.043 ;
2013-03-03 01:03:33 +00:00
}
else
{
// for the Mac automap they're shown up the top, hence the different layout
2016-10-15 00:53:15 +00:00
x = 265 * ( SWIDTH / 640. ) ;
y0 = 27 * ( SHEIGHT / 480. ) ;
y1 = 44 * ( SHEIGHT / 480. ) ;
y2 = 61 * ( SHEIGHT / 480. ) ;
2013-03-03 01:03:33 +00:00
}
# elif defined(DXX_BUILD_DESCENT_II)
2016-10-15 00:53:15 +00:00
const auto & s1 = " F9/F10 Changes viewing distance " ;
const auto s2 = TXT_AUTOMAP_MARKER ;
x = SWIDTH / 10.666 ;
y0 = SHEIGHT / 1.126 ;
y1 = SHEIGHT / 1.083 ;
y2 = SHEIGHT / 1.043 ;
2013-03-03 01:03:33 +00:00
# endif
2018-05-19 23:21:42 +00:00
auto & game_font = * GAME_FONT ;
gr_string ( canvas , game_font , x , y0 , TXT_TURN_SHIP ) ;
gr_string ( canvas , game_font , x , y1 , s1 ) ;
gr_string ( canvas , game_font , x , y2 , s2 ) ;
2016-10-15 00:53:15 +00:00
}
2007-04-01 05:06:35 +00:00
2017-02-11 21:42:46 +00:00
}
2020-08-28 00:18:45 +00:00
gr_set_current_canvas ( am . automap_view ) ;
2017-02-11 21:42:46 +00:00
auto & canvas = * grd_curcanv ;
2006-03-20 17:12:09 +00:00
2017-02-11 21:42:46 +00:00
gr_clear_canvas ( canvas , BM_XRGB ( 0 , 0 , 0 ) ) ;
2006-03-20 17:12:09 +00:00
2017-02-11 21:42:46 +00:00
g3_start_frame ( canvas ) ;
2006-03-20 17:12:09 +00:00
render_start_frame ( ) ;
2011-05-20 10:23:28 +00:00
if ( ! PlayerCfg . AutomapFreeFlight )
2020-08-28 00:18:45 +00:00
vm_vec_scale_add ( am . view_position , am . view_target , am . viewMatrix . fvec , - am . viewDist ) ;
2011-05-20 10:23:28 +00:00
2020-08-28 00:18:45 +00:00
g3_set_view_matrix ( am . view_position , am . viewMatrix , am . zoom ) ;
2006-03-20 17:12:09 +00:00
2017-03-11 19:56:23 +00:00
draw_all_edges ( * grd_curcanv , am ) ;
2006-03-20 17:12:09 +00:00
// Draw player...
2016-02-12 04:02:28 +00:00
const auto & self_ship_rgb = player_rgb [ get_player_or_team_color ( Player_num ) ] ;
const auto closest_color = BM_XRGB ( self_ship_rgb . r , self_ship_rgb . g , self_ship_rgb . b ) ;
2017-02-11 21:42:46 +00:00
draw_player ( canvas , vcobjptr ( get_local_player ( ) . objnum ) , closest_color ) ;
2006-03-20 17:12:09 +00:00
2020-08-28 00:18:45 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2017-07-26 03:15:59 +00:00
DrawMarkers ( vcobjptr , canvas , am ) ;
2020-08-28 00:18:45 +00:00
# endif
2006-03-20 17:12:09 +00:00
// Draw player(s)...
2019-06-27 03:26:20 +00:00
const unsigned show_all_players = ( Game_mode & GM_MULTI_COOP ) | | Netgame . game_flag . show_on_map ;
if ( show_all_players | | ( Game_mode & GM_TEAM ) )
{
const unsigned local_player_team = get_team ( Player_num ) ;
2017-08-13 20:38:31 +00:00
for ( unsigned i = 0 ; i < N_players ; + + i )
{
2019-06-27 03:26:20 +00:00
if ( i = = Player_num )
continue ;
if ( show_all_players | | local_player_team = = get_team ( i ) )
{
2018-06-24 05:06:15 +00:00
auto & plr = * vcplayerptr ( i ) ;
auto & objp = * vcobjptr ( plr . objnum ) ;
if ( objp . type = = OBJ_PLAYER )
2015-12-03 03:26:49 +00:00
{
2016-02-12 04:02:28 +00:00
const auto & other_ship_rgb = player_rgb [ get_player_or_team_color ( i ) ] ;
2017-02-11 21:42:46 +00:00
draw_player ( canvas , objp , BM_XRGB ( other_ship_rgb . r , other_ship_rgb . g , other_ship_rgb . b ) ) ;
2006-03-20 17:12:09 +00:00
}
}
}
}
2017-07-26 03:15:59 +00:00
range_for ( const auto & & objp , vcobjptr )
2014-10-12 23:05:46 +00:00
{
2006-03-20 17:12:09 +00:00
switch ( objp - > type ) {
case OBJ_HOSTAGE :
2014-11-13 03:41:29 +00:00
{
auto sphere_point = g3_rotate_point ( objp - > pos ) ;
2020-08-28 00:18:45 +00:00
g3_draw_sphere ( canvas , sphere_point , objp - > size , am . hostage_color ) ;
2014-11-13 03:41:29 +00:00
}
2006-03-20 17:12:09 +00:00
break ;
case OBJ_POWERUP :
2020-08-28 00:18:45 +00:00
if ( LevelUniqueAutomapState . Automap_visited [ objp - > segnum ]
# ifndef NDEBUG
| | Automap_debug_show_all_segments
# endif
)
2013-12-15 18:32:10 +00:00
{
2013-12-15 18:08:12 +00:00
ubyte id = get_powerup_id ( objp ) ;
2016-02-12 04:02:28 +00:00
unsigned r , g , b ;
2013-12-15 18:08:12 +00:00
if ( id = = POW_KEY_RED )
2016-02-12 04:02:28 +00:00
r = 63 * 2 , g = 5 * 2 , b = 5 * 2 ;
2013-12-15 18:08:12 +00:00
else if ( id = = POW_KEY_BLUE )
2016-02-12 04:02:28 +00:00
r = 5 * 2 , g = 5 * 2 , b = 63 * 2 ;
2013-12-15 18:08:12 +00:00
else if ( id = = POW_KEY_GOLD )
2016-02-12 04:02:28 +00:00
r = 63 * 2 , g = 63 * 2 , b = 10 * 2 ;
2013-12-15 18:08:12 +00:00
else
break ;
2014-11-13 03:41:29 +00:00
{
2016-02-12 04:02:28 +00:00
const auto color = gr_find_closest_color ( r , g , b ) ;
2014-11-13 03:41:29 +00:00
auto sphere_point = g3_rotate_point ( objp - > pos ) ;
2017-02-11 21:42:46 +00:00
g3_draw_sphere ( canvas , sphere_point , objp - > size * 4 , color ) ;
2014-11-13 03:41:29 +00:00
}
2006-03-20 17:12:09 +00:00
}
break ;
2016-11-20 23:12:00 +00:00
default :
break ;
2006-03-20 17:12:09 +00:00
}
}
g3_end_frame ( ) ;
2017-02-11 21:42:46 +00:00
name_frame ( canvas , am ) ;
2008-02-24 14:41:27 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2008-02-24 14:41:27 +00:00
{
2020-07-22 03:11:18 +00:00
const auto HighlightMarker = MarkerState . HighlightMarker ;
if ( MarkerState . message . valid_index ( HighlightMarker ) )
2018-03-10 18:32:02 +00:00
{
2018-03-10 22:45:04 +00:00
auto & m = MarkerState . message [ HighlightMarker ] ;
2020-07-22 03:11:18 +00:00
gr_printf ( canvas , * canvas . cv_font , ( SWIDTH / 64 ) , ( SHEIGHT / 18 ) , " Marker %u%c %s " , static_cast < unsigned > ( HighlightMarker ) + 1 , m [ 0 ] ? ' : ' : 0 , & m [ 0 ] ) ;
2018-03-10 18:32:02 +00:00
}
2008-02-24 14:41:27 +00:00
}
2013-03-03 01:03:33 +00:00
# endif
2011-01-06 13:56:26 +00:00
2011-01-10 15:12:04 +00:00
if ( PlayerCfg . MouseFlightSim & & PlayerCfg . MouseFSIndicator )
2017-02-11 21:42:42 +00:00
{
2017-02-11 21:42:46 +00:00
const auto gwidth = canvas . cv_bitmap . bm_w ;
const auto gheight = canvas . cv_bitmap . bm_h ;
2020-08-28 00:18:45 +00:00
auto & raw_mouse_axis = am . controls . raw_mouse_axis ;
2017-03-11 19:56:22 +00:00
show_mousefs_indicator ( canvas , raw_mouse_axis [ 0 ] , raw_mouse_axis [ 1 ] , raw_mouse_axis [ 2 ] , gwidth - ( gheight / 8 ) , gheight - ( gheight / 8 ) , gheight / 5 ) ;
2017-02-11 21:42:42 +00:00
}
2006-03-20 17:12:09 +00:00
2020-08-28 00:18:45 +00:00
am . t2 = timer_query ( ) ;
2015-07-18 03:49:47 +00:00
const auto vsync = CGameCfg . VSync ;
2015-11-24 04:05:35 +00:00
const auto bound = F1_0 / ( vsync ? MAXIMUM_FPS : CGameArg . SysMaxFPS ) ;
2015-12-24 04:01:26 +00:00
const auto may_sleep = ! CGameArg . SysNoNiceFPS & & ! vsync ;
2020-08-28 00:18:45 +00:00
while ( am . t2 - am . t1 < bound ) // ogl is fast enough that the automap can read the input too fast and you start to turn really slow. So delay a bit (and free up some cpu :)
2011-02-03 00:05:06 +00:00
{
2014-12-03 03:14:11 +00:00
if ( Game_mode & GM_MULTI )
multi_do_frame ( ) ; // during long wait, keep packets flowing
2015-07-18 03:49:47 +00:00
if ( may_sleep )
2013-12-09 15:28:34 +00:00
timer_delay ( F1_0 > > 8 ) ;
2020-08-28 00:18:45 +00:00
am . t2 = timer_update ( ) ;
2011-02-03 00:05:06 +00:00
}
2020-08-28 00:18:45 +00:00
if ( am . pause_game )
2011-02-03 00:05:06 +00:00
{
2020-08-28 00:18:45 +00:00
FrameTime = am . t2 - am . t1 ;
2012-05-14 17:06:28 +00:00
calc_d_tick ( ) ;
2011-02-03 00:05:06 +00:00
}
2020-08-28 00:18:45 +00:00
am . t1 = am . t2 ;
2011-02-03 00:05:06 +00:00
}
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2020-05-17 23:35:26 +00:00
# define MAP_BACKGROUND_FILENAME (((SWIDTH>=640&&SHEIGHT>=480) && PHYSFSX_exists("maph.pcx",1))?"maph.pcx":"map.pcx")
2013-03-03 01:03:33 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2020-05-17 23:35:26 +00:00
# define MAP_BACKGROUND_FILENAME ((HIRESMODE && PHYSFSX_exists("mapb.pcx",1))?"mapb.pcx":"map.pcx")
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2020-08-28 00:18:45 +00:00
static void recompute_automap_segment_visibility ( const d_level_unique_automap_state & LevelUniqueAutomapState , const object & plrobj , automap & am )
2013-12-15 18:32:10 +00:00
{
2020-08-28 00:18:45 +00:00
recompute_automap_segment_visibility ( LevelUniqueAutomapState , plrobj . ctype . player_info . powerup_flags & PLAYER_FLAGS_MAP_ALL , plrobj . segnum , am ) ;
2013-12-15 18:32:10 +00:00
}
2020-08-28 00:18:45 +00:00
static window_event_result automap_key_command ( const d_event & event , automap & am )
2010-03-26 14:05:40 +00:00
{
2019-03-03 00:31:08 +00:00
auto & Objects = LevelUniqueObjectState . Objects ;
# if defined(DXX_BUILD_DESCENT_I) || !defined(NDEBUG)
auto & vmobjptr = Objects . vmptr ;
# endif
# if defined(DXX_BUILD_DESCENT_II)
auto & vmobjptridx = Objects . vmptridx ;
# endif
2011-01-14 09:51:13 +00:00
int c = event_key_get ( event ) ;
2010-03-26 14:05:40 +00:00
switch ( c )
{
2018-06-16 04:13:37 +00:00
# if DXX_USE_SCREENSHOT
2010-03-26 14:05:40 +00:00
case KEY_PRINT_SCREEN : {
2017-11-05 20:49:08 +00:00
gr_set_default_canvas ( ) ;
2010-03-26 14:05:40 +00:00
save_screen_shot ( 1 ) ;
2014-08-06 02:10:49 +00:00
return window_event_result : : handled ;
2010-03-26 14:05:40 +00:00
}
2018-06-16 04:13:37 +00:00
# endif
2010-03-26 14:05:40 +00:00
case KEY_ESC :
2020-08-28 00:18:45 +00:00
if ( am . leave_mode = = 0 )
2010-03-26 14:05:40 +00:00
{
2014-08-06 02:10:49 +00:00
return window_event_result : : close ;
2010-03-26 14:05:40 +00:00
}
2014-08-06 02:10:49 +00:00
return window_event_result : : handled ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
case KEY_ALTED + KEY_F : // Alt+F shows full map, if cheats enabled
if ( cheats . enabled )
{
cheats . fullautomap = ! cheats . fullautomap ;
2013-12-15 12:11:14 +00:00
// if cheat of map powerup, work with full depth
2016-10-02 00:34:48 +00:00
auto & plrobj = get_local_plrobj ( ) ;
2020-08-28 00:18:45 +00:00
recompute_automap_segment_visibility ( LevelUniqueAutomapState , plrobj , am ) ;
2013-03-03 01:03:33 +00:00
}
2014-08-06 02:10:49 +00:00
return window_event_result : : handled ;
2013-03-03 01:03:33 +00:00
# endif
2010-03-26 14:05:40 +00:00
# ifndef NDEBUG
case KEY_DEBUGGED + KEY_F : {
2013-12-15 18:32:10 +00:00
Automap_debug_show_all_segments = ! Automap_debug_show_all_segments ;
2016-10-02 00:34:48 +00:00
auto & plrobj = get_local_plrobj ( ) ;
2020-08-28 00:18:45 +00:00
recompute_automap_segment_visibility ( LevelUniqueAutomapState , plrobj , am ) ;
2010-03-26 14:05:40 +00:00
}
2014-08-06 02:10:49 +00:00
return window_event_result : : handled ;
2010-03-26 14:05:40 +00:00
# endif
case KEY_F9 :
2020-08-28 00:18:45 +00:00
if ( am . segment_limit > 1 )
{
am . segment_limit - - ;
adjust_segment_limit ( am , am . segment_limit ) ;
2010-03-26 14:05:40 +00:00
}
2014-08-06 02:10:49 +00:00
return window_event_result : : handled ;
2010-03-26 14:05:40 +00:00
case KEY_F10 :
2020-08-28 00:18:45 +00:00
if ( am . segment_limit < am . max_segments_away ) {
am . segment_limit + + ;
adjust_segment_limit ( am , am . segment_limit ) ;
2010-03-26 14:05:40 +00:00
}
2014-08-06 02:10:49 +00:00
return window_event_result : : handled ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2010-03-26 14:05:40 +00:00
case KEY_1 :
case KEY_2 :
case KEY_3 :
case KEY_4 :
case KEY_5 :
case KEY_6 :
case KEY_7 :
case KEY_8 :
case KEY_9 :
case KEY_0 :
{
2018-03-10 22:45:04 +00:00
const auto game_mode = Game_mode ;
2020-07-22 03:11:18 +00:00
const auto max_numplayers = Netgame . max_numplayers ;
const auto maxdrop = MarkerState . get_markers_per_player ( game_mode , max_numplayers ) ;
const uint8_t marker_num = c - KEY_1 ;
2018-03-10 22:45:04 +00:00
if ( marker_num < = maxdrop )
{
2020-07-22 03:11:18 +00:00
const auto gmi = convert_player_marker_index_to_game_marker_index ( game_mode , max_numplayers , Player_num , player_marker_index { marker_num } ) ;
if ( MarkerState . imobjidx [ gmi ] ! = object_none )
MarkerState . HighlightMarker = gmi ;
2018-03-10 22:45:04 +00:00
}
else
2020-07-22 03:11:18 +00:00
MarkerState . HighlightMarker = game_marker_index : : None ;
2010-03-26 14:05:40 +00:00
}
2014-08-06 02:10:49 +00:00
return window_event_result : : handled ;
2010-03-26 14:05:40 +00:00
case KEY_D + KEY_CTRLED :
2018-03-10 22:45:04 +00:00
{
const auto HighlightMarker = MarkerState . HighlightMarker ;
2020-07-22 03:11:18 +00:00
if ( ! MarkerState . imobjidx . valid_index ( HighlightMarker ) )
2018-03-10 22:45:04 +00:00
return window_event_result : : handled ;
auto & mo = MarkerState . imobjidx [ HighlightMarker ] ;
if ( mo = = object_none )
return window_event_result : : handled ;
2017-11-05 20:49:08 +00:00
gr_set_default_canvas ( ) ;
2020-12-19 16:13:26 +00:00
if ( nm_messagebox_str ( menu_title { nullptr } , nm_messagebox_tie ( TXT_YES , TXT_NO ) , menu_subtitle { " Delete Marker? " } ) = = 0 )
2020-10-22 02:26:16 +00:00
{
2016-01-09 16:38:14 +00:00
/* FIXME: this event should be sent to other players
* so that they remove the marker .
*/
2020-05-02 21:18:42 +00:00
obj_delete ( LevelUniqueObjectState , Segments , vmobjptridx ( std : : exchange ( mo , object_none ) ) ) ;
2018-03-10 18:32:02 +00:00
MarkerState . message [ HighlightMarker ] = { } ;
2020-07-22 03:11:18 +00:00
MarkerState . HighlightMarker = game_marker_index : : None ;
2010-03-26 14:05:40 +00:00
}
set_screen_mode ( SCREEN_GAME ) ;
}
2014-08-06 02:10:49 +00:00
return window_event_result : : handled ;
2010-03-26 14:05:40 +00:00
# ifndef RELEASE
2012-04-22 09:38:14 +00:00
case KEY_F11 : //KEY_COMMA:
2010-03-26 14:05:40 +00:00
if ( MarkerScale > .5 )
MarkerScale - = .5 ;
2014-08-06 02:10:49 +00:00
return window_event_result : : handled ;
2012-04-22 09:38:14 +00:00
case KEY_F12 : //KEY_PERIOD:
2010-03-26 14:05:40 +00:00
if ( MarkerScale < 30.0 )
MarkerScale + = .5 ;
2014-08-06 02:10:49 +00:00
return window_event_result : : handled ;
2013-03-03 01:03:33 +00:00
# endif
2010-03-26 14:05:40 +00:00
# endif
}
2014-08-06 02:10:49 +00:00
return window_event_result : : ignored ;
2010-03-26 14:05:40 +00:00
}
2020-08-28 00:18:45 +00:00
static window_event_result automap_process_input ( const d_event & event , automap & am )
2009-12-02 13:49:54 +00:00
{
2020-08-28 00:18:45 +00:00
kconfig_read_controls ( am . controls , event , 1 ) ;
2011-02-06 13:25:37 +00:00
2020-08-28 00:18:45 +00:00
if ( ! am . controls . state . automap & & am . leave_mode = = 1 )
2009-12-02 13:49:54 +00:00
{
2014-08-06 02:10:49 +00:00
return window_event_result : : close ;
2009-12-02 13:49:54 +00:00
}
2020-08-28 00:18:45 +00:00
if ( am . controls . state . automap )
2011-02-02 00:36:49 +00:00
{
2020-08-28 00:18:45 +00:00
am . controls . state . automap = 0 ;
if ( am . leave_mode = = 0 )
2009-12-02 13:49:54 +00:00
{
2014-08-06 02:10:49 +00:00
return window_event_result : : close ;
2009-12-02 13:49:54 +00:00
}
}
2014-08-06 02:10:49 +00:00
return window_event_result : : ignored ;
2010-01-20 11:04:09 +00:00
}
2020-10-12 03:28:26 +00:00
}
2020-08-28 00:18:45 +00:00
window_event_result automap : : event_handler ( const d_event & event )
2010-01-20 11:04:09 +00:00
{
2019-03-03 00:31:08 +00:00
auto & Objects = LevelUniqueObjectState . Objects ;
auto & vcobjptr = Objects . vcptr ;
auto & vmobjptr = Objects . vmptr ;
2014-10-04 21:47:13 +00:00
switch ( event . type )
2010-01-20 11:04:09 +00:00
{
2010-02-25 08:00:15 +00:00
case EVENT_WINDOW_ACTIVATED :
2020-10-12 03:28:26 +00:00
game_flush_inputs ( controls ) ;
2010-12-28 18:11:10 +00:00
event_toggle_focus ( 1 ) ;
2011-02-02 00:36:49 +00:00
key_toggle_repeat ( 0 ) ;
2010-07-16 11:07:42 +00:00
break ;
case EVENT_WINDOW_DEACTIVATED :
2010-12-28 18:11:10 +00:00
event_toggle_focus ( 0 ) ;
2011-02-02 00:36:49 +00:00
key_toggle_repeat ( 1 ) ;
2010-02-25 08:00:15 +00:00
break ;
2019-08-18 20:37:29 +00:00
# if SDL_MAJOR_VERSION == 2
case EVENT_WINDOW_RESIZE :
2020-08-28 00:18:45 +00:00
init_automap_subcanvas ( automap_view , grd_curscreen - > sc_canvas ) ;
2019-08-18 20:37:29 +00:00
break ;
# endif
2011-02-03 00:05:06 +00:00
case EVENT_IDLE :
2020-09-11 03:08:02 +00:00
# if DXX_MAX_BUTTONS_PER_JOYSTICK
2011-02-02 00:36:49 +00:00
case EVENT_JOYSTICK_BUTTON_UP :
case EVENT_JOYSTICK_BUTTON_DOWN :
2020-09-11 03:08:02 +00:00
# endif
# if DXX_MAX_AXES_PER_JOYSTICK
2011-02-02 00:36:49 +00:00
case EVENT_JOYSTICK_MOVED :
2020-09-11 03:08:02 +00:00
# endif
2011-02-02 00:36:49 +00:00
case EVENT_MOUSE_BUTTON_UP :
case EVENT_MOUSE_BUTTON_DOWN :
case EVENT_MOUSE_MOVED :
2013-12-10 01:58:56 +00:00
case EVENT_KEY_RELEASE :
2020-08-28 00:18:45 +00:00
return automap_process_input ( event , * this ) ;
2010-03-26 14:05:40 +00:00
case EVENT_KEY_COMMAND :
2011-05-07 11:29:26 +00:00
{
2020-08-28 00:18:45 +00:00
window_event_result kret = automap_key_command ( event , * this ) ;
2014-08-06 02:10:49 +00:00
if ( kret = = window_event_result : : ignored )
2020-08-28 00:18:45 +00:00
kret = automap_process_input ( event , * this ) ;
2011-05-07 11:29:26 +00:00
return kret ;
}
2010-01-20 11:04:09 +00:00
case EVENT_WINDOW_DRAW :
2016-10-28 03:39:41 +00:00
{
auto & plrobj = get_local_plrobj ( ) ;
2020-08-28 00:18:45 +00:00
automap_apply_input ( * this , plrobj . orient , plrobj . pos ) ;
2016-10-28 03:39:41 +00:00
}
2020-08-28 00:18:45 +00:00
draw_automap ( vcobjptr , * this ) ;
2010-01-20 11:04:09 +00:00
break ;
case EVENT_WINDOW_CLOSE :
2020-08-28 00:18:45 +00:00
if ( ! pause_game )
ConsoleObject - > mtype . phys_info . flags | = old_wiggle ; // Restore wiggle
2010-12-28 18:11:10 +00:00
event_toggle_focus ( 0 ) ;
2011-02-02 00:36:49 +00:00
key_toggle_repeat ( 1 ) ;
2020-08-28 00:18:45 +00:00
/* grd_curcanv points to `automap_view`, so grd_curcanv
Clear canvas to fix missing exit tunnel movie
Global variable `grd_curcanv` is set to a variety of canvases, some of
which are local stack variables. Use of global variables in this way is
fragile, but works as long as the global is not used beyond the life of
the backing local.
Unfortunately, some existing uses do access the canvas beyond the
lifetime of the backing local. Playing movies sets the font of the
current canvas. If the current canvas is an expired stack variable,
setting the font overwrites other stack data. This data corruption
causes various symptoms, such as inability to play the escape tunnel
movie.
Prior to 03cca2b3dce62ae29c1ab7509df5105423365b4a, the corruption on
playing the endlevel movie had no user-visible effect. That commit
created a large local variable, which changed stack layout. Starting
with that commit, the corruption causes the movie to play as all black.
Fix this, and protect against some other data corruption possiblities,
by clearing the global when the local goes out of scope.
Reported-by: Havner <https://github.com/dxx-rebirth/dxx-rebirth/issues/345> (only as cutscene failure to play, not as the underlying corruption issue)
2017-11-05 20:49:08 +00:00
* would become a dangling pointer after the call to delete .
* Redirect it to the default screen to avoid pointing to
* freed memory . Setting grd_curcanv to nullptr would be
* better , but some code assumes that grd_curcanv is never
* nullptr , so instead set it to the default canvas .
* Eventually , grd_curcanv will be removed entirely .
*/
gr_set_default_canvas ( ) ;
2020-08-28 00:18:45 +00:00
window_set_visible ( * Game_wind , 1 ) ;
2010-01-29 03:36:44 +00:00
Automap_active = 0 ;
2013-12-13 22:48:42 +00:00
multi_send_msgsend_state ( msgsend_none ) ;
2014-08-06 02:10:49 +00:00
return window_event_result : : ignored ; // continue closing
2013-02-21 00:20:26 +00:00
2020-05-27 03:07:17 +00:00
case EVENT_LOOP_BEGIN_LOOP :
2020-08-28 00:18:45 +00:00
kconfig_begin_loop ( controls ) ;
2020-05-27 03:07:17 +00:00
break ;
2010-01-20 11:04:09 +00:00
default :
2014-08-06 02:10:49 +00:00
return window_event_result : : ignored ;
2010-01-20 11:04:09 +00:00
break ;
}
2014-08-06 02:10:49 +00:00
return window_event_result : : handled ;
2009-12-02 13:49:54 +00:00
}
2006-03-20 17:12:09 +00:00
2014-07-16 02:35:14 +00:00
void do_automap ( )
2009-12-27 12:27:44 +00:00
{
2019-03-03 00:31:08 +00:00
auto & Objects = LevelUniqueObjectState . Objects ;
auto & vmobjptr = Objects . vmptr ;
2013-01-06 21:03:57 +00:00
palette_array_t pal ;
2020-08-28 00:18:45 +00:00
auto am = std : : make_unique < automap > ( grd_curscreen - > sc_canvas , 0 , 0 , SWIDTH , SHEIGHT ) ;
2018-09-19 02:13:29 +00:00
const auto max_edges = LevelSharedSegmentState . Num_segments * 12 ;
2016-08-06 19:55:24 +00:00
am - > max_edges = max_edges ;
2020-05-02 21:18:42 +00:00
am - > edges = std : : make_unique < Edge_info [ ] > ( max_edges ) ;
am - > drawingListBright = std : : make_unique < Edge_info * [ ] > ( max_edges ) ;
2006-03-20 17:12:09 +00:00
2020-08-28 00:18:45 +00:00
init_automap_colors ( * am ) ;
2016-12-10 17:51:11 +00:00
am - > pause_game = ! ( ( Game_mode & GM_MULTI ) & & ( ! Endlevel_sequence ) ) ; // Set to 1 if everything is paused during automap...No pause during net.
2006-03-20 17:12:09 +00:00
2009-12-02 13:49:54 +00:00
if ( am - > pause_game ) {
2020-08-28 00:18:45 +00:00
window_set_visible ( * Game_wind , 0 ) ;
2006-03-20 17:12:09 +00:00
}
2015-10-03 17:17:49 +00:00
else
{
2011-02-06 13:25:37 +00:00
am - > old_wiggle = ConsoleObject - > mtype . phys_info . flags & PF_WIGGLE ; // Save old wiggle
ConsoleObject - > mtype . phys_info . flags & = ~ PF_WIGGLE ; // Turn off wiggle
}
2006-03-20 17:12:09 +00:00
2009-12-27 12:27:44 +00:00
//Max_edges = min(MAX_EDGES_FROM_VERTS(Num_vertices),MAX_EDGES); //make maybe smaller than max
2006-03-20 17:12:09 +00:00
2017-11-05 20:49:08 +00:00
gr_set_default_canvas ( ) ;
2009-12-02 13:49:54 +00:00
2011-05-20 10:23:28 +00:00
if ( am - > viewDist = = 0 )
am - > viewDist = ZOOM_DEFAULT ;
2009-12-02 13:49:54 +00:00
2016-07-03 00:54:16 +00:00
auto & plrobj = get_local_plrobj ( ) ;
am - > viewMatrix = plrobj . orient ;
2011-05-20 10:23:28 +00:00
am - > tangles . p = PITCH_DEFAULT ;
am - > tangles . h = 0 ;
am - > tangles . b = 0 ;
2016-07-03 00:54:16 +00:00
am - > view_target = plrobj . pos ;
2011-05-20 10:23:28 +00:00
if ( PlayerCfg . AutomapFreeFlight )
2016-07-03 00:54:16 +00:00
vm_vec_scale_add ( am - > view_position , plrobj . pos , am - > viewMatrix . fvec , - ZOOM_DEFAULT ) ;
2009-12-02 13:49:54 +00:00
2010-12-10 23:18:17 +00:00
am - > t1 = am - > entry_time = timer_query ( ) ;
2009-12-02 13:49:54 +00:00
am - > t2 = am - > t1 ;
//Fill in Automap_visited from Objects[Players[Player_num].objnum].segnum
2020-08-28 00:18:45 +00:00
recompute_automap_segment_visibility ( LevelUniqueAutomapState , plrobj , * am ) ;
2009-12-02 13:49:54 +00:00
// ZICO - code from above to show frame in OGL correctly. Redundant, but better readable.
// KREATOR - Now applies to all platforms so double buffering is supported
2017-09-10 04:28:41 +00:00
{
const auto pcx_error = pcx_read_bitmap ( MAP_BACKGROUND_FILENAME , am - > automap_background , pal ) ;
2019-07-07 22:00:02 +00:00
if ( pcx_error ! = pcx_result : : SUCCESS )
2017-09-10 04:28:41 +00:00
con_printf ( CON_URGENT , DXX_STRINGIZE_FL ( __FILE__ , __LINE__ , " automap: File %s - PCX error: %s " ) , MAP_BACKGROUND_FILENAME , pcx_errormsg ( pcx_error ) ) ;
else
gr_remap_bitmap_good ( am - > automap_background , pal , - 1 , - 1 ) ;
}
2019-08-18 20:37:29 +00:00
init_automap_subcanvas ( am - > automap_view , grd_curscreen - > sc_canvas ) ;
2009-12-02 13:49:54 +00:00
gr_palette_load ( gr_palette ) ;
2010-01-29 03:36:44 +00:00
Automap_active = 1 ;
2013-12-13 22:48:42 +00:00
multi_send_msgsend_state ( msgsend_automap ) ;
2020-10-22 02:26:16 +00:00
am - > send_creation_events ( ) ;
2020-08-28 00:18:45 +00:00
am . release ( ) ;
2006-03-20 17:12:09 +00:00
}
2020-08-28 00:18:45 +00:00
namespace {
2006-03-20 17:12:09 +00:00
2020-08-28 00:18:45 +00:00
void draw_all_edges ( grs_canvas & canvas , automap & am )
2006-03-20 17:12:09 +00:00
{
2020-05-17 23:35:25 +00:00
auto & LevelSharedVertexState = LevelSharedSegmentState . get_vertex_state ( ) ;
auto & Vertices = LevelSharedVertexState . get_vertices ( ) ;
2017-03-10 01:22:33 +00:00
int j ;
2015-10-03 17:17:49 +00:00
unsigned nbright = 0 ;
2006-03-20 17:12:09 +00:00
ubyte nfacing , nnfacing ;
fix distance ;
2017-02-22 03:05:43 +00:00
fix min_distance = INT32_MAX ;
2006-03-20 17:12:09 +00:00
2018-12-30 00:43:57 +00:00
auto & vcvertptr = Vertices . vcptr ;
2020-08-28 00:18:45 +00:00
range_for ( auto & i , unchecked_partial_range ( am . edges . get ( ) , am . end_valid_edges ) )
2017-03-10 01:22:33 +00:00
{
const auto e = & i ;
2006-03-20 17:12:09 +00:00
if ( ! ( e - > flags & EF_USED ) ) continue ;
if ( e - > flags & EF_TOO_FAR ) continue ;
2006-08-07 00:27:18 +00:00
if ( e - > flags & EF_FRONTIER ) { // A line that is between what we have seen and what we haven't
2020-08-28 00:18:45 +00:00
if ( ( ! ( e - > flags & EF_SECRET ) ) & & ( e - > color = = am . wall_normal_color ) )
2006-08-07 00:27:18 +00:00
continue ; // If a line isn't secret and is normal color, then don't draw it
2006-03-20 17:12:09 +00:00
}
distance = Segment_points [ e - > verts [ 1 ] ] . p3_z ;
if ( min_distance > distance )
min_distance = distance ;
2018-12-30 00:43:57 +00:00
if ( ! rotate_list ( vcvertptr , e - > verts ) . uand )
2015-10-18 21:01:18 +00:00
{ //all off screen?
2006-03-20 17:12:09 +00:00
nfacing = nnfacing = 0 ;
2017-08-11 23:43:54 +00:00
auto & tv1 = * vcvertptr ( e - > verts [ 0 ] ) ;
2006-03-20 17:12:09 +00:00
j = 0 ;
while ( j < e - > num_faces & & ( nfacing = = 0 | | nnfacing = = 0 ) ) {
2018-12-13 02:31:38 +00:00
if ( ! g3_check_normal_facing ( tv1 , vcsegptr ( e - > segnum [ j ] ) - > shared_segment : : sides [ e - > sides [ j ] ] . normals [ 0 ] ) )
2006-03-20 17:12:09 +00:00
nfacing + + ;
else
nnfacing + + ;
j + + ;
}
if ( nfacing & & nnfacing ) {
// a contour line
2020-08-28 00:18:45 +00:00
am . drawingListBright [ nbright + + ] = e ;
2006-03-20 17:12:09 +00:00
} else if ( e - > flags & ( EF_DEFINING | EF_GRATE ) ) {
if ( nfacing = = 0 ) {
2016-02-12 04:02:28 +00:00
const uint8_t color = ( e - > flags & EF_NO_FADE )
? e - > color
: gr_fade_table [ 8 ] [ e - > color ] ;
2017-03-11 19:56:23 +00:00
g3_draw_line ( canvas , Segment_points [ e - > verts [ 0 ] ] , Segment_points [ e - > verts [ 1 ] ] , color ) ;
2006-03-20 17:12:09 +00:00
} else {
2020-08-28 00:18:45 +00:00
am . drawingListBright [ nbright + + ] = e ;
2006-03-20 17:12:09 +00:00
}
}
}
}
if ( min_distance < 0 ) min_distance = 0 ;
// Sort the bright ones using a shell sort
2020-08-28 00:18:45 +00:00
const auto & & range = unchecked_partial_range ( am . drawingListBright . get ( ) , nbright ) ;
2017-12-24 00:28:35 +00:00
std : : sort ( range . begin ( ) , range . end ( ) , [ ] ( const Edge_info * const a , const Edge_info * const b ) {
2015-10-03 17:17:49 +00:00
const auto & v1 = a - > verts [ 0 ] ;
const auto & v2 = b - > verts [ 0 ] ;
return Segment_points [ v1 ] . p3_z < Segment_points [ v2 ] . p3_z ;
} ) ;
2006-03-20 17:12:09 +00:00
// Draw the bright ones
2015-10-03 17:17:49 +00:00
range_for ( const auto e , range )
{
const auto p1 = & Segment_points [ e - > verts [ 0 ] ] ;
const auto p2 = & Segment_points [ e - > verts [ 1 ] ] ;
2006-03-20 17:12:09 +00:00
fix dist ;
dist = p1 - > p3_z - min_distance ;
// Make distance be 1.0 to 0.0, where 0.0 is 10 segments away;
if ( dist < 0 ) dist = 0 ;
2020-08-28 00:18:45 +00:00
if ( dist > = am . farthest_dist ) continue ;
2006-03-20 17:12:09 +00:00
2016-02-12 04:02:28 +00:00
const auto color = ( e - > flags & EF_NO_FADE )
? e - > color
2020-08-28 00:18:45 +00:00
: gr_fade_table [ f2i ( ( F1_0 - fixdiv ( dist , am . farthest_dist ) ) * 31 ) ] [ e - > color ] ;
2017-03-11 19:56:23 +00:00
g3_draw_line ( canvas , * p1 , * p2 , color ) ;
2006-03-20 17:12:09 +00:00
}
}
//==================================================================
//
// All routines below here are used to build the Edge list
//
//==================================================================
//finds edge, filling in edge_ptr. if found old edge, returns index, else return -1
2020-08-28 00:18:45 +00:00
static std : : pair < Edge_info & , unsigned > automap_find_edge ( automap & am , const unsigned v0 , const unsigned v1 )
2006-03-20 17:12:09 +00:00
{
long vv , evv ;
2011-06-30 10:23:38 +00:00
int hash , oldhash ;
2006-03-20 17:12:09 +00:00
vv = ( v1 < < 16 ) + v0 ;
2020-08-28 00:18:45 +00:00
oldhash = hash = ( ( v0 * 5 + v1 ) % am . max_edges ) ;
2017-03-10 01:22:33 +00:00
for ( ; ; )
{
2020-08-28 00:18:45 +00:00
auto & e = am . edges [ hash ] ;
2017-03-10 01:22:33 +00:00
const auto ev0 = e . verts [ 0 ] ;
const auto ev1 = e . verts [ 1 ] ;
2006-03-20 17:12:09 +00:00
evv = ( ev1 < < 16 ) + ev0 ;
2017-03-10 01:22:33 +00:00
if ( e . num_faces = = 0 )
return { e , hash } ;
else if ( evv = = vv )
return { e , UINT32_MAX } ;
2006-03-20 17:12:09 +00:00
else {
2020-08-28 00:18:45 +00:00
if ( + + hash = = am . max_edges ) hash = 0 ;
2006-03-20 17:12:09 +00:00
if ( hash = = oldhash ) Error ( " Edge list full! " ) ;
}
}
}
2020-08-28 00:18:45 +00:00
static void add_one_edge ( automap & am , unsigned va , unsigned vb , const uint8_t color , const unsigned side , const segnum_t segnum , const uint8_t flags )
2016-09-30 01:49:57 +00:00
{
2020-08-28 00:18:45 +00:00
if ( am . num_edges > = am . max_edges )
{
2006-03-20 17:12:09 +00:00
// GET JOHN! (And tell him that his
// MAX_EDGES_FROM_VERTS formula is hosed.)
// If he's not around, save the mine,
// and send him mail so he can look
// at the mine later. Don't modify it.
// This is important if this happens.
Int3 ( ) ; // LOOK ABOVE!!!!!!
return ;
}
if ( va > vb ) {
2014-12-14 05:22:59 +00:00
std : : swap ( va , vb ) ;
2006-03-20 17:12:09 +00:00
}
2017-03-10 01:22:33 +00:00
const auto & & ef = automap_find_edge ( am , va , vb ) ;
const auto e = & ef . first ;
2006-03-20 17:12:09 +00:00
2017-03-10 01:22:33 +00:00
if ( ef . second ! = UINT32_MAX )
{
2006-03-20 17:12:09 +00:00
e - > verts [ 0 ] = va ;
e - > verts [ 1 ] = vb ;
e - > color = color ;
e - > num_faces = 1 ;
e - > flags = EF_USED | EF_DEFINING ; // Assume a normal line
e - > sides [ 0 ] = side ;
e - > segnum [ 0 ] = segnum ;
2020-08-28 00:18:45 +00:00
+ + am . num_edges ;
2017-03-10 01:22:33 +00:00
const auto i = ef . second + 1 ;
2020-08-28 00:18:45 +00:00
if ( am . end_valid_edges < i )
am . end_valid_edges = i ;
2006-03-20 17:12:09 +00:00
} else {
2020-08-28 00:18:45 +00:00
if ( color ! = am . wall_normal_color )
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2020-08-28 00:18:45 +00:00
if ( color ! = am . wall_revealed_color )
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
e - > color = color ;
if ( e - > num_faces < 4 ) {
2009-12-02 13:49:54 +00:00
e - > sides [ e - > num_faces ] = side ;
2006-03-20 17:12:09 +00:00
e - > segnum [ e - > num_faces ] = segnum ;
e - > num_faces + + ;
}
}
2016-09-30 01:49:57 +00:00
e - > flags | = flags ;
2006-03-20 17:12:09 +00:00
}
2020-08-28 00:18:45 +00:00
static void add_one_unknown_edge ( automap & am , unsigned va , unsigned vb )
2009-12-27 12:27:44 +00:00
{
2006-03-20 17:12:09 +00:00
if ( va > vb ) {
2014-12-14 05:22:59 +00:00
std : : swap ( va , vb ) ;
2006-03-20 17:12:09 +00:00
}
2017-03-10 01:22:33 +00:00
const auto & & ef = automap_find_edge ( am , va , vb ) ;
if ( ef . second = = UINT32_MAX )
ef . first . flags | = EF_FRONTIER ; // Mark as a border edge
2006-03-20 17:12:09 +00:00
}
2020-08-28 00:18:45 +00:00
static void add_segment_edges ( fvcsegptr & vcsegptr , fvcwallptr & vcwallptr , automap & am , const vcsegptridx_t seg )
2006-03-20 17:12:09 +00:00
{
2019-08-15 01:34:22 +00:00
auto & ControlCenterState = LevelUniqueObjectState . ControlCenterState ;
2020-04-04 19:30:22 +00:00
auto & WallAnims = GameSharedState . WallAnims ;
2019-03-03 00:31:08 +00:00
# if defined(DXX_BUILD_DESCENT_II)
auto & Objects = LevelUniqueObjectState . Objects ;
auto & vmobjptr = Objects . vmptr ;
# endif
2006-03-20 17:12:09 +00:00
ubyte color ;
2017-02-19 19:33:38 +00:00
for ( unsigned sn = 0 ; sn < MAX_SIDES_PER_SEGMENT ; + + sn )
{
2016-09-30 01:49:57 +00:00
uint8_t hidden_flag = 0 ;
2017-03-10 01:22:34 +00:00
uint8_t is_grate = 0 ;
2016-09-30 01:49:57 +00:00
uint8_t no_fade = 0 ;
2006-03-20 17:12:09 +00:00
color = 255 ;
2020-08-24 01:31:28 +00:00
if ( seg - > shared_segment : : children [ sn ] = = segment_none ) {
2020-08-28 00:18:45 +00:00
color = am . wall_normal_color ;
2006-03-20 17:12:09 +00:00
}
2013-03-03 01:03:33 +00:00
switch ( seg - > special ) {
2006-03-20 17:12:09 +00:00
case SEGMENT_IS_FUELCEN :
color = BM_XRGB ( 29 , 27 , 13 ) ;
break ;
case SEGMENT_IS_CONTROLCEN :
2019-08-15 01:34:22 +00:00
if ( ControlCenterState . Control_center_present )
2006-03-20 17:12:09 +00:00
color = BM_XRGB ( 29 , 0 , 0 ) ;
break ;
case SEGMENT_IS_ROBOTMAKER :
color = BM_XRGB ( 29 , 0 , 31 ) ;
break ;
}
2018-12-13 02:31:38 +00:00
const auto wall_num = seg - > shared_segment : : sides [ sn ] . wall_num ;
if ( wall_num ! = wall_none )
{
auto & w = * vcwallptr ( wall_num ) ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2016-02-12 04:02:28 +00:00
auto trigger_num = w . trigger ;
2018-12-30 00:43:58 +00:00
auto & Triggers = LevelUniqueWallSubsystemState . Triggers ;
auto & vmtrgptr = Triggers . vmptr ;
2020-07-05 23:34:32 +00:00
if ( trigger_num ! = trigger_none & & vmtrgptr ( trigger_num ) - > type = = trigger_action : : secret_exit )
2006-03-20 17:12:09 +00:00
{
2006-08-07 00:27:18 +00:00
color = BM_XRGB ( 29 , 0 , 31 ) ;
2016-09-30 01:49:57 +00:00
no_fade = EF_NO_FADE ;
2006-03-20 17:12:09 +00:00
goto Here ;
}
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2016-02-12 04:02:28 +00:00
switch ( w . type )
{
2006-03-20 17:12:09 +00:00
case WALL_DOOR :
2020-12-19 16:13:26 +00:00
if ( ( w . keys = = wall_key : : blue & & ( color = am . wall_door_blue , true ) ) | |
( w . keys = = wall_key : : gold & & ( color = am . wall_door_gold , true ) ) | |
( w . keys = = wall_key : : red & & ( color = am . wall_door_red , true ) ) )
2017-03-10 01:22:34 +00:00
{
2016-09-30 01:49:57 +00:00
no_fade = EF_NO_FADE ;
2016-02-12 04:02:28 +00:00
} else if ( ! ( WallAnims [ w . clip_num ] . flags & WCF_HIDDEN ) ) {
2020-08-24 01:31:28 +00:00
const auto connected_seg = seg - > shared_segment : : children [ sn ] ;
2013-12-26 22:21:16 +00:00
if ( connected_seg ! = segment_none ) {
2019-12-22 05:34:08 +00:00
const shared_segment & vcseg = * vcsegptr ( connected_seg ) ;
2015-04-22 02:44:30 +00:00
const auto & connected_side = find_connect_side ( seg , vcseg ) ;
2019-12-22 05:34:08 +00:00
auto & wall = * vcwallptr ( vcseg . sides [ connected_side ] . wall_num ) ;
2018-06-24 05:06:15 +00:00
switch ( wall . keys )
2015-04-22 02:44:30 +00:00
{
2020-12-19 16:13:26 +00:00
case wall_key : : blue :
2020-08-28 00:18:45 +00:00
color = am . wall_door_blue ;
2016-09-30 01:49:57 +00:00
no_fade = EF_NO_FADE ;
break ;
2020-12-19 16:13:26 +00:00
case wall_key : : gold :
2020-08-28 00:18:45 +00:00
color = am . wall_door_gold ;
2016-09-30 01:49:57 +00:00
no_fade = EF_NO_FADE ;
break ;
2020-12-19 16:13:26 +00:00
case wall_key : : red :
2020-08-28 00:18:45 +00:00
color = am . wall_door_red ;
2016-09-30 01:49:57 +00:00
no_fade = EF_NO_FADE ;
break ;
2015-04-22 02:44:30 +00:00
default :
2020-08-28 00:18:45 +00:00
color = am . wall_door_color ;
2015-04-22 02:44:30 +00:00
break ;
2006-03-20 17:12:09 +00:00
}
}
} else {
2020-08-28 00:18:45 +00:00
color = am . wall_normal_color ;
2016-09-30 01:49:57 +00:00
hidden_flag = EF_SECRET ;
2006-03-20 17:12:09 +00:00
}
break ;
case WALL_CLOSED :
// Make grates draw properly
2013-12-15 12:11:14 +00:00
// NOTE: In original D1, is_grate is 1, hidden_flag not used so grates never fade. I (zico) like this so I leave this alone for now.
2020-12-19 16:13:26 +00:00
if ( ! ( is_grate = WALL_IS_DOORWAY ( GameBitmaps , Textures , vcwallptr , seg , sn ) & WALL_IS_DOORWAY_FLAG : : rendpast ) )
2016-09-30 01:49:57 +00:00
hidden_flag = EF_SECRET ;
2020-08-28 00:18:45 +00:00
color = am . wall_normal_color ;
2006-03-20 17:12:09 +00:00
break ;
case WALL_BLASTABLE :
// Hostage doors
2020-08-28 00:18:45 +00:00
color = am . wall_door_color ;
2006-03-20 17:12:09 +00:00
break ;
}
}
2019-12-16 01:56:59 +00:00
if ( seg = = Player_init [ Player_num ] . segnum )
2006-03-20 17:12:09 +00:00
color = BM_XRGB ( 31 , 0 , 31 ) ;
if ( color ! = 255 ) {
2013-12-15 12:11:14 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
// If they have a map powerup, draw unvisited areas in dark blue.
2013-12-15 12:11:14 +00:00
// NOTE: D1 originally had this part of code but w/o cheat-check. It's only supposed to draw blue with powerup that does not exist in D1. So make this D2-only
2020-08-28 00:18:45 +00:00
# ifndef NDEBUG
2013-12-15 18:32:10 +00:00
if ( ! Automap_debug_show_all_segments )
2020-08-28 00:18:45 +00:00
# endif
2016-10-02 00:34:40 +00:00
{
auto & player_info = get_local_plrobj ( ) . ctype . player_info ;
2019-12-16 01:56:59 +00:00
if ( ( cheats . fullautomap | | player_info . powerup_flags & PLAYER_FLAGS_MAP_ALL ) & & ! LevelUniqueAutomapState . Automap_visited [ seg ] )
2020-08-28 00:18:45 +00:00
color = am . wall_revealed_color ;
2016-10-02 00:34:40 +00:00
}
2006-03-20 17:12:09 +00:00
Here :
2013-03-03 01:03:33 +00:00
# endif
2019-12-16 01:56:59 +00:00
const auto vertex_list = get_side_verts ( seg , sn ) ;
2016-09-30 01:49:57 +00:00
const uint8_t flags = hidden_flag | no_fade ;
2019-12-16 01:56:59 +00:00
add_one_edge ( am , vertex_list [ 0 ] , vertex_list [ 1 ] , color , sn , seg , flags ) ;
add_one_edge ( am , vertex_list [ 1 ] , vertex_list [ 2 ] , color , sn , seg , flags ) ;
add_one_edge ( am , vertex_list [ 2 ] , vertex_list [ 3 ] , color , sn , seg , flags ) ;
add_one_edge ( am , vertex_list [ 3 ] , vertex_list [ 0 ] , color , sn , seg , flags ) ;
2006-03-20 17:12:09 +00:00
if ( is_grate ) {
2016-09-30 01:49:57 +00:00
const uint8_t grate_flags = flags | EF_GRATE ;
2019-12-16 01:56:59 +00:00
add_one_edge ( am , vertex_list [ 0 ] , vertex_list [ 2 ] , color , sn , seg , grate_flags ) ;
add_one_edge ( am , vertex_list [ 1 ] , vertex_list [ 3 ] , color , sn , seg , grate_flags ) ;
2006-03-20 17:12:09 +00:00
}
}
}
}
// Adds all the edges from a segment we haven't visited yet.
2020-08-28 00:18:45 +00:00
static void add_unknown_segment_edges ( automap & am , const shared_segment & seg )
2006-03-20 17:12:09 +00:00
{
2020-08-28 00:18:45 +00:00
for ( const auto sn : xrange ( MAX_SIDES_PER_SEGMENT ) )
2017-02-19 19:33:38 +00:00
{
2006-03-20 17:12:09 +00:00
// Only add edges that have no children
2018-12-30 00:43:57 +00:00
if ( seg . children [ sn ] = = segment_none ) {
const auto vertex_list = get_side_verts ( seg , sn ) ;
2006-03-20 17:12:09 +00:00
2009-12-27 12:27:44 +00:00
add_one_unknown_edge ( am , vertex_list [ 0 ] , vertex_list [ 1 ] ) ;
add_one_unknown_edge ( am , vertex_list [ 1 ] , vertex_list [ 2 ] ) ;
add_one_unknown_edge ( am , vertex_list [ 2 ] , vertex_list [ 3 ] ) ;
add_one_unknown_edge ( am , vertex_list [ 3 ] , vertex_list [ 0 ] ) ;
2006-03-20 17:12:09 +00:00
}
}
}
2020-08-28 00:18:45 +00:00
void automap_build_edge_list ( automap & am , int add_all_edges )
2020-08-28 00:18:45 +00:00
{
2006-03-20 17:12:09 +00:00
// clear edge list
2020-08-28 00:18:45 +00:00
for ( auto & i : unchecked_partial_range ( am . edges . get ( ) , am . max_edges ) )
2017-03-10 01:22:33 +00:00
{
i . num_faces = 0 ;
i . flags = 0 ;
2006-03-20 17:12:09 +00:00
}
2020-08-28 00:18:45 +00:00
am . num_edges = 0 ;
am . end_valid_edges = 0 ;
2006-03-20 17:12:09 +00:00
2018-12-30 00:43:58 +00:00
auto & Walls = LevelUniqueWallSubsystemState . Walls ;
auto & vcwallptr = Walls . vcptr ;
2013-12-15 18:32:10 +00:00
if ( add_all_edges ) {
2006-03-20 17:12:09 +00:00
// Cheating, add all edges as visited
2016-02-12 04:02:28 +00:00
range_for ( const auto & & segp , vcsegptridx )
2015-06-13 22:42:16 +00:00
{
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2020-08-24 01:31:28 +00:00
if ( segp - > shared_segment : : segnum ! = segment_none )
2006-08-07 00:27:18 +00:00
# endif
2006-03-20 17:12:09 +00:00
{
2017-07-26 03:15:59 +00:00
add_segment_edges ( vcsegptr , vcwallptr , am , segp ) ;
2006-03-20 17:12:09 +00:00
}
2015-06-13 22:42:16 +00:00
}
2006-03-20 17:12:09 +00:00
} else {
// Not cheating, add visited edges, and then unvisited edges
2016-02-12 04:02:28 +00:00
range_for ( const auto & & segp , vcsegptridx )
2015-06-13 22:42:16 +00:00
{
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2020-08-24 01:31:28 +00:00
if ( segp - > shared_segment : : segnum ! = segment_none )
2006-08-07 00:27:18 +00:00
# endif
2019-08-06 02:59:40 +00:00
if ( LevelUniqueAutomapState . Automap_visited [ segp ] )
{
2017-07-26 03:15:59 +00:00
add_segment_edges ( vcsegptr , vcwallptr , am , segp ) ;
2006-03-20 17:12:09 +00:00
}
2015-06-13 22:42:16 +00:00
}
2016-02-12 04:02:28 +00:00
range_for ( const auto & & segp , vcsegptridx )
2015-06-13 22:42:16 +00:00
{
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2020-08-24 01:31:28 +00:00
if ( segp - > shared_segment : : segnum ! = segment_none )
2006-08-07 00:27:18 +00:00
# endif
2019-08-06 02:59:40 +00:00
if ( ! LevelUniqueAutomapState . Automap_visited [ segp ] )
{
2015-06-13 22:42:16 +00:00
add_unknown_segment_edges ( am , segp ) ;
2006-03-20 17:12:09 +00:00
}
2015-06-13 22:42:16 +00:00
}
2006-03-20 17:12:09 +00:00
}
// Find unnecessary lines (These are lines that don't have to be drawn because they have small curvature)
2020-08-28 00:18:45 +00:00
for ( auto & i : unchecked_partial_range ( am . edges . get ( ) , am . end_valid_edges ) )
2017-03-10 01:22:33 +00:00
{
const auto e = & i ;
2006-03-20 17:12:09 +00:00
if ( ! ( e - > flags & EF_USED ) ) continue ;
2017-03-10 01:22:33 +00:00
const auto num_faces = e - > num_faces ;
if ( num_faces < 2 )
continue ;
for ( unsigned e1 = 0 ; e1 < num_faces ; + + e1 )
{
const auto e1segnum = e - > segnum [ e1 ] ;
2018-12-13 02:31:38 +00:00
const auto & e1siden0 = vcsegptr ( e1segnum ) - > shared_segment : : sides [ e - > sides [ e1 ] ] . normals [ 0 ] ;
2017-03-10 01:22:33 +00:00
for ( unsigned e2 = 1 ; e2 < num_faces ; + + e2 )
{
if ( e1 = = e2 )
continue ;
const auto e2segnum = e - > segnum [ e2 ] ;
if ( e1segnum = = e2segnum )
continue ;
2018-12-13 02:31:38 +00:00
if ( vm_vec_dot ( e1siden0 , vcsegptr ( e2segnum ) - > shared_segment : : sides [ e - > sides [ e2 ] ] . normals [ 0 ] ) > ( F1_0 - ( F1_0 / 10 ) ) )
2017-03-10 01:22:33 +00:00
{
e - > flags & = ( ~ EF_DEFINING ) ;
break ;
2006-03-20 17:12:09 +00:00
}
}
if ( ! ( e - > flags & EF_DEFINING ) )
break ;
}
2009-12-02 13:49:54 +00:00
}
2006-03-20 17:12:09 +00:00
}
2020-08-28 00:18:45 +00:00
}
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2014-12-22 04:35:48 +00:00
static unsigned Marker_index ;
2006-03-20 17:12:09 +00:00
void InitMarkerInput ( )
2006-08-07 00:27:18 +00:00
{
2006-03-20 17:12:09 +00:00
//find free marker slot
2018-03-10 22:45:04 +00:00
const auto game_mode = Game_mode ;
2020-07-22 03:11:18 +00:00
const auto max_numplayers = Netgame . max_numplayers ;
const auto maxdrop = MarkerState . get_markers_per_player ( game_mode , max_numplayers ) ;
const auto & & game_marker_range = get_game_marker_range ( game_mode , max_numplayers , Player_num , maxdrop ) ;
const auto & & player_marker_range = get_player_marker_range ( maxdrop ) ;
2020-08-06 03:47:56 +00:00
const auto & & zipped_marker_range = zip ( player_marker_range , unchecked_partial_range ( & MarkerState . imobjidx [ * game_marker_range . begin ( ) ] , maxdrop ) ) ;
2020-07-22 03:11:18 +00:00
const auto & & mb = zipped_marker_range . begin ( ) ;
const auto & & me = zipped_marker_range . end ( ) ;
auto iter = mb ;
for ( ; ; )
2006-03-20 17:12:09 +00:00
{
2020-08-06 03:47:56 +00:00
auto & & [ pmi , objidx ] = * iter ;
2020-07-22 03:11:18 +00:00
if ( objidx = = object_none ) //found free slot!
{
MarkerState . MarkerBeingDefined = pmi ;
break ;
}
if ( + + iter = = me ) //no free slot
{
if ( game_mode & GM_MULTI )
{
//in multi, replace oldest
MarkerState . MarkerBeingDefined = static_cast < player_marker_index > ( ( static_cast < unsigned > ( MarkerState . LastMarkerDropped ) + 1 ) & ( maxdrop - 1 ) ) ;
break ;
}
else
{
HUD_init_message_literal ( HM_DEFAULT , " No free marker slots " ) ;
return ;
}
2006-03-20 17:12:09 +00:00
}
}
//got a free slot. start inputting marker message
Marker_input [ 0 ] = 0 ;
Marker_index = 0 ;
2011-02-02 00:36:49 +00:00
key_toggle_repeat ( 1 ) ;
2006-08-07 00:27:18 +00:00
}
2006-03-20 17:12:09 +00:00
2020-10-12 03:28:26 +00:00
window_event_result MarkerInputMessage ( int key , control_info & Controls )
2006-08-07 00:27:18 +00:00
{
2019-03-03 00:31:08 +00:00
auto & Objects = LevelUniqueObjectState . Objects ;
auto & vmobjptr = Objects . vmptr ;
auto & vmobjptridx = Objects . vmptridx ;
2008-05-07 14:02:01 +00:00
switch ( key )
{
case KEY_LEFT :
case KEY_BACKSP :
case KEY_PAD4 :
if ( Marker_index > 0 )
Marker_index - - ;
Marker_input [ Marker_index ] = 0 ;
break ;
case KEY_ENTER :
2018-03-10 22:45:04 +00:00
{
2020-07-22 03:11:18 +00:00
const auto player_marker_num = MarkerState . MarkerBeingDefined ;
MarkerState . LastMarkerDropped = player_marker_num ;
const auto game_marker_num = convert_player_marker_index_to_game_marker_index ( Game_mode , Netgame . max_numplayers , Player_num , player_marker_num ) ;
MarkerState . message [ game_marker_num ] = Marker_input ;
DropMarker ( vmobjptridx , vmsegptridx , get_local_plrobj ( ) , game_marker_num , player_marker_num ) ;
2018-03-10 22:45:04 +00:00
}
2019-04-04 04:29:03 +00:00
DXX_BOOST_FALLTHROUGH ;
2016-07-15 03:43:04 +00:00
case KEY_F8 :
case KEY_ESC :
2020-07-22 03:11:18 +00:00
MarkerState . MarkerBeingDefined = player_marker_index : : None ;
2011-02-02 00:36:49 +00:00
key_toggle_repeat ( 0 ) ;
2020-10-12 03:28:26 +00:00
game_flush_inputs ( Controls ) ;
2008-05-07 14:02:01 +00:00
break ;
default :
2008-11-17 23:38:43 +00:00
{
int ascii = key_ascii ( ) ;
2006-08-07 00:27:18 +00:00
if ( ( ascii < 255 ) )
2014-12-22 04:35:48 +00:00
if ( Marker_index < Marker_input . size ( ) - 1 )
2006-08-07 00:27:18 +00:00
{
Marker_input [ Marker_index + + ] = ascii ;
Marker_input [ Marker_index ] = 0 ;
}
2014-08-06 02:10:49 +00:00
return window_event_result : : ignored ;
2006-08-07 00:27:18 +00:00
}
2006-03-20 17:12:09 +00:00
}
2014-08-06 02:10:49 +00:00
return window_event_result : : handled ;
2006-08-07 00:27:18 +00:00
}
2013-03-03 01:03:33 +00:00
# endif
2020-08-28 00:18:45 +00:00
2015-12-13 18:00:48 +00:00
}