mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Add unlock condition text to Challenges menu
Has ifdef'd out code for conditions to change between white and yellow when achieved to match V1 behaviour... wasn't able to figure out why it wasn't working, so dummied out for now.
This commit is contained in:
parent
6d3a812ff3
commit
cc9a65c8f8
5 changed files with 248 additions and 11 deletions
|
|
@ -1101,6 +1101,8 @@ extern struct challengesmenu_s {
|
||||||
INT16 offset; // To make the icons move smoothly when we transition!
|
INT16 offset; // To make the icons move smoothly when we transition!
|
||||||
|
|
||||||
UINT8 currentunlock;
|
UINT8 currentunlock;
|
||||||
|
char *unlockcondition;
|
||||||
|
|
||||||
tic_t unlockanim;
|
tic_t unlockanim;
|
||||||
|
|
||||||
SINT8 row, hilix, focusx;
|
SINT8 row, hilix, focusx;
|
||||||
|
|
|
||||||
|
|
@ -4720,6 +4720,9 @@ challengedesc:
|
||||||
V_DrawLSTitleLowString(BASEVIDWIDTH/2 - offset, y+6, 0, str);
|
V_DrawLSTitleLowString(BASEVIDWIDTH/2 - offset, y+6, 0, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!challengesmenu.fade)
|
// Conditions for unlock
|
||||||
V_DrawThinString(20, 120 + 60, V_ALLOWLOWERCASE, "Press (B)");
|
if (challengesmenu.unlockcondition != NULL)
|
||||||
|
{
|
||||||
|
V_DrawCenteredString(BASEVIDWIDTH/2, 120 + 40, V_ALLOWLOWERCASE, challengesmenu.unlockcondition);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1776,15 +1776,14 @@ static inline size_t M_StringHeight(const char *string)
|
||||||
void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtype)
|
void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtype)
|
||||||
{
|
{
|
||||||
const UINT8 pid = 0;
|
const UINT8 pid = 0;
|
||||||
size_t max = 0, start = 0, i, strlines;
|
size_t max = 0, start = 0, strlines = 0, i;
|
||||||
static char *message = NULL;
|
static char *message = NULL;
|
||||||
Z_Free(message);
|
Z_Free(message);
|
||||||
message = Z_StrDup(string);
|
message = Z_StrDup(string);
|
||||||
DEBFILE(message);
|
DEBFILE(message);
|
||||||
|
|
||||||
// Rudementary word wrapping.
|
// Rudementary word wrapping.
|
||||||
// Simple and effective. Does not handle nonuniform letter sizes, colors, etc. but who cares.
|
// Simple and effective. Does not handle nonuniform letter sizes, etc. but who cares.
|
||||||
strlines = 0;
|
|
||||||
for (i = 0; message[i]; i++)
|
for (i = 0; message[i]; i++)
|
||||||
{
|
{
|
||||||
if (message[i] == ' ')
|
if (message[i] == ' ')
|
||||||
|
|
@ -1799,6 +1798,8 @@ void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtyp
|
||||||
max = 0;
|
max = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
else if (message[i] & 0x80)
|
||||||
|
continue;
|
||||||
else
|
else
|
||||||
max += 8;
|
max += 8;
|
||||||
|
|
||||||
|
|
@ -6859,13 +6860,14 @@ menu_t *M_InterruptMenuWithChallenges(menu_t *desiredmenu)
|
||||||
|
|
||||||
if (challengesmenu.pending || desiredmenu == NULL)
|
if (challengesmenu.pending || desiredmenu == NULL)
|
||||||
{
|
{
|
||||||
memset(setup_explosions, 0, sizeof(setup_explosions));
|
|
||||||
challengesmenu.currentunlock = MAXUNLOCKABLES;
|
challengesmenu.currentunlock = MAXUNLOCKABLES;
|
||||||
M_PopulateChallengeGrid();
|
challengesmenu.unlockcondition = NULL;
|
||||||
|
|
||||||
|
M_PopulateChallengeGrid();
|
||||||
if (gamedata->challengegrid)
|
if (gamedata->challengegrid)
|
||||||
challengesmenu.extradata = M_ChallengeGridExtraData();
|
challengesmenu.extradata = M_ChallengeGridExtraData();
|
||||||
|
|
||||||
|
memset(setup_explosions, 0, sizeof(setup_explosions));
|
||||||
memset(&challengesmenu.unlockcount, 0, sizeof(challengesmenu.unlockcount));
|
memset(&challengesmenu.unlockcount, 0, sizeof(challengesmenu.unlockcount));
|
||||||
for (i = 0; i < MAXUNLOCKABLES; i++)
|
for (i = 0; i < MAXUNLOCKABLES; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -6899,6 +6901,7 @@ static void M_ChallengesAutoFocus(UINT8 unlockid, boolean fresh)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
challengesmenu.currentunlock = unlockid;
|
challengesmenu.currentunlock = unlockid;
|
||||||
|
challengesmenu.unlockcondition = M_BuildConditionSetString(challengesmenu.currentunlock);
|
||||||
challengesmenu.unlockanim = 0;
|
challengesmenu.unlockanim = 0;
|
||||||
|
|
||||||
if (gamedata->challengegrid == NULL || challengesmenu.extradata == NULL)
|
if (gamedata->challengegrid == NULL || challengesmenu.extradata == NULL)
|
||||||
|
|
@ -7099,6 +7102,9 @@ void M_ChallengesTick(void)
|
||||||
gamedata->unlocked[challengesmenu.currentunlock] = true;
|
gamedata->unlocked[challengesmenu.currentunlock] = true;
|
||||||
M_UpdateUnlockablesAndExtraEmblems(true);
|
M_UpdateUnlockablesAndExtraEmblems(true);
|
||||||
|
|
||||||
|
// Update shown description just in case..?
|
||||||
|
challengesmenu.unlockcondition = M_BuildConditionSetString(challengesmenu.currentunlock);
|
||||||
|
|
||||||
challengesmenu.unlockcount[CC_TALLY]++;
|
challengesmenu.unlockcount[CC_TALLY]++;
|
||||||
challengesmenu.unlockcount[CC_ANIM]++;
|
challengesmenu.unlockcount[CC_ANIM]++;
|
||||||
|
|
||||||
|
|
@ -7213,6 +7219,8 @@ boolean M_ChallengesInputs(INT32 ch)
|
||||||
Z_Free(challengesmenu.extradata);
|
Z_Free(challengesmenu.extradata);
|
||||||
challengesmenu.extradata = NULL;
|
challengesmenu.extradata = NULL;
|
||||||
|
|
||||||
|
challengesmenu.unlockcondition = NULL;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -7336,6 +7344,7 @@ boolean M_ChallengesInputs(INT32 ch)
|
||||||
// After movement has been determined, figure out the current selection.
|
// After movement has been determined, figure out the current selection.
|
||||||
i = (challengesmenu.col * CHALLENGEGRIDHEIGHT) + challengesmenu.row;
|
i = (challengesmenu.col * CHALLENGEGRIDHEIGHT) + challengesmenu.row;
|
||||||
challengesmenu.currentunlock = (gamedata->challengegrid[i]);
|
challengesmenu.currentunlock = (gamedata->challengegrid[i]);
|
||||||
|
challengesmenu.unlockcondition = M_BuildConditionSetString(challengesmenu.currentunlock);
|
||||||
|
|
||||||
challengesmenu.hilix = challengesmenu.col;
|
challengesmenu.hilix = challengesmenu.col;
|
||||||
challengesmenu.hiliy = challengesmenu.row;
|
challengesmenu.hiliy = challengesmenu.row;
|
||||||
|
|
|
||||||
223
src/m_cond.c
223
src/m_cond.c
|
|
@ -480,6 +480,8 @@ void M_ClearSecrets(void)
|
||||||
// ----------------------
|
// ----------------------
|
||||||
// Condition set checking
|
// Condition set checking
|
||||||
// ----------------------
|
// ----------------------
|
||||||
|
|
||||||
|
// See also M_GetConditionString
|
||||||
UINT8 M_CheckCondition(condition_t *cn)
|
UINT8 M_CheckCondition(condition_t *cn)
|
||||||
{
|
{
|
||||||
switch (cn->type)
|
switch (cn->type)
|
||||||
|
|
@ -564,7 +566,226 @@ static UINT8 M_CheckConditionSet(conditionset_t *c)
|
||||||
return achievedSoFar;
|
return achievedSoFar;
|
||||||
}
|
}
|
||||||
|
|
||||||
void M_CheckUnlockConditions(void)
|
// See also M_CheckCondition
|
||||||
|
static const char *M_GetConditionString(condition_t *cn)
|
||||||
|
{
|
||||||
|
INT32 i;
|
||||||
|
char *title = NULL;
|
||||||
|
const char *work = NULL;
|
||||||
|
|
||||||
|
#define BUILDCONDITIONTITLE(i) (M_MapLocked(i+1) ? Z_StrDup("???") : G_BuildMapTitle(i+1))
|
||||||
|
|
||||||
|
switch (cn->type)
|
||||||
|
{
|
||||||
|
case UC_PLAYTIME: // Requires total playing time >= x
|
||||||
|
return va("Play for %i:%02i:%02i",
|
||||||
|
G_TicsToHours(cn->requirement),
|
||||||
|
G_TicsToMinutes(cn->requirement, false),
|
||||||
|
G_TicsToSeconds(cn->requirement));
|
||||||
|
case UC_MATCHESPLAYED: // Requires any level completed >= x times
|
||||||
|
return va("Play %d matches", cn->requirement);
|
||||||
|
case UC_POWERLEVEL: // Requires power level >= x on a certain gametype
|
||||||
|
return va("Get a PWR of %d in %s", cn->requirement,
|
||||||
|
(cn->extrainfo1 == PWRLV_RACE)
|
||||||
|
? "Race"
|
||||||
|
: "Battle");
|
||||||
|
case UC_GAMECLEAR: // Requires game beaten >= x times
|
||||||
|
if (cn->requirement > 1)
|
||||||
|
return va("Beat game %d times", cn->requirement);
|
||||||
|
else
|
||||||
|
return va("Beat the game");
|
||||||
|
case UC_OVERALLTIME: // Requires overall time <= x
|
||||||
|
return va("Get overall time of %i:%02i:%02i",
|
||||||
|
G_TicsToHours(cn->requirement),
|
||||||
|
G_TicsToMinutes(cn->requirement, false),
|
||||||
|
G_TicsToSeconds(cn->requirement));
|
||||||
|
case UC_MAPVISITED: // Requires map x to be visited
|
||||||
|
case UC_MAPBEATEN: // Requires map x to be beaten
|
||||||
|
case UC_MAPENCORE: // Requires map x to be beaten in encore
|
||||||
|
{
|
||||||
|
if (cn->requirement >= nummapheaders || !mapheaderinfo[cn->requirement])
|
||||||
|
return va("INVALID MAP CONDITION \"%d:%d\"", cn->type, cn->requirement);
|
||||||
|
|
||||||
|
title = BUILDCONDITIONTITLE(cn->requirement);
|
||||||
|
work = va("%s %s%s",
|
||||||
|
(cn->type == UC_MAPVISITED) ? "Visit" : "Beat",
|
||||||
|
title,
|
||||||
|
(cn->type == UC_MAPENCORE) ? " in Encore Mode" : "");
|
||||||
|
Z_Free(title);
|
||||||
|
return work;
|
||||||
|
}
|
||||||
|
case UC_MAPTIME: // Requires time on map <= x
|
||||||
|
{
|
||||||
|
if (cn->extrainfo1 >= nummapheaders || !mapheaderinfo[cn->extrainfo1])
|
||||||
|
return va("INVALID MAP CONDITION \"%d:%d:%d\"", cn->type, cn->extrainfo1, cn->requirement);
|
||||||
|
|
||||||
|
title = BUILDCONDITIONTITLE(cn->extrainfo1);
|
||||||
|
work = va("Beat %s in %i:%02i.%02i", title,
|
||||||
|
G_TicsToMinutes(cn->requirement, true),
|
||||||
|
G_TicsToSeconds(cn->requirement),
|
||||||
|
G_TicsToCentiseconds(cn->requirement));
|
||||||
|
|
||||||
|
Z_Free(title);
|
||||||
|
return work;
|
||||||
|
}
|
||||||
|
case UC_TOTALEMBLEMS: // Requires number of emblems >= x
|
||||||
|
return va("Get %d medals", cn->requirement);
|
||||||
|
case UC_EMBLEM: // Requires emblem x to be obtained
|
||||||
|
{
|
||||||
|
INT32 checkLevel;
|
||||||
|
|
||||||
|
i = cn->requirement-1;
|
||||||
|
checkLevel = G_MapNumber(emblemlocations[i].level);
|
||||||
|
|
||||||
|
if (checkLevel >= nummapheaders || !mapheaderinfo[checkLevel])
|
||||||
|
return va("INVALID MEDAL MAP \"%d:%d\"", cn->requirement, checkLevel);
|
||||||
|
|
||||||
|
title = BUILDCONDITIONTITLE(checkLevel);
|
||||||
|
switch (emblemlocations[i].type)
|
||||||
|
{
|
||||||
|
case ET_MAP:
|
||||||
|
work = va("Beat %s", title);
|
||||||
|
break;
|
||||||
|
case ET_TIME:
|
||||||
|
if (emblemlocations[i].color <= 0 || emblemlocations[i].color >= numskincolors)
|
||||||
|
{
|
||||||
|
Z_Free(title);
|
||||||
|
return va("INVALID MEDAL COLOR \"%d:%d\"", cn->requirement, checkLevel);
|
||||||
|
}
|
||||||
|
work = va("Get the %s Medal for %s", skincolors[emblemlocations[i].color].name, title);
|
||||||
|
break;
|
||||||
|
case ET_GLOBAL:
|
||||||
|
default:
|
||||||
|
work = va("Find a secret in %s", title);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Z_Free(title);
|
||||||
|
return work;
|
||||||
|
}
|
||||||
|
case UC_UNLOCKABLE: // Requires unlockable x to be obtained
|
||||||
|
return va("Get \"%s\"",
|
||||||
|
gamedata->unlocked[cn->requirement-1]
|
||||||
|
? unlockables[cn->requirement-1].name
|
||||||
|
: "???");
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// UC_MAPTRIGGER and UC_CONDITIONSET are explicitly very hard to support proper descriptions for
|
||||||
|
return va("UNSUPPORTED CONDITION \"%d\"", cn->type);
|
||||||
|
|
||||||
|
#undef BUILDCONDITIONTITLE
|
||||||
|
}
|
||||||
|
|
||||||
|
//#define ACHIEVEDBRITE
|
||||||
|
|
||||||
|
char *M_BuildConditionSetString(UINT8 unlockid)
|
||||||
|
{
|
||||||
|
conditionset_t *c = NULL;
|
||||||
|
UINT32 lastID = 0;
|
||||||
|
condition_t *cn;
|
||||||
|
#ifdef ACHIEVEDBRITE
|
||||||
|
boolean achieved = false;
|
||||||
|
#endif
|
||||||
|
size_t len = 1024, worklen;
|
||||||
|
static char message[1024] = "";
|
||||||
|
const char *work = NULL;
|
||||||
|
size_t max = 0, start = 0, strlines = 0, i;
|
||||||
|
|
||||||
|
message[0] = '\0';
|
||||||
|
|
||||||
|
if (unlockid >= MAXUNLOCKABLES)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!unlockables[unlockid].conditionset)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = &conditionSets[unlockables[unlockid].conditionset-1];
|
||||||
|
|
||||||
|
for (i = 0; i < c->numconditions; ++i)
|
||||||
|
{
|
||||||
|
cn = &c->condition[i];
|
||||||
|
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
worklen = 3;
|
||||||
|
if (lastID == cn->id)
|
||||||
|
{
|
||||||
|
strncat(message, "\n& ", len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strncat(message, "\nOR ", len);
|
||||||
|
worklen++;
|
||||||
|
}
|
||||||
|
len -= worklen;
|
||||||
|
}
|
||||||
|
lastID = cn->id;
|
||||||
|
|
||||||
|
#ifdef ACHIEVEDBRITE
|
||||||
|
achieved = M_CheckCondition(cn);
|
||||||
|
|
||||||
|
if (achieved)
|
||||||
|
{
|
||||||
|
strncat(message, "\0x82", len);
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
work = M_GetConditionString(cn);
|
||||||
|
worklen = strlen(work);
|
||||||
|
|
||||||
|
strncat(message, work, len);
|
||||||
|
len -= worklen;
|
||||||
|
|
||||||
|
#ifdef ACHIEVEDBRITE
|
||||||
|
if (achieved)
|
||||||
|
{
|
||||||
|
strncat(message, "\0x80", len);
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rudementary word wrapping.
|
||||||
|
// Simple and effective. Does not handle nonuniform letter sizes, etc. but who cares.
|
||||||
|
for (i = 0; message[i]; i++)
|
||||||
|
{
|
||||||
|
if (message[i] == ' ')
|
||||||
|
{
|
||||||
|
start = i;
|
||||||
|
max += 4;
|
||||||
|
}
|
||||||
|
else if (message[i] == '\n')
|
||||||
|
{
|
||||||
|
strlines = i;
|
||||||
|
start = 0;
|
||||||
|
max = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (message[i] & 0x80)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
max += 8;
|
||||||
|
|
||||||
|
// Start trying to wrap if presumed length exceeds the screen width.
|
||||||
|
if (max >= BASEVIDWIDTH && start > 0)
|
||||||
|
{
|
||||||
|
message[start] = '\n';
|
||||||
|
max -= (start-strlines)*8;
|
||||||
|
strlines = start;
|
||||||
|
start = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void M_CheckUnlockConditions(void)
|
||||||
{
|
{
|
||||||
INT32 i;
|
INT32 i;
|
||||||
conditionset_t *c;
|
conditionset_t *c;
|
||||||
|
|
|
||||||
|
|
@ -171,12 +171,15 @@ extern INT32 numemblems;
|
||||||
extern UINT32 unlocktriggers;
|
extern UINT32 unlocktriggers;
|
||||||
|
|
||||||
void M_NewGameDataStruct(void);
|
void M_NewGameDataStruct(void);
|
||||||
|
|
||||||
|
// Challenges menu stuff
|
||||||
void M_PopulateChallengeGrid(void);
|
void M_PopulateChallengeGrid(void);
|
||||||
UINT8 *M_ChallengeGridExtraData(void);
|
UINT8 *M_ChallengeGridExtraData(void);
|
||||||
|
char *M_BuildConditionSetString(UINT8 unlockid);
|
||||||
#define CHE_NONE 0
|
#define CHE_NONE 0
|
||||||
#define CHE_HINT 1
|
#define CHE_HINT 1
|
||||||
#define CHE_CONNECTEDLEFT 2
|
#define CHE_CONNECTEDLEFT (1<<1)
|
||||||
#define CHE_CONNECTEDUP 4
|
#define CHE_CONNECTEDUP (1<<2)
|
||||||
#define CHE_DONTDRAW (CHE_CONNECTEDLEFT|CHE_CONNECTEDUP)
|
#define CHE_DONTDRAW (CHE_CONNECTEDLEFT|CHE_CONNECTEDUP)
|
||||||
|
|
||||||
// Condition set setup
|
// Condition set setup
|
||||||
|
|
@ -187,7 +190,6 @@ void M_ClearConditionSet(UINT8 set);
|
||||||
void M_ClearSecrets(void);
|
void M_ClearSecrets(void);
|
||||||
|
|
||||||
// Updating conditions and unlockables
|
// Updating conditions and unlockables
|
||||||
void M_CheckUnlockConditions(void);
|
|
||||||
UINT8 M_CheckCondition(condition_t *cn);
|
UINT8 M_CheckCondition(condition_t *cn);
|
||||||
boolean M_UpdateUnlockablesAndExtraEmblems(boolean loud);
|
boolean M_UpdateUnlockablesAndExtraEmblems(boolean loud);
|
||||||
UINT8 M_GetNextAchievedUnlock(void);
|
UINT8 M_GetNextAchievedUnlock(void);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue