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"
2020-09-06 10:44:58 +00:00
2020-09-06 18:49:43 +00:00
CVAR ( Bool , am_followplayer , true , CVAR_ARCHIVE )
CVAR ( Bool , am_rotate , true , CVAR_ARCHIVE )
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 ;
FixedBitArray < MAXSECTORS > show2dsector ;
FixedBitArray < MAXWALLS > show2dwall ;
FixedBitArray < MAXSPRITES > show2dsprite ;
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
for ( int i = 0 ; i < numwalls ; i + + )
{
// get map min and max coordinates
2020-09-06 21:12:47 +00:00
if ( wall [ i ] . x < x_min_bound ) x_min_bound = wall [ i ] . x ;
if ( wall [ i ] . y < y_min_bound ) y_min_bound = wall [ i ] . y ;
if ( wall [ i ] . x > x_max_bound ) x_max_bound = wall [ i ] . x ;
if ( wall [ i ] . y > y_max_bound ) y_max_bound = wall [ i ] . 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 ;
int ms = screen - > FrameTime ;
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 ;
}
nonsharedtimer = screen - > FrameTime ;
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 )
// Only store what's needed. Unfortunately for sprites it is not that easy
. SerializeMemory ( " mappedsectors " , show2dsector . Storage ( ) , ( numsectors + 7 ) / 8 )
. SerializeMemory ( " mappedwalls " , show2dwall . Storage ( ) , ( numwalls + 7 ) / 8 )
. SerializeMemory ( " mappedsprites " , show2dsprite . Storage ( ) , MAXSPRITES / 8 )
. EndObject ( ) ;
}
}
2020-09-06 10:44:58 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void ClearAutomap ( )
{
2020-09-06 18:49:43 +00:00
show2dsector . Zero ( ) ;
show2dwall . Zero ( ) ;
show2dsprite . Zero ( ) ;
x_min_bound = INT_MAX ;
2020-09-06 10:44:58 +00:00
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void MarkSectorSeen ( int i )
{
if ( i > = 0 )
{
show2dsector . Set ( i ) ;
auto wal = & wall [ sector [ i ] . wallptr ] ;
for ( int j = sector [ i ] . wallnum ; j > 0 ; j - - , wal + + )
{
i = wal - > nextsector ;
if ( i < 0 ) continue ;
if ( wal - > cstat & 0x0071 ) continue ;
if ( wall [ wal - > nextwall ] . cstat & 0x0071 ) continue ;
if ( sector [ i ] . lotag = = 32767 ) continue ;
if ( sector [ i ] . ceilingz > = sector [ i ] . floorz ) continue ;
show2dsector . Set ( i ) ;
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-09-06 18:49:43 +00:00
void drawlinergb ( int32_t x1 , int32_t y1 , int32_t x2 , int32_t y2 , PalEntry p )
{
twod - > AddLine ( x1 / 4096.f , y1 / 4096.f , x2 / 4096.f , y2 / 4096.f , windowxy1 . x , windowxy1 . y , windowxy2 . x , windowxy2 . y , p ) ;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
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 ] ;
if ( ! ( g_gameType & GAMEFLAG_SW ) )
{
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 )
if ( sector [ wal - > nextsector ] . floorz ! = sector [ wal - > nextsector ] . ceilingz )
if ( ( ( wal - > cstat | wall [ wal - > nextwall ] . cstat ) & ( 16 + 32 ) ) = = 0 )
if ( sector [ i ] . floorz = = sector [ wal - > nextsector ] . floorz )
return false ;
if ( sector [ i ] . floorpicnum ! = sector [ wal - > nextsector ] . floorpicnum )
return false ;
if ( sector [ i ] . floorshade ! = sector [ wal - > nextsector ] . floorshade )
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 startwall = sector [ i ] . wallptr ;
int endwall = sector [ i ] . wallptr + sector [ i ] . wallnum ;
int z1 = sector [ i ] . ceilingz ;
int z2 = sector [ i ] . floorz ;
walltype * wal ;
int j ;
for ( j = startwall , wal = & wall [ startwall ] ; j < endwall ; j + + , wal + + )
{
int k = wal - > nextwall ;
2021-04-12 18:54:12 +00:00
if ( k < 0 | | k > = numwalls ) continue ;
2020-09-06 18:49:43 +00:00
2021-04-12 18:54:12 +00:00
int s = wal - > nextsector ;
if ( s < 0 | | s > = numsectors ) continue ;
if ( sector [ s ] . ceilingz = = z1 & & sector [ s ] . floorz = = z2 )
2020-09-06 18:49:43 +00:00
if ( ( ( wal - > cstat | wall [ wal - > nextwall ] . cstat ) & ( 16 + 32 ) ) = = 0 ) continue ;
if ( ShowRedLine ( j , i ) )
{
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
auto wal2 = & wall [ wal - > point2 ] ;
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 - - )
{
if ( ! gFullMap & & ! show2dsector [ i ] & & ! ( g_gameType & GAMEFLAG_SW ) ) continue ;
int startwall = sector [ i ] . wallptr ;
int endwall = sector [ i ] . wallptr + sector [ i ] . wallnum ;
walltype * wal ;
int j ;
for ( j = startwall , wal = & wall [ startwall ] ; j < endwall ; j + + , wal + + )
{
if ( wal - > nextwall > = 0 ) continue ;
2021-04-02 20:52:46 +00:00
if ( ! gFullMap & & ! tileGetTexture ( wal - > picnum ) - > isValid ( ) ) continue ;
2020-09-06 18:49:43 +00:00
if ( ( g_gameType & GAMEFLAG_SW ) & & ! gFullMap & & ! show2dwall [ j ] )
continue ;
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
int k = wal - > point2 ;
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 ;
int oy1 = py1 - cposx ;
int ox2 = px2 - cposx ;
int oy2 = py2 - cposx ;
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 ;
TArray < int > floorsprites ;
for ( int i = numsectors - 1 ; i > = 0 ; 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
SectIterator it ( i ) ;
int s ;
while ( ( s = it . NextIndex ( ) ) > = 0 )
{
if ( sprite [ s ] . cstat & CSTAT_SPRITE_INVISIBLE )
continue ;
if ( ( sprite [ s ] . cstat & CSTAT_SPRITE_ALIGNMENT_MASK ) = = CSTAT_SPRITE_ALIGNMENT_FLOOR )
{
if ( ( sprite [ s ] . cstat & ( CSTAT_SPRITE_ONE_SIDED | CSTAT_SPRITE_YFLIP ) ) = = ( CSTAT_SPRITE_ONE_SIDED | CSTAT_SPRITE_YFLIP ) )
continue ; // upside down
floorsprites . Push ( s ) ;
}
}
if ( sector [ i ] . floorstat & CSTAT_SECTOR_SKY ) continue ;
2021-04-01 18:47:05 +00:00
int picnum = sector [ i ] . floorpicnum ;
if ( ( unsigned ) picnum > = ( unsigned ) MAXTILES ) continue ;
2021-04-02 20:52:46 +00:00
auto mesh = sectorGeometry . get ( i , 0 , { 0.f , 0.f } ) ;
2021-03-20 11:47:51 +00:00
vertices . Resize ( mesh - > vertices . Size ( ) ) ;
for ( unsigned j = 0 ; j < mesh - > vertices . Size ( ) ; j + + )
{
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 } ;
}
int translation = TRANSLATION ( Translation_Remap + curbasepal , sector [ i ] . floorpal ) ;
setgotpic ( picnum ) ;
twod - > AddPoly ( tileGetTexture ( picnum , true ) , vertices . Data ( ) , vertices . Size ( ) , nullptr , 0 , translation , shadeToLight ( sector [ i ] . floorshade ) ,
LegacyRenderStyles [ STYLE_Translucent ] , windowxy1 . x , windowxy1 . y , windowxy2 . x + 1 , windowxy2 . y + 1 ) ;
}
qsort ( floorsprites . Data ( ) , floorsprites . Size ( ) , sizeof ( int ) , [ ] ( const void * a , const void * b )
{
int A = * ( int * ) a ;
int B = * ( int * ) b ;
if ( sprite [ A ] . z ! = sprite [ B ] . z ) return sprite [ B ] . z - sprite [ A ] . z ;
return A - B ; // ensures stable sort.
} ) ;
vertices . Resize ( 4 ) ;
for ( auto sn : floorsprites )
{
2021-04-01 18:47:05 +00:00
if ( ! gFullMap & & ! show2dsprite [ sn ] ) continue ;
2021-03-20 11:47:51 +00:00
auto spr = & sprite [ sn ] ;
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 ;
if ( ( sector [ spr - > sectnum ] . ceilingstat & CSTAT_SECTOR_SKY ) ) shade = sector [ spr - > sectnum ] . ceilingshade ;
else shade = sector [ spr - > sectnum ] . floorshade ;
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 ( ) ;
2021-02-27 11:30:20 +00:00
int width = screen - > GetWidth ( ) ;
2020-09-06 18:49:43 +00:00
if ( automapMode = = am_full )
{
twod - > ClearScreen ( ) ;
renderDrawMapView ( x , y , gZoom , follow_a ) ;
}
2021-02-27 11:30:20 +00:00
int32_t tmpydim = ( width * 5 ) / 8 ;
2020-09-06 18:49:43 +00:00
drawredlines ( x , y , gZoom , follow_a ) ;
drawwhitelines ( x , y , gZoom , follow_a ) ;
2021-01-02 07:23:01 +00:00
if ( ! gi - > DrawAutomapPlayer ( 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
}