From 017e62f4b27e25bf2861782759a9c56f4f0b29c8 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 23 Jan 2023 12:33:35 +0000 Subject: [PATCH 01/14] New console command "minigen" - Generates "MINIMAP.png" in your srb2home - Uses inherited automap code to render to a temporary buffer - Because am_map.c is a mess of filescope static variables right now, this only works when the automap is disabled. - Currently an equal alternate method to SLADE's map image export, but because we're in control, additional features can be added later... - TODO: Off vertically by one pixel on GHZ. Otherwise effectively identical in shape - TODO: the colours are rancid, I wonder if they were even updated for the 2.2 palette Related: - Use identical linear-time mechanisms for detecting borders of map geometry between automap and minimap - Automap was previously using iteration over all vertices - Minimap was previously pointlessly writing min/max values twice --- src/am_map.c | 121 +++++++++++++++++++++++++++++++++++++++++-------- src/am_map.h | 3 ++ src/d_netcmd.c | 1 + src/k_hud.c | 2 - src/m_misc.cpp | 37 +++++++++++++++ src/m_misc.h | 2 + 6 files changed, 144 insertions(+), 22 deletions(-) diff --git a/src/am_map.c b/src/am_map.c index f5543aec6..b85258dd2 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -156,6 +156,9 @@ static boolean draw_grid = false; boolean automapactive = false; boolean am_recalc = false; //added : 05-02-98 : true when screen size changes static boolean am_stopped = true; +static boolean am_minigen = false; + +static UINT8 *am_buf = NULL; static INT32 f_x, f_y; // location of window on screen (always zero for both) static INT32 f_w, f_h; // size of window on screen (always the screen width and height respectively) @@ -256,25 +259,24 @@ static inline void AM_restoreScaleAndLoc(void) */ static void AM_findMinMaxBoundaries(void) { - size_t i; fixed_t a; fixed_t b; - min_x = min_y = +INT32_MAX; - max_x = max_y = -INT32_MAX; + node_t *bsp = &nodes[numnodes-1]; - 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; + min_x = bsp->bbox[0][BOXLEFT]; + max_x = bsp->bbox[0][BOXRIGHT]; + min_y = bsp->bbox[0][BOXBOTTOM]; + max_y = bsp->bbox[0][BOXTOP]; - if (vertexes[i].y < min_y) - min_y = vertexes[i].y; - else if (vertexes[i].y > max_y) - max_y = vertexes[i].y; - } + if (bsp->bbox[1][BOXLEFT] < min_x) + min_x = bsp->bbox[1][BOXLEFT]; + if (bsp->bbox[1][BOXRIGHT] > max_x) + max_x = bsp->bbox[1][BOXRIGHT]; + if (bsp->bbox[1][BOXBOTTOM] < min_y) + min_y = bsp->bbox[1][BOXBOTTOM]; + if (bsp->bbox[1][BOXTOP] > max_y) + max_y = bsp->bbox[1][BOXTOP]; max_w = (max_x >>= FRACTOMAPBITS) - (min_x >>= FRACTOMAPBITS); max_h = (max_y >>= FRACTOMAPBITS) - (min_y >>= FRACTOMAPBITS); @@ -282,8 +284,26 @@ static void AM_findMinMaxBoundaries(void) a = FixedDiv(f_w<>FRACBITS; + } + min_scale_mtof = a; + max_scale_mtof = f_h; + } + else + { + if (am_minigen) + { + f_w = FixedMul(b, max_w)>>FRACBITS; + } + min_scale_mtof = b; + max_scale_mtof = f_w; + } + max_scale_mtof = FixedDiv(max_scale_mtof<= vid.width || yy >= vid.height) + if (xx < 0 || yy < 0 || xx >= f_w || yy >= f_h) return; // off the screen - dest[(yy*vid.width) + xx] = cc; + am_buf[(yy*f_w) + xx] = cc; } // @@ -916,7 +936,7 @@ static void AM_drawGrid(INT32 color) // Determines visible lines, draws them. // This is LineDef based, not LineSeg based. // -static inline void AM_drawWalls(void) +static void AM_drawWalls(void) { size_t i; static mline_t l; @@ -1151,3 +1171,64 @@ void AM_Drawer(void) if (!followplayer) AM_drawCrosshair(XHAIRCOLORS); } + +UINT8 *AM_MinimapGenerate(INT32 wh) +{ + UINT8 *buf = NULL; + + if (automapactive) + return NULL; + + am_minigen = true; + + AM_drawFline = AM_drawFline_soft; // yes, even in GL + + //AM_FrameBufferInit(); + f_x = f_y = 0; + f_w = f_h = wh; + am_buf = NULL; + + //AM_LevelInit(); + AM_findMinMaxBoundaries(); + scale_mtof = FixedMul(min_scale_mtof, FRACUNIT-FRACUNIT/20); + scale_ftom = FixedDiv(FRACUNIT, scale_mtof); + + //AM_initVariables(); + f_oldloc.x = INT32_MAX; + + m_paninc.x = m_paninc.y = 0; + ftom_zoommul = FRACUNIT; + mtof_zoommul = FRACUNIT; + + m_w = FTOM(f_w); + m_h = FTOM(f_h); + + //AM_changeWindowLoc(); + m_x = min_x - FixedMul(m_w, FRACUNIT/40); + m_y = min_y - FixedMul(m_h, FRACUNIT/40); + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; + + // for saving & restoring + old_m_x = m_x; + old_m_y = m_y; + old_m_w = m_w; + old_m_h = m_h; + + buf = malloc(2 + (f_w*f_h)); + + am_buf = buf+2; + + //AM_clearFB(BACKGROUND); + memset(am_buf, 0xff, (f_w*f_h)); + AM_drawWalls(); + + am_buf = NULL; + am_recalc = true; + + am_minigen = false; + + buf[0] = (UINT8)f_w; + buf[1] = (UINT8)f_h; + return buf; +} diff --git a/src/am_map.h b/src/am_map.h index 56a5f9616..be32f342c 100644 --- a/src/am_map.h +++ b/src/am_map.h @@ -48,6 +48,9 @@ void AM_Start(void); // Called to force the automap to quit if the level is completed while it is up. void AM_Stop(void); +// Minimap generation +UINT8 *AM_MinimapGenerate(INT32 wh); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 2cc507cb8..70680f355 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -934,6 +934,7 @@ void D_RegisterClientCommands(void) COM_AddCommand("screenshot", M_ScreenShot); COM_AddCommand("startmovie", Command_StartMovie_f); COM_AddCommand("stopmovie", Command_StopMovie_f); + COM_AddCommand("minigen", M_MinimapGenerate); CV_RegisterVar(&cv_screenshot_option); CV_RegisterVar(&cv_screenshot_folder); diff --git a/src/k_hud.c b/src/k_hud.c index 0e5af2687..37b9aa99e 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -3186,8 +3186,6 @@ static void K_drawKartMinimapIcon(fixed_t objx, fixed_t objy, INT32 hudx, INT32 fixed_t xoffset, yoffset; fixed_t xscale, yscale, zoom; - maxx = maxy = INT32_MAX; - minx = miny = INT32_MIN; minx = bsp->bbox[0][BOXLEFT]; maxx = bsp->bbox[0][BOXRIGHT]; miny = bsp->bbox[0][BOXBOTTOM]; diff --git a/src/m_misc.cpp b/src/m_misc.cpp index bbdb9efbd..08270f0db 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -1638,6 +1638,43 @@ boolean M_ScreenshotResponder(event_t *ev) return true; } +void M_MinimapGenerate(void) +{ +#ifdef USE_PNG + char *filepath = va(pandf, srb2home, "MINIMAP.png"); + boolean ret = false; + UINT8 *linear = NULL; + INT32 wh = 100; + + if (gamestate != GS_LEVEL) + { + CONS_Alert(CONS_ERROR, "You must be in a level to generate a preliminary minimap!\n"); + return; + } + + linear = AM_MinimapGenerate(wh); + + if (linear == NULL) + goto failure; + + M_CreateScreenShotPalette(); + ret = M_SavePNG(filepath, linear+2, linear[0], linear[1], screenshot_palette); + +failure: + if (linear != NULL) + free(linear); + + if (ret) + { + CONS_Printf(M_GetText("%s saved.\nRemember that this is not a complete minimap,\nand must be edited before putting in-game.\n"), filepath); + } + else + { + CONS_Alert(CONS_ERROR, M_GetText("Couldn't create %s\n"), filepath); + } +#endif //#ifdef USE_PNG +} + // ========================================================================== // TRANSLATION FUNCTIONS // ========================================================================== diff --git a/src/m_misc.h b/src/m_misc.h index a11a384c6..d739c0f57 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -70,6 +70,8 @@ void M_ScreenShot(void); void M_DoScreenShot(void); boolean M_ScreenshotResponder(event_t *ev); +void M_MinimapGenerate(void); + void Command_SaveConfig_f(void); void Command_LoadConfig_f(void); void Command_ChangeConfig_f(void); From 8269db8f99b30c28231f332839a6f4abdb053154 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 23 Jan 2023 18:38:52 +0000 Subject: [PATCH 02/14] Rework automap/minigen colours - All pre-existing colours are now actually what the code says they should be for the 2.2 palette - RR-specific colour changes. - Remove all noclimb-specific line colours - Render areas that can't be stepped up/down onto as walls - Add colours for - Tripwire (cyan, but not 0xff cyan) - Finish Line (grey) - FOF info (blue) - Use a low-intensity colour to signal possible offroad/hazard sector or stairjank step - Rework to support drawing in multiple passes, so that information that is strictly more important (solid walls, finish line) will not be obscured at minimap resolution by nearby lines signalling offroad/stairjank Related: - Added K_TerrainHasAffect - Returns true if terrain has any properties which would affect the player's gameplay, false if not. --- src/am_map.c | 300 +++++++++++++++++++++++++++++++++++++++--------- src/k_terrain.c | 17 +++ src/k_terrain.h | 14 +++ 3 files changed, 274 insertions(+), 57 deletions(-) diff --git a/src/am_map.c b/src/am_map.c index b85258dd2..f492053de 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -26,43 +26,39 @@ #endif // For use if I do walls with outsides/insides -static const UINT8 REDS = (8*16); +static const UINT8 REDS = (2*16); static const UINT8 REDRANGE = 16; static const UINT8 GRAYS = (1*16); static const UINT8 GRAYSRANGE = 16; -static const UINT8 BROWNS = (3*16); -static const UINT8 YELLOWS = (7*16); -static const UINT8 GREENS = (10*16); +static const UINT8 BROWNS = (15*16); +static const UINT8 YELLOWS = (5*16)+8; +static const UINT8 GREENS = (6*16); +static const UINT8 CYANS = (8*16); +static const UINT8 BLUES = (9*16); static const UINT8 DBLACK = 31; static const UINT8 DWHITE = 0; -static const UINT8 NOCLIMBREDS = 248; -static const UINT8 NOCLIMBREDRANGE = 8; -static const UINT8 NOCLIMBGRAYS = 204; -static const UINT8 NOCLIMBBROWNS = (2*16); -static const UINT8 NOCLIMBYELLOWS = (11*16); - // Automap colors #define BACKGROUND DBLACK #define WALLCOLORS (REDS + REDRANGE/2) #define WALLRANGE (REDRANGE/2) -#define NOCLIMBWALLCOLORS (NOCLIMBREDS + NOCLIMBREDRANGE/2) -#define NOCLIMBWALLRANGE (NOCLIMBREDRANGE/2) #define THOKWALLCOLORS REDS #define THOKWALLRANGE REDRANGE -#define NOCLIMBTHOKWALLCOLORS NOCLIMBREDS -#define NOCLIMBTHOKWALLRANGE NOCLIMBREDRANGE -#define TSWALLCOLORS GRAYS -#define TSWALLRANGE GRAYSRANGE -#define NOCLIMBTSWALLCOLORS NOCLIMBGRAYS +#define TSWALLCOLORS DWHITE +#define TSFINISHLINE GRAYS +#define TSTRIPWIRE (CYANS + 4) +#define TSFOFINFO (BLUES + 4) #define FDWALLCOLORS BROWNS -#define NOCLIMBFDWALLCOLORS NOCLIMBBROWNS #define CDWALLCOLORS YELLOWS -#define NOCLIMBCDWALLCOLORS NOCLIMBYELLOWS #define THINGCOLORS GREENS #define GRIDCOLORS (GRAYS + GRAYSRANGE/2) -#define XHAIRCOLORS DWHITE +#define XHAIRCOLORS GRAYS + +// Automap passes +#define PASS_SOLID 1 +#define PASS_INTANGIBLE 2 +#define PASS_FOF 4 // controls #define AM_PANUPKEY KEY_UPARROW @@ -932,14 +928,93 @@ static void AM_drawGrid(INT32 color) } } +#define SLOPEPARAMS(slope, end1, end2, normalheight) \ + end1 = (P_GetZAt(slope, lines[i].v1->x, lines[i].v1->y, normalheight) + FRACUNIT/2) >> FRACBITS; \ + end2 = (P_GetZAt(slope, lines[i].v2->x, lines[i].v2->y, normalheight) + FRACUNIT/2) >> FRACBITS; + +static ffloor_t *AM_CompareFOFs(size_t i, ffloor_t *rover, ffloor_t *secondarystore) +{ + ffloor_t *secondaryrover = NULL; + + for (; rover; rover = rover->next) + { + fixed_t rovt1, rovt2; + fixed_t rovb1, rovb2; + + if (!(rover->fofflags & FOF_EXISTS)) + continue; + if (!(rover->fofflags & FOF_BLOCKPLAYER)) + continue; + + SLOPEPARAMS(*rover->t_slope, rovt1, rovt2, *rover->topheight) + SLOPEPARAMS(*rover->b_slope, rovb1, rovb2, *rover->bottomheight) + + for (secondaryrover = secondarystore; secondaryrover; secondaryrover = secondaryrover->next) + { + fixed_t sect1, sect2; + fixed_t secb1, secb2; + + terrain_t *terrain1 = NULL; + terrain_t *terrain2 = NULL; + + if (!(secondaryrover->fofflags & FOF_EXISTS)) + continue; + if (!(secondaryrover->fofflags & FOF_BLOCKPLAYER)) + continue; + if (secondaryrover->secnum == rover->secnum) + break; + + SLOPEPARAMS(*secondaryrover->t_slope, sect1, sect2, *secondaryrover->topheight) + SLOPEPARAMS(*secondaryrover->b_slope, secb1, secb2, *secondaryrover->bottomheight) + + if (rovt1 != sect1) + continue; + if (rovt2 != sect2) + continue; + if (rovb1 != secb1) + continue; + if (rovb2 != secb2) + continue; + + if (sectors[rover->secnum].damagetype != sectors[secondaryrover->secnum].damagetype + || sectors[rover->secnum].friction != sectors[secondaryrover->secnum].friction + || sectors[rover->secnum].offroad != sectors[secondaryrover->secnum].offroad) + continue; + + if (*rover->toppic != *secondaryrover->toppic) + { + terrain1 = K_GetTerrainForFlatNum(*rover->toppic); + terrain2 = K_GetTerrainForFlatNum(*secondaryrover->toppic); + } + else if (*rover->bottompic != *secondaryrover->bottompic) + { + terrain1 = K_GetTerrainForFlatNum(*rover->bottompic); + terrain2 = K_GetTerrainForFlatNum(*secondaryrover->bottompic); + } + + if ((terrain1 && K_TerrainHasAffect(terrain1)) + || (terrain2 && K_TerrainHasAffect(terrain2))) + continue; + + break; + } + + if (secondaryrover == NULL) + break; + } + + return rover; +} + // // Determines visible lines, draws them. // This is LineDef based, not LineSeg based. // -static void AM_drawWalls(void) +static void AM_drawWalls(UINT8 pass) { size_t i; static mline_t l; + const fixed_t maxstep = P_BaseStepUp()>>FRACBITS; fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends fixed_t backf1 = 0, backf2 = 0, backc1 = 0, backc2 = 0; // back floor ceiling ends @@ -950,71 +1025,180 @@ static void AM_drawWalls(void) l.b.x = lines[i].v2->x >> FRACTOMAPBITS; l.b.y = lines[i].v2->y >> FRACTOMAPBITS; -#define SLOPEPARAMS(slope, end1, end2, normalheight) \ - end1 = P_GetZAt(slope, lines[i].v1->x, lines[i].v1->y, normalheight); \ - end2 = P_GetZAt(slope, lines[i].v2->x, lines[i].v2->y, normalheight); - SLOPEPARAMS(lines[i].frontsector->f_slope, frontf1, frontf2, lines[i].frontsector->floorheight) SLOPEPARAMS(lines[i].frontsector->c_slope, frontc1, frontc2, lines[i].frontsector->ceilingheight) - if (lines[i].backsector) { - SLOPEPARAMS(lines[i].backsector->f_slope, backf1, backf2, lines[i].backsector->floorheight) - SLOPEPARAMS(lines[i].backsector->c_slope, backc1, backc2, lines[i].backsector->ceilingheight) - } -#undef SLOPEPARAMS if (!lines[i].backsector) // 1-sided { - if (lines[i].flags & ML_NOCLIMB) - AM_drawMline(&l, NOCLIMBWALLCOLORS); - else + if (!(pass & PASS_SOLID)) + ; + else if (frontf1 != frontc1 || frontf2 != frontc2 || lines[i].frontsector->f_slope) + { + AM_drawMline(&l, TSWALLCOLORS); + } + else if (!am_minigen) + { AM_drawMline(&l, WALLCOLORS); + } + continue; } - else if ((backf1 == backc1 && backf2 == backc2) // Back is thok barrier + + SLOPEPARAMS(lines[i].backsector->f_slope, backf1, backf2, lines[i].backsector->floorheight) + SLOPEPARAMS(lines[i].backsector->c_slope, backc1, backc2, lines[i].backsector->ceilingheight) + + if ((backf1 == backc1 && backf2 == backc2) // Back is thok barrier || (frontf1 == frontc1 && frontf2 == frontc2)) // Front is thok barrier { if (backf1 == backc1 && backf2 == backc2 && frontf1 == frontc1 && frontf2 == frontc2) // BOTH are thok barriers { - if (lines[i].flags & ML_NOCLIMB) - AM_drawMline(&l, NOCLIMBTSWALLCOLORS); - else - AM_drawMline(&l, TSWALLCOLORS); + if (!am_minigen && (pass & PASS_INTANGIBLE)) + { + AM_drawMline(&l, GRIDCOLORS); + } } - else + else if (pass & PASS_SOLID) { - if (lines[i].flags & ML_NOCLIMB) - AM_drawMline(&l, NOCLIMBTHOKWALLCOLORS); - else - AM_drawMline(&l, THOKWALLCOLORS); + AM_drawMline(&l, TSWALLCOLORS); } } else { - if (lines[i].flags & ML_NOCLIMB) { - if (backf1 != frontf1 || backf2 != frontf2) { - AM_drawMline(&l, NOCLIMBFDWALLCOLORS); // floor level change - } - else if (backc1 != frontc1 || backc2 != frontc2) { - AM_drawMline(&l, NOCLIMBCDWALLCOLORS); // ceiling level change + if (lines[i].flags & (ML_IMPASSABLE|ML_BLOCKPLAYERS)) + { + if (pass & PASS_SOLID) + AM_drawMline(&l, TSWALLCOLORS); // Completely solid course boundary + } + else if ((lines[i].flags & ML_MIDSOLID) + && sides[lines->sidenum[0]].midtexture) + { + if (pass & PASS_SOLID) + AM_drawMline(&l, TSWALLCOLORS); // solid midtexture, likely a course boundary + } + if ((backf1 != frontf1 && abs(backf1 - frontf1) > maxstep) + || (backf2 != frontf2 && abs(backf2 - frontf2) > maxstep)) + { + if (pass & PASS_SOLID) + AM_drawMline(&l, TSWALLCOLORS); // floor-wall, likely a course boundary + } + else if (lines[i].special == 2001) + { + if (pass & PASS_SOLID) + AM_drawMline(&l, TSFINISHLINE); // finish line + } + else if (P_IsLineTripWire(&lines[i])) + { + if (pass & PASS_SOLID) + AM_drawMline(&l, TSTRIPWIRE); // tripwire shortcut + } + else if (backf1 != frontf1 || backf2 != frontf2) + { + if (pass & PASS_INTANGIBLE) + AM_drawMline(&l, FDWALLCOLORS); // floorlevel change + } + else if (backc1 != frontc1 || backc2 != frontc2) + { + if (!(pass & PASS_INTANGIBLE)) + ; + else if (abs(backc1 - frontc1) < maxstep + || abs(backc2 - frontc2) < maxstep) + { + AM_drawMline(&l, CDWALLCOLORS); // ceilinglevel change } else - AM_drawMline(&l, NOCLIMBTSWALLCOLORS); + { + AM_drawMline(&l, GRIDCOLORS); // ceiling-wall, not likely to be a course boundary but flagged up just in case + } + } + else if (lines[i].frontsector->damagetype != lines[i].backsector->damagetype + || lines[i].frontsector->friction != lines[i].backsector->friction + || lines[i].frontsector->offroad != lines[i].backsector->offroad) + { + if (pass & PASS_INTANGIBLE) + AM_drawMline(&l, FDWALLCOLORS); // Functionality boundary } else { - if (backf1 != frontf1 || backf2 != frontf2) { - AM_drawMline(&l, FDWALLCOLORS); // floor level change + terrain_t *terrain1 = NULL; + terrain_t *terrain2 = NULL; + UINT8 defercol = GRIDCOLORS; + + if (lines[i].frontsector->floorpic != lines[i].backsector->floorpic) + { + terrain1 = K_GetTerrainForFlatNum(lines[i].frontsector->floorpic); + terrain2 = K_GetTerrainForFlatNum(lines[i].backsector->ceilingpic); + defercol = FDWALLCOLORS; // possible floor offroad boundary } - else if (backc1 != frontc1 || backc2 != frontc2) { - AM_drawMline(&l, CDWALLCOLORS); // ceiling level change + else if (lines[i].frontsector->ceilingpic != lines[i].backsector->ceilingpic) + { + terrain1 = K_GetTerrainForFlatNum(lines[i].frontsector->floorpic); + terrain2 = K_GetTerrainForFlatNum(lines[i].backsector->ceilingpic); + defercol = CDWALLCOLORS; // possible ceiling offroad boundary + } + + if ((terrain1 && K_TerrainHasAffect(terrain1)) + || (terrain2 && K_TerrainHasAffect(terrain2))) + { + if (pass & PASS_INTANGIBLE) + AM_drawMline(&l, defercol); // Yep, definitely a functionality boundary } else - AM_drawMline(&l, TSWALLCOLORS); + { + ffloor_t *rover = NULL; + + if (lines[i].frontsector->ffloors || lines[i].backsector->ffloors) + { + if (lines[i].backsector->ffloors == NULL) + { + // Check frontside for one solid + for (rover = lines[i].frontsector->ffloors; rover; rover = rover->next) + { + if (!(rover->fofflags & FOF_EXISTS)) + continue; + if (!(rover->fofflags & FOF_BLOCKPLAYER)) + continue; + break; + } + } + else if (lines[i].frontsector->ffloors == NULL) + { + // Check backside for one solid + for (rover = lines[i].backsector->ffloors; rover; rover = rover->next) + { + if (!(rover->fofflags & FOF_EXISTS)) + continue; + if (!(rover->fofflags & FOF_BLOCKPLAYER)) + continue; + break; + } + } + else + { + // Check to see if any secnums exist in one but not the other. + rover = AM_CompareFOFs(i, lines[i].frontsector->ffloors, lines[i].backsector->ffloors); + if (rover == NULL) + rover = AM_CompareFOFs(i, lines[i].backsector->ffloors, lines[i].frontsector->ffloors); + } + } + + if (rover != NULL) + { + if (pass & PASS_FOF) + AM_drawMline(&l, TSFOFINFO); // a FOF is here but we don't know how to distinguish them yet + } + else if (!am_minigen) + { + if (pass & PASS_INTANGIBLE) + AM_drawMline(&l, GRIDCOLORS); // likely low-relevance line + } + } } } } } +#undef SLOPEPARAMS + // // Rotation in 2D. // Used to rotate player arrow line character. @@ -1165,7 +1349,7 @@ void AM_Drawer(void) AM_clearFB(BACKGROUND); if (draw_grid) AM_drawGrid(GRIDCOLORS); - AM_drawWalls(); + AM_drawWalls(PASS_FOF|PASS_INTANGIBLE|PASS_SOLID); AM_drawPlayers(); AM_drawThings(THINGCOLORS); @@ -1221,7 +1405,9 @@ UINT8 *AM_MinimapGenerate(INT32 wh) //AM_clearFB(BACKGROUND); memset(am_buf, 0xff, (f_w*f_h)); - AM_drawWalls(); + AM_drawWalls(PASS_FOF); + AM_drawWalls(PASS_INTANGIBLE); + AM_drawWalls(PASS_SOLID); am_buf = NULL; am_recalc = true; diff --git a/src/k_terrain.c b/src/k_terrain.c index ae0275e05..0bac71c63 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -1629,6 +1629,23 @@ static void K_TerrainDefaults(terrain_t *terrain) terrain->flags = TRF_REMAP; } +/*-------------------------------------------------- + boolean K_TerrainHasAffect(terrain_t *terrain) + + See header file for description. +--------------------------------------------------*/ + +boolean K_TerrainHasAffect(terrain_t *terrain) +{ + return (terrain->friction != 0 + || terrain->offroad != 0 + || terrain->damageType != -1 + || terrain->trickPanel != 0 + || terrain->speedPad != 0 + || terrain->springStrength != 0 + || terrain->flags != 0); +} + /*-------------------------------------------------- static void K_NewTerrainDefs(void) diff --git a/src/k_terrain.h b/src/k_terrain.h index 1f6dce930..c8a94aba5 100644 --- a/src/k_terrain.h +++ b/src/k_terrain.h @@ -594,6 +594,20 @@ boolean K_InitTerrainPwad(UINT16 wadNum); void K_InitTerrain(void); +/*-------------------------------------------------- + boolean K_TerrainHasAffect(terrain_t *terrain) + + Checks if Terrain block has a gameplay-affecting property. + + Input Arguments:- + terrain - Terrain structure to default. + + Return:- + false if functionally default, otherwise true. +--------------------------------------------------*/ + +boolean K_TerrainHasAffect(terrain_t *terrain); + #ifdef __cplusplus } // extern "C" #endif From 073c3ed4c2fbeff676ee12cfae5296b219f77c94 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 23 Jan 2023 19:16:45 +0000 Subject: [PATCH 03/14] Refactor in preperation for scaling feature Return a `minigen_t` struct with explicit width and height instead of extending the UINT8 buffer by 2 to provide that information in a very datatype-limited way. --- src/am_map.c | 17 +++++++++-------- src/am_map.h | 8 +++++++- src/m_misc.cpp | 12 ++++++------ src/typedef.h | 1 + 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/am_map.c b/src/am_map.c index f492053de..7193005a8 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -1356,13 +1356,16 @@ void AM_Drawer(void) if (!followplayer) AM_drawCrosshair(XHAIRCOLORS); } -UINT8 *AM_MinimapGenerate(INT32 wh) +minigen_t *AM_MinimapGenerate(INT32 wh) { - UINT8 *buf = NULL; + static minigen_t ret = {0}; if (automapactive) return NULL; + ret.w = ret.h = 0; + ret.buf = NULL; + am_minigen = true; AM_drawFline = AM_drawFline_soft; // yes, even in GL @@ -1399,9 +1402,9 @@ UINT8 *AM_MinimapGenerate(INT32 wh) old_m_w = m_w; old_m_h = m_h; - buf = malloc(2 + (f_w*f_h)); - - am_buf = buf+2; + ret.w = f_w; + ret.h = f_h; + am_buf = ret.buf = malloc((f_w*f_h)); //AM_clearFB(BACKGROUND); memset(am_buf, 0xff, (f_w*f_h)); @@ -1414,7 +1417,5 @@ UINT8 *AM_MinimapGenerate(INT32 wh) am_minigen = false; - buf[0] = (UINT8)f_w; - buf[1] = (UINT8)f_h; - return buf; + return &ret; } diff --git a/src/am_map.h b/src/am_map.h index be32f342c..c3f80e5ad 100644 --- a/src/am_map.h +++ b/src/am_map.h @@ -48,8 +48,14 @@ void AM_Start(void); // Called to force the automap to quit if the level is completed while it is up. void AM_Stop(void); +struct minigen_t +{ + INT32 w, h; + UINT8 *buf; +}; + // Minimap generation -UINT8 *AM_MinimapGenerate(INT32 wh); +minigen_t *AM_MinimapGenerate(INT32 wh); #ifdef __cplusplus } // extern "C" diff --git a/src/m_misc.cpp b/src/m_misc.cpp index 08270f0db..4a222a629 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -1643,7 +1643,7 @@ void M_MinimapGenerate(void) #ifdef USE_PNG char *filepath = va(pandf, srb2home, "MINIMAP.png"); boolean ret = false; - UINT8 *linear = NULL; + minigen_t *minigen = NULL; INT32 wh = 100; if (gamestate != GS_LEVEL) @@ -1652,17 +1652,17 @@ void M_MinimapGenerate(void) return; } - linear = AM_MinimapGenerate(wh); + minigen = AM_MinimapGenerate(wh); - if (linear == NULL) + if (minigen == NULL || minigen->buf == NULL) goto failure; M_CreateScreenShotPalette(); - ret = M_SavePNG(filepath, linear+2, linear[0], linear[1], screenshot_palette); + ret = M_SavePNG(filepath, minigen->buf, minigen->w, minigen->h, screenshot_palette); failure: - if (linear != NULL) - free(linear); + if (minigen->buf != NULL) + free(minigen->buf); if (ret) { diff --git a/src/typedef.h b/src/typedef.h index 3aa08b765..269dd26ab 100644 --- a/src/typedef.h +++ b/src/typedef.h @@ -26,6 +26,7 @@ extern "C" { // am_map.h TYPEDEF (fpoint_t); TYPEDEF (fline_t); +TYPEDEF (minigen_t); // command.h TYPEDEF (vsbuf_t); From 5cd0f14345f9c9501b5dffb9c8a80009559c512e Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 23 Jan 2023 19:17:35 +0000 Subject: [PATCH 04/14] Add an explicit error for attempting to generate a preliminary minimap while the automap is open. --- src/m_misc.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/m_misc.cpp b/src/m_misc.cpp index 4a222a629..79738c3f0 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -1652,6 +1652,12 @@ void M_MinimapGenerate(void) return; } + if (automapactive) + { + CONS_Alert(CONS_ERROR, "The automap is active! Please deactivate it and try again.\n"); + return; + } + minigen = AM_MinimapGenerate(wh); if (minigen == NULL || minigen->buf == NULL) From 281265f7775de36ffd8fa870a3e70782547ed13c Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 23 Jan 2023 19:18:19 +0000 Subject: [PATCH 05/14] AM_MinimapGenerate: return NULL if malloc fails --- src/am_map.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/am_map.c b/src/am_map.c index 7193005a8..314d3ad8c 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -1406,6 +1406,9 @@ minigen_t *AM_MinimapGenerate(INT32 wh) ret.h = f_h; am_buf = ret.buf = malloc((f_w*f_h)); + if (ret.buf == NULL) + return NULL; + //AM_clearFB(BACKGROUND); memset(am_buf, 0xff, (f_w*f_h)); AM_drawWalls(PASS_FOF); From ab58883d8524fe721fac7a5a4f1ec096b4ced62b Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 23 Jan 2023 19:59:14 +0000 Subject: [PATCH 06/14] `minigen` command: Support `-m(ultiplier)` parameter Supports values between 1 and 10, with 1 being the default. If a multiplier greater than 1 is provided, the filename will take the form "MINIMAP-%d.png", where %d is the multiplier. --- src/m_misc.cpp | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/m_misc.cpp b/src/m_misc.cpp index 79738c3f0..7717e86a3 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -1641,10 +1641,12 @@ boolean M_ScreenshotResponder(event_t *ev) void M_MinimapGenerate(void) { #ifdef USE_PNG - char *filepath = va(pandf, srb2home, "MINIMAP.png"); + char *filepath; boolean ret = false; minigen_t *minigen = NULL; INT32 wh = 100; + size_t option_scale; + INT32 mul = 1; if (gamestate != GS_LEVEL) { @@ -1658,6 +1660,36 @@ void M_MinimapGenerate(void) return; } + option_scale = COM_CheckPartialParm("-m"); + + if (option_scale) + { + if (COM_Argc() < option_scale + 2)/* no argument after? */ + { + CONS_Alert(CONS_ERROR, + "No multiplier follows parameter '%s'.\n", + COM_Argv(option_scale)); + return; + } + + mul = atoi(COM_Argv(option_scale + 1)); + + if (mul < 1 || mul > 10) + { + CONS_Alert(CONS_ERROR, + "Multiplier %d must be within range 1-10.\n", + mul); + return; + } + + wh *= mul; + filepath = va("%s" PATHSEP "MINIMAP-%d.png", srb2home, mul); + } + else + { + filepath = va("%s" PATHSEP "MINIMAP.png", srb2home); + } + minigen = AM_MinimapGenerate(wh); if (minigen == NULL || minigen->buf == NULL) @@ -1673,6 +1705,10 @@ failure: if (ret) { CONS_Printf(M_GetText("%s saved.\nRemember that this is not a complete minimap,\nand must be edited before putting in-game.\n"), filepath); + if (mul != 1) + { + CONS_Printf("You should divide its size by %d!\n", mul); + } } else { From 8ed510ca88bcd1d024c768378a32d9fdc9f93da3 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 24 Jan 2023 14:46:25 +0000 Subject: [PATCH 07/14] Precalculate as much shared minimap/automap data on level load as possible - `P_InitMinimapInfo` - Writes to `p_local.h` extern struct - Handles everything previously distributed across multiple K_drawKartMinimapIcon calls (and most of AM_findMinMaxBoundaries) - Reduces complexity of drawKartMinimapIcon significantly - Last prerequisite before implementing user-placable minimap boundaries... --- src/am_map.c | 62 ++++++++------------------------ src/am_map.h | 2 +- src/k_hud.c | 95 +++++++++++--------------------------------------- src/m_misc.cpp | 4 +-- src/p_local.h | 12 +++++++ src/p_setup.c | 64 ++++++++++++++++++++++++++++++++++ 6 files changed, 113 insertions(+), 126 deletions(-) diff --git a/src/am_map.c b/src/am_map.c index 314d3ad8c..0618ec4ee 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -255,51 +255,21 @@ static inline void AM_restoreScaleAndLoc(void) */ static void AM_findMinMaxBoundaries(void) { - fixed_t a; - fixed_t b; + fixed_t a, b; - node_t *bsp = &nodes[numnodes-1]; + min_x = minimapinfo.min_x << MAPBITS; + max_x = minimapinfo.max_x << MAPBITS; + min_y = minimapinfo.min_y << MAPBITS; + max_y = minimapinfo.max_y << MAPBITS; - min_x = bsp->bbox[0][BOXLEFT]; - max_x = bsp->bbox[0][BOXRIGHT]; - min_y = bsp->bbox[0][BOXBOTTOM]; - max_y = bsp->bbox[0][BOXTOP]; - - if (bsp->bbox[1][BOXLEFT] < min_x) - min_x = bsp->bbox[1][BOXLEFT]; - if (bsp->bbox[1][BOXRIGHT] > max_x) - max_x = bsp->bbox[1][BOXRIGHT]; - if (bsp->bbox[1][BOXBOTTOM] < min_y) - min_y = bsp->bbox[1][BOXBOTTOM]; - if (bsp->bbox[1][BOXTOP] > max_y) - max_y = bsp->bbox[1][BOXTOP]; - - max_w = (max_x >>= FRACTOMAPBITS) - (min_x >>= FRACTOMAPBITS); - max_h = (max_y >>= FRACTOMAPBITS) - (min_y >>= FRACTOMAPBITS); + max_w = minimapinfo.map_w << MAPBITS; + max_h = minimapinfo.map_h << MAPBITS; a = FixedDiv(f_w<>FRACBITS; - } - min_scale_mtof = a; - max_scale_mtof = f_h; - } - else - { - if (am_minigen) - { - f_w = FixedMul(b, max_w)>>FRACBITS; - } - min_scale_mtof = b; - max_scale_mtof = f_w; - } - max_scale_mtof = FixedDiv(max_scale_mtof<bbox[0][BOXLEFT]; - maxx = bsp->bbox[0][BOXRIGHT]; - miny = bsp->bbox[0][BOXBOTTOM]; - maxy = bsp->bbox[0][BOXTOP]; - - if (bsp->bbox[1][BOXLEFT] < minx) - minx = bsp->bbox[1][BOXLEFT]; - if (bsp->bbox[1][BOXRIGHT] > maxx) - maxx = bsp->bbox[1][BOXRIGHT]; - if (bsp->bbox[1][BOXBOTTOM] < miny) - miny = bsp->bbox[1][BOXBOTTOM]; - if (bsp->bbox[1][BOXTOP] > maxy) - maxy = bsp->bbox[1][BOXTOP]; - - // You might be wondering why these are being bitshift here - // it's because mapwidth and height would otherwise overflow for maps larger than half the size possible... - // map boundaries and sizes will ALWAYS be whole numbers thankfully - // later calculations take into consideration that these are actually not in terms of FRACUNIT though - minx >>= FRACBITS; - maxx >>= FRACBITS; - miny >>= FRACBITS; - maxy >>= FRACBITS; - - mapwidth = maxx - minx; - mapheight = maxy - miny; - - // These should always be small enough to be bitshift back right now - xoffset = (minx + mapwidth/2)<width, mapwidth); - yscale = FixedDiv(AutomapPic->height, mapheight); - zoom = FixedMul(min(xscale, yscale), FRACUNIT-FRACUNIT/20); - - amnumxpos = (FixedMul(objx, zoom) - FixedMul(xoffset, zoom)); - amnumypos = -(FixedMul(objy, zoom) - FixedMul(yoffset, zoom)); + amnumxpos = (FixedMul(objx, minimapinfo.zoom) - minimapinfo.offs_x); + amnumypos = -(FixedMul(objy, minimapinfo.zoom) - minimapinfo.offs_y); if (encoremode) amnumxpos = -amnumxpos; - amxpos = amnumxpos + ((hudx + AutomapPic->width/2 - (icon->width/2))<height/2 - (icon->height/2))<width/2 + (icon->width/2))<width)-SHORT(icon->width))/2)<height)-SHORT(icon->height))/2)<minimapPic; - - if (!AutomapPic) + if (minimapinfo.minimap_pic == NULL) { return; // no pic, just get outta here } @@ -3352,28 +3302,25 @@ static void K_drawKartMinimap(void) if (!minimaptrans) return; - x = MINI_X - (AutomapPic->width/2); - y = MINI_Y - (AutomapPic->height/2); + x = MINI_X - (SHORT(minimapinfo.minimap_pic->width)/2); + y = MINI_Y - (SHORT(minimapinfo.minimap_pic->height)/2); minimaptrans = ((10-minimaptrans)<width), y, splitflags|V_FLIP, AutomapPic); + V_DrawScaledPatch(x+SHORT(minimapinfo.minimap_pic->width), y, splitflags|minimaptrans|V_FLIP, minimapinfo.minimap_pic); else - V_DrawScaledPatch(x, y, splitflags, AutomapPic); + V_DrawScaledPatch(x, y, splitflags|minimaptrans, minimapinfo.minimap_pic); - { - splitflags &= ~minimaptrans; - splitflags |= V_HUDTRANSHALF; - } + // most icons will be rendered semi-ghostly. + splitflags |= V_HUDTRANSHALF; // let offsets transfer to the heads, too! if (encoremode) - x += SHORT(AutomapPic->leftoffset); + x += SHORT(minimapinfo.minimap_pic->leftoffset); else - x -= SHORT(AutomapPic->leftoffset); - y -= SHORT(AutomapPic->topoffset); + x -= SHORT(minimapinfo.minimap_pic->leftoffset); + y -= SHORT(minimapinfo.minimap_pic->topoffset); // initialize for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) @@ -3402,7 +3349,7 @@ static void K_drawKartMinimap(void) interpx = R_InterpolateFixed(g->mo->old_x, g->mo->x); interpy = R_InterpolateFixed(g->mo->old_y, g->mo->y); - K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap, AutomapPic); + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap); g = g->next; } @@ -3469,13 +3416,13 @@ static void K_drawKartMinimap(void) interpx = R_InterpolateFixed(mobj->old_x, mobj->x); interpy = R_InterpolateFixed(mobj->old_y, mobj->y); - K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap, AutomapPic); + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap); // Target reticule if ((gametype == GT_RACE && players[i].position == spbplace) || (gametype == GT_BATTLE && K_IsPlayerWanted(&players[i]))) { - K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic); + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, NULL); } } } @@ -3532,7 +3479,7 @@ static void K_drawKartMinimap(void) interpx = R_InterpolateFixed(mobj->old_x, mobj->x); interpy = R_InterpolateFixed(mobj->old_y, mobj->y); - K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap, AutomapPic); + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap); } // draw our local players here, opaque. @@ -3565,7 +3512,7 @@ static void K_drawKartMinimap(void) interpy = R_InterpolateFixed(bossinfo.weakspots[i].spot->old_y, bossinfo.weakspots[i].spot->y); // temporary graphic? - K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, colormap, AutomapPic); + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, colormap); } } diff --git a/src/m_misc.cpp b/src/m_misc.cpp index 7717e86a3..6c17583e2 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -1644,7 +1644,6 @@ void M_MinimapGenerate(void) char *filepath; boolean ret = false; minigen_t *minigen = NULL; - INT32 wh = 100; size_t option_scale; INT32 mul = 1; @@ -1682,7 +1681,6 @@ void M_MinimapGenerate(void) return; } - wh *= mul; filepath = va("%s" PATHSEP "MINIMAP-%d.png", srb2home, mul); } else @@ -1690,7 +1688,7 @@ void M_MinimapGenerate(void) filepath = va("%s" PATHSEP "MINIMAP.png", srb2home); } - minigen = AM_MinimapGenerate(wh); + minigen = AM_MinimapGenerate(mul); if (minigen == NULL || minigen->buf == NULL) goto failure; diff --git a/src/p_local.h b/src/p_local.h index 89c9197c4..0c0bea7f2 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -520,6 +520,18 @@ extern fixed_t bmaporgy; // origin of block map extern mobj_t **blocklinks; // for thing chains extern precipmobj_t **precipblocklinks; // special blockmap for precip rendering +extern struct minimapinfo +{ + patch_t *minimap_pic; + UINT8 mapthingcount; + INT32 min_x, min_y; + INT32 max_x, max_y; + INT32 map_w, map_h; + INT32 minimap_w, minimap_h; + fixed_t offs_x, offs_y; + fixed_t zoom; +} minimapinfo; + // // P_INTER // diff --git a/src/p_setup.c b/src/p_setup.c index ab3b8b306..6ac25edfa 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -8134,6 +8134,68 @@ static void P_InitGametype(void) } } +struct minimapinfo minimapinfo; + +static void P_InitMinimapInfo(void) +{ + fixed_t a; + fixed_t b; + + node_t *bsp = &nodes[numnodes-1]; + + minimapinfo.minimap_pic = mapheaderinfo[gamemap-1]->minimapPic; + + minimapinfo.mapthingcount = 0; + // TODO iterate over mapthings to look for possible user-defined bounds + + minimapinfo.min_x = bsp->bbox[0][BOXLEFT]; + minimapinfo.max_x = bsp->bbox[0][BOXRIGHT]; + minimapinfo.min_y = bsp->bbox[0][BOXBOTTOM]; + minimapinfo.max_y = bsp->bbox[0][BOXTOP]; + + if (bsp->bbox[1][BOXLEFT] < minimapinfo.min_x) + minimapinfo.min_x = bsp->bbox[1][BOXLEFT]; + if (bsp->bbox[1][BOXRIGHT] > minimapinfo.max_x) + minimapinfo.max_x = bsp->bbox[1][BOXRIGHT]; + if (bsp->bbox[1][BOXBOTTOM] < minimapinfo.min_y) + minimapinfo.min_y = bsp->bbox[1][BOXBOTTOM]; + if (bsp->bbox[1][BOXTOP] > minimapinfo.max_y) + minimapinfo.max_y = bsp->bbox[1][BOXTOP]; + + // You might be wondering why these are being bitshift here + // it's because mapwidth and height would otherwise overflow for maps larger than half the size possible... + // map boundaries and sizes will ALWAYS be whole numbers thankfully + // later calculations take into consideration that these are actually not in terms of FRACUNIT though + minimapinfo.map_w = (minimapinfo.max_x >>= FRACBITS) - (minimapinfo.min_x >>= FRACBITS); + minimapinfo.map_h = (minimapinfo.max_y >>= FRACBITS) - (minimapinfo.min_y >>= FRACBITS); + + minimapinfo.minimap_w = minimapinfo.minimap_h = 100; + + a = FixedDiv(minimapinfo.minimap_w<>(FRACBITS-4); + minimapinfo.zoom = a; + } + else + { + if (a != b) + { + minimapinfo.minimap_w = FixedMul(b, minimapinfo.map_w)>>(FRACBITS-4); + } + minimapinfo.zoom = b; + } + + minimapinfo.zoom >>= (FRACBITS-4); + minimapinfo.zoom -= (minimapinfo.zoom/20); + + // These should always be small enough to be bitshift back right now + minimapinfo.offs_x = FixedMul((minimapinfo.min_x + minimapinfo.map_w/2) << FRACBITS, minimapinfo.zoom); + minimapinfo.offs_y = FixedMul((minimapinfo.min_y + minimapinfo.map_h/2) << FRACBITS, minimapinfo.zoom); +} + /** Loads a level from a lump or external wad. * * \param fromnetsave If true, skip some stuff because we're loading a netgame snapshot. @@ -8416,6 +8478,8 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) skyboxmo[0] = skyboxviewpnts[0]; skyboxmo[1] = skyboxcenterpnts[0]; + P_InitMinimapInfo(); + for (numcoopstarts = 0; numcoopstarts < MAXPLAYERS; numcoopstarts++) if (!playerstarts[numcoopstarts]) break; From b4dcc12e4ff87b51e7e51d32c5793a2a2247a1a6 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 24 Jan 2023 16:10:01 +0000 Subject: [PATCH 08/14] Support for user-specified minimap bounds The totally-not-a-secret reason I made this branch. - doomednum 770 (associated with polyobject anchors 760/761 and skybox centerpoint 780) - Place exactly two in a map to draw an implicit rectangle. - Supports top-left/bottom-right AND bottom-left/top-right placements. - I_Errors if you place too many (or only one). - You don't *have* to have these, this is just a bonus if you're a map like Power Plant or CDSS1 negatively affected by your skybox. --- src/info/mobjs.h | 1 + src/p_local.h | 1 - src/p_setup.c | 79 ++++++++++++++++++++++++++++++++++++------------ 3 files changed, 60 insertions(+), 21 deletions(-) diff --git a/src/info/mobjs.h b/src/info/mobjs.h index 6d1c86690..420089a39 100644 --- a/src/info/mobjs.h +++ b/src/info/mobjs.h @@ -730,6 +730,7 @@ _(OVERLAY) _(ANGLEMAN) _(POLYANCHOR) _(POLYSPAWN) +_(MINIMAPBOUND) // Skybox objects _(SKYBOX) diff --git a/src/p_local.h b/src/p_local.h index 0c0bea7f2..c58ff19cf 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -523,7 +523,6 @@ extern precipmobj_t **precipblocklinks; // special blockmap for precip rendering extern struct minimapinfo { patch_t *minimap_pic; - UINT8 mapthingcount; INT32 min_x, min_y; INT32 max_x, max_y; INT32 map_w, map_h; diff --git a/src/p_setup.c b/src/p_setup.c index 6ac25edfa..b51786f24 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -8138,6 +8138,7 @@ struct minimapinfo minimapinfo; static void P_InitMinimapInfo(void) { + size_t i, count; fixed_t a; fixed_t b; @@ -8145,29 +8146,67 @@ static void P_InitMinimapInfo(void) minimapinfo.minimap_pic = mapheaderinfo[gamemap-1]->minimapPic; - minimapinfo.mapthingcount = 0; - // TODO iterate over mapthings to look for possible user-defined bounds + minimapinfo.min_x = minimapinfo.max_x = minimapinfo.min_y = minimapinfo.max_y = INT32_MAX; + count = 0; + for (i = 0; i < nummapthings; i++) + { + if (mapthings[i].type != mobjinfo[MT_MINIMAPBOUND].doomednum) + continue; + count++; - minimapinfo.min_x = bsp->bbox[0][BOXLEFT]; - minimapinfo.max_x = bsp->bbox[0][BOXRIGHT]; - minimapinfo.min_y = bsp->bbox[0][BOXBOTTOM]; - minimapinfo.max_y = bsp->bbox[0][BOXTOP]; + if (mapthings[i].x < minimapinfo.min_x) + { + minimapinfo.max_x = minimapinfo.min_x; + minimapinfo.min_x = mapthings[i].x; + } + else + { + minimapinfo.max_x = mapthings[i].x; + } - if (bsp->bbox[1][BOXLEFT] < minimapinfo.min_x) - minimapinfo.min_x = bsp->bbox[1][BOXLEFT]; - if (bsp->bbox[1][BOXRIGHT] > minimapinfo.max_x) - minimapinfo.max_x = bsp->bbox[1][BOXRIGHT]; - if (bsp->bbox[1][BOXBOTTOM] < minimapinfo.min_y) - minimapinfo.min_y = bsp->bbox[1][BOXBOTTOM]; - if (bsp->bbox[1][BOXTOP] > minimapinfo.max_y) - minimapinfo.max_y = bsp->bbox[1][BOXTOP]; + if (mapthings[i].y < minimapinfo.min_y) + { + minimapinfo.max_y = minimapinfo.min_y; + minimapinfo.min_y = mapthings[i].y; + } + else + { + minimapinfo.max_y = mapthings[i].y; + } + } - // You might be wondering why these are being bitshift here - // it's because mapwidth and height would otherwise overflow for maps larger than half the size possible... - // map boundaries and sizes will ALWAYS be whole numbers thankfully - // later calculations take into consideration that these are actually not in terms of FRACUNIT though - minimapinfo.map_w = (minimapinfo.max_x >>= FRACBITS) - (minimapinfo.min_x >>= FRACBITS); - minimapinfo.map_h = (minimapinfo.max_y >>= FRACBITS) - (minimapinfo.min_y >>= FRACBITS); + if (count == 0) + { + minimapinfo.min_x = bsp->bbox[0][BOXLEFT]; + minimapinfo.max_x = bsp->bbox[0][BOXRIGHT]; + minimapinfo.min_y = bsp->bbox[0][BOXBOTTOM]; + minimapinfo.max_y = bsp->bbox[0][BOXTOP]; + + if (bsp->bbox[1][BOXLEFT] < minimapinfo.min_x) + minimapinfo.min_x = bsp->bbox[1][BOXLEFT]; + if (bsp->bbox[1][BOXRIGHT] > minimapinfo.max_x) + minimapinfo.max_x = bsp->bbox[1][BOXRIGHT]; + if (bsp->bbox[1][BOXBOTTOM] < minimapinfo.min_y) + minimapinfo.min_y = bsp->bbox[1][BOXBOTTOM]; + if (bsp->bbox[1][BOXTOP] > minimapinfo.max_y) + minimapinfo.max_y = bsp->bbox[1][BOXTOP]; + + // You might be wondering why these are being bitshift here + // it's because mapwidth and height would otherwise overflow for maps larger than half the size possible... + // map boundaries and sizes will ALWAYS be whole numbers thankfully + // later calculations take into consideration that these are actually not in terms of FRACUNIT though + minimapinfo.min_x >>= FRACBITS; + minimapinfo.max_x >>= FRACBITS; + minimapinfo.min_y >>= FRACBITS; + minimapinfo.max_y >>= FRACBITS; + } + else if (count != 2) + { + I_Error("P_InitMinimapInfo: Too %s minimap helper objects! (found %s of mapthingnum %d, should have 2)", + (count < 2 ? "few" : "many"), sizeu1(count), mobjinfo[MT_MINIMAPBOUND].doomednum); + } + minimapinfo.map_w = minimapinfo.max_x - minimapinfo.min_x; + minimapinfo.map_h = minimapinfo.max_y - minimapinfo.min_y; minimapinfo.minimap_w = minimapinfo.minimap_h = 100; From 247165d29e1f62b0171424b09777aee6e6726631 Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Wed, 12 Feb 2025 02:50:13 +0100 Subject: [PATCH 09/14] Fix compile errors --- src/k_hud.c | 7 +++---- src/k_terrain.c | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index 83ca966e7..05b48d11d 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -3568,13 +3568,13 @@ static void K_drawKartMinimap(void) interpx = R_InterpolateFixed(mobj->old_x, mobj->x); interpy = R_InterpolateFixed(mobj->old_y, mobj->y); - K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap, AutomapPic); + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap); // Target reticule if ((gametype == GT_RACE && players[localplayers[i]].position == spbplace) || (gametype == GT_BATTLE && K_IsPlayerWanted(&players[localplayers[i]]))) { - K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic); + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, NULL); } if (!nocontest) @@ -3586,8 +3586,7 @@ static void K_drawKartMinimap(void) y - FixedMul(FSIN(ang), ICON_DOT_RADIUS), splitflags, kp_minimapdot, - colormap, - AutomapPic + colormap ); } } diff --git a/src/k_terrain.c b/src/k_terrain.c index 0bac71c63..6832ebbb8 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -1640,7 +1640,7 @@ boolean K_TerrainHasAffect(terrain_t *terrain) return (terrain->friction != 0 || terrain->offroad != 0 || terrain->damageType != -1 - || terrain->trickPanel != 0 +// || terrain->trickPanel != 0 || terrain->speedPad != 0 || terrain->springStrength != 0 || terrain->flags != 0); From 1b163a93f9860e87434de09ebee64e36431f5e04 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 24 Jan 2023 18:48:48 +0000 Subject: [PATCH 10/14] AM_DrawWalls: correct issue with the planes to grab terrain from being incorrect (copypaste error) --- src/am_map.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/am_map.c b/src/am_map.c index 0618ec4ee..604a9cb33 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -1096,12 +1096,12 @@ static void AM_drawWalls(UINT8 pass) if (lines[i].frontsector->floorpic != lines[i].backsector->floorpic) { terrain1 = K_GetTerrainForFlatNum(lines[i].frontsector->floorpic); - terrain2 = K_GetTerrainForFlatNum(lines[i].backsector->ceilingpic); + terrain2 = K_GetTerrainForFlatNum(lines[i].backsector->floorpic); defercol = FDWALLCOLORS; // possible floor offroad boundary } else if (lines[i].frontsector->ceilingpic != lines[i].backsector->ceilingpic) { - terrain1 = K_GetTerrainForFlatNum(lines[i].frontsector->floorpic); + terrain1 = K_GetTerrainForFlatNum(lines[i].frontsector->ceilingpic); terrain2 = K_GetTerrainForFlatNum(lines[i].backsector->ceilingpic); defercol = CDWALLCOLORS; // possible ceiling offroad boundary } From c9b532ad84c2754cd3f3c9f0f5b10d136b922f75 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 24 Jan 2023 18:59:13 +0000 Subject: [PATCH 11/14] minigen: Add black fragments to common objects on valid road - Drawn underneath absolutely everything else, because it's the least specific of all the guides minigen can provide - "Common objects" includes: - Rings/spheres - Waypoints - Item boxes/spots - Overtime kiosk - Rings - Item Capsules - The above were chosen because they're a good distinctor between sectors that are valid to drive on and sectors that would be valid were there no impassable lines or massive height differences preventing the player from getting there. Related: - K_TerrainHasAffect now has a "bad only" check mode. - If true only report back for strong friction, any offroad, any damage, or stairjank. --- src/am_map.c | 59 ++++++++++++++++++++++++++++++++++++++----------- src/k_terrain.c | 13 ++++++++--- src/k_terrain.h | 7 +++--- 3 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/am_map.c b/src/am_map.c index 604a9cb33..e2c29f6cb 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -962,8 +962,8 @@ static ffloor_t *AM_CompareFOFs(size_t i, ffloor_t *rover, ffloor_t *secondaryst terrain2 = K_GetTerrainForFlatNum(*secondaryrover->bottompic); } - if ((terrain1 && K_TerrainHasAffect(terrain1)) - || (terrain2 && K_TerrainHasAffect(terrain2))) + if ((terrain1 && K_TerrainHasAffect(terrain1, false)) + || (terrain2 && K_TerrainHasAffect(terrain2, false))) continue; break; @@ -1106,8 +1106,8 @@ static void AM_drawWalls(UINT8 pass) defercol = CDWALLCOLORS; // possible ceiling offroad boundary } - if ((terrain1 && K_TerrainHasAffect(terrain1)) - || (terrain2 && K_TerrainHasAffect(terrain2))) + if ((terrain1 && K_TerrainHasAffect(terrain1, false)) + || (terrain2 && K_TerrainHasAffect(terrain2, false))) { if (pass & PASS_INTANGIBLE) AM_drawMline(&l, defercol); // Yep, definitely a functionality boundary @@ -1239,13 +1239,6 @@ static inline void AM_drawPlayers(void) player_t *p; INT32 color = GREENS; - if (!multiplayer) - { - AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 16<mo->angle, DWHITE, plr->mo->x, plr->mo->y); - return; - } - - // multiplayer (how??) for (i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i] || players[i].spectator) @@ -1272,7 +1265,46 @@ static inline void AM_drawThings(UINT8 colors) t = sectors[i].thinglist; while (t) { - AM_drawLineCharacter(thintriangle_guy, NUMTHINTRIANGLEGUYLINES, 16<angle, colors, t->x, t->y); + if (!t->player) + AM_drawLineCharacter(thintriangle_guy, NUMTHINTRIANGLEGUYLINES, 16<angle, colors, t->x, t->y); + t = t->snext; + } + } +} + +static inline void AM_drawSpecialThingsOnly(UINT8 colors) +{ + size_t i; + + for (i = 0; i < numsectors; i++) + { + terrain_t *terrain = NULL; + mobj_t *t = NULL; + + if (sectors[i].damagetype != 0 + || sectors[i].friction < ORIG_FRICTION + || sectors[i].offroad != 0) + continue; + + terrain = K_GetTerrainForFlatNum(sectors[i].floorpic); + if (!terrain) + terrain = K_GetTerrainForFlatNum(sectors[i].ceilingpic); + + if (terrain && K_TerrainHasAffect(terrain, true)) + continue; + + t = sectors[i].thinglist; + while (t) + { + if (t->type == MT_RANDOMITEM + || t->type == MT_PAPERITEMSPOT + || t->type == MT_OVERTIME_CENTER + || t->type == MT_RING + || t->type == MT_BLUESPHERE + || t->type == MT_WAYPOINT + || t->type == MT_ITEMCAPSULE + || t->flags & MF_SPRING) + AM_drawLineCharacter(thintriangle_guy, NUMTHINTRIANGLEGUYLINES, 16<angle, colors, t->x, t->y); t = t->snext; } } @@ -1320,8 +1352,8 @@ void AM_Drawer(void) AM_clearFB(BACKGROUND); if (draw_grid) AM_drawGrid(GRIDCOLORS); AM_drawWalls(PASS_FOF|PASS_INTANGIBLE|PASS_SOLID); - AM_drawPlayers(); AM_drawThings(THINGCOLORS); + AM_drawPlayers(); if (!followplayer) AM_drawCrosshair(XHAIRCOLORS); } @@ -1377,6 +1409,7 @@ minigen_t *AM_MinimapGenerate(INT32 mul) //AM_clearFB(BACKGROUND); memset(am_buf, 0xff, (f_w*f_h)); + AM_drawSpecialThingsOnly(BACKGROUND); AM_drawWalls(PASS_FOF); AM_drawWalls(PASS_INTANGIBLE); AM_drawWalls(PASS_SOLID); diff --git a/src/k_terrain.c b/src/k_terrain.c index 6832ebbb8..35f14516a 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -1635,12 +1635,19 @@ static void K_TerrainDefaults(terrain_t *terrain) See header file for description. --------------------------------------------------*/ -boolean K_TerrainHasAffect(terrain_t *terrain) +boolean K_TerrainHasAffect(terrain_t *terrain, boolean badonly) { - return (terrain->friction != 0 + if (terrain->friction > 0 || terrain->offroad != 0 || terrain->damageType != -1 -// || terrain->trickPanel != 0 + || (terrain->flags & TRF_STAIRJANK)) + return true; + + if (badonly) + return false; + + return (terrain->friction != 0 + //|| terrain->trickPanel != 0 || terrain->speedPad != 0 || terrain->springStrength != 0 || terrain->flags != 0); diff --git a/src/k_terrain.h b/src/k_terrain.h index c8a94aba5..12367a2d3 100644 --- a/src/k_terrain.h +++ b/src/k_terrain.h @@ -595,18 +595,19 @@ boolean K_InitTerrainPwad(UINT16 wadNum); void K_InitTerrain(void); /*-------------------------------------------------- - boolean K_TerrainHasAffect(terrain_t *terrain) + boolean K_TerrainHasAffect(terrain_t *terrain, boolean badonly) Checks if Terrain block has a gameplay-affecting property. Input Arguments:- - terrain - Terrain structure to default. + terrain - Terrain structure to compare with default. + badonly - Only checks for negative properties if true Return:- false if functionally default, otherwise true. --------------------------------------------------*/ -boolean K_TerrainHasAffect(terrain_t *terrain); +boolean K_TerrainHasAffect(terrain_t *terrain, boolean badonly); #ifdef __cplusplus } // extern "C" From 39997e8c677826c7ab6160062b89a2df5a5ef3a8 Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Tue, 18 Feb 2025 23:48:03 +0100 Subject: [PATCH 12/14] Fix compile again --- src/am_map.c | 4 ++-- src/k_terrain.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/am_map.c b/src/am_map.c index e2c29f6cb..0fc8e568b 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -1034,7 +1034,7 @@ static void AM_drawWalls(UINT8 pass) } else { - if (lines[i].flags & (ML_IMPASSABLE|ML_BLOCKPLAYERS)) + if (lines[i].flags & (ML_IMPASSABLE|ML_EFFECT6)) { if (pass & PASS_SOLID) AM_drawMline(&l, TSWALLCOLORS); // Completely solid course boundary @@ -1298,7 +1298,7 @@ static inline void AM_drawSpecialThingsOnly(UINT8 colors) { if (t->type == MT_RANDOMITEM || t->type == MT_PAPERITEMSPOT - || t->type == MT_OVERTIME_CENTER + //|| t->type == MT_OVERTIME_CENTER || t->type == MT_RING || t->type == MT_BLUESPHERE || t->type == MT_WAYPOINT diff --git a/src/k_terrain.c b/src/k_terrain.c index 35f14516a..7166e2d21 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -1639,8 +1639,8 @@ boolean K_TerrainHasAffect(terrain_t *terrain, boolean badonly) { if (terrain->friction > 0 || terrain->offroad != 0 - || terrain->damageType != -1 - || (terrain->flags & TRF_STAIRJANK)) + || terrain->damageType != -1) + //|| (terrain->flags & TRF_STAIRJANK)) return true; if (badonly) From 0838417ebd1cb6107b8f19a8886d5b0a391e531f Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Wed, 19 Feb 2025 01:07:46 +0100 Subject: [PATCH 13/14] Fix v.drawOnMinimap --- src/lua_hudlib.c | 67 ++++++++---------------------------------------- 1 file changed, 10 insertions(+), 57 deletions(-) diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 810dc2b24..a5a5edc4f 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -606,7 +606,6 @@ static int libd_drawOnMinimap(lua_State *L) huddrawlist_h list; // variables used to replicate k_kart's mmap drawer: - patch_t *AutomapPic; INT32 mx, my; INT32 splitflags, minimaptrans; @@ -617,12 +616,6 @@ static int libd_drawOnMinimap(lua_State *L) fixed_t amnumxpos, amnumypos; INT32 amxpos, amypos; - node_t *bsp = &nodes[numnodes-1]; - fixed_t maxx, minx, maxy, miny; - - fixed_t mapwidth, mapheight; - fixed_t xoffset, yoffset; - fixed_t xscale, yscale, zoom; fixed_t patchw, patchh; HUDONLY // only run this function in hud hooks @@ -691,65 +684,25 @@ static int libd_drawOnMinimap(lua_State *L) if (stplyr != &players[displayplayers[0]]) return 0; - AutomapPic = mapheaderinfo[gamemap-1]->minimapPic; - - if (!AutomapPic) + if (minimapinfo.minimap_pic == NULL) { return 0; // no pic, just get outta here } - mx = MM_X - (AutomapPic->width/2); - my = MM_Y - (AutomapPic->height/2); + mx = MM_X - (minimapinfo.minimap_pic->width/2); + my = MM_Y - (minimapinfo.minimap_pic->height/2); // let offsets transfer to the heads, too! if (encoremode) - mx += SHORT(AutomapPic->leftoffset); + mx += SHORT(minimapinfo.minimap_pic->leftoffset); else - mx -= SHORT(AutomapPic->leftoffset); - my -= SHORT(AutomapPic->topoffset); + mx -= SHORT(minimapinfo.minimap_pic->leftoffset); + my -= SHORT(minimapinfo.minimap_pic->topoffset); // now that we have replicated this behavior, we can draw an icon from our supplied x, y coordinates by replicating k_kart.c's totally understandable uncommented code!!! - // get map boundaries using nodes - maxx = maxy = INT32_MAX; - minx = miny = INT32_MIN; - minx = bsp->bbox[0][BOXLEFT]; - maxx = bsp->bbox[0][BOXRIGHT]; - miny = bsp->bbox[0][BOXBOTTOM]; - maxy = bsp->bbox[0][BOXTOP]; - - if (bsp->bbox[1][BOXLEFT] < minx) - minx = bsp->bbox[1][BOXLEFT]; - if (bsp->bbox[1][BOXRIGHT] > maxx) - maxx = bsp->bbox[1][BOXRIGHT]; - if (bsp->bbox[1][BOXBOTTOM] < miny) - miny = bsp->bbox[1][BOXBOTTOM]; - if (bsp->bbox[1][BOXTOP] > maxy) - maxy = bsp->bbox[1][BOXTOP]; - - // You might be wondering why these are being bitshift here - // it's because mapwidth and height would otherwise overflow for maps larger than half the size possible... - // map boundaries and sizes will ALWAYS be whole numbers thankfully - // later calculations take into consideration that these are actually not in terms of FRACUNIT though - minx >>= FRACBITS; - maxx >>= FRACBITS; - miny >>= FRACBITS; - maxy >>= FRACBITS; - - // these are our final map boundaries: - mapwidth = maxx - minx; - mapheight = maxy - miny; - - // These should always be small enough to be bitshift back right now - xoffset = (minx + mapwidth/2)<width, mapwidth); - yscale = FixedDiv(AutomapPic->height, mapheight); - zoom = FixedMul(min(xscale, yscale), FRACUNIT-FRACUNIT/20); - - amnumxpos = (FixedMul(x, zoom) - FixedMul(xoffset, zoom)); - amnumypos = -(FixedMul(y, zoom) - FixedMul(yoffset, zoom)); + amnumxpos = (FixedMul(x, minimapinfo.zoom) - minimapinfo.offs_x); + amnumypos = -(FixedMul(y, minimapinfo.zoom) - minimapinfo.offs_y); if (encoremode) amnumxpos = -amnumxpos; @@ -761,8 +714,8 @@ static int libd_drawOnMinimap(lua_State *L) if (centered) patchw = patchh = 0; // patch is supposedly already centered, don't butt in. - amxpos = amnumxpos + ((mx + AutomapPic->width/2)<height/2)<width/2)<height/2)< Date: Tue, 18 Feb 2025 19:26:10 -0500 Subject: [PATCH 14/14] renanble minimapdot drawing code --- src/k_hud.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index 05b48d11d..956a4af07 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -3196,14 +3196,14 @@ static void K_drawKartMinimapDot(fixed_t objx, fixed_t objy, INT32 hudx, INT32 h fixed_t amnumxpos, amnumypos; INT32 amxpos, amypos; - amnumxpos = (/*FixedMul(*/objx/*, minimapinfo.zoom) - minimapinfo.offs_x*/); - amnumypos = -(/*FixedMul(*/objy/*,, minimapinfo.zoom) - minimapinfo.offs_y*/); + amnumxpos = (FixedMul(objx, minimapinfo.zoom) - minimapinfo.offs_x); + amnumypos = -(FixedMul(objy, minimapinfo.zoom) - minimapinfo.offs_y); if (encoremode) amnumxpos = -amnumxpos; - amxpos = (amnumxpos / FRACUNIT) /*+ (SHORT(minimapinfo.minimap_pic->width) / 2)*/; - amypos = (amnumypos / FRACUNIT) /*+ (SHORT(minimapinfo.minimap_pic->height) / 2)*/; + amxpos = (amnumxpos / FRACUNIT) + (SHORT(minimapinfo.minimap_pic->width) / 2); + amypos = (amnumypos / FRACUNIT) + (SHORT(minimapinfo.minimap_pic->height) / 2); if (flags & V_NOSCALESTART) {