From 3e476568eaa649c1fa77295f8762618fbf8baa94 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 28 Mar 2023 13:50:05 +0100 Subject: [PATCH] mapheader_t: AssociatedMusic property Enables things like the Goin' Down!? segment in Speed Highway to be connected directly to access to that map. --- src/deh_soc.c | 26 +++++++++++++++++++++++-- src/doomstat.h | 4 +++- src/p_setup.c | 9 ++++----- src/s_sound.c | 52 ++++++++++++++++++++++++++++++-------------------- 4 files changed, 62 insertions(+), 29 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index f286a7ce1..f2c5315a6 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1187,8 +1187,30 @@ void readlevelheader(MYFILE *f, char * name) mapheaderinfo[num]->musname_size = j; } } - else if (fastcmp(word, "MUSICSLOT")) - deh_warning("Level header %d: MusicSlot parameter is deprecated and will be removed.\nUse \"Music\" instead.", num); + else if (fastcmp(word, "ASSOCIATEDMUSIC")) + { + if (fastcmp(word2, "NONE")) + { + mapheaderinfo[num]->associatedmus[0][0] = 0; // becomes empty string + mapheaderinfo[num]->associatedmus_size = 0; + } + else + { + UINT8 j = 0; // i was declared elsewhere + tmp = strtok(word2, ","); + do { + if (j >= MAXMUSNAMES) + break; + deh_strlcpy(mapheaderinfo[num]->associatedmus[j], tmp, + sizeof(mapheaderinfo[num]->associatedmus[j]), va("Level header %d: music", num)); + j++; + } while ((tmp = strtok(NULL,",")) != NULL); + + if (tmp != NULL) + deh_warning("Level header %d: additional associated music slots past %d discarded", num, MAXMUSNAMES); + mapheaderinfo[num]->associatedmus_size = j; + } + } else if (fastcmp(word, "MUSICTRACK")) mapheaderinfo[num]->mustrack = ((UINT16)i - 1); else if (fastcmp(word, "MUSICPOS")) diff --git a/src/doomstat.h b/src/doomstat.h index 2bf01f261..5a8f40814 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -445,9 +445,11 @@ struct mapheader_t // Music information char musname[MAXMUSNAMES][7]; ///< Music tracks to play. First dimension is the track number, second is the music string. "" for no music. + UINT8 musname_size; ///< Number of music tracks defined + char associatedmus[MAXMUSNAMES][7]; ///< Associated music tracks for sound test unlock. + UINT8 associatedmus_size; ///< Number of associated music tracks defined UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore. UINT32 muspos; ///< Music position to jump to. - UINT8 musname_size; ///< Number of music tracks defined // Sky information UINT8 weather; ///< See preciptype_t diff --git a/src/p_setup.c b/src/p_setup.c index 8da76e19e..9511bb542 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -382,8 +382,6 @@ void P_DeleteFlickies(INT16 i) */ static void P_ClearSingleMapHeaderInfo(INT16 num) { - UINT8 i = 0; - mapheaderinfo[num]->lvlttl[0] = '\0'; mapheaderinfo[num]->subttl[0] = '\0'; mapheaderinfo[num]->zonttl[0] = '\0'; @@ -391,11 +389,12 @@ static void P_ClearSingleMapHeaderInfo(INT16 num) mapheaderinfo[num]->typeoflevel = 0; mapheaderinfo[num]->gravity = DEFAULT_GRAVITY; mapheaderinfo[num]->keywords[0] = '\0'; - for (i = 0; i < MAXMUSNAMES; i++) - mapheaderinfo[num]->musname[i][0] = 0; + mapheaderinfo[num]->musname[0][0] = 0; + mapheaderinfo[num]->musname_size = 0; + mapheaderinfo[num]->associatedmus[0][0] = 0; + mapheaderinfo[num]->associatedmus_size = 0; mapheaderinfo[num]->mustrack = 0; mapheaderinfo[num]->muspos = 0; - mapheaderinfo[num]->musname_size = 0; mapheaderinfo[num]->weather = PRECIP_NONE; snprintf(mapheaderinfo[num]->skytexture, 5, "SKY1"); mapheaderinfo[num]->skytexture[4] = 0; diff --git a/src/s_sound.c b/src/s_sound.c index f0c18cbd4..8e6977eb7 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1362,33 +1362,43 @@ musicdef_t *musicdefstart = NULL; struct cursongcredit cursongcredit; // Currently displayed song credit info struct soundtest soundtest; // Sound Test (sound test) +static void S_InsertMusicAtSoundTestSequenceTail(const char *musname, UINT16 map, musicdef_t ***tail) +{ + UINT8 i = 0; + musicdef_t *def = S_FindMusicDef(musname, &i); + + if (def == NULL) + return; + + if (def->sequence.id == soundtest.sequence.id) + return; + + def->sequence.id = soundtest.sequence.id; + def->sequence.map = map; + + // So what we're doing here is to avoid iterating + // for every insertion, we dereference the pointer + // to get **tail from S_PopulateSoundTestSequence, + // then dereference that to get the musicdef_t *. + // We do it this way so that soundtest.sequence.next + // can be handled natively without special cases. + // I have officially lost my MIND. ~toast 270323 + *(*tail) = def; + *tail = &def->sequence.next; +} + static void S_InsertMapIntoSoundTestSequence(UINT16 map, musicdef_t ***tail) { - UINT8 i, j; - (void)tail; + UINT8 i; for (i = 0; i < mapheaderinfo[map]->musname_size; i++) { - musicdef_t *def = S_FindMusicDef(mapheaderinfo[map]->musname[i], &j); + S_InsertMusicAtSoundTestSequenceTail(mapheaderinfo[map]->musname[i], map, tail); + } - if (def == NULL) - continue; - - if (def->sequence.id == soundtest.sequence.id) - continue; - - def->sequence.id = soundtest.sequence.id; - def->sequence.map = map; - - // So what we're doing here is to avoid iterating - // for every insertion, we dereference the pointer - // to get **tail from S_PopulateSoundTestSequence, - // then dereference that to get the musicdef_t *. - // We do it this way so that soundtest.sequence.next - // can be handled natively without special cases. - // I have officially lost my MIND. ~toast 270323 - *(*tail) = def; - *tail = &def->sequence.next; + for (i = 0; i < mapheaderinfo[map]->associatedmus_size; i++) + { + S_InsertMusicAtSoundTestSequenceTail(mapheaderinfo[map]->associatedmus[i], map, tail); } }