From d061dd09fdd0633e2ae30992080113d71400431d Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 3 Dec 2022 14:52:58 +0000 Subject: [PATCH] Removing `extraemblem_t` - You can now create an unlockable that gives you an emblem only with SECRET_EXTRAEMBLEM. - One step above the completely rewardless squares from Kirby Air Ride. - Added color to `unlockable_t`. - Can be used both with user-specified icons (remappable green->color) and with non-SECRET_SKIN default graphics (invincibility full-range remap) - Replaced condition type UC_EXTRAEMBLEM with the more general UC_UNLOCKABLE. - MAXUNLOCKABLES is now == MAXCONDITIONSETS --- src/deh_soc.c | 103 +++++------------------------------------------ src/deh_soc.h | 1 - src/dehacked.c | 32 --------------- src/g_game.c | 17 +------- src/k_menudraw.c | 56 ++++++++++++++------------ src/m_cond.c | 99 ++++++++++++++------------------------------- src/m_cond.h | 28 +++---------- 7 files changed, 77 insertions(+), 259 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index c85c3da4a..d63301901 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -2203,88 +2203,6 @@ void reademblemdata(MYFILE *f, INT32 num) Z_Free(s); } -void readextraemblemdata(MYFILE *f, INT32 num) -{ - char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); - char *word = s; - char *word2; - char *tmp; - INT32 value; - - memset(&extraemblems[num-1], 0, sizeof(extraemblem_t)); - - do - { - if (myfgets(s, MAXLINELEN, f)) - { - if (s[0] == '\n') - break; - - // First remove trailing newline, if there is one - tmp = strchr(s, '\n'); - if (tmp) - *tmp = '\0'; - - tmp = strchr(s, '#'); - if (tmp) - *tmp = '\0'; - if (s == tmp) - continue; // Skip comment lines, but don't break. - - // Get the part before the " = " - tmp = strchr(s, '='); - if (tmp) - *(tmp-1) = '\0'; - else - break; - strupr(word); - - // Now get the part after - word2 = tmp += 2; - - value = atoi(word2); // used for numerical settings - - if (fastcmp(word, "NAME")) - deh_strlcpy(extraemblems[num-1].name, word2, - sizeof (extraemblems[num-1].name), va("Extra emblem %d: name", num)); - else if (fastcmp(word, "OBJECTIVE")) - deh_strlcpy(extraemblems[num-1].description, word2, - sizeof (extraemblems[num-1].description), va("Extra emblem %d: objective", num)); - else if (fastcmp(word, "CONDITIONSET")) - extraemblems[num-1].conditionset = (UINT8)value; - else if (fastcmp(word, "SHOWCONDITIONSET")) - extraemblems[num-1].showconditionset = (UINT8)value; - else - { - strupr(word2); - if (fastcmp(word, "SPRITE")) - { - if (word2[0] >= 'A' && word2[0] <= 'Z') - value = word2[0]; - else - value += 'A'-1; - - if (value < 'A' || value > 'Z') - deh_warning("Emblem %d: sprite must be from A - Z (1 - 26)", num); - else - extraemblems[num-1].sprite = (UINT8)value; - } - else if (fastcmp(word, "COLOR")) - extraemblems[num-1].color = get_number(word2); - else - deh_warning("Extra emblem %d: unknown word '%s'", num, word); - } - } - } while (!myfeof(f)); - - if (!extraemblems[num-1].sprite) - extraemblems[num-1].sprite = 'C'; - if (!extraemblems[num-1].color) - extraemblems[num-1].color = SKINCOLOR_RED; - - Z_Free(s); -} - void readunlockable(MYFILE *f, INT32 num) { char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); @@ -2294,7 +2212,6 @@ void readunlockable(MYFILE *f, INT32 num) INT32 i; memset(&unlockables[num], 0, sizeof(unlockable_t)); - unlockables[num].objective[0] = '/'; do { @@ -2329,10 +2246,7 @@ void readunlockable(MYFILE *f, INT32 num) if (fastcmp(word, "NAME")) deh_strlcpy(unlockables[num].name, word2, - sizeof (unlockables[num].name), va("Unlockable %d: name", num)); - else if (fastcmp(word, "OBJECTIVE")) - deh_strlcpy(unlockables[num].objective, word2, - sizeof (unlockables[num].objective), va("Unlockable %d: objective", num)); + sizeof (unlockables[num].name), va("Unlockable %d: name", num+1)); else { strupr(word2); @@ -2351,8 +2265,6 @@ void readunlockable(MYFILE *f, INT32 num) unlockables[num].type = SECRET_SKIN; else if (fastcmp(word2, "WARP")) unlockables[num].type = SECRET_WARP; - else if (fastcmp(word2, "LEVELSELECT")) - unlockables[num].type = SECRET_LEVELSELECT; else if (fastcmp(word2, "TIMEATTACK")) unlockables[num].type = SECRET_TIMEATTACK; else if (fastcmp(word2, "BREAKTHECAPSULES")) @@ -2387,6 +2299,11 @@ void readunlockable(MYFILE *f, INT32 num) Z_Free(unlockables[num].icon); unlockables[num].icon = Z_StrDup(word2); } + else if (fastcmp(word, "COLOR")) + { + unlockables[num].color = get_number(word2); + CONS_Printf("%d+1 has color %s\n",num+1, skincolors[unlockables[num].color].name); + } else deh_warning("Unlockable %d: unknown word '%s'", num+1, word); } @@ -2515,15 +2432,15 @@ static void readcondition(UINT8 set, UINT32 id, char *word2) return; } } - else if (fastcmp(params[0], "EXTRAEMBLEM")) + else if (fastcmp(params[0], "UNLOCKABLE")) { PARAMCHECK(1); - ty = UC_EXTRAEMBLEM; + ty = UC_UNLOCKABLE; re = atoi(params[1]); - if (re <= 0 || re > MAXEXTRAEMBLEMS) + if (re <= 0 || re > MAXUNLOCKABLES) { - deh_warning("Extra emblem %d out of range (1 - %d) for condition ID %d", re, MAXEXTRAEMBLEMS, id+1); + deh_warning("Unlockable %d out of range (1 - %d) for condition ID %d", re, MAXUNLOCKABLES, id+1); return; } } diff --git a/src/deh_soc.h b/src/deh_soc.h index 92985ad2f..d6d4d9e01 100644 --- a/src/deh_soc.h +++ b/src/deh_soc.h @@ -60,7 +60,6 @@ void readwipes(MYFILE *f); void readmaincfg(MYFILE *f); void readconditionset(MYFILE *f, UINT8 setnum); void readunlockable(MYFILE *f, INT32 num); -void readextraemblemdata(MYFILE *f, INT32 num); void reademblemdata(MYFILE *f, INT32 num); void readsound(MYFILE *f, INT32 num); void readframe(MYFILE *f, INT32 num); diff --git a/src/dehacked.c b/src/dehacked.c index cc8ecc58e..005924ef4 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -278,32 +278,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) } continue; } - else if (fastcmp(word, "EXTRAEMBLEM")) - { - if (!mainfile && !gamedataadded) - { - deh_warning("You must define a custom gamedata to use \"%s\"", word); - ignorelines(f); - } - else - { - if (!word2) - i = numextraemblems + 1; - - if (i > 0 && i <= MAXEXTRAEMBLEMS) - { - if (numextraemblems < i) - numextraemblems = i; - readextraemblemdata(f, i); - } - else - { - deh_warning("Extra emblem number %d out of range (1 - %d)", i, MAXEXTRAEMBLEMS); - ignorelines(f); - } - } - continue; - } if (word2) { if (fastcmp(word, "THING") || fastcmp(word, "MOBJ") || fastcmp(word, "OBJECT")) @@ -593,12 +567,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) clear_emblems(); } - if (clearall || fastcmp(word2, "EXTRAEMBLEMS")) - { - memset(&extraemblems, 0, sizeof(extraemblems)); - numextraemblems = 0; - } - if (clearall || fastcmp(word2, "CONDITIONSETS")) clear_conditionsets(); diff --git a/src/g_game.c b/src/g_game.c index e2f0524ee..bafbf2ec3 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4389,13 +4389,6 @@ void G_LoadGameData(void) gamedata->collected[j+i] = ((rtemp >> j) & 1); i += j; } - for (i = 0; i < MAXEXTRAEMBLEMS;) - { - rtemp = READUINT8(save_p); - for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j) - gamedata->extraCollected[j+i] = ((rtemp >> j) & 1); - i += j; - } for (i = 0; i < MAXUNLOCKABLES;) { rtemp = READUINT8(save_p); @@ -4520,7 +4513,7 @@ void G_SaveGameData(void) return; } - length = (4+4+4+1+(MAXEMBLEMS)+MAXEXTRAEMBLEMS+MAXUNLOCKABLES+MAXCONDITIONSETS+4+4); + length = (4+4+4+1+(MAXEMBLEMS+MAXUNLOCKABLES+MAXCONDITIONSETS)+4+4); length += nummapheaders * (MAXMAPLUMPNAME+1+4+4); save_p = savebuffer = (UINT8 *)malloc(length); @@ -4546,14 +4539,6 @@ void G_SaveGameData(void) WRITEUINT8(save_p, btemp); i += j; } - for (i = 0; i < MAXEXTRAEMBLEMS;) // MAXEXTRAEMBLEMS * 1; - { - btemp = 0; - for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j) - btemp |= (gamedata->extraCollected[j+i] << j); - WRITEUINT8(save_p, btemp); - i += j; - } for (i = 0; i < MAXUNLOCKABLES;) // MAXUNLOCKABLES * 1; { btemp = 0; diff --git a/src/k_menudraw.c b/src/k_menudraw.c index d33794e37..c72871577 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -4468,6 +4468,9 @@ void M_DrawChallenges(void) const char *str; INT16 offset; unlockable_t *ref = NULL; + patch_t *pat; + UINT8 *colormap; + fixed_t siz; { patch_t *bg = W_CachePatchName("M_XTRABG", PU_CACHE); @@ -4517,50 +4520,51 @@ void M_DrawChallenges(void) goto drawborder; } + pat = missingpat; + colormap = NULL; if (ref->icon != NULL) { - patch_t *pat = W_CachePatchName(ref->icon, PU_CACHE); - fixed_t siz = (SHORT(pat->width) << FRACBITS); - - siz = FixedDiv(((ref->majorunlock) ? 32 : 16) << FRACBITS, siz); - - V_DrawFixedPatch( - x*FRACUNIT, y*FRACUNIT, - siz, - 0, pat, - NULL - ); - - goto drawborder; + pat = W_CachePatchName(ref->icon, PU_CACHE); + if (ref->color != SKINCOLOR_NONE && ref->color < numskincolors) + { + colormap = R_GetTranslationColormap(TC_DEFAULT, ref->color, GTC_MENUCACHE); + } } - - switch (ref->type) + else switch (ref->type) { + // add all SECRET_ENCORE, etc up here before SECRET_SKIN case SECRET_SKIN: { INT32 skin = M_UnlockableSkinNum(ref); if (skin != -1) { - UINT8 *colormap = R_GetTranslationColormap(skin, skins[skin].prefcolor, GTC_MENUCACHE); - UINT8 size = (ref->majorunlock) ? FACE_WANTED : FACE_RANK; - V_DrawMappedPatch(x, y, 0, faceprefix[skin][size], colormap); + colormap = R_GetTranslationColormap(skin, skins[skin].prefcolor, GTC_MENUCACHE); + pat = faceprefix[skin][(ref->majorunlock) ? FACE_WANTED : FACE_RANK]; } - else - { - V_DrawMappedPatch(x, y, 0, missingpat, NULL); - } - break; } default: { - patch_t *pat = W_CachePatchName(va("UN_RR00%c", ref->majorunlock ? 'B' : 'A'), PU_CACHE); - V_DrawMappedPatch(x, y, 0, pat, NULL); - //V_DrawString(x, y, V_ALLOWLOWERCASE, va("%c", ref->name[0])); + pat = W_CachePatchName(va("UN_RR00%c", ref->majorunlock ? 'B' : 'A'), PU_CACHE); + if (ref->color != SKINCOLOR_NONE && ref->color < numskincolors) + { + CONS_Printf(" color for %d is %s\n", num, skincolors[unlockables[num].color].name); + colormap = R_GetTranslationColormap(TC_RAINBOW, ref->color, GTC_MENUCACHE); + } break; } } + siz = (SHORT(pat->width) << FRACBITS); + siz = FixedDiv(((ref->majorunlock) ? 32 : 16) << FRACBITS, siz); + + V_DrawFixedPatch( + x*FRACUNIT, y*FRACUNIT, + siz, + 0, pat, + colormap + ); + drawborder: if (i != challengesmenu.hilix) continue; diff --git a/src/m_cond.c b/src/m_cond.c index c05a6a169..4bf644e23 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -37,15 +37,11 @@ conditionset_t conditionSets[MAXCONDITIONSETS]; // Emblem locations emblem_t emblemlocations[MAXEMBLEMS]; -// Extra emblems -extraemblem_t extraemblems[MAXEXTRAEMBLEMS]; - // Unlockables unlockable_t unlockables[MAXUNLOCKABLES]; -// Number of emblems and extra emblems +// Number of emblems INT32 numemblems = 0; -INT32 numextraemblems = 0; // Create a new gamedata_t, for start-up void M_NewGameDataStruct(void) @@ -442,8 +438,6 @@ void M_ClearSecrets(void) for (i = 0; i < MAXEMBLEMS; ++i) gamedata->collected[i] = false; - for (i = 0; i < MAXEXTRAEMBLEMS; ++i) - gamedata->extraCollected[i] = false; for (i = 0; i < MAXUNLOCKABLES; ++i) gamedata->unlocked[i] = false; for (i = 0; i < MAXCONDITIONSETS; ++i) @@ -511,8 +505,8 @@ UINT8 M_CheckCondition(condition_t *cn) return (M_GotEnoughEmblems(cn->requirement)); case UC_EMBLEM: // Requires emblem x to be obtained return gamedata->collected[cn->requirement-1]; - case UC_EXTRAEMBLEM: // Requires extra emblem x to be obtained - return gamedata->extraCollected[cn->requirement-1]; + case UC_UNLOCKABLE: // Requires unlockable x to be obtained + return gamedata->unlocked[cn->requirement-1]; case UC_CONDITIONSET: // requires condition set x to already be achieved return M_Achieved(cn->requirement-1); } @@ -574,32 +568,11 @@ boolean M_UpdateUnlockablesAndExtraEmblems(boolean loud) // Just in case they aren't to sync M_CheckLevelEmblems(); M_CompletionEmblems(); - } - // Go through extra emblems - for (i = 0; i < numextraemblems; ++i) - { - if (gamedata->extraCollected[i] || !extraemblems[i].conditionset) - { - continue; - } - - if ((gamedata->extraCollected[i] = M_Achieved(extraemblems[i].conditionset - 1)) == false) - { - continue; - } - - if (loud) - { - strcat(cechoText, va("Got \"%s\" medal!\n", extraemblems[i].name)); - } - ++cechoLines; - } - - // Fun part: if any of those unlocked we need to go through the - // unlock conditions AGAIN just in case an emblem reward was reached - if (cechoLines) + // Fun part: if any of those unlocked we need to go through the + // unlock conditions AGAIN just in case an emblem reward was reached M_CheckUnlockConditions(); + } // Go through unlockables for (i = 0; i < MAXUNLOCKABLES; ++i) @@ -643,6 +616,8 @@ UINT8 M_GetNextAchievedUnlock(void) { UINT8 i; + M_CheckUnlockConditions(); + // Go through unlockables for (i = 0; i < MAXUNLOCKABLES; ++i) { @@ -801,13 +776,17 @@ INT32 M_CountEmblems(void) INT32 found = 0, i; for (i = 0; i < numemblems; ++i) { - if (gamedata->collected[i]) - found++; + if (!gamedata->collected[i]) + continue; + found++; } - for (i = 0; i < numextraemblems; ++i) + for (i = 0; i < MAXUNLOCKABLES; ++i) { - if (gamedata->extraCollected[i]) - found++; + if (unlockables[i].type != SECRET_EXTRAEMBLEM) + continue; + if (!gamedata->unlocked[i]) + continue; + found++; } return found; } @@ -823,13 +802,21 @@ UINT8 M_GotEnoughEmblems(INT32 number) INT32 i, gottenemblems = 0; for (i = 0; i < numemblems; ++i) { - if (gamedata->collected[i]) - if (++gottenemblems >= number) return true; + if (!gamedata->collected[i]) + continue; + if (++gottenemblems < number) + continue; + return true; } - for (i = 0; i < numextraemblems; ++i) + for (i = 0; i < MAXUNLOCKABLES; ++i) { - if (gamedata->extraCollected[i]) - if (++gottenemblems >= number) return true; + if (unlockables[i].type != SECRET_EXTRAEMBLEM) + continue; + if (!gamedata->unlocked[i]) + continue; + if (++gottenemblems < number) + continue; + return true; } return false; } @@ -938,29 +925,3 @@ const char *M_GetEmblemPatch(emblem_t *em, boolean big) return pnamebuf; } - -skincolornum_t M_GetExtraEmblemColor(extraemblem_t *em) -{ - if (!em || em->color >= numskincolors) - return SKINCOLOR_NONE; - return em->color; -} - -const char *M_GetExtraEmblemPatch(extraemblem_t *em, boolean big) -{ - static char pnamebuf[7]; - - if (!big) - strcpy(pnamebuf, "GOTITn"); - else - strcpy(pnamebuf, "EMBMn0"); - - I_Assert(em->sprite >= 'A' && em->sprite <= 'Z'); - - if (!big) - pnamebuf[5] = em->sprite; - else - pnamebuf[4] = em->sprite; - - return pnamebuf; -} diff --git a/src/m_cond.h b/src/m_cond.h index 1332cd45f..f839155fa 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -32,7 +32,7 @@ typedef enum UC_TRIGGER, // TRIGGER [trigger number] UC_TOTALEMBLEMS, // TOTALEMBLEMS [number of emblems] UC_EMBLEM, // EMBLEM [emblem number] - UC_EXTRAEMBLEM, // EXTRAEMBLEM [extra emblem number] + UC_UNLOCKABLE, // UNLOCKABLE [unlockable number] UC_CONDITIONSET, // CONDITIONSET [condition set number] } conditiontype_t; @@ -78,22 +78,13 @@ typedef struct char *stringVar; ///< String version char hint[110]; ///< Hint for emblem hints menu } emblem_t; -typedef struct -{ - char name[20]; ///< Name of the goal (used in the "emblem awarded" cecho) - char description[40]; ///< Description of goal (used in statistics) - UINT8 conditionset; ///< Condition set that awards this emblem. - UINT8 showconditionset; ///< Condition set that shows this emblem. - UINT8 sprite; ///< emblem sprite to use, 0 - 25 - UINT16 color; ///< skincolor to use -} extraemblem_t; // Unlockable information typedef struct { char name[64]; - char objective[64]; char *icon; + UINT16 color; UINT8 conditionset; INT16 type; INT16 variable; @@ -105,8 +96,9 @@ typedef struct #define SECRET_HEADER 1 // Does nothing on its own, just serves as a header for the menu #define SECRET_SKIN 2 // Allow this character to be selected -#define SECRET_WARP 3 // Selectable warp -#define SECRET_LEVELSELECT 4 // Selectable level select +#define SECRET_WARP 3 // Selectable warp (todo Followers) + +#define SECRET_EXTRAEMBLEM 4 // Extra Emblems (formerly extraemblem_t) #define SECRET_TIMEATTACK 5 // Enables Time Attack on the main menu #define SECRET_BREAKTHECAPSULES 6 // Enables Break the Capsules on the main menu @@ -126,8 +118,7 @@ typedef struct // you seriously need to get a life. #define MAXCONDITIONSETS UINT8_MAX #define MAXEMBLEMS 512 -#define MAXEXTRAEMBLEMS 16 -#define MAXUNLOCKABLES (MAXCONDITIONSETS-MAXEXTRAEMBLEMS) +#define MAXUNLOCKABLES MAXCONDITIONSETS #define CHALLENGEGRIDHEIGHT 5 @@ -144,9 +135,6 @@ typedef struct // EMBLEMS COLLECTED boolean collected[MAXEMBLEMS]; - // EXTRA EMBLEMS COLLECTED - boolean extraCollected[MAXEXTRAEMBLEMS]; - // UNLOCKABLES UNLOCKED boolean unlocked[MAXUNLOCKABLES]; @@ -166,11 +154,9 @@ extern gamedata_t *gamedata; extern conditionset_t conditionSets[MAXCONDITIONSETS]; extern emblem_t emblemlocations[MAXEMBLEMS]; -extern extraemblem_t extraemblems[MAXEXTRAEMBLEMS]; extern unlockable_t unlockables[MAXUNLOCKABLES]; extern INT32 numemblems; -extern INT32 numextraemblems; extern UINT32 unlocktriggers; @@ -207,8 +193,6 @@ INT32 M_CountEmblems(void); emblem_t *M_GetLevelEmblems(INT32 mapnum); skincolornum_t M_GetEmblemColor(emblem_t *em); const char *M_GetEmblemPatch(emblem_t *em, boolean big); -skincolornum_t M_GetExtraEmblemColor(extraemblem_t *em); -const char *M_GetExtraEmblemPatch(extraemblem_t *em, boolean big); // If you're looking to compare stats for unlocks or what not, use these // They stop checking upon reaching the target number so they