mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-04-25 20:20:57 +00:00
1474 lines
31 KiB
C
1474 lines
31 KiB
C
// Emacs style mode select -*- C++ -*-
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// $Id:$
|
|
//
|
|
// Copyright (C) 1993-1996 by id Software, Inc.
|
|
//
|
|
// This source is available for distribution and/or modification
|
|
// only under the terms of the DOOM Source Code License as
|
|
// published by id Software. All rights reserved.
|
|
//
|
|
// The source is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
|
// for more details.
|
|
//
|
|
//
|
|
// $Log:$
|
|
//
|
|
// DESCRIPTION: the automap code
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
#include "g_level.h"
|
|
#include "z_zone.h"
|
|
#include "doomdef.h"
|
|
#include "st_stuff.h"
|
|
#include "p_local.h"
|
|
#include "p_lnspec.h"
|
|
#include "w_wad.h"
|
|
|
|
#include "m_cheat.h"
|
|
#include "i_system.h"
|
|
|
|
// Needs access to LFB.
|
|
#include "v_video.h"
|
|
|
|
#include "v_text.h"
|
|
|
|
extern patch_t *hu_font[];
|
|
|
|
// State.
|
|
#include "doomstat.h"
|
|
#include "r_state.h"
|
|
|
|
// Data.
|
|
#include "dstrings.h"
|
|
|
|
#include "am_map.h"
|
|
|
|
static int Background, YourColor, WallColor, TSWallColor,
|
|
FDWallColor, CDWallColor, ThingColor,
|
|
SecretWallColor, GridColor, XHairColor,
|
|
NotSeenColor,
|
|
LockedColor,
|
|
AlmostBackground;
|
|
|
|
cvar_t *am_backcolor,
|
|
*am_yourcolor,
|
|
*am_wallcolor,
|
|
*am_tswallcolor,
|
|
*am_fdwallcolor,
|
|
*am_cdwallcolor,
|
|
*am_thingcolor,
|
|
*am_gridcolor,
|
|
*am_xhaircolor,
|
|
*am_notseencolor,
|
|
*am_lockedcolor,
|
|
*am_usecustomcolors,
|
|
*am_ovyourcolor,
|
|
*am_ovwallcolor,
|
|
*am_ovthingcolor,
|
|
*am_ovotherwallscolor,
|
|
*am_ovunseencolor;
|
|
|
|
cvar_t *am_rotate;
|
|
cvar_t *am_overlay;
|
|
cvar_t *am_showsecrets, *am_showmonsters, *am_showtime;
|
|
|
|
// drawing stuff
|
|
#define FB (screen)
|
|
|
|
#define AM_PANDOWNKEY KEY_DOWNARROW
|
|
#define AM_PANUPKEY KEY_UPARROW
|
|
#define AM_PANRIGHTKEY KEY_RIGHTARROW
|
|
#define AM_PANLEFTKEY KEY_LEFTARROW
|
|
#define AM_ZOOMINKEY KEY_EQUALS
|
|
#define AM_ZOOMINKEY2 0x4e // DIK_ADD
|
|
#define AM_ZOOMOUTKEY KEY_MINUS
|
|
#define AM_ZOOMOUTKEY2 0x4a // DIK_SUBTRACT
|
|
#define AM_GOBIGKEY 0x0b // DIK_0
|
|
#define AM_FOLLOWKEY 'f'
|
|
#define AM_GRIDKEY 'g'
|
|
#define AM_MARKKEY 'm'
|
|
#define AM_CLEARMARKKEY 'c'
|
|
|
|
#define AM_NUMMARKPOINTS 10
|
|
|
|
// scale on entry
|
|
#define INITSCALEMTOF (.2*FRACUNIT)
|
|
// how much the automap moves window per tic in frame-buffer coordinates
|
|
// moves 140 pixels in 1 second
|
|
#define F_PANINC (140/TICRATE)
|
|
// how much zoom-in per tic
|
|
// goes to 2x in 1 second
|
|
#define M_ZOOMIN ((int) (1.02*FRACUNIT))
|
|
// how much zoom-out per tic
|
|
// pulls out to 0.5x in 1 second
|
|
#define M_ZOOMOUT ((int) (FRACUNIT/1.02))
|
|
|
|
// translates between frame-buffer and map distances
|
|
#define FTOM(x) FixedMul(((x)<<16),scale_ftom)
|
|
#define MTOF(x) (FixedMul((x),scale_mtof)>>16)
|
|
// translates between frame-buffer and map coordinates
|
|
#define CXMTOF(x) (MTOF((x)-m_x)/* - f_x*/)
|
|
#define CYMTOF(y) (f_h - MTOF((y)-m_y)/* + f_y*/)
|
|
|
|
typedef struct {
|
|
int x, y;
|
|
} fpoint_t;
|
|
|
|
typedef struct {
|
|
fpoint_t a, b;
|
|
} fline_t;
|
|
|
|
typedef struct {
|
|
fixed_t x,y;
|
|
} mpoint_t;
|
|
|
|
typedef struct {
|
|
mpoint_t a, b;
|
|
} mline_t;
|
|
|
|
typedef struct {
|
|
fixed_t slp, islp;
|
|
} islope_t;
|
|
|
|
|
|
|
|
//
|
|
// The vector graphics for the automap.
|
|
// A line drawing of the player pointing right,
|
|
// starting from the middle.
|
|
//
|
|
#define R ((8*PLAYERRADIUS)/7)
|
|
mline_t player_arrow[] = {
|
|
{ { -R+R/8, 0 }, { R, 0 } }, // -----
|
|
{ { R, 0 }, { R-R/2, R/4 } }, // ----->
|
|
{ { R, 0 }, { R-R/2, -R/4 } },
|
|
{ { -R+R/8, 0 }, { -R-R/8, R/4 } }, // >---->
|
|
{ { -R+R/8, 0 }, { -R-R/8, -R/4 } },
|
|
{ { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>--->
|
|
{ { -R+3*R/8, 0 }, { -R+R/8, -R/4 } }
|
|
};
|
|
#undef R
|
|
#define NUMPLYRLINES (sizeof(player_arrow)/sizeof(mline_t))
|
|
|
|
#define R ((8*PLAYERRADIUS)/7)
|
|
mline_t cheat_player_arrow[] = {
|
|
{ { -R+R/8, 0 }, { R, 0 } }, // -----
|
|
{ { R, 0 }, { R-R/2, R/6 } }, // ----->
|
|
{ { R, 0 }, { R-R/2, -R/6 } },
|
|
{ { -R+R/8, 0 }, { -R-R/8, R/6 } }, // >----->
|
|
{ { -R+R/8, 0 }, { -R-R/8, -R/6 } },
|
|
{ { -R+3*R/8, 0 }, { -R+R/8, R/6 } }, // >>----->
|
|
{ { -R+3*R/8, 0 }, { -R+R/8, -R/6 } },
|
|
{ { -R/2, 0 }, { -R/2, -R/6 } }, // >>-d--->
|
|
{ { -R/2, -R/6 }, { -R/2+R/6, -R/6 } },
|
|
{ { -R/2+R/6, -R/6 }, { -R/2+R/6, R/4 } },
|
|
{ { -R/6, 0 }, { -R/6, -R/6 } }, // >>-dd-->
|
|
{ { -R/6, -R/6 }, { 0, -R/6 } },
|
|
{ { 0, -R/6 }, { 0, R/4 } },
|
|
{ { R/6, R/4 }, { R/6, -R/7 } }, // >>-ddt->
|
|
{ { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } },
|
|
{ { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } }
|
|
};
|
|
#undef R
|
|
#define NUMCHEATPLYRLINES (sizeof(cheat_player_arrow)/sizeof(mline_t))
|
|
|
|
#define R (FRACUNIT)
|
|
// [RH] Avoid lots of warnings without compiler-specific #pragmas
|
|
#define L(a,b,c,d) { {(fixed_t)((a)*R),(fixed_t)((b)*R)}, {(fixed_t)((c)*R),(fixed_t)((d)*R)} }
|
|
mline_t triangle_guy[] = {
|
|
L (-.867,-.5, .867,-.5),
|
|
L (.867,-.5, 0,1),
|
|
L (0,1, -.867,-.5)
|
|
};
|
|
#define NUMTRIANGLEGUYLINES (sizeof(triangle_guy)/sizeof(mline_t))
|
|
|
|
mline_t thintriangle_guy[] = {
|
|
L (-.5,-.7, 1,0),
|
|
L (1,0, -.5,.7),
|
|
L (-.5,.7, -.5,-.7)
|
|
};
|
|
#undef L
|
|
#undef R
|
|
#define NUMTHINTRIANGLEGUYLINES (sizeof(thintriangle_guy)/sizeof(mline_t))
|
|
|
|
|
|
|
|
|
|
static int cheating = 0;
|
|
static int grid = 0;
|
|
|
|
static int leveljuststarted = 1; // kluge until AM_LevelInit() is called
|
|
|
|
BOOL automapactive = false;
|
|
|
|
// location of window on screen
|
|
static int f_x;
|
|
static int f_y;
|
|
|
|
// size of window on screen
|
|
static int f_w;
|
|
static int f_h;
|
|
static int f_p; // [RH] # of bytes from start of a line to start of next
|
|
|
|
static byte *fb; // pseudo-frame buffer
|
|
static int amclock;
|
|
|
|
static mpoint_t m_paninc; // how far the window pans each tic (map coords)
|
|
static fixed_t mtof_zoommul; // how far the window zooms in each tic (map coords)
|
|
static fixed_t ftom_zoommul; // how far the window zooms in each tic (fb coords)
|
|
|
|
static fixed_t m_x, m_y; // LL x,y where the window is on the map (map coords)
|
|
static fixed_t m_x2, m_y2; // UR x,y where the window is on the map (map coords)
|
|
|
|
//
|
|
// width/height of window on map (map coords)
|
|
//
|
|
static fixed_t m_w;
|
|
static fixed_t m_h;
|
|
|
|
// based on level size
|
|
static fixed_t min_x;
|
|
static fixed_t min_y;
|
|
static fixed_t max_x;
|
|
static fixed_t max_y;
|
|
|
|
static fixed_t max_w; // max_x-min_x,
|
|
static fixed_t max_h; // max_y-min_y
|
|
|
|
// based on player size
|
|
static fixed_t min_w;
|
|
static fixed_t min_h;
|
|
|
|
|
|
static fixed_t min_scale_mtof; // used to tell when to stop zooming out
|
|
static fixed_t max_scale_mtof; // used to tell when to stop zooming in
|
|
|
|
// old stuff for recovery later
|
|
static fixed_t old_m_w, old_m_h;
|
|
static fixed_t old_m_x, old_m_y;
|
|
|
|
// old location used by the Follower routine
|
|
static mpoint_t f_oldloc;
|
|
|
|
// used by MTOF to scale from map-to-frame-buffer coords
|
|
static fixed_t scale_mtof = (fixed_t)INITSCALEMTOF;
|
|
// used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof)
|
|
static fixed_t scale_ftom;
|
|
|
|
static player_t *plr; // the player represented by an arrow
|
|
|
|
static patch_t *marknums[10]; // numbers used for marking by the automap
|
|
static mpoint_t markpoints[AM_NUMMARKPOINTS]; // where the points are
|
|
static int markpointnum = 0; // next point to be assigned
|
|
|
|
static int followplayer = 1; // specifies whether to follow the player around
|
|
|
|
// [RH] Not static so that the DeHackEd code can reach it.
|
|
unsigned char cheat_amap_seq[] = { 0xb2, 0x26, 0x26, 0x2e, 0xff };
|
|
static cheatseq_t cheat_amap = { cheat_amap_seq, 0 };
|
|
|
|
static BOOL stopped = true;
|
|
|
|
extern BOOL viewactive;
|
|
|
|
void AM_rotatePoint (fixed_t *x, fixed_t *y);
|
|
|
|
|
|
void V_MarkRect (int x, int y, int width, int height);
|
|
|
|
// Calculates the slope and slope according to the x-axis of a line
|
|
// segment in map coordinates (with the upright y-axis n' all) so
|
|
// that it can be used with the brain-dead drawing stuff.
|
|
|
|
void
|
|
AM_getIslope
|
|
( mline_t* ml,
|
|
islope_t* is )
|
|
{
|
|
int dx, dy;
|
|
|
|
dy = ml->a.y - ml->b.y;
|
|
dx = ml->b.x - ml->a.x;
|
|
if (!dy) is->islp = (dx<0?-MAXINT:MAXINT);
|
|
else is->islp = FixedDiv(dx, dy);
|
|
if (!dx) is->slp = (dy<0?-MAXINT:MAXINT);
|
|
else is->slp = FixedDiv(dy, dx);
|
|
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
void AM_activateNewScale(void)
|
|
{
|
|
m_x += m_w/2;
|
|
m_y += m_h/2;
|
|
m_w = FTOM(f_w);
|
|
m_h = FTOM(f_h);
|
|
m_x -= m_w/2;
|
|
m_y -= m_h/2;
|
|
m_x2 = m_x + m_w;
|
|
m_y2 = m_y + m_h;
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
void AM_saveScaleAndLoc(void)
|
|
{
|
|
old_m_x = m_x;
|
|
old_m_y = m_y;
|
|
old_m_w = m_w;
|
|
old_m_h = m_h;
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
void AM_restoreScaleAndLoc(void)
|
|
{
|
|
m_w = old_m_w;
|
|
m_h = old_m_h;
|
|
if (!followplayer) {
|
|
m_x = old_m_x;
|
|
m_y = old_m_y;
|
|
} else {
|
|
m_x = plr->camera->x - m_w/2;
|
|
m_y = plr->camera->y - m_h/2;
|
|
}
|
|
m_x2 = m_x + m_w;
|
|
m_y2 = m_y + m_h;
|
|
|
|
// Change the scaling multipliers
|
|
scale_mtof = FixedDiv(f_w<<FRACBITS, m_w);
|
|
scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
|
|
}
|
|
|
|
//
|
|
// adds a marker at the current location
|
|
//
|
|
void AM_addMark(void)
|
|
{
|
|
markpoints[markpointnum].x = m_x + m_w/2;
|
|
markpoints[markpointnum].y = m_y + m_h/2;
|
|
markpointnum = (markpointnum + 1) % AM_NUMMARKPOINTS;
|
|
}
|
|
|
|
//
|
|
// Determines bounding box of all vertices,
|
|
// sets global variables controlling zoom range.
|
|
//
|
|
void AM_findMinMaxBoundaries(void)
|
|
{
|
|
int i;
|
|
fixed_t a;
|
|
fixed_t b;
|
|
|
|
min_x = min_y = MAXINT;
|
|
max_x = max_y = -MAXINT;
|
|
|
|
for (i=0;i<numvertexes;i++) {
|
|
if (vertexes[i].x < min_x)
|
|
min_x = vertexes[i].x;
|
|
else if (vertexes[i].x > max_x)
|
|
max_x = vertexes[i].x;
|
|
|
|
if (vertexes[i].y < min_y)
|
|
min_y = vertexes[i].y;
|
|
else if (vertexes[i].y > max_y)
|
|
max_y = vertexes[i].y;
|
|
}
|
|
|
|
max_w = max_x - min_x;
|
|
max_h = max_y - min_y;
|
|
|
|
min_w = 2*PLAYERRADIUS; // const? never changed?
|
|
min_h = 2*PLAYERRADIUS;
|
|
|
|
a = FixedDiv((screen.width)<<FRACBITS, max_w);
|
|
b = FixedDiv((screen.height)<<FRACBITS, max_h);
|
|
|
|
min_scale_mtof = a < b ? a : b;
|
|
max_scale_mtof = FixedDiv((screen.height)<<FRACBITS, 2*PLAYERRADIUS);
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
void AM_changeWindowLoc(void)
|
|
{
|
|
if (m_paninc.x || m_paninc.y) {
|
|
followplayer = 0;
|
|
f_oldloc.x = MAXINT;
|
|
}
|
|
|
|
m_x += m_paninc.x;
|
|
m_y += m_paninc.y;
|
|
|
|
if (m_x + m_w/2 > max_x)
|
|
m_x = max_x - m_w/2;
|
|
else if (m_x + m_w/2 < min_x)
|
|
m_x = min_x - m_w/2;
|
|
|
|
if (m_y + m_h/2 > max_y)
|
|
m_y = max_y - m_h/2;
|
|
else if (m_y + m_h/2 < min_y)
|
|
m_y = min_y - m_h/2;
|
|
|
|
m_x2 = m_x + m_w;
|
|
m_y2 = m_y + m_h;
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
void AM_initVariables(void)
|
|
{
|
|
int pnum;
|
|
static event_t st_notify = { ev_keyup, AM_MSGENTERED };
|
|
|
|
automapactive = true;
|
|
|
|
f_oldloc.x = MAXINT;
|
|
amclock = 0;
|
|
|
|
m_paninc.x = m_paninc.y = 0;
|
|
ftom_zoommul = FRACUNIT;
|
|
mtof_zoommul = FRACUNIT;
|
|
|
|
m_w = FTOM(screen.width);
|
|
m_h = FTOM(screen.height);
|
|
|
|
// find player to center on initially
|
|
if (!playeringame[pnum = consoleplayer])
|
|
for (pnum=0;pnum<MAXPLAYERS;pnum++)
|
|
if (playeringame[pnum])
|
|
break;
|
|
|
|
plr = &players[pnum];
|
|
m_x = plr->mo->x - m_w/2;
|
|
m_y = plr->mo->y - m_h/2;
|
|
AM_changeWindowLoc();
|
|
|
|
// for saving & restoring
|
|
old_m_x = m_x;
|
|
old_m_y = m_y;
|
|
old_m_w = m_w;
|
|
old_m_h = m_h;
|
|
|
|
// inform the status bar of the change
|
|
ST_Responder (&st_notify);
|
|
}
|
|
|
|
void AM_initColors (BOOL overlayed)
|
|
{
|
|
unsigned int *palette;
|
|
|
|
if (screen.is8bit)
|
|
palette = DefaultPalette->colors;
|
|
else
|
|
palette = NULL;
|
|
|
|
if (overlayed) {
|
|
YourColor = V_GetColorFromString (palette, am_ovyourcolor->string);
|
|
SecretWallColor =
|
|
WallColor = V_GetColorFromString (palette, am_ovwallcolor->string);
|
|
ThingColor = V_GetColorFromString (palette, am_ovthingcolor->string);
|
|
FDWallColor =
|
|
CDWallColor =
|
|
LockedColor = V_GetColorFromString (palette, am_ovotherwallscolor->string);
|
|
NotSeenColor =
|
|
TSWallColor = V_GetColorFromString (palette, am_ovunseencolor->string);
|
|
} else if (am_usecustomcolors->value) {
|
|
/* Use the custom colors in the am_* cvars */
|
|
Background = V_GetColorFromString (palette, am_backcolor->string);
|
|
YourColor = V_GetColorFromString (palette, am_yourcolor->string);
|
|
SecretWallColor =
|
|
WallColor = V_GetColorFromString (palette, am_wallcolor->string);
|
|
TSWallColor = V_GetColorFromString (palette, am_tswallcolor->string);
|
|
FDWallColor = V_GetColorFromString (palette, am_fdwallcolor->string);
|
|
CDWallColor = V_GetColorFromString (palette, am_cdwallcolor->string);
|
|
ThingColor = V_GetColorFromString (palette, am_thingcolor->string);
|
|
GridColor = V_GetColorFromString (palette, am_gridcolor->string);
|
|
XHairColor = V_GetColorFromString (palette, am_xhaircolor->string);
|
|
NotSeenColor = V_GetColorFromString (palette, am_notseencolor->string);
|
|
LockedColor = V_GetColorFromString (palette, am_lockedcolor->string);
|
|
{
|
|
unsigned int ba = V_GetColorFromString (NULL, am_backcolor->string);
|
|
int r = RPART(ba) - 16;
|
|
int g = GPART(ba) - 16;
|
|
int b = BPART(ba) - 16;
|
|
if (r < 0)
|
|
r += 32;
|
|
if (g < 0)
|
|
g += 32;
|
|
if (b < 0)
|
|
b += 32;
|
|
|
|
if (screen.is8bit)
|
|
AlmostBackground = BestColor (DefaultPalette->basecolors, r, g , b, DefaultPalette->numcolors);
|
|
else
|
|
AlmostBackground = MAKERGB(r,g,b);
|
|
}
|
|
|
|
} else {
|
|
/* Use colors corresponding to the original Doom's */
|
|
Background = V_GetColorFromString (palette, "00 00 00");
|
|
YourColor = V_GetColorFromString (palette, "FF FF FF");
|
|
AlmostBackground = V_GetColorFromString (palette, "10 10 10");
|
|
SecretWallColor =
|
|
WallColor = V_GetColorFromString (palette, "fc 00 00");
|
|
TSWallColor = V_GetColorFromString (palette, "80 80 80");
|
|
FDWallColor = V_GetColorFromString (palette, "bc 78 48");
|
|
LockedColor =
|
|
CDWallColor = V_GetColorFromString (palette, "fc fc 00");
|
|
ThingColor = V_GetColorFromString (palette, "74 fc 6c");
|
|
GridColor = V_GetColorFromString (palette, "4c 4c 4c");
|
|
XHairColor = V_GetColorFromString (palette, "80 80 80");
|
|
NotSeenColor = V_GetColorFromString (palette, "6c 6c 6c");
|
|
}
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
void AM_loadPics(void)
|
|
{
|
|
int i;
|
|
char namebuf[9];
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
sprintf(namebuf, "AMMNUM%d", i);
|
|
marknums[i] = W_CacheLumpName (namebuf, PU_STATIC);
|
|
}
|
|
}
|
|
|
|
void AM_unloadPics(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 10; i++)
|
|
Z_ChangeTag (marknums[i], PU_CACHE);
|
|
}
|
|
|
|
void AM_clearMarks(void)
|
|
{
|
|
int i;
|
|
|
|
for (i=0;i<AM_NUMMARKPOINTS;i++)
|
|
markpoints[i].x = -1; // means empty
|
|
markpointnum = 0;
|
|
}
|
|
|
|
//
|
|
// should be called at the start of every level
|
|
// right now, i figure it out myself
|
|
//
|
|
void AM_LevelInit(void)
|
|
{
|
|
leveljuststarted = 0;
|
|
|
|
AM_clearMarks();
|
|
|
|
AM_findMinMaxBoundaries();
|
|
scale_mtof = FixedDiv(min_scale_mtof, (int) (0.7*FRACUNIT));
|
|
if (scale_mtof > max_scale_mtof)
|
|
scale_mtof = min_scale_mtof;
|
|
scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
void AM_Stop (void)
|
|
{
|
|
static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED };
|
|
|
|
AM_unloadPics ();
|
|
automapactive = false;
|
|
ST_Responder (&st_notify);
|
|
stopped = true;
|
|
BorderNeedRefresh = true;
|
|
viewactive = true;
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
void AM_Start (void)
|
|
{
|
|
static char lastmap[8] = "";
|
|
|
|
if (!stopped) AM_Stop();
|
|
stopped = false;
|
|
if (strncmp (lastmap, level.mapname, 8)) {
|
|
AM_LevelInit();
|
|
strncpy (lastmap, level.mapname, 8);
|
|
}
|
|
AM_initVariables();
|
|
AM_loadPics();
|
|
}
|
|
|
|
//
|
|
// set the window scale to the maximum size
|
|
//
|
|
void AM_minOutWindowScale(void)
|
|
{
|
|
scale_mtof = min_scale_mtof;
|
|
scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
|
|
}
|
|
|
|
//
|
|
// set the window scale to the minimum size
|
|
//
|
|
void AM_maxOutWindowScale(void)
|
|
{
|
|
scale_mtof = max_scale_mtof;
|
|
scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
|
|
}
|
|
|
|
|
|
void Cmd_Togglemap (void *plyr, int argc, char **argv)
|
|
{
|
|
if (gamestate != GS_LEVEL)
|
|
return;
|
|
|
|
SB_state = -1;
|
|
if (!automapactive) {
|
|
AM_Start ();
|
|
if (am_overlay->value)
|
|
viewactive = true;
|
|
else
|
|
viewactive = false;
|
|
} else {
|
|
if (am_overlay->value && viewactive) {
|
|
viewactive = false;
|
|
SB_state = -1;
|
|
} else {
|
|
AM_Stop ();
|
|
}
|
|
}
|
|
|
|
if (automapactive)
|
|
AM_initColors (viewactive);
|
|
}
|
|
|
|
//
|
|
// Handle events (user inputs) in automap mode
|
|
//
|
|
BOOL AM_Responder (event_t *ev)
|
|
{
|
|
int rc;
|
|
static int cheatstate = 0;
|
|
static int bigstate = 0;
|
|
|
|
rc = false;
|
|
|
|
if (automapactive && ev->type == ev_keydown) {
|
|
|
|
rc = true;
|
|
switch(ev->data1) {
|
|
case AM_PANRIGHTKEY: // pan right
|
|
if (!followplayer) m_paninc.x = FTOM(F_PANINC);
|
|
else rc = false;
|
|
break;
|
|
case AM_PANLEFTKEY: // pan left
|
|
if (!followplayer) m_paninc.x = -FTOM(F_PANINC);
|
|
else rc = false;
|
|
break;
|
|
case AM_PANUPKEY: // pan up
|
|
if (!followplayer) m_paninc.y = FTOM(F_PANINC);
|
|
else rc = false;
|
|
break;
|
|
case AM_PANDOWNKEY: // pan down
|
|
if (!followplayer) m_paninc.y = -FTOM(F_PANINC);
|
|
else rc = false;
|
|
break;
|
|
case AM_ZOOMOUTKEY: // zoom out
|
|
case AM_ZOOMOUTKEY2:
|
|
mtof_zoommul = M_ZOOMOUT;
|
|
ftom_zoommul = M_ZOOMIN;
|
|
break;
|
|
case AM_ZOOMINKEY: // zoom in
|
|
case AM_ZOOMINKEY2:
|
|
mtof_zoommul = M_ZOOMIN;
|
|
ftom_zoommul = M_ZOOMOUT;
|
|
break;
|
|
case AM_GOBIGKEY:
|
|
bigstate = !bigstate;
|
|
if (bigstate) {
|
|
AM_saveScaleAndLoc();
|
|
AM_minOutWindowScale();
|
|
}
|
|
else AM_restoreScaleAndLoc();
|
|
break;
|
|
default:
|
|
switch (ev->data2) {
|
|
case AM_FOLLOWKEY:
|
|
followplayer = !followplayer;
|
|
f_oldloc.x = MAXINT;
|
|
Printf (PRINT_HIGH, "%s\n", followplayer ? AMSTR_FOLLOWON : AMSTR_FOLLOWOFF);
|
|
break;
|
|
case AM_GRIDKEY:
|
|
grid = !grid;
|
|
Printf (PRINT_HIGH, "%s\n", grid ? AMSTR_GRIDON : AMSTR_GRIDOFF);
|
|
break;
|
|
case AM_MARKKEY:
|
|
Printf (PRINT_HIGH, "%s %d\n", AMSTR_MARKEDSPOT, markpointnum);
|
|
AM_addMark();
|
|
break;
|
|
case AM_CLEARMARKKEY:
|
|
AM_clearMarks();
|
|
Printf (PRINT_HIGH, "%s\n", AMSTR_MARKSCLEARED);
|
|
break;
|
|
default:
|
|
cheatstate=0;
|
|
rc = false;
|
|
}
|
|
}
|
|
if (!deathmatch->value && cht_CheckCheat(&cheat_amap, (char)ev->data2)) {
|
|
rc = true; // [RH] Eat last keypress of cheat sequence
|
|
cheating = (cheating+1) % 3;
|
|
}
|
|
}
|
|
|
|
else if (ev->type == ev_keyup) {
|
|
rc = false;
|
|
switch (ev->data1) {
|
|
case AM_PANRIGHTKEY:
|
|
if (!followplayer) m_paninc.x = 0;
|
|
break;
|
|
case AM_PANLEFTKEY:
|
|
if (!followplayer) m_paninc.x = 0;
|
|
break;
|
|
case AM_PANUPKEY:
|
|
if (!followplayer) m_paninc.y = 0;
|
|
break;
|
|
case AM_PANDOWNKEY:
|
|
if (!followplayer) m_paninc.y = 0;
|
|
break;
|
|
case AM_ZOOMOUTKEY:
|
|
case AM_ZOOMOUTKEY2:
|
|
case AM_ZOOMINKEY:
|
|
case AM_ZOOMINKEY2:
|
|
mtof_zoommul = FRACUNIT;
|
|
ftom_zoommul = FRACUNIT;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
//
|
|
// Zooming
|
|
//
|
|
void AM_changeWindowScale (void)
|
|
{
|
|
// Change the scaling multipliers
|
|
scale_mtof = FixedMul(scale_mtof, mtof_zoommul);
|
|
scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
|
|
|
|
if (scale_mtof < min_scale_mtof)
|
|
AM_minOutWindowScale();
|
|
else if (scale_mtof > max_scale_mtof)
|
|
AM_maxOutWindowScale();
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
void AM_doFollowPlayer(void)
|
|
{
|
|
if (f_oldloc.x != plr->camera->x || f_oldloc.y != plr->camera->y) {
|
|
m_x = FTOM(MTOF(plr->camera->x)) - m_w/2;
|
|
m_y = FTOM(MTOF(plr->camera->y)) - m_h/2;
|
|
m_x2 = m_x + m_w;
|
|
m_y2 = m_y + m_h;
|
|
f_oldloc.x = plr->camera->x;
|
|
f_oldloc.y = plr->camera->y;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Updates on Game Tick
|
|
//
|
|
void AM_Ticker (void)
|
|
{
|
|
if (!automapactive)
|
|
return;
|
|
|
|
amclock++;
|
|
|
|
if (followplayer)
|
|
AM_doFollowPlayer();
|
|
|
|
// Change the zoom if necessary
|
|
if (ftom_zoommul != FRACUNIT)
|
|
AM_changeWindowScale();
|
|
|
|
// Change x,y location
|
|
if (m_paninc.x || m_paninc.y)
|
|
AM_changeWindowLoc();
|
|
}
|
|
|
|
|
|
//
|
|
// Clear automap frame buffer.
|
|
//
|
|
void AM_clearFB (int color)
|
|
{
|
|
int y;
|
|
|
|
if (screen.is8bit) {
|
|
if (f_w == f_p)
|
|
memset (fb, color, f_w*f_h);
|
|
else
|
|
for (y = 0; y < f_h; y++)
|
|
memset (fb + y * f_p, color, f_w);
|
|
} else {
|
|
int x;
|
|
int *line;
|
|
|
|
line = (int *)(fb);
|
|
for (y = 0; y < f_h; y++) {
|
|
for (x = 0; x < f_w; x++) {
|
|
line[x] = color;
|
|
}
|
|
line += f_p >> 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Automap clipping of lines.
|
|
//
|
|
// Based on Cohen-Sutherland clipping algorithm but with a slightly
|
|
// faster reject and precalculated slopes. If the speed is needed,
|
|
// use a hash algorithm to handle the common cases.
|
|
//
|
|
BOOL AM_clipMline (mline_t *ml, fline_t *fl)
|
|
{
|
|
enum {
|
|
LEFT =1,
|
|
RIGHT =2,
|
|
BOTTOM =4,
|
|
TOP =8
|
|
};
|
|
|
|
register int outcode1 = 0;
|
|
register int outcode2 = 0;
|
|
register int
|
|
outside;
|
|
|
|
fpoint_t tmp;
|
|
int dx;
|
|
int dy;
|
|
|
|
|
|
#define DOOUTCODE(oc, mx, my) \
|
|
(oc) = 0; \
|
|
if ((my) < 0) (oc) |= TOP; \
|
|
else if ((my) >= f_h) (oc) |= BOTTOM; \
|
|
if ((mx) < 0) (oc) |= LEFT; \
|
|
else if ((mx) >= f_w) (oc) |= RIGHT;
|
|
|
|
// do trivial rejects and outcodes
|
|
if (ml->a.y > m_y2)
|
|
outcode1 = TOP;
|
|
else if (ml->a.y < m_y)
|
|
outcode1 = BOTTOM;
|
|
|
|
if (ml->b.y > m_y2)
|
|
outcode2 = TOP;
|
|
else if (ml->b.y < m_y)
|
|
outcode2 = BOTTOM;
|
|
|
|
if (outcode1 & outcode2)
|
|
return false; // trivially outside
|
|
|
|
if (ml->a.x < m_x)
|
|
outcode1 |= LEFT;
|
|
else if (ml->a.x > m_x2)
|
|
outcode1 |= RIGHT;
|
|
|
|
if (ml->b.x < m_x)
|
|
outcode2 |= LEFT;
|
|
else if (ml->b.x > m_x2)
|
|
outcode2 |= RIGHT;
|
|
|
|
if (outcode1 & outcode2)
|
|
return false; // trivially outside
|
|
|
|
// transform to frame-buffer coordinates.
|
|
fl->a.x = CXMTOF(ml->a.x);
|
|
fl->a.y = CYMTOF(ml->a.y);
|
|
fl->b.x = CXMTOF(ml->b.x);
|
|
fl->b.y = CYMTOF(ml->b.y);
|
|
|
|
DOOUTCODE(outcode1, fl->a.x, fl->a.y);
|
|
DOOUTCODE(outcode2, fl->b.x, fl->b.y);
|
|
|
|
if (outcode1 & outcode2)
|
|
return false;
|
|
|
|
while (outcode1 | outcode2) {
|
|
// may be partially inside box
|
|
// find an outside point
|
|
if (outcode1)
|
|
outside = outcode1;
|
|
else
|
|
outside = outcode2;
|
|
|
|
// clip to each side
|
|
if (outside & TOP) {
|
|
dy = fl->a.y - fl->b.y;
|
|
dx = fl->b.x - fl->a.x;
|
|
tmp.x = fl->a.x + (dx*(fl->a.y))/dy;
|
|
tmp.y = 0;
|
|
} else if (outside & BOTTOM) {
|
|
dy = fl->a.y - fl->b.y;
|
|
dx = fl->b.x - fl->a.x;
|
|
tmp.x = fl->a.x + (dx*(fl->a.y-f_h))/dy;
|
|
tmp.y = f_h-1;
|
|
} else if (outside & RIGHT) {
|
|
dy = fl->b.y - fl->a.y;
|
|
dx = fl->b.x - fl->a.x;
|
|
tmp.y = fl->a.y + (dy*(f_w-1 - fl->a.x))/dx;
|
|
tmp.x = f_w-1;
|
|
} else if (outside & LEFT) {
|
|
dy = fl->b.y - fl->a.y;
|
|
dx = fl->b.x - fl->a.x;
|
|
tmp.y = fl->a.y + (dy*(-fl->a.x))/dx;
|
|
tmp.x = 0;
|
|
}
|
|
|
|
if (outside == outcode1) {
|
|
fl->a = tmp;
|
|
DOOUTCODE(outcode1, fl->a.x, fl->a.y);
|
|
} else {
|
|
fl->b = tmp;
|
|
DOOUTCODE(outcode2, fl->b.x, fl->b.y);
|
|
}
|
|
|
|
if (outcode1 & outcode2)
|
|
return false; // trivially outside
|
|
}
|
|
|
|
return true;
|
|
}
|
|
#undef DOOUTCODE
|
|
|
|
|
|
//
|
|
// Classic Bresenham w/ whatever optimizations needed for speed
|
|
//
|
|
void AM_drawFline (fline_t *fl, int color)
|
|
{
|
|
register int x;
|
|
register int y;
|
|
register int dx;
|
|
register int dy;
|
|
register int sx;
|
|
register int sy;
|
|
register int ax;
|
|
register int ay;
|
|
register int d;
|
|
|
|
#define PUTDOTP(xx,yy,cc) fb[(yy)*f_p+(xx)]=(cc)
|
|
#define PUTDOTD(xx,yy,cc) *((int *)(fb+(yy)*f_p+((xx)<<2)))=(cc)
|
|
|
|
fl->a.x += f_x;
|
|
fl->b.x += f_x;
|
|
fl->a.y += f_y;
|
|
fl->b.y += f_y;
|
|
|
|
dx = fl->b.x - fl->a.x;
|
|
ax = 2 * (dx<0 ? -dx : dx);
|
|
sx = dx<0 ? -1 : 1;
|
|
|
|
dy = fl->b.y - fl->a.y;
|
|
ay = 2 * (dy<0 ? -dy : dy);
|
|
sy = dy<0 ? -1 : 1;
|
|
|
|
x = fl->a.x;
|
|
y = fl->a.y;
|
|
|
|
if (ax > ay) {
|
|
d = ay - ax/2;
|
|
if (screen.is8bit) {
|
|
while (1) {
|
|
PUTDOTP(x,y,(byte)color);
|
|
if (x == fl->b.x)
|
|
return;
|
|
if (d>=0) {
|
|
y += sy;
|
|
d -= ax;
|
|
}
|
|
x += sx;
|
|
d += ay;
|
|
}
|
|
} else {
|
|
while (1) {
|
|
PUTDOTD(x,y,color);
|
|
if (x == fl->b.x)
|
|
return;
|
|
if (d>=0) {
|
|
y += sy;
|
|
d -= ax;
|
|
}
|
|
x += sx;
|
|
d += ay;
|
|
}
|
|
}
|
|
} else {
|
|
d = ax - ay/2;
|
|
if (screen.is8bit) {
|
|
while (1) {
|
|
PUTDOTP(x, y, (byte)color);
|
|
if (y == fl->b.y)
|
|
return;
|
|
if (d >= 0) {
|
|
x += sx;
|
|
d -= ay;
|
|
}
|
|
y += sy;
|
|
d += ax;
|
|
}
|
|
} else {
|
|
while (1) {
|
|
PUTDOTD(x, y, color);
|
|
if (y == fl->b.y)
|
|
return;
|
|
if (d >= 0) {
|
|
x += sx;
|
|
d -= ay;
|
|
}
|
|
y += sy;
|
|
d += ax;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Clip lines, draw visible parts of lines.
|
|
//
|
|
void AM_drawMline (mline_t *ml, int color)
|
|
{
|
|
static fline_t fl;
|
|
|
|
if (AM_clipMline (ml, &fl))
|
|
AM_drawFline (&fl, color); // draws it on frame buffer using fb coords
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Draws flat (floor/ceiling tile) aligned grid lines.
|
|
//
|
|
void AM_drawGrid(int color)
|
|
{
|
|
fixed_t x, y;
|
|
fixed_t start, end;
|
|
mline_t ml;
|
|
|
|
// Figure out start of vertical gridlines
|
|
start = m_x;
|
|
if ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS))
|
|
start += (MAPBLOCKUNITS<<FRACBITS)
|
|
- ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS));
|
|
end = m_x + m_w;
|
|
|
|
// draw vertical gridlines
|
|
ml.a.y = m_y;
|
|
ml.b.y = m_y+m_h;
|
|
for (x=start; x<end; x+=(MAPBLOCKUNITS<<FRACBITS)) {
|
|
ml.a.x = x;
|
|
ml.b.x = x;
|
|
if (am_rotate->value) {
|
|
AM_rotatePoint (&ml.a.x, &ml.a.y);
|
|
AM_rotatePoint (&ml.b.x, &ml.b.y);
|
|
}
|
|
AM_drawMline(&ml, color);
|
|
}
|
|
|
|
// Figure out start of horizontal gridlines
|
|
start = m_y;
|
|
if ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS))
|
|
start += (MAPBLOCKUNITS<<FRACBITS)
|
|
- ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS));
|
|
end = m_y + m_h;
|
|
|
|
// draw horizontal gridlines
|
|
ml.a.x = m_x;
|
|
ml.b.x = m_x + m_w;
|
|
for (y=start; y<end; y+=(MAPBLOCKUNITS<<FRACBITS)) {
|
|
ml.a.y = y;
|
|
ml.b.y = y;
|
|
if (am_rotate->value) {
|
|
AM_rotatePoint (&ml.a.x, &ml.a.y);
|
|
AM_rotatePoint (&ml.b.x, &ml.b.y);
|
|
}
|
|
AM_drawMline(&ml, color);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Determines visible lines, draws them.
|
|
// This is LineDef based, not LineSeg based.
|
|
//
|
|
void AM_drawWalls(void)
|
|
{
|
|
int i;
|
|
static mline_t l;
|
|
|
|
for (i=0;i<numlines;i++) {
|
|
l.a.x = lines[i].v1->x;
|
|
l.a.y = lines[i].v1->y;
|
|
l.b.x = lines[i].v2->x;
|
|
l.b.y = lines[i].v2->y;
|
|
|
|
if (am_rotate->value) {
|
|
AM_rotatePoint (&l.a.x, &l.a.y);
|
|
AM_rotatePoint (&l.b.x, &l.b.y);
|
|
}
|
|
|
|
if (cheating || (lines[i].flags & ML_MAPPED)) {
|
|
if ((lines[i].flags & ML_DONTDRAW) && !cheating)
|
|
continue;
|
|
if (!lines[i].backsector) {
|
|
AM_drawMline(&l, WallColor);
|
|
} else {
|
|
if (lines[i].special == 39) { // teleporters
|
|
AM_drawMline(&l, WallColor);
|
|
} else if (lines[i].flags & ML_SECRET) { // secret door
|
|
if (cheating)
|
|
AM_drawMline(&l, SecretWallColor);
|
|
else
|
|
AM_drawMline(&l, WallColor);
|
|
} else if (lines[i].special == Door_LockedRaise ||
|
|
lines[i].special == ACS_LockedExecute) {
|
|
AM_drawMline (&l, LockedColor); // [RH] locked special
|
|
} else if (lines[i].backsector->floorheight
|
|
!= lines[i].frontsector->floorheight) {
|
|
AM_drawMline(&l, FDWallColor); // floor level change
|
|
} else if (lines[i].backsector->ceilingheight
|
|
!= lines[i].frontsector->ceilingheight) {
|
|
AM_drawMline(&l, CDWallColor); // ceiling level change
|
|
} else if (cheating) {
|
|
AM_drawMline(&l, TSWallColor);
|
|
}
|
|
}
|
|
} else if (plr->powers[pw_allmap]) {
|
|
if (!(lines[i].flags & ML_DONTDRAW))
|
|
AM_drawMline(&l, NotSeenColor);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Rotation in 2D.
|
|
// Used to rotate player arrow line character.
|
|
//
|
|
void AM_rotate (fixed_t *x, fixed_t *y, angle_t a)
|
|
{
|
|
fixed_t tmpx;
|
|
|
|
tmpx =
|
|
FixedMul(*x,finecosine[a>>ANGLETOFINESHIFT])
|
|
- FixedMul(*y,finesine[a>>ANGLETOFINESHIFT]);
|
|
|
|
*y =
|
|
FixedMul(*x,finesine[a>>ANGLETOFINESHIFT])
|
|
+ FixedMul(*y,finecosine[a>>ANGLETOFINESHIFT]);
|
|
|
|
*x = tmpx;
|
|
}
|
|
|
|
void AM_rotatePoint (fixed_t *x, fixed_t *y)
|
|
{
|
|
*x -= plr->mo->x;
|
|
*y -= plr->mo->y;
|
|
AM_rotate (x, y, ANG90 - plr->mo->angle);
|
|
*x += plr->mo->x;
|
|
*y += plr->mo->y;
|
|
}
|
|
|
|
void
|
|
AM_drawLineCharacter
|
|
( mline_t* lineguy,
|
|
int lineguylines,
|
|
fixed_t scale,
|
|
angle_t angle,
|
|
int color,
|
|
fixed_t x,
|
|
fixed_t y )
|
|
{
|
|
int i;
|
|
mline_t l;
|
|
|
|
for (i=0;i<lineguylines;i++) {
|
|
l.a.x = lineguy[i].a.x;
|
|
l.a.y = lineguy[i].a.y;
|
|
|
|
if (scale) {
|
|
l.a.x = FixedMul(scale, l.a.x);
|
|
l.a.y = FixedMul(scale, l.a.y);
|
|
}
|
|
|
|
if (angle)
|
|
AM_rotate(&l.a.x, &l.a.y, angle);
|
|
|
|
l.a.x += x;
|
|
l.a.y += y;
|
|
|
|
l.b.x = lineguy[i].b.x;
|
|
l.b.y = lineguy[i].b.y;
|
|
|
|
if (scale) {
|
|
l.b.x = FixedMul(scale, l.b.x);
|
|
l.b.y = FixedMul(scale, l.b.y);
|
|
}
|
|
|
|
if (angle)
|
|
AM_rotate(&l.b.x, &l.b.y, angle);
|
|
|
|
l.b.x += x;
|
|
l.b.y += y;
|
|
|
|
AM_drawMline(&l, color);
|
|
}
|
|
}
|
|
|
|
void AM_drawPlayers(void)
|
|
{
|
|
int i;
|
|
player_t* p;
|
|
int their_color = -1;
|
|
int color;
|
|
angle_t angle;
|
|
mpoint_t pt;
|
|
|
|
if (!netgame) {
|
|
if (am_rotate->value)
|
|
angle = ANG90;
|
|
else
|
|
angle = plr->mo->angle;
|
|
|
|
if (cheating)
|
|
AM_drawLineCharacter
|
|
(cheat_player_arrow, NUMCHEATPLYRLINES, 0,
|
|
angle, YourColor, plr->mo->x, plr->mo->y);
|
|
else
|
|
AM_drawLineCharacter
|
|
(player_arrow, NUMPLYRLINES, 0, angle,
|
|
YourColor, plr->mo->x, plr->mo->y);
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < MAXPLAYERS; i++) {
|
|
their_color++;
|
|
p = &players[i];
|
|
|
|
if ((deathmatch->value && !demoplayback) && p != plr)
|
|
continue;
|
|
|
|
if (!playeringame[i])
|
|
continue;
|
|
|
|
if (p->powers[pw_invisibility])
|
|
color = AlmostBackground;
|
|
else if (screen.is8bit)
|
|
color = BestColor (DefaultPalette->basecolors,
|
|
RPART(p->userinfo.color),
|
|
GPART(p->userinfo.color),
|
|
BPART(p->userinfo.color),
|
|
DefaultPalette->numcolors);
|
|
else
|
|
color = p->userinfo.color;
|
|
|
|
pt.x = p->mo->x;
|
|
pt.y = p->mo->y;
|
|
angle = p->mo->angle;
|
|
|
|
if (am_rotate->value) {
|
|
if (p == plr) {
|
|
angle = ANG90;
|
|
} else {
|
|
AM_rotatePoint (&pt.x, &pt.y);
|
|
angle += ANG90 - plr->mo->angle;
|
|
}
|
|
}
|
|
|
|
AM_drawLineCharacter
|
|
(player_arrow, NUMPLYRLINES, 0, p->mo->angle,
|
|
color, pt.x, pt.y);
|
|
}
|
|
|
|
}
|
|
|
|
void AM_drawThings (int color)
|
|
{
|
|
int i;
|
|
mobj_t* t;
|
|
mpoint_t p;
|
|
angle_t angle;
|
|
|
|
for (i=0;i<numsectors;i++) {
|
|
t = sectors[i].thinglist;
|
|
while (t) {
|
|
p.x = t->x;
|
|
p.y = t->y;
|
|
angle = t->angle;
|
|
|
|
if (am_rotate->value) {
|
|
AM_rotatePoint (&p.x, &p.y);
|
|
angle += ANG90 - plr->mo->angle;
|
|
}
|
|
|
|
AM_drawLineCharacter
|
|
(thintriangle_guy, NUMTHINTRIANGLEGUYLINES,
|
|
16<<FRACBITS, angle, color, p.x, p.y);
|
|
t = t->snext;
|
|
}
|
|
}
|
|
}
|
|
|
|
void AM_drawMarks(void)
|
|
{
|
|
int i, fx, fy, w, h;
|
|
mpoint_t pt;
|
|
|
|
for (i=0;i<AM_NUMMARKPOINTS;i++) {
|
|
if (markpoints[i].x != -1) {
|
|
// w = SHORT(marknums[i]->width);
|
|
// h = SHORT(marknums[i]->height);
|
|
w = 5; // because something's wrong with the wad, i guess
|
|
h = 6; // because something's wrong with the wad, i guess
|
|
|
|
pt.x = markpoints[i].x;
|
|
pt.y = markpoints[i].y;
|
|
|
|
if (am_rotate->value)
|
|
AM_rotatePoint (&pt.x, &pt.y);
|
|
|
|
fx = CXMTOF(pt.x);
|
|
fy = CYMTOF(pt.y) - 3;
|
|
|
|
if (fx >= f_x && fx <= f_w - w && fy >= f_y && fy <= f_h - h)
|
|
V_DrawPatchCleanNoMove(fx, fy, &FB, marknums[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void AM_drawCrosshair(int color)
|
|
{
|
|
fb[f_p*((f_h+1)/2)+(f_w/2)] = (byte)color; // single point for now
|
|
}
|
|
|
|
void AM_Drawer (void)
|
|
{
|
|
if (!automapactive)
|
|
return;
|
|
|
|
fb = screen.buffer;
|
|
if (!viewactive) {
|
|
// [RH] Set f_? here now to handle automap overlaying
|
|
// and view size adjustments.
|
|
f_x = f_y = 0;
|
|
f_w = screen.width;
|
|
f_h = ST_Y;
|
|
f_p = screen.pitch;
|
|
|
|
AM_clearFB(Background);
|
|
} else {
|
|
f_x = viewwindowx;
|
|
f_y = viewwindowy;
|
|
f_w = realviewwidth;
|
|
f_h = realviewheight;
|
|
f_p = screen.pitch;
|
|
}
|
|
AM_activateNewScale();
|
|
|
|
if (grid)
|
|
AM_drawGrid(GridColor);
|
|
|
|
AM_drawWalls();
|
|
AM_drawPlayers();
|
|
if (cheating==2)
|
|
AM_drawThings(ThingColor);
|
|
|
|
if (!viewactive)
|
|
AM_drawCrosshair(XHairColor);
|
|
|
|
AM_drawMarks();
|
|
|
|
if (!viewactive) {
|
|
|
|
char line[64+10];
|
|
int y, i, time = level.time / TICRATE, height;
|
|
|
|
height = (hu_font[0]->height + 1) * CleanYfac;
|
|
|
|
if (deathmatch->value)
|
|
y = ST_Y - height + 1;
|
|
else {
|
|
y = ST_Y - height * 2 + 1;
|
|
|
|
if (am_showmonsters->value) {
|
|
sprintf (line, TEXTCOLOR_RED "MONSTERS:"
|
|
TEXTCOLOR_NORMAL " %d / %d",
|
|
level.killed_monsters, level.total_monsters);
|
|
V_DrawTextClean (CR_GREY,0, y, line);
|
|
}
|
|
|
|
if (am_showsecrets->value) {
|
|
sprintf (line, TEXTCOLOR_RED "SECRETS:"
|
|
TEXTCOLOR_NORMAL " %d / %d",
|
|
level.found_secrets, level.total_secrets);
|
|
V_DrawTextClean (CR_GREY, screen.width - V_StringWidth (line) * CleanXfac, y, line);
|
|
}
|
|
|
|
y += height;
|
|
}
|
|
|
|
line[0] = '\x8a';
|
|
line[1] = CR_RED + 'A';
|
|
i = 0;
|
|
while (i < 8 && level.mapname[i]) {
|
|
line[2 + i++] = level.mapname[i];
|
|
}
|
|
i += 2;
|
|
line[i++] = ':';
|
|
line[i++] = ' ';
|
|
line[i++] = '\x8a';
|
|
line[i++] = '-';
|
|
strcpy (&line[i], level.level_name);
|
|
V_DrawTextClean (CR_GREY, 0, y, line);
|
|
|
|
if (am_showtime->value) {
|
|
sprintf (line, " %02d:%02d:%02d", time/3600, (time%3600)/60, time%60); // Time
|
|
V_DrawTextClean (CR_RED, screen.width - V_StringWidth (line) * CleanXfac, y, line);
|
|
}
|
|
|
|
}
|
|
}
|