2020-09-06 10:44:58 +00:00
//-------------------------------------------------------------------------
/*
Copyright ( C ) 1996 , 2003 - 3 D Realms Entertainment
Copyright ( C ) 2020 - Christoph Oelckers
This file is part of Duke Nukem 3 D version 1.5 - Atomic Edition
Duke Nukem 3 D is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation ; either version 2
of the License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
See the GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
Original Source : 1996 - Todd Replogle
Prepared for public release : 03 / 21 / 2003 - Charlie Wiederhold , 3 D Realms
Modifications for JonoF ' s port by Jonathon Fowler ( jf @ jonof . id . au )
*/
//-------------------------------------------------------------------------
# include "automap.h"
# include "c_dispatch.h"
# include "c_cvars.h"
# include "gstrings.h"
# include "printf.h"
2020-09-06 11:39:57 +00:00
# include "serializer.h"
2020-09-06 18:49:43 +00:00
# include "v_2ddrawer.h"
# include "earcut.hpp"
# include "buildtiles.h"
# include "d_event.h"
# include "c_bind.h"
# include "gamestate.h"
# include "gamecontrol.h"
# include "quotemgr.h"
# include "v_video.h"
# include "gamestruct.h"
2020-10-13 19:38:24 +00:00
# include "v_draw.h"
2021-03-20 11:47:51 +00:00
# include "sectorgeometry.h"
# include "gamefuncs.h"
2021-12-16 05:10:59 +00:00
# include "hw_sections.h"
2021-11-27 20:19:15 +00:00
# include "coreactor.h"
2020-09-06 18:49:43 +00:00
CVAR ( Bool , am_followplayer , true , CVAR_ARCHIVE )
CVAR ( Bool , am_rotate , true , CVAR_ARCHIVE )
2021-07-09 22:18:59 +00:00
CVAR ( Float , am_linealpha , 1.0f , CVAR_ARCHIVE )
CVAR ( Int , am_linethickness , 1 , CVAR_ARCHIVE )
2020-09-06 18:49:43 +00:00
CVAR ( Bool , am_textfont , false , CVAR_ARCHIVE )
CVAR ( Bool , am_showlabel , false , CVAR_ARCHIVE )
CVAR ( Bool , am_nameontop , false , CVAR_ARCHIVE )
2020-09-06 10:44:58 +00:00
2020-09-06 18:49:43 +00:00
int automapMode ;
2020-09-06 21:12:47 +00:00
static float am_zoomdir ;
2020-09-06 18:49:43 +00:00
int follow_x = INT_MAX , follow_y = INT_MAX , follow_a = INT_MAX ;
static int gZoom = 768 ;
2020-09-06 10:44:58 +00:00
bool automapping ;
bool gFullMap ;
2021-11-20 23:03:56 +00:00
BitArray show2dsector ;
BitArray show2dwall ;
2020-09-06 18:49:43 +00:00
static int x_min_bound = INT_MAX , y_min_bound , x_max_bound , y_max_bound ;
CVAR ( Color , am_twosidedcolor , 0xaaaaaa , CVAR_ARCHIVE )
CVAR ( Color , am_onesidedcolor , 0xaaaaaa , CVAR_ARCHIVE )
CVAR ( Color , am_playercolor , 0xaaaaaa , CVAR_ARCHIVE )
CVAR ( Color , am_ovtwosidedcolor , 0xaaaaaa , CVAR_ARCHIVE )
CVAR ( Color , am_ovonesidedcolor , 0xaaaaaa , CVAR_ARCHIVE )
CVAR ( Color , am_ovplayercolor , 0xaaaaaa , CVAR_ARCHIVE )
2020-09-06 10:44:58 +00:00
2020-09-06 11:39:57 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-09-06 18:49:43 +00:00
CCMD ( allmap )
{
if ( ! CheckCheatmode ( true , false ) )
{
gFullMap = ! gFullMap ;
Printf ( " %s \n " , GStrings ( gFullMap ? " SHOW MAP: ON " : " SHOW MAP: OFF " ) ) ;
}
}
CCMD ( togglemap )
{
if ( gamestate = = GS_LEVEL )
{
automapMode + + ;
if ( automapMode = = am_count ) automapMode = am_off ;
2021-01-02 03:46:58 +00:00
if ( isBlood ( ) & & automapMode = = am_overlay ) automapMode = am_full ; // todo: investigate if this can be re-enabled
2020-09-06 18:49:43 +00:00
}
}
CCMD ( togglefollow )
{
am_followplayer = ! am_followplayer ;
auto msg = quoteMgr . GetQuote ( am_followplayer ? 84 : 83 ) ;
if ( ! msg | | ! * msg ) msg = am_followplayer ? GStrings ( " FOLLOW MODE ON " ) : GStrings ( " FOLLOW MODE Off " ) ;
2020-09-06 21:12:47 +00:00
Printf ( PRINT_NOTIFY , " %s \n " , msg ) ;
if ( am_followplayer ) follow_x = INT_MAX ;
2020-09-06 18:49:43 +00:00
}
2020-09-06 21:12:47 +00:00
CCMD ( togglerotate )
{
am_rotate = ! am_rotate ;
2020-09-07 17:56:28 +00:00
auto msg = am_rotate ? GStrings ( " TXT_ROTATE_ON " ) : GStrings ( " TXT_ROTATE_OFF " ) ;
2020-09-06 21:12:47 +00:00
Printf ( PRINT_NOTIFY , " %s \n " , msg ) ;
}
2020-09-06 18:49:43 +00:00
CCMD ( am_zoom )
2020-09-06 11:39:57 +00:00
{
2020-09-06 18:49:43 +00:00
if ( argv . argc ( ) > = 2 )
{
am_zoomdir = ( float ) atof ( argv [ 1 ] ) ;
}
2020-09-06 11:39:57 +00:00
}
2020-09-06 18:49:43 +00:00
//==========================================================================
//
// AM_Responder
// Handle automap exclusive bindings.
//
//==========================================================================
bool AM_Responder ( event_t * ev , bool last )
{
if ( ev - > type = = EV_KeyDown | | ev - > type = = EV_KeyUp )
{
if ( am_followplayer )
{
// check for am_pan* and ignore in follow mode
const char * defbind = AutomapBindings . GetBind ( ev - > data1 ) ;
if ( defbind & & ! strnicmp ( defbind , " +am_pan " , 7 ) ) return false ;
}
bool res = C_DoKey ( ev , & AutomapBindings , nullptr ) ;
if ( res & & ev - > type = = EV_KeyUp & & ! last )
{
// If this is a release event we also need to check if it released a button in the main Bindings
// so that that button does not get stuck.
const char * defbind = Bindings . GetBind ( ev - > data1 ) ;
return ( ! defbind | | defbind [ 0 ] ! = ' + ' ) ; // Let G_Responder handle button releases
}
return res ;
}
return false ;
}
2020-09-06 11:39:57 +00:00
2020-09-06 10:44:58 +00:00
//---------------------------------------------------------------------------
//
2020-09-06 18:49:43 +00:00
//
2020-09-06 10:44:58 +00:00
//
2020-09-06 18:49:43 +00:00
//---------------------------------------------------------------------------
static void CalcMapBounds ( )
{
2020-09-06 21:12:47 +00:00
x_min_bound = INT_MAX ;
y_min_bound = INT_MAX ;
x_max_bound = INT_MIN ;
y_max_bound = INT_MIN ;
2020-09-06 18:49:43 +00:00
2021-11-26 19:55:13 +00:00
for ( auto & wal : walls ( ) )
2020-09-06 18:49:43 +00:00
{
// get map min and max coordinates
2021-11-26 19:55:13 +00:00
if ( wal . x < x_min_bound ) x_min_bound = wal . x ;
if ( wal . y < y_min_bound ) y_min_bound = wal . y ;
if ( wal . x > x_max_bound ) x_max_bound = wal . x ;
if ( wal . y > y_max_bound ) y_max_bound = wal . y ;
2020-09-06 18:49:43 +00:00
}
}
//---------------------------------------------------------------------------
//
//
2020-09-06 10:44:58 +00:00
//
//---------------------------------------------------------------------------
2020-09-06 18:49:43 +00:00
void AutomapControl ( )
2020-09-06 10:44:58 +00:00
{
2020-09-06 18:49:43 +00:00
static int nonsharedtimer ;
2021-05-11 23:50:41 +00:00
int ms = ( int ) screen - > FrameTime ;
2020-09-06 18:49:43 +00:00
int interval ;
2020-09-06 21:12:47 +00:00
int panvert = 0 , panhorz = 0 ;
2020-09-06 18:49:43 +00:00
if ( nonsharedtimer > 0 | | ms < nonsharedtimer )
2020-09-06 10:44:58 +00:00
{
2020-09-06 18:49:43 +00:00
interval = ms - nonsharedtimer ;
}
else
{
interval = 0 ;
}
2021-05-11 23:50:41 +00:00
nonsharedtimer = ms ;
2020-09-06 18:49:43 +00:00
if ( System_WantGuiCapture ( ) )
return ;
if ( automapMode ! = am_off )
{
2020-09-06 21:12:47 +00:00
const int keymove = 4 ;
2020-09-06 18:49:43 +00:00
if ( am_zoomdir > 0 )
{
gZoom = xs_CRoundToInt ( gZoom * am_zoomdir ) ;
}
else if ( am_zoomdir < 0 )
{
gZoom = xs_CRoundToInt ( gZoom / - am_zoomdir ) ;
}
am_zoomdir = 0 ;
2020-09-07 18:39:07 +00:00
double j = interval * 35. / gZoom ;
2020-09-06 18:49:43 +00:00
if ( buttonMap . ButtonDown ( gamefunc_Enlarge_Screen ) )
2021-01-04 11:16:09 +00:00
gZoom + = ( int ) MulScaleF ( j , max ( gZoom , 256 ) , 6 ) ;
2020-09-06 18:49:43 +00:00
if ( buttonMap . ButtonDown ( gamefunc_Shrink_Screen ) )
2021-01-04 11:16:09 +00:00
gZoom - = ( int ) MulScaleF ( j , max ( gZoom , 256 ) , 6 ) ;
2020-09-06 18:49:43 +00:00
2020-09-06 21:12:47 +00:00
gZoom = clamp ( gZoom , 48 , 2048 ) ;
if ( ! am_followplayer )
{
if ( buttonMap . ButtonDown ( gamefunc_AM_PanLeft ) )
panhorz + = keymove ;
2020-09-06 18:49:43 +00:00
2020-09-06 21:12:47 +00:00
if ( buttonMap . ButtonDown ( gamefunc_AM_PanRight ) )
panhorz - = keymove ;
2020-09-06 18:49:43 +00:00
2020-09-06 21:12:47 +00:00
if ( buttonMap . ButtonDown ( gamefunc_AM_PanUp ) )
panvert + = keymove ;
2020-09-06 18:49:43 +00:00
2020-09-06 21:12:47 +00:00
if ( buttonMap . ButtonDown ( gamefunc_AM_PanDown ) )
panvert - = keymove ;
2020-09-06 18:49:43 +00:00
2021-01-04 11:36:54 +00:00
int momx = MulScale ( panvert , bcos ( follow_a ) , 9 ) ;
int momy = MulScale ( panvert , bsin ( follow_a ) , 9 ) ;
2020-09-06 18:49:43 +00:00
2021-01-04 11:36:54 +00:00
momx + = MulScale ( panhorz , bsin ( follow_a ) , 9 ) ;
momy + = MulScale ( panhorz , - bcos ( follow_a ) , 9 ) ;
2020-09-06 18:49:43 +00:00
2020-09-07 18:39:07 +00:00
follow_x + = int ( momx * j ) ;
follow_y + = int ( momy * j ) ;
2020-09-06 18:49:43 +00:00
2020-09-06 21:12:47 +00:00
if ( x_min_bound = = INT_MAX ) CalcMapBounds ( ) ;
follow_x = clamp ( follow_x , x_min_bound , x_max_bound ) ;
follow_y = clamp ( follow_y , y_min_bound , y_max_bound ) ;
}
2020-09-06 10:44:58 +00:00
}
}
2020-09-06 18:49:43 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void SerializeAutomap ( FSerializer & arc )
{
if ( arc . BeginObject ( " automap " ) )
{
arc ( " automapping " , automapping )
( " fullmap " , gFullMap )
2021-11-20 23:24:47 +00:00
( " mappedsectors " , show2dsector )
( " mappedwalls " , show2dwall )
2020-09-06 18:49:43 +00:00
. EndObject ( ) ;
}
}
2020-09-06 10:44:58 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void ClearAutomap ( )
{
2020-09-06 18:49:43 +00:00
show2dsector . Zero ( ) ;
show2dwall . Zero ( ) ;
x_min_bound = INT_MAX ;
2020-09-06 10:44:58 +00:00
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-12-02 00:05:07 +00:00
void MarkSectorSeen ( sectortype * sec )
2020-09-06 10:44:58 +00:00
{
2021-12-02 00:05:07 +00:00
if ( sec )
2020-09-06 10:44:58 +00:00
{
2021-12-02 00:05:07 +00:00
show2dsector . Set ( sectnum ( sec ) ) ;
for ( auto & wal : wallsofsector ( sec ) )
2020-09-06 10:44:58 +00:00
{
2021-12-02 00:05:07 +00:00
if ( ! wal . twoSided ( ) ) continue ;
if ( wal . cstat & 0x0071 ) continue ;
if ( wal . nextWall ( ) - > cstat & 0x0071 ) continue ;
auto osec = wal . nextSector ( ) ;
if ( osec - > lotag = = 32767 ) continue ;
if ( osec - > ceilingz > = osec - > floorz ) continue ;
show2dsector . Set ( sectnum ( osec ) ) ;
2020-09-06 10:44:58 +00:00
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-09-06 18:49:43 +00:00
void drawlinergb ( int32_t x1 , int32_t y1 , int32_t x2 , int32_t y2 , PalEntry p )
{
2021-07-09 22:18:59 +00:00
if ( am_linethickness > = 2 ) {
2021-10-26 16:54:43 +00:00
twod - > AddThickLine ( x1 / 4096 , y1 / 4096 , x2 / 4096 , y2 / 4096 , am_linethickness , p , uint8_t ( am_linealpha * 255 ) ) ;
2021-07-09 22:18:59 +00:00
} else {
// Use more efficient thin line drawing routine.
twod - > AddLine ( x1 / 4096.f , y1 / 4096.f , x2 / 4096.f , y2 / 4096.f , windowxy1 . x , windowxy1 . y , windowxy2 . x , windowxy2 . y , p , uint8_t ( am_linealpha * 255 ) ) ;
}
2020-09-06 18:49:43 +00:00
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
PalEntry RedLineColor ( )
{
// todo:
// Blood uses palette index 12 (99,99,99)
// Exhumed uses palette index 111 (roughly 170,170,170) but darkens the line in overlay mode the farther it is away from the player in vertical direction.
// Shadow Warrior uses palette index 152 in overlay mode and index 12 in full map mode. (152: 84, 88, 40)
return automapMode = = am_overlay ? * am_ovtwosidedcolor : * am_twosidedcolor ;
}
PalEntry WhiteLineColor ( )
{
// todo:
// Blood uses palette index 24
// Exhumed uses palette index 111 (roughly 170,170,170) but darkens the line in overlay mode the farther it is away from the player in vertical direction.
// Shadow Warrior uses palette index 24 (60,60,60)
return automapMode = = am_overlay ? * am_ovonesidedcolor : * am_onesidedcolor ;
}
PalEntry PlayerLineColor ( )
{
return automapMode = = am_overlay ? * am_ovplayercolor : * am_playercolor ;
}
CCMD ( printpalcol )
{
if ( argv . argc ( ) < 2 ) return ;
int i = atoi ( argv [ 1 ] ) ;
Printf ( " %d, %d, %d \n " , GPalette . BaseColors [ i ] . r , GPalette . BaseColors [ i ] . g , GPalette . BaseColors [ i ] . b ) ;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
bool ShowRedLine ( int j , int i )
{
auto wal = & wall [ j ] ;
2021-07-11 02:39:54 +00:00
if ( ! isSWALL ( ) )
2020-09-06 18:49:43 +00:00
{
return ! gFullMap & & ! show2dsector [ wal - > nextsector ] ;
}
else
{
if ( ! gFullMap )
{
if ( ! show2dwall [ j ] ) return false ;
int k = wal - > nextwall ;
if ( k > j & & ! show2dwall [ k ] ) return false ; //???
}
if ( automapMode = = am_full )
{
if ( sector [ i ] . floorz ! = sector [ i ] . ceilingz )
2021-11-26 19:55:13 +00:00
if ( wal - > nextSector ( ) - > floorz ! = wal - > nextSector ( ) - > ceilingz )
if ( ( ( wal - > cstat | wal - > nextWall ( ) - > cstat ) & ( 16 + 32 ) ) = = 0 )
if ( sector [ i ] . floorz = = wal - > nextSector ( ) - > floorz )
2020-09-06 18:49:43 +00:00
return false ;
2021-11-26 19:55:13 +00:00
if ( sector [ i ] . floorpicnum ! = wal - > nextSector ( ) - > floorpicnum )
2020-09-06 18:49:43 +00:00
return false ;
2021-11-26 19:55:13 +00:00
if ( sector [ i ] . floorshade ! = wal - > nextSector ( ) - > floorshade )
2020-09-06 18:49:43 +00:00
return false ;
}
return true ;
}
}
//---------------------------------------------------------------------------
//
// two sided lines
//
//---------------------------------------------------------------------------
void drawredlines ( int cposx , int cposy , int czoom , int cang )
{
2020-11-14 09:05:42 +00:00
int xvect = - bsin ( cang ) * czoom ;
int yvect = - bcos ( cang ) * czoom ;
2021-02-27 11:30:20 +00:00
int width = screen - > GetWidth ( ) ;
int height = screen - > GetHeight ( ) ;
2020-09-06 18:49:43 +00:00
for ( int i = 0 ; i < numsectors ; i + + )
{
if ( ! gFullMap & & ! show2dsector [ i ] ) continue ;
int z1 = sector [ i ] . ceilingz ;
int z2 = sector [ i ] . floorz ;
2021-12-05 20:18:55 +00:00
for ( auto & wal : wallsofsector ( i ) )
2020-09-06 18:49:43 +00:00
{
2021-12-05 20:18:55 +00:00
if ( ! wal . twoSided ( ) ) continue ;
2020-09-06 18:49:43 +00:00
2021-12-05 20:18:55 +00:00
auto osec = wal . nextSector ( ) ;
2021-04-12 18:54:12 +00:00
2021-12-05 20:18:55 +00:00
if ( osec - > ceilingz = = z1 & & osec - > floorz = = z2 )
if ( ( ( wal . cstat | wal . nextWall ( ) - > cstat ) & ( 16 + 32 ) ) = = 0 ) continue ;
2020-09-06 18:49:43 +00:00
2021-12-05 20:18:55 +00:00
if ( ShowRedLine ( wallnum ( & wal ) , i ) )
2020-09-06 18:49:43 +00:00
{
2021-12-05 20:18:55 +00:00
int ox = wal . x - cposx ;
int oy = wal . y - cposy ;
2021-02-27 11:30:20 +00:00
int x1 = DMulScale ( ox , xvect , - oy , yvect , 16 ) + ( width < < 11 ) ;
2021-03-20 11:47:51 +00:00
int y1 = DMulScale ( oy , xvect , ox , yvect , 16 ) + ( height < < 11 ) ;
2020-09-06 18:49:43 +00:00
2021-12-05 20:18:55 +00:00
auto wal2 = wal . point2Wall ( ) ;
2020-09-06 18:49:43 +00:00
ox = wal2 - > x - cposx ;
oy = wal2 - > y - cposy ;
2021-02-27 11:30:20 +00:00
int x2 = DMulScale ( ox , xvect , - oy , yvect , 16 ) + ( width < < 11 ) ;
2021-03-20 11:47:51 +00:00
int y2 = DMulScale ( oy , xvect , ox , yvect , 16 ) + ( height < < 11 ) ;
2020-09-06 18:49:43 +00:00
drawlinergb ( x1 , y1 , x2 , y2 , RedLineColor ( ) ) ;
}
}
}
}
//---------------------------------------------------------------------------
//
// one sided lines
//
//---------------------------------------------------------------------------
static void drawwhitelines ( int cposx , int cposy , int czoom , int cang )
{
2020-11-14 09:05:42 +00:00
int xvect = - bsin ( cang ) * czoom ;
int yvect = - bcos ( cang ) * czoom ;
2021-02-27 11:30:20 +00:00
int width = screen - > GetWidth ( ) ;
int height = screen - > GetHeight ( ) ;
2020-09-06 18:49:43 +00:00
for ( int i = numsectors - 1 ; i > = 0 ; i - - )
{
2021-07-11 02:39:54 +00:00
if ( ! gFullMap & & ! show2dsector [ i ] & & ! isSWALL ( ) ) continue ;
2020-09-06 18:49:43 +00:00
2021-12-05 20:18:55 +00:00
for ( auto & wal : wallsofsector ( i ) )
2020-09-06 18:49:43 +00:00
{
2021-12-05 20:18:55 +00:00
if ( wal . nextwall > = 0 ) continue ;
if ( ! gFullMap & & ! tileGetTexture ( wal . picnum ) - > isValid ( ) ) continue ;
2020-09-06 18:49:43 +00:00
2021-12-05 20:18:55 +00:00
if ( isSWALL ( ) & & ! gFullMap & & ! show2dwall [ wallnum ( & wal ) ] )
2020-09-06 18:49:43 +00:00
continue ;
2021-12-05 20:18:55 +00:00
int ox = wal . x - cposx ;
int oy = wal . y - cposy ;
2021-02-27 11:30:20 +00:00
int x1 = DMulScale ( ox , xvect , - oy , yvect , 16 ) + ( width < < 11 ) ;
2021-03-20 11:47:51 +00:00
int y1 = DMulScale ( oy , xvect , ox , yvect , 16 ) + ( height < < 11 ) ;
2020-09-06 18:49:43 +00:00
2021-12-05 20:18:55 +00:00
int k = wal . point2 ;
2020-09-06 18:49:43 +00:00
auto wal2 = & wall [ k ] ;
ox = wal2 - > x - cposx ;
oy = wal2 - > y - cposy ;
2021-02-27 11:30:20 +00:00
int x2 = DMulScale ( ox , xvect , - oy , yvect , 16 ) + ( width < < 11 ) ;
2021-03-20 11:47:51 +00:00
int y2 = DMulScale ( oy , xvect , ox , yvect , 16 ) + ( height < < 11 ) ;
2020-09-06 18:49:43 +00:00
drawlinergb ( x1 , y1 , x2 , y2 , WhiteLineColor ( ) ) ;
}
}
}
2021-03-20 11:47:51 +00:00
//---------------------------------------------------------------------------
//
// player sprite fallback
//
//---------------------------------------------------------------------------
2020-09-06 18:49:43 +00:00
void DrawPlayerArrow ( int cposx , int cposy , int cang , int pl_x , int pl_y , int zoom , int pl_angle )
{
int arrow [ ] =
{
0 , 65536 , 0 , - 65536 ,
0 , 65536 , - 32768 , 32878 ,
0 , 65536 , 32768 , 32878 ,
} ;
2020-11-14 09:05:42 +00:00
int xvect = - bsin ( cang ) * zoom ;
int yvect = - bcos ( cang ) * zoom ;
2020-09-06 18:49:43 +00:00
2020-11-14 09:05:42 +00:00
int pxvect = - bsin ( pl_angle ) ;
int pyvect = - bcos ( pl_angle ) ;
2020-09-06 18:49:43 +00:00
2021-02-27 11:30:20 +00:00
int width = screen - > GetWidth ( ) ;
int height = screen - > GetHeight ( ) ;
2020-09-06 18:49:43 +00:00
for ( int i = 0 ; i < 12 ; i + = 4 )
{
2021-01-04 10:40:08 +00:00
int px1 = DMulScale ( arrow [ i ] , pxvect , - arrow [ i + 1 ] , pyvect , 16 ) ;
2021-02-27 11:30:20 +00:00
int py1 = DMulScale ( arrow [ i + 1 ] , pxvect , arrow [ i ] , pyvect , 16 ) + ( height < < 11 ) ;
2021-01-04 10:40:08 +00:00
int px2 = DMulScale ( arrow [ i + 2 ] , pxvect , - arrow [ i + 3 ] , pyvect , 16 ) ;
2021-02-27 11:30:20 +00:00
int py2 = DMulScale ( arrow [ i + 3 ] , pxvect , arrow [ i + 2 ] , pyvect , 16 ) + ( height < < 11 ) ;
2020-09-06 18:49:43 +00:00
int ox1 = px1 - cposx ;
2021-11-28 23:44:28 +00:00
int oy1 = py1 - cposy ;
2020-09-06 18:49:43 +00:00
int ox2 = px2 - cposx ;
2021-11-28 23:44:28 +00:00
int oy2 = py2 - cposy ;
2020-09-06 18:49:43 +00:00
2021-02-27 11:30:20 +00:00
int sx1 = DMulScale ( ox1 , xvect , - oy1 , yvect , 16 ) + ( width < < 11 ) ;
2021-03-20 11:47:51 +00:00
int sy1 = DMulScale ( oy1 , xvect , ox1 , yvect , 16 ) + ( height < < 11 ) ;
2021-02-27 11:30:20 +00:00
int sx2 = DMulScale ( ox2 , xvect , - oy2 , yvect , 16 ) + ( width < < 11 ) ;
2021-03-20 11:47:51 +00:00
int sy2 = DMulScale ( oy2 , xvect , ox2 , yvect , 16 ) + ( height < < 11 ) ;
2020-09-06 18:49:43 +00:00
drawlinergb ( sx1 , sy1 , sx2 , sy2 , WhiteLineColor ( ) ) ;
}
}
2021-03-20 11:47:51 +00:00
//---------------------------------------------------------------------------
//
// floor textures
//
//---------------------------------------------------------------------------
void renderDrawMapView ( int cposx , int cposy , int czoom , int cang )
{
int xvect = - bsin ( cang ) * czoom ;
int yvect = - bcos ( cang ) * czoom ;
int width = screen - > GetWidth ( ) ;
int height = screen - > GetHeight ( ) ;
TArray < FVector4 > vertices ;
2021-11-27 20:19:15 +00:00
TArray < spritetype * > floorsprites ;
2021-03-20 11:47:51 +00:00
for ( int i = numsectors - 1 ; i > = 0 ; i - - )
{
2021-11-27 20:19:15 +00:00
auto sect = & sector [ i ] ;
2021-04-01 18:47:05 +00:00
if ( ! gFullMap & & ! show2dsector [ i ] ) continue ;
2021-03-20 11:47:51 +00:00
//Collect floor sprites to draw
2021-11-27 20:19:15 +00:00
TSectIterator < DCoreActor > it ( sect ) ;
while ( auto act = it . Next ( ) )
2021-03-20 11:47:51 +00:00
{
2021-11-27 20:19:15 +00:00
auto spr = & act - > s ( ) ;
2021-11-26 19:55:13 +00:00
if ( spr - > cstat & CSTAT_SPRITE_INVISIBLE )
2021-03-20 11:47:51 +00:00
continue ;
2021-11-26 19:55:13 +00:00
if ( ( spr - > cstat & CSTAT_SPRITE_ALIGNMENT_MASK ) = = CSTAT_SPRITE_ALIGNMENT_FLOOR )
2021-03-20 11:47:51 +00:00
{
2021-11-26 19:55:13 +00:00
if ( ( spr - > cstat & ( CSTAT_SPRITE_ONE_SIDED | CSTAT_SPRITE_YFLIP ) ) = = ( CSTAT_SPRITE_ONE_SIDED | CSTAT_SPRITE_YFLIP ) )
2021-03-20 11:47:51 +00:00
continue ; // upside down
2021-11-27 20:19:15 +00:00
floorsprites . Push ( spr ) ;
2021-03-20 11:47:51 +00:00
}
}
2021-11-27 20:19:15 +00:00
if ( sect - > floorstat & CSTAT_SECTOR_SKY ) continue ;
2021-03-20 11:47:51 +00:00
2021-11-27 20:19:15 +00:00
int picnum = sect - > floorpicnum ;
2021-04-01 18:47:05 +00:00
if ( ( unsigned ) picnum > = ( unsigned ) MAXTILES ) continue ;
2021-12-14 16:40:03 +00:00
int translation = TRANSLATION ( Translation_Remap + curbasepal , sector [ i ] . floorpal ) ;
PalEntry light = shadeToLight ( sector [ i ] . floorshade ) ;
setgotpic ( picnum ) ;
2021-12-15 12:08:09 +00:00
for ( auto sect : sectionsPerSector [ i ] )
2021-03-20 11:47:51 +00:00
{
2021-12-14 08:03:19 +00:00
TArray < int > * indices ;
auto mesh = sectionGeometry . get ( sect , 0 , { 0.f , 0.f } , & indices ) ;
2021-12-14 16:40:03 +00:00
vertices . Resize ( mesh - > vertices . Size ( ) ) ;
for ( unsigned j = 0 ; j < mesh - > vertices . Size ( ) ; j + + )
2021-05-02 22:15:09 +00:00
{
int ox = int ( mesh - > vertices [ j ] . X * 16.f ) - cposx ;
int oy = int ( mesh - > vertices [ j ] . Y * - 16.f ) - cposy ;
int x1 = DMulScale ( ox , xvect , - oy , yvect , 16 ) + ( width < < 11 ) ;
int y1 = DMulScale ( oy , xvect , ox , yvect , 16 ) + ( height < < 11 ) ;
vertices [ j ] = { x1 / 4096.f , y1 / 4096.f , mesh - > texcoords [ j ] . X , mesh - > texcoords [ j ] . Y } ;
}
2021-03-20 11:47:51 +00:00
2021-12-14 16:40:03 +00:00
# ifdef _DEBUG
// visualize the triangulator being used.
2021-12-15 12:08:09 +00:00
if ( sectionsPerSector [ i ] [ 0 ] - > geomflags & NoEarcut ) light . r = light . b = 80 ;
2021-12-14 16:40:03 +00:00
# endif
twod - > AddPoly ( tileGetTexture ( picnum , true ) , vertices . Data ( ) , vertices . Size ( ) , ( unsigned * ) indices - > Data ( ) , indices - > Size ( ) , translation , light ,
LegacyRenderStyles [ STYLE_Translucent ] , windowxy1 . x , windowxy1 . y , windowxy2 . x + 1 , windowxy2 . y + 1 ) ;
}
2021-03-20 11:47:51 +00:00
}
2021-11-27 20:19:15 +00:00
qsort ( floorsprites . Data ( ) , floorsprites . Size ( ) , sizeof ( spritetype * ) , [ ] ( const void * a , const void * b )
2021-03-20 11:47:51 +00:00
{
2021-11-27 20:19:15 +00:00
auto A = * ( spritetype * * ) a ;
auto B = * ( spritetype * * ) b ;
if ( A - > z ! = B - > z ) return B - > z - A - > z ;
return A - > time - B - > time ; // ensures stable sort.
2021-03-20 11:47:51 +00:00
} ) ;
vertices . Resize ( 4 ) ;
2021-11-27 20:19:15 +00:00
for ( auto spr : floorsprites )
2021-03-20 11:47:51 +00:00
{
2021-11-27 20:19:15 +00:00
if ( ! gFullMap & & ! ( spr - > cstat2 & CSTAT2_SPRITE_MAPPED ) ) continue ;
2021-03-20 11:47:51 +00:00
vec2_t pp [ 4 ] ;
2021-03-26 19:28:44 +00:00
GetFlatSpritePosition ( spr , spr - > pos . vec2 , pp , true ) ;
2021-03-20 11:47:51 +00:00
for ( unsigned j = 0 ; j < 4 ; j + + )
{
int ox = pp [ j ] . x - cposx ;
int oy = pp [ j ] . y - cposy ;
int x1 = DMulScale ( ox , xvect , - oy , yvect , 16 ) + ( width < < 11 ) ;
int y1 = DMulScale ( oy , xvect , ox , yvect , 16 ) + ( height < < 11 ) ;
vertices [ j ] = { x1 / 4096.f , y1 / 4096.f , j = = 1 | | j = = 2 ? 1.f : 0.f , j = = 2 | | j = = 3 ? 1.f : 0.f } ;
}
int shade ;
2021-11-26 19:55:13 +00:00
if ( ( spr - > sector ( ) - > ceilingstat & CSTAT_SECTOR_SKY ) ) shade = spr - > sector ( ) - > ceilingshade ;
else shade = spr - > sector ( ) - > floorshade ;
2021-03-20 11:47:51 +00:00
shade + = spr - > shade ;
PalEntry color = shadeToLight ( shade ) ;
FRenderStyle rs = LegacyRenderStyles [ STYLE_Translucent ] ;
float alpha = 1 ;
if ( spr - > cstat & CSTAT_SPRITE_TRANSLUCENT )
{
rs = GetRenderStyle ( 0 , ! ! ( spr - > cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT ) ) ;
alpha = GetAlphaFromBlend ( ( spr - > cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT ) ? DAMETH_TRANS2 : DAMETH_TRANS1 , 0 ) ;
color . a = uint8_t ( alpha * 255 ) ;
}
int translation = TRANSLATION ( Translation_Remap + curbasepal , spr - > pal ) ;
int picnum = spr - > picnum ;
setgotpic ( picnum ) ;
const static unsigned indices [ ] = { 0 , 1 , 2 , 0 , 2 , 3 } ;
twod - > AddPoly ( tileGetTexture ( picnum , true ) , vertices . Data ( ) , vertices . Size ( ) , indices , 6 , translation , color , rs ,
windowxy1 . x , windowxy1 . y , windowxy2 . x + 1 , windowxy2 . y + 1 ) ;
}
}
2020-09-06 18:49:43 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-01-02 07:23:01 +00:00
void DrawOverheadMap ( int pl_x , int pl_y , int pl_angle , double const smoothratio )
2020-09-06 10:44:58 +00:00
{
2020-09-06 21:12:47 +00:00
if ( am_followplayer | | follow_x = = INT_MAX )
{
follow_x = pl_x ;
follow_y = pl_y ;
}
int x = follow_x ;
int y = follow_y ;
2020-09-06 18:49:43 +00:00
follow_a = am_rotate ? pl_angle : 0 ;
2020-09-06 21:12:47 +00:00
AutomapControl ( ) ;
2020-09-06 18:49:43 +00:00
if ( automapMode = = am_full )
{
twod - > ClearScreen ( ) ;
renderDrawMapView ( x , y , gZoom , follow_a ) ;
}
drawredlines ( x , y , gZoom , follow_a ) ;
drawwhitelines ( x , y , gZoom , follow_a ) ;
2021-11-26 22:11:59 +00:00
if ( ! gi - > DrawAutomapPlayer ( pl_x , pl_y , x , y , gZoom , follow_a , smoothratio ) )
2020-09-06 19:15:59 +00:00
DrawPlayerArrow ( x , y , follow_a , pl_x , pl_y , gZoom , - pl_angle ) ;
2020-09-06 18:49:43 +00:00
2020-09-06 10:44:58 +00:00
}