M_ChallengeGridExtraData

Precalculates adjacency rules for challengegrid instead of doing it in the drawer
- Simplifies `M_DrawChallenges` a lot, at the expense of a pretty complicated function living in `m_cond.c`
- Handles registering entries both not to be drawn (for non-primary components of `majorunlock` unlockables) and for hint highlights (new for this commit)
    - Hint highlights are a sky blue
This commit is contained in:
toaster 2022-12-01 21:55:05 +00:00
parent b8674e35e1
commit 85160b1dc1
5 changed files with 197 additions and 29 deletions

View file

@ -1091,6 +1091,8 @@ extern struct challengesmenu_s {
UINT8 currentunlock;
tic_t unlockanim;
UINT8 *extradata;
boolean pending;
} challengesmenu;

View file

@ -4461,7 +4461,7 @@ void M_DrawAddons(void)
void M_DrawChallenges(void)
{
INT32 x = 20, y = 20;
UINT8 i, j, num;
UINT8 i, j, id, num, work;
unlockable_t *ref = NULL;
{
@ -4487,13 +4487,26 @@ void M_DrawChallenges(void)
x = currentMenu->x;
y = currentMenu->y;
if (!gamedata->challengegrid)
{
V_DrawString(x, y, V_REDMAP, "No challenges available!?");
return;
}
for (i = 0; i < gamedata->challengegridwidth; i++)
{
y = currentMenu->y-16;
for (j = 0; j < CHALLENGEGRIDHEIGHT; j++)
{
y += 16;
num = gamedata->challengegrid[(i * CHALLENGEGRIDHEIGHT) + j];
id = (i * CHALLENGEGRIDHEIGHT) + j;
if (challengesmenu.extradata[id] == CHE_DONTDRAW)
{
continue;
}
num = gamedata->challengegrid[id];
// Empty spots in the grid are always unconnected.
if (num >= MAXUNLOCKABLES)
@ -4502,30 +4515,6 @@ void M_DrawChallenges(void)
continue;
}
// Is the spot above me also me?
if (j > 0 && gamedata->challengegrid[(i * CHALLENGEGRIDHEIGHT) + (j - 1)] == num)
{
continue;
}
// Is the spot to the left of me also me?
if (i > 0)
{
// Standard
if (gamedata->challengegrid[((i - 1) * CHALLENGEGRIDHEIGHT) + j] == num)
{
continue;
}
}
else if (gamedata->challengegridwidth > 2)
{
// Conditional modulo
if (gamedata->challengegrid[((gamedata->challengegridwidth - 1) * CHALLENGEGRIDHEIGHT) + j] == num)
{
continue;
}
}
// Okay, this is what we want to draw.
ref = &unlockables[num];
@ -4533,9 +4522,10 @@ void M_DrawChallenges(void)
if ((gamedata->unlocked[num] == false)
|| (num == challengesmenu.currentunlock && challengesmenu.unlockanim < UNLOCKTIME/2))
{
num = (ref->majorunlock) ? 2 : 1;
V_DrawFill(x, y, 16*num, 16*num,
((i & num) != (j & num) ? 12 : 14) + (num-1)*4); // funny checkerboard pattern
work = (ref->majorunlock) ? 2 : 1;
V_DrawFill(x, y, 16*work, 16*work,
((challengesmenu.extradata[id] == CHE_HINT) ? 130 : 12)
+ ((i & work) != (j & work) ? 0 : 2) + (work-1)); // funny checkerboard pattern
continue;
}

View file

@ -6837,6 +6837,8 @@ void M_ChallengesTick(void)
challengesmenu.pending = false;
G_SaveGameData();
}
Z_Free(challengesmenu.extradata);
challengesmenu.extradata = M_ChallengeGridExtraData();
}
else if (challengesmenu.unlockanim >= UNLOCKTIME)
{
@ -6865,6 +6867,8 @@ boolean M_ChallengesInputs(INT32 ch)
gamedata->challengegrid = NULL;
gamedata->challengegridwidth = 0;
M_PopulateChallengeGrid();
Z_Free(challengesmenu.extradata);
challengesmenu.extradata = M_ChallengeGridExtraData();
challengesmenu.unlockanim = 0;
return true;
}
@ -6882,6 +6886,10 @@ boolean M_ChallengesInputs(INT32 ch)
{
M_GoBack(0);
M_SetMenuDelay(pid);
Z_Free(challengesmenu.extradata);
challengesmenu.extradata = NULL;
return true;
}

View file

@ -233,6 +233,170 @@ quickcheckagain:
}
}
UINT8 *M_ChallengeGridExtraData(void)
{
UINT8 i, j, num, id, tempid, work;
UINT8 *extradata;
boolean idchange;
if (!gamedata->challengegrid)
{
return NULL;
}
extradata = Z_Malloc(
(gamedata->challengegridwidth * CHALLENGEGRIDHEIGHT * sizeof(UINT8)),
PU_STATIC, NULL);
if (!extradata)
{
I_Error("M_ChallengeGridExtraData: was not able to allocate extradata");
}
//CONS_Printf(" --- \n");
for (i = 0; i < gamedata->challengegridwidth; i++)
{
for (j = 0; j < CHALLENGEGRIDHEIGHT; j++)
{
id = (i * CHALLENGEGRIDHEIGHT) + j;
num = gamedata->challengegrid[id];
idchange = false;
extradata[id] = CHE_NONE;
// Empty spots in the grid are always unconnected.
if (num >= MAXUNLOCKABLES)
{
continue;
}
// Check the spot above.
if (j > 0)
{
tempid = (i * CHALLENGEGRIDHEIGHT) + (j - 1);
work = gamedata->challengegrid[tempid];
if (work == num)
{
extradata[id] = CHE_DONTDRAW;
// Get the id to write extra hint data to.
// This check is safe because extradata's order of population
if (extradata[tempid] == CHE_DONTDRAW)
{
//CONS_Printf(" %d - %d above %d is invalid, check to left\n", num, tempid, id);
if (i > 0)
{
tempid -= CHALLENGEGRIDHEIGHT;
}
else
{
tempid = ((gamedata->challengegridwidth - 1) * CHALLENGEGRIDHEIGHT) + j - 1;
}
}
/*else
CONS_Printf(" %d - %d above %d is valid\n", num, tempid, id);*/
id = tempid;
idchange = true;
if (extradata[id] == CHE_HINT)
{
continue;
}
}
else if (work < MAXUNLOCKABLES && gamedata->unlocked[work])
{
extradata[id] = CHE_HINT;
}
}
// Check the spot to the left.
{
if (i > 0)
{
tempid = ((i - 1) * CHALLENGEGRIDHEIGHT) + j;
}
else
{
tempid = ((gamedata->challengegridwidth - 1) * CHALLENGEGRIDHEIGHT) + j;
}
work = gamedata->challengegrid[tempid];
if (work == num)
{
if (!idchange && (i > 0 || gamedata->challengegridwidth > 2))
{
//CONS_Printf(" %d - %d to left of %d is valid\n", work, tempid, id);
// If we haven't already updated our id, it's the one to our left.
if (extradata[id] == CHE_HINT)
{
extradata[tempid] = CHE_HINT;
}
extradata[id] = CHE_DONTDRAW;
id = tempid;
}
/*else
CONS_Printf(" %d - %d to left of %d is invalid\n", work, tempid, id);*/
}
else if (work < MAXUNLOCKABLES && gamedata->unlocked[work])
{
extradata[id] = CHE_HINT;
continue;
}
}
// Since we're not modifying id past this point, the conditions become much simpler.
if (extradata[id] == CHE_HINT)
{
continue;
}
// Check the spot below.
if (j < CHALLENGEGRIDHEIGHT-1)
{
tempid = (i * CHALLENGEGRIDHEIGHT) + (j + 1);
work = gamedata->challengegrid[tempid];
if (work == num)
{
;
}
else if (work < MAXUNLOCKABLES && gamedata->unlocked[work])
{
extradata[id] = CHE_HINT;
continue;
}
}
// Check the spot to the right.
{
if (i < (gamedata->challengegridwidth - 1))
{
tempid = ((i + 1) * CHALLENGEGRIDHEIGHT) + j;
}
else
{
tempid = j;
}
work = gamedata->challengegrid[tempid];
if (work == num)
{
;
}
else if (work < MAXUNLOCKABLES && gamedata->unlocked[work])
{
extradata[id] = CHE_HINT;
continue;
}
}
}
}
return extradata;
}
void M_AddRawCondition(UINT8 set, UINT8 id, conditiontype_t c, INT32 r, INT16 x1, INT16 x2)
{
condition_t *cond;

View file

@ -175,6 +175,10 @@ extern UINT32 unlocktriggers;
void M_NewGameDataStruct(void);
void M_PopulateChallengeGrid(void);
UINT8 *M_ChallengeGridExtraData(void);
#define CHE_NONE 0
#define CHE_HINT 1
#define CHE_DONTDRAW 2
// Condition set setup
void M_AddRawCondition(UINT8 set, UINT8 id, conditiontype_t c, INT32 r, INT16 x1, INT16 x2);