diff --git a/src/am_map.cpp b/src/am_map.cpp index f50903c66e..28f9d4d636 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -26,6 +26,7 @@ //----------------------------------------------------------------------------- #include +#include #include "doomdef.h" #include "templates.h" @@ -65,28 +66,99 @@ #include "earcut.hpp" +//============================================================================= +// +// Global state +// +//============================================================================= + +enum +{ + AM_NUMMARKPOINTS = 10, +}; + +// C++ cannot do static const floats in a class, so these need to be global... +static const double PLAYERRADIUS = 16.; // player radius for automap checking +static const double M_ZOOMIN = (1.02); // how much zoom-in per tic - goes to 2x in 1 second +static const double M_ZOOMOUT = (1 / 1.02); // how much zoom-out per tic - pulls out to 0.5x in 1 second + +static FTextureID marknums[AM_NUMMARKPOINTS]; // numbers used for marking by the automap +bool automapactive = false; + +//============================================================================= +// +// Types +// +//============================================================================= + +struct fpoint_t +{ + int x, y; +}; + +struct fline_t +{ + fpoint_t a, b; +}; + +struct mpoint_t +{ + double x, y; +}; + +struct mline_t +{ + mpoint_t a, b; +}; + +struct islope_t +{ + double slp, islp; +}; + //============================================================================= // // CVARs // //============================================================================= -CVAR (Int, am_rotate, 0, CVAR_ARCHIVE); -CVAR (Int, am_overlay, 0, CVAR_ARCHIVE); -CVAR (Bool, am_showsecrets, true, CVAR_ARCHIVE); -CVAR (Bool, am_showmonsters, true, CVAR_ARCHIVE); -CVAR (Bool, am_showitems, false, CVAR_ARCHIVE); -CVAR (Bool, am_showtime, true, CVAR_ARCHIVE); -CVAR (Bool, am_showtotaltime, false, CVAR_ARCHIVE); -CVAR (Int, am_colorset, 0, CVAR_ARCHIVE); -CVAR (Bool, am_customcolors, true, CVAR_ARCHIVE); -CVAR (Int, am_map_secrets, 1, CVAR_ARCHIVE); -CVAR (Int, am_drawmapback, 1, CVAR_ARCHIVE); -CVAR (Bool, am_showkeys, true, CVAR_ARCHIVE); -CVAR (Int, am_showtriggerlines, 0, CVAR_ARCHIVE); -CVAR (Int, am_showthingsprites, 0, CVAR_ARCHIVE); +CVAR(Bool, am_textured, false, CVAR_ARCHIVE) +CVAR(Int, am_showsubsector, -1, 0); -CUSTOM_CVAR (Int, am_emptyspacemargin, 0, CVAR_ARCHIVE) + +CUSTOM_CVAR(Int, am_showalllines, -1, CVAR_NOINITCALL) // This is a cheat so don't save it. +{ + if (currentUILevel && currentUILevel->automap) + currentUILevel->automap->UpdateShowAllLines(); +} + +EXTERN_CVAR(Bool, sv_cheats) +CUSTOM_CVAR(Int, am_cheat, 0, 0) +{ + // No automap cheat in net games when cheats are disabled! + if (netgame && !sv_cheats && self != 0) + { + self = 0; + } +} + + +CVAR(Int, am_rotate, 0, CVAR_ARCHIVE); +CVAR(Int, am_overlay, 0, CVAR_ARCHIVE); +CVAR(Bool, am_showsecrets, true, CVAR_ARCHIVE); +CVAR(Bool, am_showmonsters, true, CVAR_ARCHIVE); +CVAR(Bool, am_showitems, false, CVAR_ARCHIVE); +CVAR(Bool, am_showtime, true, CVAR_ARCHIVE); +CVAR(Bool, am_showtotaltime, false, CVAR_ARCHIVE); +CVAR(Int, am_colorset, 0, CVAR_ARCHIVE); +CVAR(Bool, am_customcolors, true, CVAR_ARCHIVE); +CVAR(Int, am_map_secrets, 1, CVAR_ARCHIVE); +CVAR(Int, am_drawmapback, 1, CVAR_ARCHIVE); +CVAR(Bool, am_showkeys, true, CVAR_ARCHIVE); +CVAR(Int, am_showtriggerlines, 0, CVAR_ARCHIVE); +CVAR(Int, am_showthingsprites, 0, CVAR_ARCHIVE); + +CUSTOM_CVAR(Int, am_emptyspacemargin, 0, CVAR_ARCHIVE) { if (self < 0) { @@ -97,12 +169,86 @@ CUSTOM_CVAR (Int, am_emptyspacemargin, 0, CVAR_ARCHIVE) self = 90; } - if (nullptr != StatusBar) + if (nullptr != StatusBar && currentUILevel && currentUILevel->automap) { - AM_NewResolution(); + currentUILevel->automap->NewResolution(); } } +//============================================================================= +// +// map functions +// +//============================================================================= + +CVAR(Bool, am_followplayer, true, CVAR_ARCHIVE) +CVAR(Bool, am_portaloverlay, true, CVAR_ARCHIVE) +CVAR(Bool, am_showgrid, false, CVAR_ARCHIVE) +CVAR(Float, am_zoomdir, 0, CVAR_ARCHIVE) + +CCMD(am_togglefollow) +{ + am_followplayer = !am_followplayer; + if (currentUILevel && currentUILevel->automap) + currentUILevel->automap->ResetFollowLocation(); + Printf("%s\n", GStrings(am_followplayer ? "AMSTR_FOLLOWON" : "AMSTR_FOLLOWOFF")); +} + +CCMD(am_togglegrid) +{ + am_showgrid = !am_showgrid; + Printf("%s\n", GStrings(am_showgrid ? "AMSTR_GRIDON" : "AMSTR_GRIDOFF")); +} + +CCMD(am_toggletexture) +{ + am_textured = !am_textured; + Printf("%s\n", GStrings(am_textured ? "AMSTR_TEXON" : "AMSTR_TEXOFF")); +} + +CCMD(am_setmark) +{ + if (currentUILevel && currentUILevel->automap) + { + int m = currentUILevel->automap->addMark(); + if (m >= 0) + { + Printf("%s %d\n", GStrings("AMSTR_MARKEDSPOT"), m); + } + } +} + +CCMD(am_clearmarks) +{ + if (currentUILevel && currentUILevel->automap && currentUILevel->automap->clearMarks()) + { + Printf("%s\n", GStrings("AMSTR_MARKSCLEARED")); + } +} + +CCMD(am_gobig) +{ + if (currentUILevel && currentUILevel->automap) + currentUILevel->automap->GoBig(); +} + +CCMD(togglemap) +{ + if (gameaction == ga_nothing) + { + gameaction = ga_togglemap; + } +} + +CCMD(am_zoom) +{ + if (argv.argc() >= 2) + { + am_zoomdir = (float)atof(argv[1]); + } +} + + //============================================================================= // // Automap colors @@ -223,7 +369,7 @@ static const char *ColorNames[] = { "UnexploredSecretColor", "PortalColor", "AlmostBackgroundColor", - NULL + nullptr }; struct AMColorset @@ -521,12 +667,61 @@ void AM_ClearColorsets() AMModOverlay.defined = false; AMMod.defined = false; } + //============================================================================= // // // //============================================================================= +static void AM_initColors(bool overlayed) +{ + if (overlayed) + { + if (am_customcolors && AMModOverlay.defined) + { + AMColors = AMModOverlay; + } + else + { + AMColors.initFromCVars(cv_overlay); + } + } + else if (am_customcolors && AMMod.defined) + { + AMColors = AMMod; + } + else switch (am_colorset) + { + default: + /* Use the custom colors in the am_* cvars */ + AMColors.initFromCVars(cv_standard); + break; + + case 1: // Doom + // Use colors corresponding to the original Doom's + AMColors.initFromColors(DoomColors, false); + break; + + case 2: // Strife + // Use colors corresponding to the original Strife's + AMColors.initFromColors(StrifeColors, false); + break; + + case 3: // Raven + // Use colors corresponding to the original Raven's + AMColors.initFromColors(RavenColors, true); + break; + + } +} + +//============================================================================= +// +// custom color parser +// +//============================================================================= + void FMapInfoParser::ParseAMColors(bool overlay) { bool colorset = false; @@ -578,7 +773,7 @@ void FMapInfoParser::ParseAMColors(bool overlay) else { int i; - for (i = 0; ColorNames[i] != NULL; i++) + for (i = 0; ColorNames[i] != nullptr; i++) { if (nextKey.CompareNoCase(ColorNames[i]) == 0) { @@ -586,13 +781,13 @@ void FMapInfoParser::ParseAMColors(bool overlay) FString color = sc.String; FString colorName = V_GetColorStringByName(color); if(!colorName.IsEmpty()) color = colorName; - int colorval = V_GetColorFromString(NULL, color); + int colorval = V_GetColorFromString(nullptr, color); cset.c[i].FromRGB(RPART(colorval), GPART(colorval), BPART(colorval)); colorset = true; break; } } - if (ColorNames[i]== NULL) + if (ColorNames[i]== nullptr) { sc.ScriptError("Unknown key '%s'", nextKey.GetChars()); } @@ -600,136 +795,6 @@ void FMapInfoParser::ParseAMColors(bool overlay) } } -//============================================================================= -// -// -// -//============================================================================= - -// scale on entry -#define INITSCALEMTOF .2 -// used by MTOF to scale from map-to-frame-buffer coords -static double scale_mtof = INITSCALEMTOF; -// used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof) -static double scale_ftom; - -// translates between frame-buffer and map distances -inline double FTOM(double x) -{ - return x * scale_ftom; -} - -inline double MTOF(double x) -{ - return x * scale_mtof; -} - -static int bigstate = 0; -static bool textured = 1; // internal toggle for texture mode -static int MapPortalGroup; - -CUSTOM_CVAR(Bool, am_textured, false, CVAR_ARCHIVE) -{ - textured |= self; -} - -CVAR(Int, am_showsubsector, -1, 0); - - -// Disable the ML_DONTDRAW line flag if x% of all lines in a map are flagged with it -// (To counter annoying mappers who think they are smart by making the automap unusable) -bool am_showallenabled; - -CUSTOM_CVAR (Int, am_showalllines, -1, 0) // This is a cheat so don't save it. -{ - int flagged = 0; - int total = 0; - if (self > 0 && level.lines.Size() > 0) - { - for(auto &line : level.lines) - { - // disregard intra-sector lines - if (line.frontsector == line.backsector) continue; - - // disregard control sectors for deep water - if (line.frontsector->e->FakeFloor.Sectors.Size() > 0) continue; - - // disregard control sectors for 3D-floors - if (line.frontsector->e->XFloor.attached.Size() > 0) continue; - - total++; - if (line.flags & ML_DONTDRAW) flagged++; - } - am_showallenabled = (flagged * 100 / total >= self); - } - else if (self == 0) - { - am_showallenabled = true; - } - else - { - am_showallenabled = false; - } -} - -EXTERN_CVAR (Bool, sv_cheats) -CUSTOM_CVAR (Int, am_cheat, 0, 0) -{ - // No automap cheat in net games when cheats are disabled! - if (netgame && !sv_cheats && self != 0) - { - self = 0; - } -} - - - -#define AM_NUMMARKPOINTS 10 - -// player radius for automap checking -#define PLAYERRADIUS 16. - -// how much the automap moves window per tic in frame-buffer coordinates -// moves 140 pixels at 320x200 in 1 second -#define F_PANINC (140/TICRATE) -// how much zoom-in per tic -// goes to 2x in 1 second -#define M_ZOOMIN (1.02) -// how much zoom-out per tic -// pulls out to 0.5x in 1 second -#define M_ZOOMOUT (1/1.02) - -// translates between frame-buffer and map coordinates -#define CXMTOF(x) int(MTOF((x)-m_x)/* - f_x*/) -#define CYMTOF(y) int(f_h - MTOF((y)-m_y)/* + f_y*/) - -struct fpoint_t -{ - int x, y; -}; - -struct fline_t -{ - fpoint_t a, b; -}; - -struct mpoint_t -{ - double x, y; -}; - -struct mline_t -{ - mpoint_t a, b; -}; - -struct islope_t -{ - double slp, islp; -}; - - - //============================================================================= // // The vector graphics for the automap. @@ -743,169 +808,11 @@ static TArray CheatMapArrow; static TArray CheatKey; static TArray EasyKey; -#define L(a,b,c,d) { {(a), (b)}, {(c), (d)} } -static 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)) - -static mline_t thintriangle_guy[] = { - L (-.5,-.7, 1,0), - L (1,0, -.5,.7), - L (-.5,.7, -.5,-.7) -}; -#define NUMTHINTRIANGLEGUYLINES (sizeof(thintriangle_guy)/sizeof(mline_t)) - -static mline_t square_guy[] = { - L (0,1,1,0), - L (1,0,0,-1), - L (0,-1,-1,0), - L (-1,0,0,1) -}; -#define NUMSQUAREGUYLINES (sizeof(square_guy)/sizeof(mline_t)) - -//============================================================================= -// -// -// -//============================================================================= - -static int grid = 0; - -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 amclock; - -static mpoint_t m_paninc; // how far the window pans each tic (map coords) -static double mtof_zoommul; // how far the window zooms in each tic (map coords) -static double am_zoomdir; - -static double m_x, m_y; // LL x,y where the window is on the map (map coords) -static double 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 double m_w; -static double m_h; - -// based on level size -static double min_x, min_y, max_x, max_y; - -static double max_w; // max_x-min_x, -static double max_h; // max_y-min_y - -// based on player size -static double min_w; -static double min_h; - - -static double min_scale_mtof; // used to tell when to stop zooming out -static double max_scale_mtof; // used to tell when to stop zooming in - -// old stuff for recovery later -static double old_m_w, old_m_h; -static double old_m_x, old_m_y; - -// old location used by the Follower routine -static mpoint_t f_oldloc; - -static FTextureID 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 FTextureID mapback; // the automap background -static double mapystart=0; // y-value for the start of the map bitmap...used in the parallax stuff. -static double mapxstart=0; //x-value for the bitmap. - -static bool stopped = true; - -static void AM_calcMinMaxMtoF(); - -static void DrawMarker (FTexture *tex, double x, double y, int yadjust, - INTBOOL flip, double xscale, double yscale, int translation, double alpha, uint32_t fillcolor, FRenderStyle renderstyle); - -void AM_rotatePoint (double *x, double *y); -void AM_rotate (double *x, double *y, DAngle an); -void AM_doFollowPlayer (); - - -//============================================================================= -// -// map functions -// -//============================================================================= - -bool AM_addMark (); -bool AM_clearMarks (); -void AM_saveScaleAndLoc (); -void AM_restoreScaleAndLoc (); -void AM_minOutWindowScale (); - - -CVAR(Bool, am_followplayer, true, CVAR_ARCHIVE) -CVAR(Bool, am_portaloverlay, true, CVAR_ARCHIVE) - - -CCMD(am_togglefollow) -{ - am_followplayer = !am_followplayer; - f_oldloc.x = FLT_MAX; - Printf ("%s\n", GStrings(am_followplayer ? "AMSTR_FOLLOWON" : "AMSTR_FOLLOWOFF")); -} - -CCMD(am_togglegrid) -{ - grid = !grid; - Printf ("%s\n", GStrings(grid ? "AMSTR_GRIDON" : "AMSTR_GRIDOFF")); -} - -CCMD(am_toggletexture) -{ - if (am_textured) - { - textured = !textured; - Printf ("%s\n", GStrings(textured ? "AMSTR_TEXON" : "AMSTR_TEXOFF")); - } -} - -CCMD(am_setmark) -{ - if (AM_addMark()) - { - Printf ("%s %d\n", GStrings("AMSTR_MARKEDSPOT"), markpointnum); - } -} - -CCMD(am_clearmarks) -{ - if (AM_clearMarks()) - { - Printf ("%s\n", GStrings("AMSTR_MARKSCLEARED")); - } -} - -CCMD(am_gobig) -{ - bigstate = !bigstate; - if (bigstate) - { - AM_saveScaleAndLoc(); - AM_minOutWindowScale(); - } - else - AM_restoreScaleAndLoc(); -} +static std::array thintriangle_guy = { { + {-.5,-.7, 1,0}, + {1,0, -.5,.7}, + {-.5,.7, -.5,-.7} +} }; //============================================================================= // @@ -913,9 +820,9 @@ CCMD(am_gobig) // //============================================================================= -void AM_ParseArrow(TArray &Arrow, const char *lumpname) +static void AM_ParseArrow(TArray &Arrow, const char *lumpname) { - const int R = int((8*PLAYERRADIUS)/7); + const int R = int((8 * PLAYERRADIUS) / 7); FScanner sc; int lump = Wads.CheckNumForFullName(lumpname, true); if (lump >= 0) @@ -960,22 +867,192 @@ void AM_StaticInit() char namebuf[9]; - for (int i = 0; i < 10; i++) + for (int i = 0; i < AM_NUMMARKPOINTS; i++) { - mysnprintf (namebuf, countof(namebuf), "AMMNUM%d", i); - marknums[i] = TexMan.CheckForTexture (namebuf, ETextureType::MiscPatch); + mysnprintf(namebuf, countof(namebuf), "AMMNUM%d", i); + marknums[i] = TexMan.CheckForTexture(namebuf, ETextureType::MiscPatch); } - markpointnum = 0; - mapback.SetInvalid(); } + +//============================================================================= +// +// the actual automap class definition +// +//============================================================================= + +IMPLEMENT_CLASS(DAutomapBase, true, false); + +class DAutomap :public DAutomapBase +{ + DECLARE_CLASS(DAutomap, DAutomapBase) + + enum + { + F_PANINC = 140 / TICRATE, // how much the automap moves window per tic in frame-buffer coordinates moves 140 pixels at 320x200 in 1 second + }; + + //FLevelLocals *Level; + // scale on entry + // used by MTOF to scale from map-to-frame-buffer coords + double scale_mtof = .2; + // used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof) + double scale_ftom; + + int bigstate; + int MapPortalGroup; + + // Disable the ML_DONTDRAW line flag if x% of all lines in a map are flagged with it + // (To counter annoying mappers who think they are smart by making the automap unusable) + bool am_showallenabled; + + // location of window on screen + int f_x; + int f_y; + + // size of window on screen + int f_w; + int f_h; + + int amclock; + + mpoint_t m_paninc; // how far the window pans each tic (map coords) + double mtof_zoommul; // how far the window zooms in each tic (map coords) + + double m_x, m_y; // LL x,y where the window is on the map (map coords) + double m_x2, m_y2; // UR x,y where the window is on the map (map coords) + + // + // width/height of window on map (map coords) + // + double m_w; + double m_h; + + // based on level size + double min_x, min_y, max_x, max_y; + + double max_w; // max_x-min_x, + double max_h; // max_y-min_y + + // based on player size + double min_w; + double min_h; + + + double min_scale_mtof; // used to tell when to stop zooming out + double max_scale_mtof; // used to tell when to stop zooming in + + // old stuff for recovery later + double old_m_w, old_m_h; + double old_m_x, old_m_y; + + // old location used by the Follower routine + mpoint_t f_oldloc; + + mpoint_t markpoints[AM_NUMMARKPOINTS]; // where the points are + int markpointnum = 0; // next point to be assigned + + FTextureID mapback; // the automap background + double mapystart = 0; // y-value for the start of the map bitmap...used in the parallax stuff. + double mapxstart = 0; //x-value for the bitmap. + + TArray points; + + // translates between frame-buffer and map distances + double FTOM(double x) + { + return x * scale_ftom; + } + + double MTOF(double x) + { + return x * scale_mtof; + } + + // translates between frame-buffer and map coordinates + int CXMTOF(double x) + { + return int(MTOF((x)-m_x)/* - f_x*/); + } + + int CYMTOF(double y) + { + return int(f_h - MTOF((y)-m_y)/* + f_y*/); + } + + void calcMinMaxMtoF(); + + void DrawMarker(FTexture *tex, double x, double y, int yadjust, + INTBOOL flip, double xscale, double yscale, int translation, double alpha, uint32_t fillcolor, FRenderStyle renderstyle); + + void rotatePoint(double *x, double *y); + void rotate(double *x, double *y, DAngle an); + void doFollowPlayer(); + void saveScaleAndLoc(); + void restoreScaleAndLoc(); + void minOutWindowScale(); + void activateNewScale(); + void findMinMaxBoundaries(); + void ClipRotatedExtents(double pivotx, double pivoty); + void ScrollParchment(double dmapx, double dmapy); + void changeWindowLoc(); + void maxOutWindowScale(); + void changeWindowScale(); + void clearFB(const AMColor &color); + bool clipMline(mline_t *ml, fline_t *fl); + void drawMline(mline_t *ml, const AMColor &color); + void drawMline(mline_t *ml, int colorindex); + void drawGrid(int color); + void drawSubsectors(); + void drawSeg(seg_t *seg, const AMColor &color); + void drawPolySeg(FPolySeg *seg, const AMColor &color); + void showSS(); + void drawWalls(bool allmap); + void drawLineCharacter(const mline_t *lineguy, size_t lineguylines, double scale, DAngle angle, const AMColor &color, double x, double y); + void drawPlayers(); + void drawKeys(); + void drawThings(); + void drawMarks(); + void drawAuthorMarkers(); + void drawCrosshair(const AMColor &color); + + +public: + bool Responder(event_t* ev, bool last) override; + void Ticker(void) override; + void Drawer(int bottom) override; + void NewResolution() override; + void LevelInit() override; + void UpdateShowAllLines() override; + void Serialize(FSerializer &arc) override; + void GoBig() override; + void ResetFollowLocation() override; + int addMark() override; + bool clearMarks() override; + DVector2 GetPosition() override; + void startDisplay() override; + +}; + +IMPLEMENT_CLASS(DAutomap, false, false) + + +//============================================================================= +// +// +// +//============================================================================= + + + + //============================================================================= // // called by the coordinate drawer // //============================================================================= -DVector2 AM_GetPosition() +DVector2 DAutomap::GetPosition() { return DVector2((m_x + m_w / 2), (m_y + m_h / 2)); } @@ -986,7 +1063,7 @@ DVector2 AM_GetPosition() // //============================================================================= -void AM_activateNewScale () +void DAutomap::activateNewScale () { m_x += m_w/2; m_y += m_h/2; @@ -1004,7 +1081,7 @@ void AM_activateNewScale () // //============================================================================= -void AM_saveScaleAndLoc () +void DAutomap::saveScaleAndLoc () { old_m_x = m_x; old_m_y = m_y; @@ -1018,7 +1095,7 @@ void AM_saveScaleAndLoc () // //============================================================================= -void AM_restoreScaleAndLoc () +void DAutomap::restoreScaleAndLoc () { m_w = old_m_w; m_h = old_m_h; @@ -1046,16 +1123,17 @@ void AM_restoreScaleAndLoc () // //============================================================================= -bool AM_addMark () +int DAutomap::addMark () { if (marknums[0].isValid()) { + auto m = markpointnum; markpoints[markpointnum].x = m_x + m_w/2; markpoints[markpointnum].y = m_y + m_h/2; markpointnum = (markpointnum + 1) % AM_NUMMARKPOINTS; - return true; + return m; } - return false; + return -1; } //============================================================================= @@ -1065,12 +1143,12 @@ bool AM_addMark () // //============================================================================= -static void AM_findMinMaxBoundaries () +void DAutomap::findMinMaxBoundaries () { min_x = min_y = FLT_MAX; max_x = max_y = FIXED_MIN; - for (auto &vert : level.vertexes) + for (auto &vert : Level->vertexes) { if (vert.fX() < min_x) min_x = vert.fX(); @@ -1089,7 +1167,7 @@ static void AM_findMinMaxBoundaries () min_w = 2*PLAYERRADIUS; // const? never changed? min_h = 2*PLAYERRADIUS; - AM_calcMinMaxMtoF(); + calcMinMaxMtoF(); } //============================================================================= @@ -1098,7 +1176,7 @@ static void AM_findMinMaxBoundaries () // //============================================================================= -static void AM_calcMinMaxMtoF() +void DAutomap::calcMinMaxMtoF() { const double safe_frame = 1.0 - am_emptyspacemargin / 100.0; double a = safe_frame * (SCREENWIDTH / max_w); @@ -1114,7 +1192,7 @@ static void AM_calcMinMaxMtoF() // //============================================================================= -static void AM_ClipRotatedExtents (double pivotx, double pivoty) +void DAutomap::ClipRotatedExtents (double pivotx, double pivoty) { if (am_rotate == 0 || (am_rotate == 2 && !viewactive)) { @@ -1128,51 +1206,6 @@ static void AM_ClipRotatedExtents (double pivotx, double pivoty) else if (m_y + m_h/2 < min_y) m_y = min_y - m_h/2; } - else - { -#if 0 - double rmin_x, rmin_y, rmax_x, rmax_y; - double xs[5], ys[5]; - int i; - - xs[0] = min_x; ys[0] = min_y; - xs[1] = max_x; ys[1] = min_y; - xs[2] = max_x; ys[2] = max_y; - xs[3] = min_x; ys[3] = max_y; - xs[4] = m_x + m_w/2; ys[4] = m_y + m_h/2; - rmin_x = rmin_y = FLT_MAX; - rmax_x = rmax_y = FIXED_MIN; - - for (i = 0; i < 5; ++i) - { - xs[i] -= pivotx; - ys[i] -= pivoty; - AM_rotate (&xs[i], &ys[i], 90. - players[consoleplayer].camera->Angles.Yaw); - - if (i == 5) - break; -// xs[i] += pivotx; -// ys[i] += pivoty; - - if (xs[i] < rmin_x) rmin_x = xs[i]; - if (xs[i] > rmax_x) rmax_x = xs[i]; - if (ys[i] < rmin_y) rmin_y = ys[i]; - if (ys[i] > rmax_y) rmax_y = ys[i]; - } - if (rmax_x < 0) - xs[4] = -rmax_x; - else if (rmin_x > 0) - xs[4] = -rmin_x; - -// if (ys[4] > rmax_y) -// ys[4] = rmax_y; -// else if (ys[4] < rmin_y) -// ys[4] = rmin_y; - AM_rotate (&xs[4], &ys[4], 270. - players[consoleplayer].camera->Angles.Yaw); - m_x = xs[4] + pivotx - m_w/2; - m_y = ys[4] + pivoty - m_h/2; -#endif - } m_x2 = m_x + m_w; m_y2 = m_y + m_h; @@ -1184,7 +1217,7 @@ static void AM_ClipRotatedExtents (double pivotx, double pivoty) // //============================================================================= -static void AM_ScrollParchment (double dmapx, double dmapy) +void DAutomap::ScrollParchment (double dmapx, double dmapy) { mapxstart = mapxstart - dmapx * scale_mtof; mapystart = mapystart - dmapy * scale_mtof; @@ -1196,7 +1229,7 @@ static void AM_ScrollParchment (double dmapx, double dmapy) { FTexture *backtex = TexMan.GetTexture(mapback); - if (backtex != NULL) + if (backtex != nullptr) { int pwidth = backtex->GetDisplayWidth(); int pheight = backtex->GetDisplayHeight(); @@ -1219,7 +1252,7 @@ static void AM_ScrollParchment (double dmapx, double dmapy) // //============================================================================= -void AM_changeWindowLoc () +void DAutomap::changeWindowLoc () { if (m_paninc.x || m_paninc.y) { @@ -1237,14 +1270,14 @@ void AM_changeWindowLoc () oincy = incy = m_paninc.y * SCREENHEIGHT / 200; if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { - AM_rotate(&incx, &incy, players[consoleplayer].camera->Angles.Yaw - 90.); + rotate(&incx, &incy, players[consoleplayer].camera->Angles.Yaw - 90.); } m_x += incx; m_y += incy; - AM_ClipRotatedExtents (oldmx + m_w/2, oldmy + m_h/2); - AM_ScrollParchment (m_x != oldmx ? oincx : 0, m_y != oldmy ? -oincy : 0); + ClipRotatedExtents (oldmx + m_w/2, oldmy + m_h/2); + ScrollParchment (m_x != oldmx ? oincx : 0, m_y != oldmy ? -oincy : 0); } @@ -1254,21 +1287,10 @@ void AM_changeWindowLoc () // //============================================================================= -void AM_initVariables () +void DAutomap::startDisplay() { int pnum; - automapactive = true; - - // Reset AM buttons - Button_AM_PanLeft.Reset(); - Button_AM_PanRight.Reset(); - Button_AM_PanUp.Reset(); - Button_AM_PanDown.Reset(); - Button_AM_ZoomIn.Reset(); - Button_AM_ZoomOut.Reset(); - - f_oldloc.x = FLT_MAX; amclock = 0; @@ -1286,7 +1308,7 @@ void AM_initVariables () assert(pnum >= 0 && pnum < MAXPLAYERS); m_x = players[pnum].camera->X() - m_w/2; m_y = players[pnum].camera->Y() - m_h/2; - AM_changeWindowLoc(); + changeWindowLoc(); // for saving & restoring old_m_x = m_x; @@ -1301,55 +1323,7 @@ void AM_initVariables () // //============================================================================= -static void AM_initColors (bool overlayed) -{ - if (overlayed) - { - if (am_customcolors && AMModOverlay.defined) - { - AMColors = AMModOverlay; - } - else - { - AMColors.initFromCVars(cv_overlay); - } - } - else if (am_customcolors && AMMod.defined) - { - AMColors = AMMod; - } - else switch(am_colorset) - { - default: - /* Use the custom colors in the am_* cvars */ - AMColors.initFromCVars(cv_standard); - break; - - case 1: // Doom - // Use colors corresponding to the original Doom's - AMColors.initFromColors(DoomColors, false); - break; - - case 2: // Strife - // Use colors corresponding to the original Strife's - AMColors.initFromColors(StrifeColors, false); - break; - - case 3: // Raven - // Use colors corresponding to the original Raven's - AMColors.initFromColors(RavenColors, true); - break; - - } -} - -//============================================================================= -// -// -// -//============================================================================= - -bool AM_clearMarks () +bool DAutomap::clearMarks () { for (int i = AM_NUMMARKPOINTS-1; i >= 0; i--) markpoints[i].x = -1; // means empty @@ -1363,63 +1337,35 @@ bool AM_clearMarks () // //============================================================================= -void AM_LevelInit () +void DAutomap::LevelInit () { - if (level.info->MapBackground.Len() == 0) + if (Level->info->MapBackground.Len() == 0) { mapback = TexMan.CheckForTexture("AUTOPAGE", ETextureType::MiscPatch); } else { - mapback = TexMan.CheckForTexture(level.info->MapBackground, ETextureType::MiscPatch); + mapback = TexMan.CheckForTexture(Level->info->MapBackground, ETextureType::MiscPatch); } - AM_clearMarks(); + clearMarks(); - AM_findMinMaxBoundaries(); + findMinMaxBoundaries(); scale_mtof = min_scale_mtof / 0.7; if (scale_mtof > max_scale_mtof) scale_mtof = min_scale_mtof; scale_ftom = 1 / scale_mtof; - am_showalllines.Callback(); + UpdateShowAllLines(); } -//============================================================================= -// -// -// -//============================================================================= - -void AM_Stop () -{ - automapactive = false; - stopped = true; - viewactive = true; -} - -//============================================================================= -// -// -// -//============================================================================= - -void AM_Start () -{ - if (!stopped) AM_Stop(); - stopped = false; - AM_initVariables(); -} - - - //============================================================================= // // set the window scale to the maximum size // //============================================================================= -void AM_minOutWindowScale () +void DAutomap::minOutWindowScale () { scale_mtof = min_scale_mtof; scale_ftom = 1/ scale_mtof; @@ -1431,7 +1377,7 @@ void AM_minOutWindowScale () // //============================================================================= -void AM_maxOutWindowScale () +void DAutomap::maxOutWindowScale () { scale_mtof = max_scale_mtof; scale_ftom = 1 / scale_mtof; @@ -1443,7 +1389,7 @@ void AM_maxOutWindowScale () // //============================================================================= -void AM_NewResolution() +void DAutomap::NewResolution() { double oldmin = min_scale_mtof; @@ -1451,73 +1397,26 @@ void AM_NewResolution() { return; // [SP] Not in a game, exit! } - AM_calcMinMaxMtoF(); + calcMinMaxMtoF(); scale_mtof = scale_mtof * min_scale_mtof / oldmin; scale_ftom = 1 / scale_mtof; if (scale_mtof < min_scale_mtof) - AM_minOutWindowScale(); + minOutWindowScale(); else if (scale_mtof > max_scale_mtof) - AM_maxOutWindowScale(); + maxOutWindowScale(); f_w = screen->GetWidth(); f_h = StatusBar->GetTopOfStatusbar(); - AM_activateNewScale(); + activateNewScale(); } -//============================================================================= -// -// -// -//============================================================================= - -CCMD (togglemap) -{ - if (gameaction == ga_nothing) - { - gameaction = ga_togglemap; - } -} - -//============================================================================= -// -// -// -//============================================================================= - -void AM_ToggleMap () -{ - if (gamestate != GS_LEVEL) - return; - - // Don't activate the automap if we're not allowed to use it. - if (dmflags2 & DF2_NO_AUTOMAP) - return; - - if (!automapactive) - { - AM_Start (); - viewactive = (am_overlay != 0.f); - } - else - { - if (am_overlay==1 && viewactive) - { - viewactive = false; - } - else - { - AM_Stop (); - } - } -} - //============================================================================= // // Handle events (user inputs) in automap mode // //============================================================================= -bool AM_Responder (event_t *ev, bool last) +bool DAutomap::Responder (event_t *ev, bool last) { if (automapactive && (ev->type == EV_KeyDown || ev->type == EV_KeyUp)) { @@ -1528,7 +1427,7 @@ bool AM_Responder (event_t *ev, bool last) if (!strnicmp(defbind, "+am_pan", 7)) return false; } - bool res = C_DoKey(ev, &AutomapBindings, NULL); + 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 @@ -1548,7 +1447,7 @@ bool AM_Responder (event_t *ev, bool last) // //============================================================================= -void AM_changeWindowScale () +void DAutomap::changeWindowScale () { double mtof_zoommul; @@ -1579,17 +1478,9 @@ void AM_changeWindowScale () scale_ftom = 1 / scale_mtof; if (scale_mtof < min_scale_mtof) - AM_minOutWindowScale(); + minOutWindowScale(); else if (scale_mtof > max_scale_mtof) - AM_maxOutWindowScale(); -} - -CCMD(am_zoom) -{ - if (argv.argc() >= 2) - { - am_zoomdir = atof(argv[1]); - } + maxOutWindowScale(); } //============================================================================= @@ -1598,7 +1489,7 @@ CCMD(am_zoom) // //============================================================================= -void AM_doFollowPlayer () +void DAutomap::doFollowPlayer () { double sx, sy; auto cam = players[consoleplayer].camera; @@ -1619,9 +1510,9 @@ void AM_doFollowPlayer () sy = (f_oldloc.y - ampos.Y); if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { - AM_rotate(&sx, &sy, cam->Angles.Yaw - 90); + rotate(&sx, &sy, cam->Angles.Yaw - 90); } - AM_ScrollParchment(sx, sy); + ScrollParchment(sx, sy); f_oldloc.x = ampos.X; f_oldloc.y = ampos.Y; @@ -1635,7 +1526,7 @@ void AM_doFollowPlayer () // //============================================================================= -void AM_Ticker () +void DAutomap::Ticker () { if (!automapactive) return; @@ -1644,7 +1535,7 @@ void AM_Ticker () if (am_followplayer) { - AM_doFollowPlayer(); + doFollowPlayer(); } else { @@ -1657,11 +1548,11 @@ void AM_Ticker () // Change the zoom if necessary if (Button_AM_ZoomIn.bDown || Button_AM_ZoomOut.bDown || am_zoomdir != 0) - AM_changeWindowScale(); + changeWindowScale(); // Change x,y location //if (m_paninc.x || m_paninc.y) - AM_changeWindowLoc(); + changeWindowLoc(); } @@ -1671,7 +1562,7 @@ void AM_Ticker () // //============================================================================= -void AM_clearFB (const AMColor &color) +void DAutomap::clearFB (const AMColor &color) { bool drawback = mapback.isValid() && am_drawmapback != 0; if (am_drawmapback == 2) @@ -1690,7 +1581,7 @@ void AM_clearFB (const AMColor &color) else { FTexture *backtex = TexMan.GetTexture(mapback); - if (backtex != NULL) + if (backtex != nullptr) { int pwidth = backtex->GetDisplayWidth(); int pheight = backtex->GetDisplayHeight(); @@ -1719,7 +1610,7 @@ void AM_clearFB (const AMColor &color) // //============================================================================= -bool AM_clipMline (mline_t *ml, fline_t *fl) +bool DAutomap::clipMline (mline_t *ml, fline_t *fl) { enum { LEFT =1, @@ -1736,12 +1627,14 @@ bool AM_clipMline (mline_t *ml, fline_t *fl) 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; + auto DOOUTCODE = [this](int &oc, double mx, double 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) @@ -1837,8 +1730,6 @@ bool AM_clipMline (mline_t *ml, fline_t *fl) return true; } -#undef DOOUTCODE - //============================================================================= // @@ -1846,19 +1737,19 @@ bool AM_clipMline (mline_t *ml, fline_t *fl) // //============================================================================= -void AM_drawMline (mline_t *ml, const AMColor &color) +void DAutomap::drawMline (mline_t *ml, const AMColor &color) { fline_t fl; - if (AM_clipMline (ml, &fl)) + if (clipMline (ml, &fl)) { screen->DrawLine (f_x + fl.a.x, f_y + fl.a.y, f_x + fl.b.x, f_y + fl.b.y, color.Index, color.RGB); } } -inline void AM_drawMline (mline_t *ml, int colorindex) +void DAutomap::drawMline (mline_t *ml, int colorindex) { - AM_drawMline(ml, AMColors[colorindex]); + drawMline(ml, AMColors[colorindex]); } //============================================================================= @@ -1867,15 +1758,15 @@ inline void AM_drawMline (mline_t *ml, int colorindex) // //============================================================================= -void AM_drawGrid (int color) +void DAutomap::drawGrid (int color) { double x, y; double start, end; mline_t ml; double minlen, extx, exty; double minx, miny; - auto bmaporgx = level.blockmap.bmaporgx; - auto bmaporgy = level.blockmap.bmaporgy; + auto bmaporgx = Level->blockmap.bmaporgx; + auto bmaporgy = Level->blockmap.bmaporgy; // [RH] Calculate a minimum for how long the grid lines should be so that // they cover the screen at any rotation. @@ -1901,10 +1792,10 @@ void AM_drawGrid (int color) ml.b.y = ml.a.y + minlen; if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { - AM_rotatePoint (&ml.a.x, &ml.a.y); - AM_rotatePoint (&ml.b.x, &ml.b.y); + rotatePoint (&ml.a.x, &ml.a.y); + rotatePoint (&ml.b.x, &ml.b.y); } - AM_drawMline(&ml, color); + drawMline(&ml, color); } // Figure out start of horizontal gridlines @@ -1921,10 +1812,10 @@ void AM_drawGrid (int color) ml.b.y = y; if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { - AM_rotatePoint (&ml.a.x, &ml.a.y); - AM_rotatePoint (&ml.b.x, &ml.b.y); + rotatePoint (&ml.a.x, &ml.a.y); + rotatePoint (&ml.b.x, &ml.b.y); } - AM_drawMline (&ml, color); + drawMline (&ml, color); } } @@ -2052,9 +1943,8 @@ sector_t * AM_FakeFlat(AActor *viewer, sector_t * sec, sector_t * dest) // //============================================================================= -void AM_drawSubsectors() +void DAutomap::drawSubsectors() { - static TArray points; std::vector indices; double scale = scale_mtof; DAngle rotation; @@ -2066,7 +1956,7 @@ void AM_drawSubsectors() PalEntry flatcolor; mpoint_t originpt; - auto &subsectors = level.subsectors; + auto &subsectors = Level->subsectors; for (unsigned i = 0; i < subsectors.Size(); ++i) { auto sub = &subsectors[i]; @@ -2093,7 +1983,7 @@ void AM_drawSubsectors() sub->firstline[j].v1->fY() }; if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { - AM_rotatePoint(&pt.x, &pt.y); + rotatePoint(&pt.x, &pt.y); } points[j].X = float(f_x + ((pt.x - m_x) * scale)); points[j].Y = float(f_y + (f_h - (pt.y - m_y) * scale)); @@ -2184,13 +2074,13 @@ void AM_drawSubsectors() // Apply the floor's rotation to the texture origin. if (rotation != 0) { - AM_rotate(&originpt.x, &originpt.y, rotation); + rotate(&originpt.x, &originpt.y, rotation); } // Apply the automap's rotation to the texture origin. if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { rotation = rotation + 90. - players[consoleplayer].camera->Angles.Yaw; - AM_rotatePoint(&originpt.x, &originpt.y); + rotatePoint(&originpt.x, &originpt.y); } originx = f_x + ((originpt.x - m_x) * scale); originy = f_y + (f_h - (originpt.y - m_y) * scale); @@ -2206,7 +2096,7 @@ void AM_drawSubsectors() colormap.Desaturation = 255 - (255 - colormap.Desaturation) / 4; } // make table based fog visible on the automap as well. - if (level.flags & LEVEL_HASFADETABLE) + if (Level->flags & LEVEL_HASFADETABLE) { colormap.FadeColor = PalEntry(0, 128, 128, 128); } @@ -2259,7 +2149,7 @@ static int AM_CheckSecret(line_t *line) { if (AMColors.isValid(AMColors.SecretSectorColor)) { - if (line->frontsector != NULL) + if (line->frontsector != nullptr) { if (line->frontsector->wasSecret()) { @@ -2267,7 +2157,7 @@ static int AM_CheckSecret(line_t *line) if (am_map_secrets==2 && !(line->flags & ML_SECRET)) return 2; } } - if (line->backsector != NULL) + if (line->backsector != nullptr) { if (line->backsector->wasSecret()) { @@ -2286,7 +2176,7 @@ static int AM_CheckSecret(line_t *line) // //============================================================================= -void AM_drawSeg(seg_t *seg, const AMColor &color) +void DAutomap::drawSeg(seg_t *seg, const AMColor &color) { mline_t l; l.a.x = seg->v1->fX(); @@ -2296,13 +2186,13 @@ void AM_drawSeg(seg_t *seg, const AMColor &color) if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { - AM_rotatePoint (&l.a.x, &l.a.y); - AM_rotatePoint (&l.b.x, &l.b.y); + rotatePoint (&l.a.x, &l.a.y); + rotatePoint (&l.b.x, &l.b.y); } - AM_drawMline(&l, color); + drawMline(&l, color); } -void AM_drawPolySeg(FPolySeg *seg, const AMColor &color) +void DAutomap::drawPolySeg(FPolySeg *seg, const AMColor &color) { mline_t l; l.a.x = seg->v1.pos.X; @@ -2312,38 +2202,38 @@ void AM_drawPolySeg(FPolySeg *seg, const AMColor &color) if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { - AM_rotatePoint (&l.a.x, &l.a.y); - AM_rotatePoint (&l.b.x, &l.b.y); + rotatePoint (&l.a.x, &l.a.y); + rotatePoint (&l.b.x, &l.b.y); } - AM_drawMline(&l, color); + drawMline(&l, color); } -void AM_showSS() +void DAutomap::showSS() { - if (am_showsubsector >= 0 && (unsigned)am_showsubsector < level.subsectors.Size()) + if (am_showsubsector >= 0 && (unsigned)am_showsubsector < Level->subsectors.Size()) { AMColor yellow; yellow.FromRGB(255,255,0); AMColor red; red.FromRGB(255,0,0); - subsector_t *sub = &level.subsectors[am_showsubsector]; + subsector_t *sub = &Level->subsectors[am_showsubsector]; for (unsigned int i = 0; i < sub->numlines; i++) { - AM_drawSeg(sub->firstline + i, yellow); + drawSeg(sub->firstline + i, yellow); } - for (auto &poly : level.Polyobjects) + for (auto &poly : Level->Polyobjects) { FPolyNode *pnode = poly.subsectorlinks; - while (pnode != NULL) + while (pnode != nullptr) { if (pnode->subsector == sub) { for (unsigned j = 0; j < pnode->segs.Size(); j++) { - AM_drawPolySeg(&pnode->segs[j], red); + drawPolySeg(&pnode->segs[j], red); } } pnode = pnode->snext; @@ -2441,15 +2331,15 @@ bool AM_checkSectorActions (sector_t *sector, bool (*function)(int, int *), int // [TP] Check whether there's a boundary on the provided line for a special that satisfies the provided function. // It's a boundary if the line can activate the special or the line's bordering sectors can activate it. // If found, specialptr and argsptr will be filled with special and args if given. -bool AM_checkSpecialBoundary (line_t &line, bool (*function)(int, int *), int *specialptr = NULL, int **argsptr = NULL) +bool AM_checkSpecialBoundary (line_t &line, bool (*function)(int, int *), int *specialptr = nullptr, int **argsptr = nullptr) { - if (specialptr == NULL) + if (specialptr == nullptr) { static int sink; specialptr = &sink; } - if (argsptr == NULL) + if (argsptr == nullptr) { static int *sink; argsptr = &sink; @@ -2466,7 +2356,7 @@ bool AM_checkSpecialBoundary (line_t &line, bool (*function)(int, int *), int *s // Check sector actions in the line's front sector -- the action has to be use-activated in order to // show up if this is a one-sided line, because the player cannot trigger sector actions by crossing // a one-sided line (since that's impossible, duh). - if (AM_checkSectorActions(line.frontsector, function, specialptr, argsptr, line.backsector == NULL)) + if (AM_checkSectorActions(line.frontsector, function, specialptr, argsptr, line.backsector == nullptr)) return true; // If it has a back sector, check sector actions in that. @@ -2500,7 +2390,7 @@ bool AM_isTriggerBoundary (line_t &line) return am_showtriggerlines == 1? AM_checkSpecialBoundary(line, [](int special, int *) { FLineSpecial *spec = P_GetLineSpecialInfo(special); - return spec != NULL + return spec != nullptr && spec->max_args >= 0 && special != Door_Open && special != Door_Close @@ -2511,14 +2401,14 @@ bool AM_isTriggerBoundary (line_t &line) }) : AM_checkSpecialBoundary(line, [](int special, int *) { FLineSpecial *spec = P_GetLineSpecialInfo(special); - return spec != NULL + return spec != nullptr && spec->max_args >= 0; }); } -bool AM_isLockBoundary (line_t &line, int *lockptr = NULL) +bool AM_isLockBoundary (line_t &line, int *lockptr = nullptr) { - if (lockptr == NULL) + if (lockptr == nullptr) { static int sink; lockptr = &sink; @@ -2571,19 +2461,19 @@ bool AM_isLockBoundary (line_t &line, int *lockptr = NULL) // //============================================================================= -void AM_drawWalls (bool allmap) +void DAutomap::drawWalls (bool allmap) { static mline_t l; int lock, color; - int numportalgroups = am_portaloverlay ? level.Displacements.size : 0; + int numportalgroups = am_portaloverlay ? Level->Displacements.size : 0; for (int p = numportalgroups - 1; p >= -1; p--) { if (p == MapPortalGroup) continue; - for (auto &line : level.lines) + for (auto &line : Level->lines) { int pg; @@ -2600,7 +2490,7 @@ void AM_drawWalls (bool allmap) bool portalmode = numportalgroups > 0 && pg != MapPortalGroup; if (pg == p) { - offset = level.Displacements.getOffset(pg, MapPortalGroup); + offset = Level->Displacements.getOffset(pg, MapPortalGroup); } else if (p == -1 && (pg == MapPortalGroup || !am_portaloverlay)) { @@ -2615,8 +2505,8 @@ void AM_drawWalls (bool allmap) if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { - AM_rotatePoint(&l.a.x, &l.a.y); - AM_rotatePoint(&l.b.x, &l.b.y); + rotatePoint(&l.a.x, &l.a.y); + rotatePoint(&l.b.x, &l.b.y); } if (am_cheat != 0 || (line.flags & ML_MAPPED)) @@ -2632,37 +2522,37 @@ void AM_drawWalls (bool allmap) if (line.automapstyle > AMLS_Default && line.automapstyle < AMLS_COUNT && (am_cheat == 0 || am_cheat >= 4)) { - AM_drawMline(&l, AUTOMAP_LINE_COLORS[line.automapstyle]); + drawMline(&l, AUTOMAP_LINE_COLORS[line.automapstyle]); continue; } if (portalmode) { - AM_drawMline(&l, AMColors.PortalColor); + drawMline(&l, AMColors.PortalColor); } else if (AM_CheckSecret(&line) == 1) { // map secret sectors like Boom - AM_drawMline(&l, AMColors.SecretSectorColor); + drawMline(&l, AMColors.SecretSectorColor); } else if (AM_CheckSecret(&line) == 2) { - AM_drawMline(&l, AMColors.UnexploredSecretColor); + drawMline(&l, AMColors.UnexploredSecretColor); } else if (line.flags & ML_SECRET) { // secret door - if (am_cheat != 0 && line.backsector != NULL) - AM_drawMline(&l, AMColors.SecretWallColor); + if (am_cheat != 0 && line.backsector != nullptr) + drawMline(&l, AMColors.SecretWallColor); else - AM_drawMline(&l, AMColors.WallColor); + drawMline(&l, AMColors.WallColor); } else if (AM_isTeleportBoundary(line) && AMColors.isValid(AMColors.IntraTeleportColor)) { // intra-level teleporters - AM_drawMline(&l, AMColors.IntraTeleportColor); + drawMline(&l, AMColors.IntraTeleportColor); } else if (AM_isExitBoundary(line) && AMColors.isValid(AMColors.InterTeleportColor)) { // inter-level/game-ending teleporters - AM_drawMline(&l, AMColors.InterTeleportColor); + drawMline(&l, AMColors.InterTeleportColor); } else if (AM_isLockBoundary(line, &lock)) { @@ -2675,40 +2565,40 @@ void AM_drawWalls (bool allmap) if (color >= 0) c.FromRGB(RPART(color), GPART(color), BPART(color)); else c = AMColors[AMColors.LockedColor]; - AM_drawMline(&l, c); + drawMline(&l, c); } else { - AM_drawMline(&l, AMColors.LockedColor); // locked special + drawMline(&l, AMColors.LockedColor); // locked special } } else if (am_showtriggerlines && AMColors.isValid(AMColors.SpecialWallColor) && AM_isTriggerBoundary(line)) { - AM_drawMline(&l, AMColors.SpecialWallColor); // wall with special non-door action the player can do + drawMline(&l, AMColors.SpecialWallColor); // wall with special non-door action the player can do } - else if (line.backsector == NULL) + else if (line.backsector == nullptr) { - AM_drawMline(&l, AMColors.WallColor); // one-sided wall + drawMline(&l, AMColors.WallColor); // one-sided wall } else if (line.backsector->floorplane != line.frontsector->floorplane) { - AM_drawMline(&l, AMColors.FDWallColor); // floor level change + drawMline(&l, AMColors.FDWallColor); // floor level change } else if (line.backsector->ceilingplane != line.frontsector->ceilingplane) { - AM_drawMline(&l, AMColors.CDWallColor); // ceiling level change + drawMline(&l, AMColors.CDWallColor); // ceiling level change } else if (AM_Check3DFloors(&line)) { - AM_drawMline(&l, AMColors.EFWallColor); // Extra floor border + drawMline(&l, AMColors.EFWallColor); // Extra floor border } else if (am_cheat > 0 && am_cheat < 4) { - AM_drawMline(&l, AMColors.TSWallColor); + drawMline(&l, AMColors.TSWallColor); } } else if (allmap || (line.flags & ML_REVEALED)) @@ -2720,7 +2610,7 @@ void AM_drawWalls (bool allmap) continue; } } - AM_drawMline(&l, AMColors.NotSeenColor); + drawMline(&l, AMColors.NotSeenColor); } } } @@ -2734,7 +2624,7 @@ void AM_drawWalls (bool allmap) // //============================================================================= -void AM_rotate(double *xp, double *yp, DAngle a) +void DAutomap::rotate(double *xp, double *yp, DAngle a) { static DAngle angle_saved = 0.; static double sinrot = 0; @@ -2762,13 +2652,13 @@ void AM_rotate(double *xp, double *yp, DAngle a) // //============================================================================= -void AM_rotatePoint (double *x, double *y) +void DAutomap::rotatePoint (double *x, double *y) { double pivotx = m_x + m_w/2; double pivoty = m_y + m_h/2; *x -= pivotx; *y -= pivoty; - AM_rotate (x, y, -players[consoleplayer].camera->Angles.Yaw + 90.); + rotate (x, y, -players[consoleplayer].camera->Angles.Yaw + 90.); *x += pivotx; *y += pivoty; } @@ -2779,15 +2669,7 @@ void AM_rotatePoint (double *x, double *y) // //============================================================================= -void -AM_drawLineCharacter -( const mline_t *lineguy, - int lineguylines, - double scale, - DAngle angle, - const AMColor &color, - double x, - double y ) +void DAutomap::drawLineCharacter(const mline_t *lineguy, size_t lineguylines, double scale, DAngle angle, const AMColor &color, double x, double y) { int i; mline_t l; @@ -2802,7 +2684,7 @@ AM_drawLineCharacter } if (angle != 0) - AM_rotate(&l.a.x, &l.a.y, angle); + rotate(&l.a.x, &l.a.y, angle); l.a.x += x; l.a.y += y; @@ -2816,12 +2698,12 @@ AM_drawLineCharacter } if (angle != 0) - AM_rotate(&l.b.x, &l.b.y, angle); + rotate(&l.b.x, &l.b.y, angle); l.b.x += x; l.b.y += y; - AM_drawMline(&l, color); + drawMline(&l, color); } } @@ -2831,7 +2713,7 @@ AM_drawLineCharacter // //============================================================================= -void AM_drawPlayers () +void DAutomap::drawPlayers () { if (am_cheat >= 2 && am_cheat != 4 && am_showthingsprites > 0) { @@ -2855,7 +2737,7 @@ void AM_drawPlayers () if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { angle = 90.; - AM_rotatePoint (&pt.x, &pt.y); + rotatePoint (&pt.x, &pt.y); } else { @@ -2872,7 +2754,7 @@ void AM_drawPlayers () arrow = &MapArrow[0]; numarrowlines = MapArrow.Size(); } - AM_drawLineCharacter(arrow, numarrowlines, 0, angle, AMColors[AMColors.YourColor], pt.x, pt.y); + drawLineCharacter(arrow, numarrowlines, 0, angle, AMColors[AMColors.YourColor], pt.x, pt.y); return; } @@ -2881,7 +2763,7 @@ void AM_drawPlayers () player_t *p = &players[i]; AMColor color; - if (!playeringame[i] || p->mo == NULL) + if (!playeringame[i] || p->mo == nullptr) { continue; } @@ -2905,13 +2787,13 @@ void AM_drawPlayers () { float h, s, v, r, g, b; - D_GetPlayerColor (i, &h, &s, &v, NULL); + D_GetPlayerColor (i, &h, &s, &v, nullptr); HSVtoRGB (&r, &g, &b, h, s, v); color.FromRGB(clamp (int(r*255.f),0,255), clamp (int(g*255.f),0,255), clamp (int(b*255.f),0,255)); } - if (p->mo != NULL) + if (p->mo != nullptr) { DVector3 pos = p->mo->PosRelative(MapPortalGroup); pt.x = pos.X; @@ -2921,11 +2803,11 @@ void AM_drawPlayers () if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { - AM_rotatePoint (&pt.x, &pt.y); + rotatePoint (&pt.x, &pt.y); angle -= players[consoleplayer].camera->Angles.Yaw - 90.; } - AM_drawLineCharacter(&MapArrow[0], MapArrow.Size(), 0, angle, color, pt.x, pt.y); + drawLineCharacter(&MapArrow[0], MapArrow.Size(), 0, angle, color, pt.x, pt.y); } } } @@ -2936,7 +2818,7 @@ void AM_drawPlayers () // //============================================================================= -void AM_drawKeys () +void DAutomap::drawKeys () { AMColor color; mpoint_t p; @@ -2945,7 +2827,7 @@ void AM_drawKeys () TThinkerIterator it(NAME_Key); AActor *key; - while ((key = it.Next()) != NULL) + while ((key = it.Next()) != nullptr) { DVector3 pos = key->PosRelative(MapPortalGroup); p.x = pos.X; @@ -2955,7 +2837,7 @@ void AM_drawKeys () if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { - AM_rotatePoint (&p.x, &p.y); + rotatePoint (&p.x, &p.y); angle += -players[consoleplayer].camera->Angles.Yaw + 90.; } @@ -2968,7 +2850,7 @@ void AM_drawKeys () if (c >= 0) color.FromRGB(RPART(c), GPART(c), BPART(c)); else color = AMColors[AMColors.ThingColor_CountItem]; - AM_drawLineCharacter(&EasyKey[0], EasyKey.Size(), 0, 0., color, p.x, p.y); + drawLineCharacter(&EasyKey[0], EasyKey.Size(), 0, 0., color, p.x, p.y); } } } @@ -2978,14 +2860,14 @@ void AM_drawKeys () // // //============================================================================= -void AM_drawThings () +void DAutomap::drawThings () { AMColor color; AActor* t; mpoint_t p; DAngle angle; - for (auto &sec : level.sectors) + for (auto &sec : Level->sectors) { t = sec.thinglist; while (t) @@ -2998,12 +2880,12 @@ void AM_drawThings () if (am_showthingsprites > 0 && t->sprite > 0) { - FTexture *texture = NULL; + FTexture *texture = nullptr; spriteframe_t *frame; int rotation = 0; // try all modes backwards until a valid texture has been found. - for(int show = am_showthingsprites; show > 0 && texture == NULL; show--) + for(int show = am_showthingsprites; show > 0 && texture == nullptr; show--) { const spritedef_t& sprite = sprites[t->sprite]; const size_t spriteIndex = sprite.spriteframes + (show > 1 ? t->frame : 0); @@ -3021,7 +2903,7 @@ void AM_drawThings () texture = TexMan.GetTexture(textureID, true); } - if (texture == NULL) goto drawTriangle; // fall back to standard display if no sprite can be found. + if (texture == nullptr) goto drawTriangle; // fall back to standard display if no sprite can be found. const double spriteXScale = (t->Scale.X * (10. / 16.) * scale_mtof); const double spriteYScale = (t->Scale.Y * (10. / 16.) * scale_mtof); @@ -3036,7 +2918,7 @@ void AM_drawThings () if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { - AM_rotatePoint (&p.x, &p.y); + rotatePoint (&p.x, &p.y); angle += -players[consoleplayer].camera->Angles.Yaw + 90.; } @@ -3067,7 +2949,7 @@ void AM_drawThings () if (c >= 0) color.FromRGB(RPART(c), GPART(c), BPART(c)); else color = AMColors[AMColors.ThingColor_CountItem]; - AM_drawLineCharacter(&CheatKey[0], CheatKey.Size(), 0, 0., color, p.x, p.y); + drawLineCharacter(&CheatKey[0], CheatKey.Size(), 0, 0., color, p.x, p.y); color.Index = -1; } else @@ -3083,7 +2965,7 @@ void AM_drawThings () if (color.Index != -1) { - AM_drawLineCharacter(thintriangle_guy, NUMTHINTRIANGLEGUYLINES, 16, angle, color, p.x, p.y); + drawLineCharacter(thintriangle_guy.data(), thintriangle_guy.size(), 16, angle, color, p.x, p.y); } if (am_cheat == 3 || am_cheat == 6) @@ -3096,7 +2978,7 @@ void AM_drawThings () { { -1, 1 }, { -1, -1 } }, }; - AM_drawLineCharacter (box, 4, t->radius, angle - t->Angles.Yaw, color, p.x, p.y); + drawLineCharacter (box, 4, t->radius, angle - t->Angles.Yaw, color, p.x, p.y); } } } @@ -3111,16 +2993,16 @@ void AM_drawThings () // //============================================================================= -static void DrawMarker (FTexture *tex, double x, double y, int yadjust, +void DAutomap::DrawMarker (FTexture *tex, double x, double y, int yadjust, INTBOOL flip, double xscale, double yscale, int translation, double alpha, uint32_t fillcolor, FRenderStyle renderstyle) { - if (tex == NULL || !tex->isValid()) + if (tex == nullptr || !tex->isValid()) { return; } if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { - AM_rotatePoint (&x, &y); + rotatePoint (&x, &y); } screen->DrawTexture (tex, CXMTOF(x) + f_x, CYMTOF(y) + yadjust + f_y, DTA_DestWidthF, tex->GetDisplayWidthDouble() * CleanXfac * xscale, @@ -3143,7 +3025,7 @@ static void DrawMarker (FTexture *tex, double x, double y, int yadjust, // //============================================================================= -void AM_drawMarks () +void DAutomap::drawMarks () { for (int i = 0; i < AM_NUMMARKPOINTS; i++) { @@ -3161,15 +3043,15 @@ void AM_drawMarks () // //============================================================================= -void AM_drawAuthorMarkers () +void DAutomap::drawAuthorMarkers () { // [RH] Draw any actors derived from AMapMarker on the automap. // If args[0] is 0, then the actor's sprite is drawn at its own location. // Otherwise, its sprite is drawn at the location of any actors whose TIDs match args[0]. - TThinkerIterator it ("MapMarker", STAT_MAPMARKER); + auto it = Level->GetThinkerIterator(NAME_MapMarker, STAT_MAPMARKER); AActor *mark; - while ((mark = it.Next()) != NULL) + while ((mark = it.Next()) != nullptr) { if (mark->flags2 & MF2_DORMANT) { @@ -3206,17 +3088,17 @@ void AM_drawAuthorMarkers () tex = TexMan.GetTexture(picnum); } } - auto it = level.GetActorIterator(mark->args[0]); + auto it = Level->GetActorIterator(mark->args[0]); AActor *marked = mark->args[0] == 0 ? mark : it.Next(); - while (marked != NULL) + while (marked != nullptr) { if (mark->args[1] == 0 || (mark->args[1] == 1 && (marked->subsector->flags & SSECMF_DRAWN))) { DrawMarker (tex, marked->X(), marked->Y(), 0, flip, mark->Scale.X, mark->Scale.Y, mark->Translation, mark->Alpha, mark->fillcolor, mark->RenderStyle); } - marked = mark->args[0] != 0 ? it.Next() : NULL; + marked = mark->args[0] != 0 ? it.Next() : nullptr; } } } @@ -3227,7 +3109,7 @@ void AM_drawAuthorMarkers () // //============================================================================= -void AM_drawCrosshair (const AMColor &color) +void DAutomap::drawCrosshair (const AMColor &color) { screen->DrawPixel(f_w/2, (f_h+1)/2, color.Index, color.RGB); } @@ -3238,12 +3120,12 @@ void AM_drawCrosshair (const AMColor &color) // //============================================================================= -void AM_Drawer (int bottom) +void DAutomap::Drawer (int bottom) { if (!automapactive) return; - bool allmap = (level.flags2 & LEVEL2_ALLMAP) != 0; + bool allmap = (Level->flags2 & LEVEL2_ALLMAP) != 0; bool allthings = allmap && players[consoleplayer].mo->FindInventory(NAME_PowerScanner, true) != nullptr; if (am_portaloverlay) @@ -3264,7 +3146,7 @@ void AM_Drawer (int bottom) f_w = screen->GetWidth (); f_h = bottom; - AM_clearFB(AMColors[AMColors.Background]); + clearFB(AMColors[AMColors.Background]); } else { @@ -3273,29 +3155,28 @@ void AM_Drawer (int bottom) f_w = viewwidth; f_h = viewheight; } - AM_activateNewScale(); + activateNewScale(); - if (am_textured && textured && !viewactive) - AM_drawSubsectors(); + if (am_textured && !viewactive) + drawSubsectors(); - if (grid) - AM_drawGrid(AMColors.GridColor); + if (am_showgrid) + drawGrid(AMColors.GridColor); - AM_drawWalls(allmap); - AM_drawPlayers(); + drawWalls(allmap); + drawPlayers(); if (G_SkillProperty(SKILLP_EasyKey)) - AM_drawKeys(); + drawKeys(); if ((am_cheat >= 2 && am_cheat != 4) || allthings) - AM_drawThings(); + drawThings(); - AM_drawAuthorMarkers(); + drawAuthorMarkers(); if (!viewactive) - AM_drawCrosshair(AMColors[AMColors.XHairColor]); + drawCrosshair(AMColors[AMColors.XHairColor]); - AM_drawMarks(); - - AM_showSS(); + drawMarks(); + showSS(); } //============================================================================= @@ -3304,14 +3185,154 @@ void AM_Drawer (int bottom) // //============================================================================= -void AM_SerializeMarkers(FSerializer &arc) +void DAutomap::Serialize(FSerializer &arc) { - if (arc.BeginObject("automarkers")) + // This only stores those variables which do not get set each time the automap is either activated or drawn. + // Especially the screen coordinates can not be brought over because the display settings may have changed. + arc("markpointnum", markpointnum) + .Array("markpoints", &markpoints[0].x, AM_NUMMARKPOINTS * 2) // write as a double array. + ("scale_mtof", scale_mtof) + ("scale_ftom", scale_ftom) + ("bigstate", bigstate) + ("min_x", min_x) + ("min_y", min_y) + ("max_x", max_x) + ("max_y", max_y) + ("min_w", min_w) + ("min_h", min_h) + ("max_w", max_w) + ("max_h", max_h) + ("min_scale_mtof", min_scale_mtof) + ("max_scale_mtof", max_scale_mtof) + ("mapback", mapback); + +} + + +//============================================================================= +// +// +// +//============================================================================= + +void DAutomap::UpdateShowAllLines() +{ + int val = am_showalllines; + int flagged = 0; + int total = 0; + if (val > 0 && Level->lines.Size() > 0) { - arc("markpointnum", markpointnum) - .Array("markpoints", &markpoints[0].x, AM_NUMMARKPOINTS*2) // write as a double array. - ("scale_mtof", scale_mtof) - ("scale_ftom", scale_ftom) - .EndObject(); + for (auto &line : Level->lines) + { + // disregard intra-sector lines + if (line.frontsector == line.backsector) continue; + + // disregard control sectors for deep water + if (line.frontsector->e->FakeFloor.Sectors.Size() > 0) continue; + + // disregard control sectors for 3D-floors + if (line.frontsector->e->XFloor.attached.Size() > 0) continue; + + total++; + if (line.flags & ML_DONTDRAW) flagged++; + } + am_showallenabled = (flagged * 100 / total >= val); + } + else if (val == 0) + { + am_showallenabled = true; + } + else + { + am_showallenabled = false; } } + +void DAutomap::GoBig() +{ + bigstate = !bigstate; + if (bigstate) + { + saveScaleAndLoc(); + minOutWindowScale(); + } + else + restoreScaleAndLoc(); +} + +void DAutomap::ResetFollowLocation() +{ + f_oldloc.x = FLT_MAX; +} + + +//============================================================================= +// +// +// +//============================================================================= + +void AM_Stop() +{ + automapactive = false; + viewactive = true; +} + +//============================================================================= +// +// +// +//============================================================================= + +void AM_ToggleMap() +{ + if (gamestate != GS_LEVEL) + return; + + // Don't activate the automap if we're not allowed to use it. + if (dmflags2 & DF2_NO_AUTOMAP) + return; + + // ... or if there is no automap. + if (!currentUILevel || !currentUILevel->automap) + return; + + if (!automapactive) + { + // Reset AM buttons + Button_AM_PanLeft.Reset(); + Button_AM_PanRight.Reset(); + Button_AM_PanUp.Reset(); + Button_AM_PanDown.Reset(); + Button_AM_ZoomIn.Reset(); + Button_AM_ZoomOut.Reset(); + + currentUILevel->automap->startDisplay(); + automapactive = true; + viewactive = (am_overlay != 0.f); + } + else + { + if (am_overlay == 1 && viewactive) + { + viewactive = false; + } + else + { + AM_Stop(); + } + } +} + +//============================================================================= +// +// +// +//============================================================================= + +DAutomapBase *AM_Create(FLevelLocals *Level) +{ + auto am = Create(); + am->Level = Level; + return am; +} diff --git a/src/am_map.h b/src/am_map.h index 22bb34670c..3665e44383 100644 --- a/src/am_map.h +++ b/src/am_map.h @@ -22,31 +22,44 @@ #ifndef __AMMAP_H__ #define __AMMAP_H__ +#include "dobject.h" + struct event_t; class FSerializer; +struct FLevelLocals; +class DAutomapBase : public DObject +{ + DECLARE_ABSTRACT_CLASS(DAutomapBase, DObject); +public: + FLevelLocals *Level; // temporary location so that it can be set from the outside. + + // Called by main loop. + virtual bool Responder(event_t* ev, bool last) = 0; + + // Called by main loop. + virtual void Ticker(void) = 0; + + // Called by main loop, + // called instead of view drawer if automap active. + virtual void Drawer(int bottom) = 0; + + virtual void NewResolution() = 0; + virtual void LevelInit() = 0; + virtual void UpdateShowAllLines() = 0; + virtual void GoBig() = 0; + virtual void ResetFollowLocation() = 0; + virtual int addMark() = 0; + virtual bool clearMarks() = 0; + virtual DVector2 GetPosition() = 0; + virtual void startDisplay() = 0; + +}; void AM_StaticInit(); void AM_ClearColorsets(); // reset data for a restart. - -// Called by main loop. -bool AM_Responder (event_t* ev, bool last); - -// Called by main loop. -void AM_Ticker (void); - -// Called by main loop, -// called instead of view drawer if automap active. -void AM_Drawer (int bottom); - -// Called to force the automap to quit -// if the level is completed while it is up. -void AM_Stop (void); - -void AM_NewResolution (); -void AM_ToggleMap (); -void AM_LevelInit (); -void AM_SerializeMarkers(FSerializer &arc); - +DAutomapBase *AM_Create(FLevelLocals *Level); +void AM_Stop(); +void AM_ToggleMap(); #endif diff --git a/src/d_main.cpp b/src/d_main.cpp index d340e7cad2..70363a70a7 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -758,7 +758,7 @@ void D_Display () screen->DrawBlend(viewsec); if (automapactive) { - AM_Drawer (hud_althud? viewheight : StatusBar->GetTopOfStatusbar()); + currentUILevel->automap->Drawer (hud_althud? viewheight : StatusBar->GetTopOfStatusbar()); } // for timing the statusbar code. diff --git a/src/g_game.cpp b/src/g_game.cpp index a6b009aaec..6c1f32227f 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -955,7 +955,7 @@ bool G_Responder (event_t *ev) { if (ST_Responder (ev)) return true; // status window ate it - if (!viewactive && AM_Responder (ev, false)) + if (!viewactive && currentUILevel->automap->Responder (ev, false)) return true; // automap ate it } else if (gamestate == GS_FINALE) @@ -986,7 +986,7 @@ bool G_Responder (event_t *ev) // the events *last* so that any bound keys get precedence. if (gamestate == GS_LEVEL && viewactive) - return AM_Responder (ev, true); + return currentUILevel->automap->Responder (ev, true); return (ev->type == EV_KeyDown || ev->type == EV_Mouse); @@ -1179,7 +1179,7 @@ void G_Ticker () { case GS_LEVEL: P_Ticker (); - AM_Ticker (); + currentUILevel->automap->Ticker (); break; case GS_TITLELEVEL: diff --git a/src/g_level.cpp b/src/g_level.cpp index 7b41cbd268..211304069b 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1019,9 +1019,8 @@ void G_DoLoadLevel (int position, bool autosave, bool newGame) E_NewGame(EventHandlerType::Global); } - P_SetupLevel (level.MapName, position, newGame); + P_SetupLevel (&level, position, newGame); - AM_LevelInit(); // [RH] Start lightning, if MAPINFO tells us to if (level.flags & LEVEL_STARTLIGHTNING) @@ -1126,6 +1125,7 @@ void G_DoLoadLevel (int position, bool autosave, bool newGame) { I_Error("no start for player %d found.", pnumerr); } + P_ResetSightCounters(true); } @@ -1452,8 +1452,6 @@ int G_FinishTravel () void FLevelLocals::Init() { - level_info_t *info; - BaseBlendA = 0.0f; // Remove underwater blend effect, if any gravity = sv_gravity * 35/TICRATE; @@ -1465,7 +1463,6 @@ void FLevelLocals::Init() info = FindLevelInfo (MapName); - info = info; skyspeed1 = info->skyspeed1; skyspeed2 = info->skyspeed2; skytexture1 = TexMan.GetTextureID(info->SkyPic1, ETextureType::Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_ReturnFirst); @@ -1976,6 +1973,7 @@ void FLevelLocals::Mark() GC::Mark(SpotState); GC::Mark(FraggleScriptThinker); GC::Mark(ACSThinker); + GC::Mark(automap); canvasTextureInfo.Mark(); for (auto &c : CorpseQueue) { diff --git a/src/g_levellocals.h b/src/g_levellocals.h index 4ca5c831a1..8cd4aa0add 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -87,6 +87,7 @@ class DACSThinker; class DFraggleThinker; class DSpotState; struct FStrifeDialogueNode; +class DAutomapBase; typedef TMap FDialogueIDMap; // maps dialogue IDs to dialogue array index (for ACS) typedef TMap FDialogueMap; // maps actor class names to dialogue array index @@ -235,10 +236,10 @@ public: { return FLineIdIterator(tagManager, tag); } - template TThinkerIterator GetThinkerIterator(FName subtype = NAME_None) + template TThinkerIterator GetThinkerIterator(FName subtype = NAME_None, int statnum = MAX_STATNUM+1) { - if (subtype == NAME_None) return TThinkerIterator(); - else return TThinkerIterator(subtype); + if (subtype == NAME_None) return TThinkerIterator(statnum); + else return TThinkerIterator(subtype, statnum); } FActorIterator GetActorIterator(int tid) { @@ -357,6 +358,7 @@ public: static const int BODYQUESIZE = 32; TObjPtr bodyque[BODYQUESIZE]; + TObjPtr automap; int bodyqueslot; int NumMapSections; diff --git a/src/namedef.h b/src/namedef.h index e3f596b067..8e1aaceda3 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -1075,3 +1075,4 @@ xx(lightflags) xx(lighttype) xx(InternalDynamicLight) xx(_a_chase_default) +xx(MapMarker) \ No newline at end of file diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index c6eb7e9252..529865a2fa 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -965,7 +965,8 @@ void G_SerializeLevel(FSerializer &arc, FLevelLocals *Level, bool hubload) ("fragglethinker", Level->FraggleScriptThinker) ("acsthinker", Level->ACSThinker) ("impactdecalcount", Level->ImpactDecalCount) - ("scrolls", Level->Scrolls); + ("scrolls", Level->Scrolls) + ("automap", Level->automap); // Hub transitions must keep the current total time @@ -988,7 +989,10 @@ void G_SerializeLevel(FSerializer &arc, FLevelLocals *Level, bool hubload) arc("zones", Level->Zones); arc("lineportals", Level->linePortals); arc("sectorportals", Level->sectorPortals); - if (arc.isReading()) Level->FinalizePortals(); + if (arc.isReading()) + { + Level->FinalizePortals(); + } // [ZZ] serialize health groups P_SerializeHealthGroups(arc); @@ -998,12 +1002,12 @@ void G_SerializeLevel(FSerializer &arc, FLevelLocals *Level, bool hubload) arc("polyobjs", Level->Polyobjects); SerializeSubsectors(arc, "subsectors"); StatusBar->SerializeMessages(arc); - AM_SerializeMarkers(arc); FRemapTable::StaticSerializeTranslations(arc); Level->canvasTextureInfo.Serialize(arc); P_SerializePlayers(Level, arc, hubload); P_SerializeSounds(arc); + // Regenerate some data that wasn't saved if (arc.isReading()) { for (auto &sec : Level->sectors) @@ -1012,12 +1016,17 @@ void G_SerializeLevel(FSerializer &arc, FLevelLocals *Level, bool hubload) } for (int i = 0; i < MAXPLAYERS; ++i) { - if (playeringame[i] && players[i].mo != NULL) + if (playeringame[i] && players[i].mo != nullptr) { FWeaponSlots::SetupWeaponSlots(players[i].mo); } } + AActor::RecreateAllAttachedLights(); + InitPortalGroups(Level); + + Level->automap->Level = Level; // Temporary workaround. At the moment this cannot be deserialized yet. + Level->automap->UpdateShowAllLines(); + } - AActor::RecreateAllAttachedLights(); - InitPortalGroups(Level); + } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 0fff24c55a..6459065fb5 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -71,6 +71,7 @@ #include "a_specialspot.h" #include "maploader/maploader.h" #include "p_acs.h" +#include "am_map.h" #include "fragglescript/t_script.h" void P_ClearUDMFKeys(); @@ -260,6 +261,8 @@ void FLevelLocals::ClearPortals() void FLevelLocals::ClearLevelData() { + ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process. + total_monsters = total_items = total_secrets = killed_monsters = found_items = found_secrets = wminfo.maxfrags = 0; @@ -348,7 +351,6 @@ void P_FreeLevelData () P_ClearUDMFKeys(); interpolator.ClearInterpolations(); // [RH] Nothing to interpolate on a fresh level. - level.ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process. SN_StopAllSequences (); DThinker::DestroyAllThinkers (); @@ -363,20 +365,20 @@ void P_FreeLevelData () // //=========================================================================== -void P_SetupLevel(const char *lumpname, int position, bool newGame) +void P_SetupLevel(FLevelLocals *Level, int position, bool newGame) { int i; - level.ShaderStartTime = I_msTimeFS(); // indicate to the shader system that the level just started + Level->ShaderStartTime = I_msTimeFS(); // indicate to the shader system that the level just started // This is motivated as follows: - level.maptype = MAPTYPE_UNKNOWN; + Level->maptype = MAPTYPE_UNKNOWN; wminfo.partime = 180; if (!savegamerestore) { - level.SetMusicVolume(level.MusicVolume); + Level->SetMusicVolume(Level->MusicVolume); for (i = 0; i < MAXPLAYERS; ++i) { players[i].killcount = players[i].secretcount @@ -411,10 +413,10 @@ void P_SetupLevel(const char *lumpname, int position, bool newGame) // Free all level data from the previous map P_FreeLevelData(); - MapData *map = P_OpenMapData(lumpname, true); + MapData *map = P_OpenMapData(Level->MapName, true); if (map == nullptr) { - I_Error("Unable to open map '%s'\n", lumpname); + I_Error("Unable to open map '%s'\n", Level->MapName.GetChars()); } // [ZZ] init per-map static handlers. we need to call this before everything is set up because otherwise scripts don't receive PlayerEntered event @@ -422,17 +424,17 @@ void P_SetupLevel(const char *lumpname, int position, bool newGame) E_InitStaticHandlers(true); // generate a checksum for the level, to be included and checked with savegames. - map->GetChecksum(level.md5); + map->GetChecksum(Level->md5); // find map num - level.lumpnum = map->lumpnum; + Level->lumpnum = map->lumpnum; if (newGame) { E_NewGame(EventHandlerType::PerMap); } - MapLoader loader(&level); - loader.LoadLevel(map, lumpname, position); + MapLoader loader(Level); + loader.LoadLevel(map, Level->MapName.GetChars(), position); delete map; // if deathmatch, randomly spawn the active players @@ -448,7 +450,7 @@ void P_SetupLevel(const char *lumpname, int position, bool newGame) } } // the same, but for random single/coop player starts - else if (level.flags2 & LEVEL2_RANDOMPLAYERSTARTS) + else if (Level->flags2 & LEVEL2_RANDOMPLAYERSTARTS) { for (i = 0; i < MAXPLAYERS; ++i) { @@ -456,14 +458,14 @@ void P_SetupLevel(const char *lumpname, int position, bool newGame) { players[i].mo = nullptr; FPlayerStart *mthing = G_PickPlayerStart(i); - P_SpawnPlayer(mthing, i, (level.flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0); + P_SpawnPlayer(mthing, i, (Level->flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0); } } } // [SP] move unfriendly players around // horribly hacky - yes, this needs rewritten. - if (level.deathmatchstarts.Size() > 0) + if (Level->deathmatchstarts.Size() > 0) { for (i = 0; i < MAXPLAYERS; ++i) { @@ -522,7 +524,7 @@ void P_SetupLevel(const char *lumpname, int position, bool newGame) // This check was previously done at run time each time the heightsec was checked. // However, since 3D floors are static data, we can easily precalculate this and store it in the sector's flags for quick access. - for (auto &s : level.sectors) + for (auto &s : Level->sectors) { if (s.heightsec != nullptr) { @@ -537,17 +539,18 @@ void P_SetupLevel(const char *lumpname, int position, bool newGame) } } - P_ResetSightCounters(true); - // Create a backup of the map data so the savegame code can toss out all fields that haven't changed in order to reduce processing time and file size. // Note that we want binary identity here, so assignment is not sufficient because it won't initialize any padding bytes. // Note that none of these structures may contain non POD fields anyway. - level.loadsectors.Resize(level.sectors.Size()); - memcpy(&level.loadsectors[0], &level.sectors[0], level.sectors.Size() * sizeof(level.sectors[0])); - level.loadlines.Resize(level.lines.Size()); - memcpy(&level.loadlines[0], &level.lines[0], level.lines.Size() * sizeof(level.lines[0])); - level.loadsides.Resize(level.sides.Size()); - memcpy(&level.loadsides[0], &level.sides[0], level.sides.Size() * sizeof(level.sides[0])); + Level->loadsectors.Resize(Level->sectors.Size()); + memcpy(&Level->loadsectors[0], &Level->sectors[0], Level->sectors.Size() * sizeof(Level->sectors[0])); + Level->loadlines.Resize(Level->lines.Size()); + memcpy(&Level->loadlines[0], &Level->lines[0], Level->lines.Size() * sizeof(Level->lines[0])); + Level->loadsides.Resize(Level->sides.Size()); + memcpy(&Level->loadsides[0], &Level->sides[0], Level->sides.Size() * sizeof(Level->sides[0])); + + Level->automap = AM_Create(Level); + Level->automap->LevelInit(); } // diff --git a/src/p_setup.h b/src/p_setup.h index a85801a325..8588ada684 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -146,7 +146,7 @@ bool P_CheckMapData(const char * mapname); // [RH] The only parameter used is mapname, so I removed playermask and skill. // On September 1, 1998, I added the position to indicate which set // of single-player start spots should be spawned in the level. -void P_SetupLevel (const char *mapname, int position, bool newGame); +void P_SetupLevel (FLevelLocals *Level, int position, bool newGame); void P_FreeLevelData(); diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index 34b9f40d84..0db6a86b9d 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -46,6 +46,7 @@ #include "d_player.h" #include "p_setup.h" #include "i_music.h" +#include "am_map.h" DVector2 AM_GetPosition(); int Net_GetLatency(int *ld, int *ad); @@ -2529,15 +2530,17 @@ DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, FormatMapName, FormatMapName) ACTION_RETURN_STRING(rets); } -static void GetAutomapPosition(DVector2 *pos) +static void GetAutomapPosition(FLevelLocals *self, DVector2 *pos) { - *pos = AM_GetPosition(); + *pos = self->automap->GetPosition(); } DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, GetAutomapPosition, GetAutomapPosition) { - PARAM_PROLOGUE; - ACTION_RETURN_VEC2(AM_GetPosition()); + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + DVector2 result; + GetAutomapPosition(self, &result); + ACTION_RETURN_VEC2(result); } static int ZGetUDMFInt(FLevelLocals *self, int type, int index, int key) diff --git a/src/v_video.cpp b/src/v_video.cpp index 61e79b5852..6e0299bbbf 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -66,6 +66,8 @@ #include "r_videoscale.h" #include "i_time.h" #include "version.h" +#include "g_levellocals.h" +#include "am_map.h" EXTERN_CVAR(Bool, cl_capfps) EXTERN_CVAR(Int, menu_resolution_custom_width) @@ -592,7 +594,8 @@ void V_OutputResized (int width, int height) C_NewModeAdjust(); // Reload crosshair if transitioned to a different size ST_LoadCrosshair(true); - AM_NewResolution(); + if (currentUILevel && currentUILevel->automap) + currentUILevel->automap->NewResolution(); } void V_CalcCleanFacs (int designwidth, int designheight, int realwidth, int realheight, int *cleanx, int *cleany, int *_cx1, int *_cx2) diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index d31692b9f6..775a38488a 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -687,7 +687,7 @@ struct LevelLocals native native static void StartSlideshow(Name whichone = 'none'); native static void WorldDone(); native static void RemoveAllBots(bool fromlist); - native static Vector2 GetAutomapPosition(); + native ui Vector2 GetAutomapPosition(); native void SetInterMusic(String nextmap); native String FormatMapName(int mapnamecolor); native bool IsJumpingAllowed() const; @@ -722,8 +722,8 @@ struct LevelLocals native return String.Format("%02d:%02d:%02d", sec / 3600, (sec % 3600) / 60, sec % 60); } - native bool CreateCeiling(sector sec, int type, line ln, double speed, double speed2, double height = 0, int crush = -1, int silent = 0, int change = 0, int crushmode = crushDoom); - native bool CreateFloor(sector sec, EFloor floortype, line ln, double speed, double height = 0, int crush = -1, int change = 0, bool crushmode = false, bool hereticlower = false); + native bool CreateCeiling(sector sec, int type, line ln, double speed, double speed2, double height = 0, int crush = -1, int silent = 0, int change = 0, int crushmode = 0 /*Floor.crushDoom*/); + native bool CreateFloor(sector sec, int floortype, line ln, double speed, double height = 0, int crush = -1, int change = 0, bool crushmode = false, bool hereticlower = false); } @@ -926,7 +926,7 @@ class Floor : MovingFloor native genFloorChg }; - deprecated("3.8") static bool CreateFloor(sector sec, EFloor floortype, line ln, double speed, double height = 0, int crush = -1, int change = 0, bool crushmode = false, bool hereticlower = false) + deprecated("3.8") static bool CreateFloor(sector sec, int floortype, line ln, double speed, double height = 0, int crush = -1, int change = 0, bool crushmode = false, bool hereticlower = false) { return level.CreateFloor(sec, floortype, ln, speed, height, crush, change, crushmode, hereticlower); } diff --git a/wadsrc/static/zscript/statusbar/alt_hud.txt b/wadsrc/static/zscript/statusbar/alt_hud.txt index 99a62603aa..93b21cddac 100644 --- a/wadsrc/static/zscript/statusbar/alt_hud.txt +++ b/wadsrc/static/zscript/statusbar/alt_hud.txt @@ -31,11 +31,6 @@ ** */ -/* - -DVector2 AM_GetPosition(); -*/ - class AltHud ui { TextureID tnt1a0;