From da639fe65f13a9f140b1483a680d15205eae1326 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 23 Jan 2023 18:38:52 +0000 Subject: [PATCH] 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 8dde145ae..d90147e28 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. @@ -1162,7 +1346,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); @@ -1218,7 +1402,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 8db5ba5d9..24af5dcb9 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -1536,6 +1536,23 @@ static void K_TerrainDefaults(terrain_t *terrain) terrain->flags = 0; } +/*-------------------------------------------------- + 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 4b452567d..92241d923 100644 --- a/src/k_terrain.h +++ b/src/k_terrain.h @@ -569,6 +569,20 @@ void K_UpdateTerrainOverlay(mobj_t *mo); void K_InitTerrain(UINT16 wadNum); +/*-------------------------------------------------- + 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