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-08-16 04:15:16 +00:00
# include "compiler-make_unique.h"
2014-10-12 23:05:46 +00:00
# include "compiler-range_for.h"
2015-10-03 17:17:49 +00:00
# include "partial_range.h"
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
2015-12-13 18:00:48 +00:00
}
}
2015-12-13 18:00:49 +00:00
namespace dsx {
2015-12-13 18:00:48 +00:00
namespace {
2014-09-07 18:06:59 +00:00
struct automap : ignore_window_pointer_t
2009-12-02 13:49:54 +00:00
{
2010-12-10 23:18:17 +00:00
fix64 entry_time ;
fix64 t1 , t2 ;
2009-12-02 13:49:54 +00:00
int leave_mode ;
int pause_game ;
2011-05-20 10:23:28 +00:00
vms_angvec tangles ;
ushort old_wiggle ; // keep 4 byte aligned
2009-12-02 13:49:54 +00:00
int max_segments_away ;
int segment_limit ;
2009-12-27 12:27:44 +00:00
// Edge list variables
int num_edges ;
2017-03-10 01:22:33 +00:00
unsigned max_edges ; //set each frame
unsigned end_valid_edges ;
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 ;
2009-12-27 12:27:44 +00:00
// Screen canvas variables
2019-08-18 20:37:29 +00:00
grs_subcanvas automap_view ;
2009-12-27 12:27:44 +00:00
2016-10-29 23:16:15 +00:00
grs_main_bitmap automap_background ;
2009-12-27 12:27:44 +00:00
// Rendering variables
fix zoom ;
2011-05-20 10:23:28 +00:00
vms_vector view_target ;
vms_vector view_position ;
2009-12-27 12:27:44 +00:00
fix farthest_dist ;
2011-05-20 10:23:28 +00:00
vms_matrix viewMatrix ;
fix viewDist ;
2009-12-27 12:27:44 +00:00
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 ;
# if defined(DXX_BUILD_DESCENT_II)
color_t wall_revealed_color ;
# endif
color_t hostage_color ;
color_t green_31 ;
color_t white_63 ;
color_t blue_48 ;
color_t red_48 ;
2011-02-06 13:25:37 +00:00
control_info controls ;
2013-12-15 18:32:10 +00:00
segment_depth_array_t depth_array ;
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 ) ) ;
}
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 ;
2013-12-15 18:32:10 +00:00
static int Automap_debug_show_all_segments ;
2019-08-06 02:59:40 +00:00
static void automap_clear_visited ( )
{
# ifndef NDEBUG
Automap_debug_show_all_segments = 0 ;
# endif
LevelUniqueAutomapState . Automap_visited = { } ;
}
2015-12-13 18:00:48 +00:00
}
2010-01-29 03:36:44 +00:00
2015-12-13 18:00:49 +00:00
namespace dsx {
2013-10-27 22:00:14 +00:00
static void init_automap_colors ( automap * am )
2006-03-20 17:12:09 +00:00
{
2009-12-27 12:27:44 +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 ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2009-12-27 12:27:44 +00:00
am - > wall_revealed_color = K_WALL_REVEALED_COLOR ;
2013-03-03 01:03:33 +00:00
# endif
2009-12-27 12:27:44 +00:00
am - > hostage_color = K_HOSTAGE_COLOR ;
am - > green_31 = K_GREEN_31 ;
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 ) ;
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)
2006-08-07 00:27:18 +00:00
// Function Prototypes
2013-09-22 22:26:27 +00:00
static void adjust_segment_limit ( automap * am , int SegmentLimit ) ;
2013-12-15 18:32:10 +00:00
static void automap_build_edge_list ( automap * am , int add_all_edges ) ;
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 .
*/
2018-12-03 04:25:11 +00:00
# define MAX_DROP_MULTI_COOP (Netgame.max_numplayers > 4 ? 2 : 4)
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)
2014-08-05 03:10:04 +00:00
2015-12-13 18:00:49 +00:00
namespace dsx {
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
unsigned d_marker_state : : get_biased_marker_num ( const unsigned game_mode , const unsigned player_num , const unsigned base_marker_num )
{
if ( game_mode & GM_MULTI_COOP )
return ( player_num * MAX_DROP_MULTI_COOP ) + base_marker_num ;
if ( game_mode & GM_MULTI )
return ( player_num * MAX_DROP_MULTI_COMPETITIVE ) + base_marker_num ;
return base_marker_num ;
}
unsigned d_marker_state : : get_markers_per_player ( const unsigned game_mode )
{
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 ;
}
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
# define DrawMarkerNumber(C,a,b,c) DrawMarkerNumber(a,b,c)
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
// -------------------------------------------------------------
2015-12-13 18:00:49 +00:00
namespace dsx {
2017-03-11 19:56:23 +00:00
static void draw_all_edges ( grs_canvas & , automap * am ) ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2017-07-26 03:15:59 +00:00
static inline void DrawMarkers ( fvcobjptr & , grs_canvas & , automap * )
2013-03-03 01:03:33 +00:00
{
}
static inline void ClearMarkers ( )
{
}
# elif defined(DXX_BUILD_DESCENT_II)
2017-02-11 21:42:44 +00:00
static void DrawMarkerNumber ( grs_canvas & canvas , const automap * am , unsigned num , 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-05-02 21:18:42 +00:00
static constexpr std : : array < std : : array < xy , 5 > , 9 > 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-05-02 21:18:42 +00:00
static constexpr std : : array < uint_fast8_t , 9 > NumOfPoints = { { 3 , 5 , 4 , 3 , 5 , 5 , 2 , 5 , 4 } } ;
2015-12-03 03:26:49 +00:00
2018-03-10 22:45:04 +00:00
const auto color = ( num = = 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 ;
range_for ( const auto & i , unchecked_partial_range ( & sArray [ num ] [ 0 ] , NumOfPoints [ num ] ) )
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
2017-07-26 03:15:59 +00:00
static void DropMarker ( fvmobjptridx & vmobjptridx , fvmsegptridx & vmsegptridx , const object & plrobj , const unsigned player_marker_num )
2006-03-20 17:12:09 +00:00
{
2018-03-10 22:45:04 +00:00
const unsigned marker_num = MarkerState . get_biased_marker_num ( Game_mode , Player_num , 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
}
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-08-07 00:27:18 +00:00
int marker_num ;
2006-03-20 17:12:09 +00:00
2015-01-12 00:26:02 +00:00
static_assert ( MAX_DROP_SINGLE + 1 < = NUM_MARKERS - 1 , " not enough markers " ) ;
2006-03-20 17:12:09 +00:00
marker_num = MAX_DROP_SINGLE + 1 ;
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
}
# define MARKER_SPHERE_SIZE 0x58000
2017-07-26 03:15:59 +00:00
static void DrawMarkers ( fvcobjptr & vcobjptr , grs_canvas & canvas , automap * const 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 ;
const auto mb = & MarkerState . imobjidx [ MarkerState . get_biased_marker_num ( game_mode , Player_num , 0 ) ] ;
const auto me = std : : next ( mb , MarkerState . get_markers_per_player ( game_mode ) ) ;
2015-12-03 03:26:49 +00:00
for ( auto iter = mb ; ; )
{
if ( * iter ! = object_none )
break ;
if ( + + iter = = me )
return ;
}
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 ) ,
} } ;
unsigned i = 0 ;
for ( auto iter = mb ; iter ! = me ; + + iter , + + i )
if ( * iter ! = object_none )
{
auto sphere_point = g3_rotate_point ( vcobjptr ( * iter ) - > 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 ] ) ;
DrawMarkerNumber ( canvas , am , i , sphere_point ) ;
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
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
void automap_clear_visited ( )
{
2019-08-06 02:59:40 +00:00
: : dcx : : automap_clear_visited ( ) ;
2006-08-07 00:27:18 +00:00
ClearMarkers ( ) ;
2006-03-20 17:12:09 +00:00
}
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
2017-02-11 21:42:45 +00:00
static void name_frame ( grs_canvas & canvas , automap * const am )
2008-02-24 14:41:27 +00:00
{
2017-02-11 21:42: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
2016-10-28 03:39:41 +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 )
{
if ( am - > controls . state . fire_primary )
{
// Reset orientation
am - > controls . state . fire_primary = 0 ;
2016-10-28 03:39:41 +00:00
am - > viewMatrix = plrorient ;
vm_vec_scale_add ( am - > view_position , plrpos , am - > viewMatrix . fvec , - ZOOM_DEFAULT ) ;
2016-05-30 11:17:42 +00:00
}
if ( am - > controls . pitch_time | | am - > controls . heading_time | | am - > controls . bank_time )
{
vms_angvec tangles ;
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 ) ;
const auto & & tempm = vm_angles_2_matrix ( tangles ) ;
am - > viewMatrix = vm_matrix_x_matrix ( am - > viewMatrix , tempm ) ;
check_and_fix_matrix ( am - > viewMatrix ) ;
}
if ( am - > controls . forward_thrust_time | | am - > controls . vertical_thrust_time | | am - > controls . sideways_thrust_time )
{
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 ) ;
// Crude wrapping check
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 ) ;
}
}
else
{
if ( am - > controls . state . fire_primary )
{
// Reset orientation
am - > viewDist = ZOOM_DEFAULT ;
am - > tangles . p = PITCH_DEFAULT ;
am - > tangles . h = 0 ;
am - > tangles . b = 0 ;
2016-10-28 03:39:41 +00:00
am - > view_target = plrpos ;
2016-05-30 11:17:42 +00:00
am - > controls . state . fire_primary = 0 ;
}
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 ) ;
if ( am - > controls . vertical_thrust_time | | am - > controls . sideways_thrust_time )
{
vms_angvec tangles1 ;
vms_vector old_vt ;
old_vt = am - > view_target ;
tangles1 = am - > tangles ;
const auto & & tempm = vm_angles_2_matrix ( tangles1 ) ;
2016-10-28 03:39:41 +00:00
vm_matrix_x_matrix ( am - > viewMatrix , plrorient , tempm ) ;
2016-05-30 11:17:42 +00:00
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 ) ;
2016-10-28 03:39:41 +00:00
if ( vm_vec_dist_quick ( am - > view_target , plrpos ) > i2f ( 1000 ) )
2016-05-30 11:17:42 +00:00
am - > view_target = old_vt ;
}
const auto & & tempm = vm_angles_2_matrix ( am - > tangles ) ;
2016-10-28 03:39:41 +00:00
vm_matrix_x_matrix ( am - > viewMatrix , plrorient , tempm ) ;
2016-05-30 11:17:42 +00:00
clamp_fix_lh ( am - > viewDist , ZOOM_MIN_VALUE , ZOOM_MAX_VALUE ) ;
}
}
2017-07-26 03:15:59 +00:00
static void draw_automap ( fvcobjptr & vcobjptr , automap * am )
2006-03-20 17:12:09 +00:00
{
2013-11-26 22:46:48 +00:00
if ( am - > leave_mode = = 0 & & am - > controls . state . automap & & ( timer_query ( ) - am - > entry_time ) > LEAVE_TIME )
2011-02-03 00:05:06 +00:00
am - > leave_mode = 1 ;
2017-11-05 20:49:08 +00:00
gr_set_default_canvas ( ) ;
2017-02-11 21:42:46 +00:00
{
auto & canvas = * grd_curcanv ;
2017-09-10 04:28:41 +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
}
2017-11-05 20:49:08 +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 )
2014-09-28 21:43:14 +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
2014-10-26 22:01:00 +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
2017-07-26 03:15:59 +00:00
DrawMarkers ( vcobjptr , canvas , am ) ;
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 ) ;
2017-02-11 21:42:46 +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 :
2019-08-06 02:59:40 +00:00
if ( LevelUniqueAutomapState . Automap_visited [ objp - > segnum ] | | Automap_debug_show_all_segments )
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
{
2018-03-10 22:45:04 +00:00
const unsigned HighlightMarker = MarkerState . HighlightMarker ;
if ( HighlightMarker < MarkerState . message . size ( ) )
2018-03-10 18:32:02 +00:00
{
2018-03-10 22:45:04 +00:00
auto & m = MarkerState . message [ HighlightMarker ] ;
if ( m [ 0 ] )
{
2018-05-19 23:21:42 +00:00
gr_printf ( canvas , * canvas . cv_font , ( SWIDTH / 64 ) , ( SHEIGHT / 18 ) , " Marker %d: %s " , HighlightMarker + 1 , & m [ 0 ] ) ;
2018-03-10 22:45:04 +00:00
}
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 ;
2017-02-11 21:42:42 +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
2011-02-03 00:05:06 +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 ;
2015-07-18 03:49:47 +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 ) ;
2015-02-05 03:03:48 +00:00
am - > t2 = timer_update ( ) ;
2011-02-03 00:05:06 +00:00
}
if ( am - > pause_game )
{
FrameTime = am - > t2 - am - > t1 ;
2012-05-14 17:06:28 +00:00
calc_d_tick ( ) ;
2011-02-03 00:05:06 +00:00
}
am - > t1 = am - > t2 ;
}
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
# define MAP_BACKGROUND_FILENAME (((SWIDTH>=640&&SHEIGHT>=480) && PHYSFSX_exists("maph.pcx",1))?"MAPH.PCX":"MAP.PCX")
# elif defined(DXX_BUILD_DESCENT_II)
2011-06-01 07:59:55 +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
2016-10-02 00:34:48 +00:00
static void recompute_automap_segment_visibility ( const object & plrobj , automap * const am )
2013-12-15 18:32:10 +00:00
{
2016-10-02 00:34:48 +00:00
auto & player_info = plrobj . ctype . player_info ;
2016-10-02 00:34:40 +00:00
int compute_depth_all_segments = ( cheats . fullautomap | | ( player_info . powerup_flags & PLAYER_FLAGS_MAP_ALL ) ) ;
2013-12-15 18:32:10 +00:00
if ( Automap_debug_show_all_segments )
compute_depth_all_segments = 1 ;
automap_build_edge_list ( am , compute_depth_all_segments ) ;
2019-08-06 02:59:40 +00:00
am - > max_segments_away = set_segment_depths ( plrobj . segnum , compute_depth_all_segments ? nullptr : & LevelUniqueAutomapState . Automap_visited , am - > depth_array ) ;
2013-12-15 18:32:10 +00:00
am - > segment_limit = am - > max_segments_away ;
adjust_segment_limit ( am , am - > segment_limit ) ;
}
2015-04-26 20:15:56 +00:00
static window_event_result automap_key_command ( window * , 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 :
if ( am - > leave_mode = = 0 )
{
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 ( ) ;
recompute_automap_segment_visibility ( 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 ( ) ;
recompute_automap_segment_visibility ( 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 :
if ( am - > segment_limit > 1 ) {
am - > segment_limit - - ;
adjust_segment_limit ( am , am - > segment_limit ) ;
}
2014-08-06 02:10:49 +00:00
return window_event_result : : handled ;
2010-03-26 14:05:40 +00:00
case KEY_F10 :
if ( am - > segment_limit < am - > max_segments_away ) {
am - > segment_limit + + ;
adjust_segment_limit ( am , am - > segment_limit ) ;
}
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 ;
const unsigned maxdrop = MarkerState . get_markers_per_player ( game_mode ) ;
2018-03-10 22:45:04 +00:00
const unsigned marker_num = c - KEY_1 ;
if ( marker_num < = maxdrop )
{
2018-03-10 22:45:04 +00:00
const unsigned biased_marker_num = MarkerState . get_biased_marker_num ( game_mode , Player_num , marker_num ) ;
2018-03-10 22:45:04 +00:00
if ( MarkerState . imobjidx [ biased_marker_num ] ! = object_none )
MarkerState . HighlightMarker = biased_marker_num ;
}
else
MarkerState . HighlightMarker = UINT8_MAX ;
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 ;
if ( HighlightMarker > = MarkerState . imobjidx . size ( ) )
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 ( ) ;
2010-03-26 14:05:40 +00:00
if ( nm_messagebox ( NULL , 2 , TXT_YES , TXT_NO , " Delete Marker? " ) = = 0 ) {
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 ] = { } ;
2018-03-10 22:45:04 +00:00
MarkerState . HighlightMarker = UINT8_MAX ;
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
}
2015-04-26 20:15:56 +00:00
static window_event_result automap_process_input ( window * , const d_event & event , automap * am )
2009-12-02 13:49:54 +00:00
{
2011-02-06 13:25:37 +00:00
Controls = am - > controls ;
kconfig_read_controls ( event , 1 ) ;
am - > controls = Controls ;
2014-07-04 03:50:50 +00:00
Controls = { } ;
2011-02-06 13:25:37 +00:00
2013-11-26 22:46:48 +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
}
2013-11-26 22:46:48 +00:00
if ( am - > controls . state . automap )
2011-02-02 00:36:49 +00:00
{
2013-11-26 22:46:48 +00:00
am - > controls . state . automap = 0 ;
2009-12-02 13:49:54 +00:00
if ( am - > leave_mode = = 0 )
{
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
}
2014-10-04 21:47:13 +00:00
static window_event_result automap_handler ( window * wind , const d_event & event , automap * am )
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 :
game_flush_inputs ( ) ;
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 :
init_automap_subcanvas ( am - > automap_view , grd_curscreen - > sc_canvas ) ;
break ;
# endif
2011-02-03 00:05:06 +00:00
case EVENT_IDLE :
2011-02-02 00:36:49 +00:00
case EVENT_JOYSTICK_BUTTON_UP :
case EVENT_JOYSTICK_BUTTON_DOWN :
case EVENT_JOYSTICK_MOVED :
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 :
2014-08-06 02:10:49 +00:00
return automap_process_input ( wind , event , am ) ;
2010-03-26 14:05:40 +00:00
case EVENT_KEY_COMMAND :
2011-05-07 11:29:26 +00:00
{
2014-08-06 02:10:49 +00:00
window_event_result kret = automap_key_command ( wind , event , am ) ;
if ( kret = = window_event_result : : ignored )
2015-01-17 18:31:41 +00:00
kret = automap_process_input ( wind , event , am ) ;
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 ( ) ;
automap_apply_input ( am , plrobj . orient , plrobj . pos ) ;
}
2017-07-26 03:15:59 +00:00
draw_automap ( vcobjptr , am ) ;
2010-01-20 11:04:09 +00:00
break ;
case EVENT_WINDOW_CLOSE :
2011-02-06 13:25:37 +00:00
if ( ! am - > pause_game )
ConsoleObject - > mtype . phys_info . flags | = am - > 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 ) ;
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
/* grd_curcanv points to `am->automap_view`, so grd_curcanv
* 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 ( ) ;
2014-08-01 03:11:28 +00:00
std : : default_delete < automap > ( ) ( am ) ;
2010-01-20 11:04:09 +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
2010-01-20 11:04:09 +00:00
break ;
2013-02-21 00:20:26 +00:00
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 ;
2014-07-25 01:47:07 +00:00
automap * am = new automap { } ;
2016-10-15 00:53:20 +00:00
window_create ( grd_curscreen - > sc_canvas , 0 , 0 , SWIDTH , SHEIGHT , automap_handler , am ) ;
2009-12-02 13:49:54 +00:00
am - > leave_mode = 0 ;
am - > max_segments_away = 0 ;
am - > segment_limit = 1 ;
2009-12-27 12:27:44 +00:00
am - > num_edges = 0 ;
2017-03-10 01:22:33 +00:00
am - > end_valid_edges = 0 ;
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 ) ;
2009-12-27 12:27:44 +00:00
am - > zoom = 0x9000 ;
am - > farthest_dist = ( F1_0 * 20 * 50 ) ; // 50 segments away
2011-05-20 10:23:28 +00:00
am - > viewDist = 0 ;
2006-03-20 17:12:09 +00:00
2009-12-27 12:27:44 +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 ) {
2010-01-29 03:36:44 +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
2016-10-02 00:34:48 +00:00
recompute_automap_segment_visibility ( 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 ) ;
2006-03-20 17:12:09 +00:00
}
2009-12-27 12:27:44 +00:00
void adjust_segment_limit ( automap * am , int SegmentLimit )
2006-03-20 17:12:09 +00:00
{
2015-10-03 17:17:49 +00:00
const auto & depth_array = am - > depth_array ;
const auto predicate = [ & depth_array , SegmentLimit ] ( const segnum_t & e1 ) {
return depth_array [ e1 ] < = SegmentLimit ;
} ;
2017-03-10 01:22:33 +00:00
range_for ( auto & i , unchecked_partial_range ( am - > edges . get ( ) , am - > end_valid_edges ) )
{
const auto e = & i ;
2015-10-03 17:17:49 +00:00
// Unchecked for speed
const auto & & range = unchecked_partial_range ( e - > segnum . begin ( ) , e - > num_faces ) ;
if ( std : : any_of ( range . begin ( ) , range . end ( ) , predicate ) )
e - > flags & = ~ EF_TOO_FAR ;
else
e - > flags | = EF_TOO_FAR ;
2006-03-20 17:12:09 +00:00
}
}
2017-03-11 19:56:23 +00:00
void draw_all_edges ( grs_canvas & canvas , automap * const am )
2006-03-20 17:12:09 +00:00
{
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 & Vertices = LevelSharedVertexState . get_vertices ( ) ;
auto & vcvertptr = Vertices . vcptr ;
2017-03-10 01:22:33 +00:00
range_for ( auto & i , unchecked_partial_range ( am - > edges . get ( ) , am - > end_valid_edges ) )
{
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
2009-12-27 12:27:44 +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
2015-10-03 17:17:48 +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 {
2015-10-03 17:17:48 +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
2015-10-03 17:17:49 +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 ;
2009-12-27 12:27:44 +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
: 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
2017-03-10 01:22:33 +00:00
static std : : pair < Edge_info & , unsigned > automap_find_edge ( automap * const 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 ;
2009-12-27 12:27:44 +00:00
oldhash = hash = ( ( v0 * 5 + v1 ) % am - > max_edges ) ;
2017-03-10 01:22:33 +00:00
for ( ; ; )
{
auto & e = am - > edges [ hash ] ;
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 {
2009-12-27 12:27:44 +00:00
if ( + + hash = = am - > max_edges ) hash = 0 ;
2006-03-20 17:12:09 +00:00
if ( hash = = oldhash ) Error ( " Edge list full! " ) ;
}
}
}
2016-09-30 01:49:57 +00:00
static void add_one_edge ( automap * const am , unsigned va , unsigned vb , const uint8_t color , const unsigned side , const segnum_t segnum , const uint8_t flags )
{
2009-12-27 12:27:44 +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 ;
2009-12-27 12:27:44 +00:00
am - > num_edges + + ;
2017-03-10 01:22:33 +00:00
const auto i = ef . second + 1 ;
if ( am - > end_valid_edges < i )
am - > end_valid_edges = i ;
2006-03-20 17:12:09 +00:00
} else {
2009-12-27 12:27:44 +00:00
if ( color ! = am - > wall_normal_color )
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2009-12-27 12:27:44 +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
}
2013-10-27 22:00:14 +00:00
static void add_one_unknown_edge ( automap * am , int va , int 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
}
2017-07-26 03:15:59 +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 ;
2013-12-26 22:21:16 +00:00
if ( seg - > children [ sn ] = = segment_none ) {
2009-12-27 12:27:44 +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 ;
2017-06-10 03:31:02 +00:00
if ( trigger_num ! = trigger_none & & vmtrgptr ( trigger_num ) - > type = = TT_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 :
2017-03-10 01:22:34 +00:00
if ( ( w . keys = = KEY_BLUE & & ( color = am - > wall_door_blue , true ) ) | |
( w . keys = = KEY_GOLD & & ( color = am - > wall_door_gold , true ) ) | |
( w . keys = = KEY_RED & & ( color = am - > wall_door_red , true ) ) )
{
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 ) ) {
2014-11-20 03:00:36 +00:00
auto connected_seg = seg - > 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
{
2016-09-30 01:49:57 +00:00
case KEY_BLUE :
color = am - > wall_door_blue ;
no_fade = EF_NO_FADE ;
break ;
case KEY_GOLD :
color = am - > wall_door_gold ;
no_fade = EF_NO_FADE ;
break ;
case KEY_RED :
color = am - > wall_door_red ;
no_fade = EF_NO_FADE ;
break ;
2015-04-22 02:44:30 +00:00
default :
color = am - > wall_door_color ;
break ;
2006-03-20 17:12:09 +00:00
}
}
} else {
2009-12-27 12:27:44 +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.
2019-12-27 02:02:23 +00:00
if ( ! ( is_grate = WALL_IS_DOORWAY ( GameBitmaps , Textures , vcwallptr , seg , sn ) & WID_RENDPAST_FLAG ) )
2016-09-30 01:49:57 +00:00
hidden_flag = EF_SECRET ;
2009-12-27 12:27:44 +00:00
color = am - > wall_normal_color ;
2006-03-20 17:12:09 +00:00
break ;
case WALL_BLASTABLE :
// Hostage doors
2009-12-27 12:27:44 +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
2013-12-15 18:32:10 +00:00
if ( ! Automap_debug_show_all_segments )
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 ] )
2009-12-27 12:27:44 +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.
2018-12-30 00:43:57 +00:00
static void add_unknown_segment_edges ( automap * am , const shared_segment & seg )
2006-03-20 17:12:09 +00:00
{
2017-02-19 19:33:38 +00:00
for ( unsigned sn = 0 ; sn < MAX_SIDES_PER_SEGMENT ; + + sn )
{
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
}
}
}
2013-12-15 18:32:10 +00:00
void automap_build_edge_list ( automap * am , int add_all_edges )
2006-03-20 17:12:09 +00:00
{
// clear edge list
2017-03-10 01:22:33 +00:00
range_for ( auto & i , unchecked_partial_range ( am - > edges . get ( ) , am - > max_edges ) )
{
i . num_faces = 0 ;
i . flags = 0 ;
2006-03-20 17:12:09 +00:00
}
2009-12-27 12:27:44 +00:00
am - > num_edges = 0 ;
2017-03-10 01:22:33 +00:00
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
2015-06-13 22:42:16 +00:00
if ( segp - > 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
2015-06-13 22:42:16 +00:00
if ( segp - > 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
2015-06-13 22:42:16 +00:00
if ( segp - > 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)
2017-03-10 01:22:33 +00:00
range_for ( auto & i , unchecked_partial_range ( am - > edges . get ( ) , am - > end_valid_edges ) )
{
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
}
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
{
2018-03-10 22:45:04 +00:00
unsigned i ;
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 ;
const auto maxdrop = MarkerState . get_markers_per_player ( game_mode ) ;
2006-03-20 17:12:09 +00:00
for ( i = 0 ; i < maxdrop ; i + + )
2018-03-10 22:45:04 +00:00
if ( MarkerState . imobjidx [ MarkerState . get_biased_marker_num ( game_mode , Player_num , i ) ] = = object_none ) //found free slot!
2006-03-20 17:12:09 +00:00
break ;
if ( i = = maxdrop ) //no free slot
{
2018-03-10 22:45:04 +00:00
if ( game_mode & GM_MULTI )
i = ( MarkerState . LastMarkerDropped + 1 ) & ( maxdrop - 1 ) ; //in multi, replace oldest
2006-03-20 17:12:09 +00:00
else {
2013-06-23 16:27:34 +00:00
HUD_init_message_literal ( HM_DEFAULT , " No free marker slots " ) ;
2006-03-20 17:12:09 +00:00
return ;
}
}
//got a free slot. start inputting marker message
Marker_input [ 0 ] = 0 ;
Marker_index = 0 ;
2018-03-10 22:45:04 +00:00
MarkerState . MarkerBeingDefined = i ;
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
2014-08-06 02:10:49 +00:00
window_event_result MarkerInputMessage ( int key )
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
{
const auto MarkerBeingDefined = MarkerState . MarkerBeingDefined ;
MarkerState . LastMarkerDropped = MarkerBeingDefined ;
2018-03-10 22:45:04 +00:00
MarkerState . message [ MarkerState . get_biased_marker_num ( Game_mode , Player_num , MarkerBeingDefined ) ] = Marker_input ;
2018-03-10 22:45:04 +00:00
DropMarker ( vmobjptridx , vmsegptridx , get_local_plrobj ( ) , MarkerBeingDefined ) ;
}
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 :
2018-03-10 22:45:04 +00:00
MarkerState . MarkerBeingDefined = UINT8_MAX ;
2011-02-02 00:36:49 +00:00
key_toggle_repeat ( 0 ) ;
2008-05-07 14:02:01 +00:00
game_flush_inputs ( ) ;
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
2015-12-13 18:00:48 +00:00
}