mirror of
				https://github.com/KartKrewDev/RingRacers.git
				synced 2025-10-30 08:01:28 +00:00 
			
		
		
		
	As promised, Encore (alt)music
- `EncoreMusic` on mapheader
    - Supports up to 3 alt musics, as with every other type
- Do not vape/nightcoreify if provided
- To avoid complicating the Alt Music logic too much, uses "side B" of the same Prison Egg CD
    - That is to say, if there are 2 encore tracks and 3 normal tracks, the second Encore track will only play if you've gotten the CD associated with the second normal track
I haven't actually tested it *with* any Encore music, but I've triplechecked literally everywhere to make sure it didn't break standard play
			
			
This commit is contained in:
		
							parent
							
								
									0f6ddefe30
								
							
						
					
					
						commit
						6e46f97847
					
				
					 8 changed files with 112 additions and 18 deletions
				
			
		| 
						 | 
				
			
			@ -1242,6 +1242,30 @@ void readlevelheader(MYFILE *f, char * name)
 | 
			
		|||
					mapheaderinfo[num]->musname_size = j;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else if (fastcmp(word, "ENCOREMUSIC"))
 | 
			
		||||
			{
 | 
			
		||||
				if (fastcmp(word2, "NONE"))
 | 
			
		||||
				{
 | 
			
		||||
					mapheaderinfo[num]->encoremusname[0][0] = 0; // becomes empty string
 | 
			
		||||
					mapheaderinfo[num]->encoremusname_size = 0;
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					UINT8 j = 0; // i was declared elsewhere
 | 
			
		||||
					tmp = strtok(word2, ",");
 | 
			
		||||
					do {
 | 
			
		||||
						if (j >= MAXMUSNAMES)
 | 
			
		||||
							break;
 | 
			
		||||
						deh_strlcpy(mapheaderinfo[num]->encoremusname[j], tmp,
 | 
			
		||||
							sizeof(mapheaderinfo[num]->encoremusname[j]), va("Level header %d: encore music", num));
 | 
			
		||||
						j++;
 | 
			
		||||
					} while ((tmp = strtok(NULL,",")) != NULL);
 | 
			
		||||
 | 
			
		||||
					if (tmp != NULL)
 | 
			
		||||
						deh_warning("Level header %d: additional music slots past %d discarded", num, MAXMUSNAMES);
 | 
			
		||||
					mapheaderinfo[num]->encoremusname_size = j;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else if (fastcmp(word, "ASSOCIATEDMUSIC"))
 | 
			
		||||
			{
 | 
			
		||||
				if (fastcmp(word2, "NONE"))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -515,10 +515,12 @@ 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.
 | 
			
		||||
	char encoremusname[MAXMUSNAMES][7];	///< Music tracks to play in Encore. First dimension is the track number, second is the music string. "" for no music.
 | 
			
		||||
	UINT16 cache_muslock[MAXMUSNAMES-1];	///< Cached Alt Music IDs
 | 
			
		||||
	char associatedmus[MAXMUSNAMES][7];		///< Associated music tracks for sound test unlock.
 | 
			
		||||
	char positionmus[7];					///< Custom Position track. Doesn't play in Encore or other fun game-controlled contexts
 | 
			
		||||
	UINT8 musname_size;						///< Number of music tracks defined
 | 
			
		||||
	UINT8 encoremusname_size;				///< Number of Encore music tracks defined
 | 
			
		||||
	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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1247,7 +1247,14 @@ void K_ResetCeremony(void)
 | 
			
		|||
			mapmusrng = 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		while (mapmusrng >= std::max<UINT8>(1, mapheaderinfo[gamemap-1]->musname_size))
 | 
			
		||||
		UINT8 limit = (encoremode && mapheaderinfo[gamemap-1]->encoremusname_size)
 | 
			
		||||
			? mapheaderinfo[gamemap-1]->encoremusname_size
 | 
			
		||||
			: mapheaderinfo[gamemap-1]->musname_size;
 | 
			
		||||
 | 
			
		||||
		if (limit < 1)
 | 
			
		||||
			limit = 1;
 | 
			
		||||
 | 
			
		||||
		while (mapmusrng >= limit)
 | 
			
		||||
		{
 | 
			
		||||
			mapmusrng--;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2507,12 +2507,36 @@ static int mapheaderinfo_get(lua_State *L)
 | 
			
		|||
			lua_rawseti(L, -2, 1 + i);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else if (fastcmp(field,"encoremusname")) // we create a table here because it saves us from a userdata nightmare
 | 
			
		||||
	{
 | 
			
		||||
		UINT8 i;
 | 
			
		||||
		lua_createtable(L, header->encoremusname_size, 0);
 | 
			
		||||
		for (i = 0; i < header->encoremusname_size; i++)
 | 
			
		||||
		{
 | 
			
		||||
			lua_pushstring(L, header->encoremusname[i]);
 | 
			
		||||
			lua_rawseti(L, -2, 1 + i);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else if (fastcmp(field,"associatedmus")) // we create a table here because it saves us from a userdata nightmare
 | 
			
		||||
	{
 | 
			
		||||
		UINT8 i;
 | 
			
		||||
		lua_createtable(L, header->associatedmus_size, 0);
 | 
			
		||||
		for (i = 0; i < header->associatedmus_size; i++)
 | 
			
		||||
		{
 | 
			
		||||
			lua_pushstring(L, header->associatedmus[i]);
 | 
			
		||||
			lua_rawseti(L, -2, 1 + i);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else if (fastcmp(field,"mustrack"))
 | 
			
		||||
		lua_pushinteger(L, header->mustrack);
 | 
			
		||||
	else if (fastcmp(field,"muspos"))
 | 
			
		||||
		lua_pushinteger(L, header->muspos);
 | 
			
		||||
	else if (fastcmp(field,"musname_size"))
 | 
			
		||||
		lua_pushinteger(L, header->musname_size);
 | 
			
		||||
	else if (fastcmp(field,"encoremusname_size"))
 | 
			
		||||
		lua_pushinteger(L, header->encoremusname_size);
 | 
			
		||||
	else if (fastcmp(field,"associatedmus_size"))
 | 
			
		||||
		lua_pushinteger(L, header->associatedmus_size);
 | 
			
		||||
	else if (fastcmp(field,"weather"))
 | 
			
		||||
		lua_pushinteger(L, header->weather);
 | 
			
		||||
	else if (fastcmp(field,"skytexture"))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1077,7 +1077,8 @@ static void M_PrecacheLevelLocks(void)
 | 
			
		|||
				if (map < nummapheaders
 | 
			
		||||
					&& mapheaderinfo[map])
 | 
			
		||||
				{
 | 
			
		||||
					for (j = 1; j < mapheaderinfo[map]->musname_size; j++)
 | 
			
		||||
					UINT8 greatersize = max(mapheaderinfo[map]->musname_size, mapheaderinfo[map]->encoremusname_size);
 | 
			
		||||
					for (j = 1; j < greatersize; j++)
 | 
			
		||||
					{
 | 
			
		||||
						if (mapheaderinfo[map]->cache_muslock[j - 1] != MAXUNLOCKABLES)
 | 
			
		||||
						{
 | 
			
		||||
| 
						 | 
				
			
			@ -1143,7 +1144,7 @@ static void M_PrecacheLevelLocks(void)
 | 
			
		|||
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
					if (j == mapheaderinfo[map]->musname_size)
 | 
			
		||||
					if (j == greatersize)
 | 
			
		||||
						CONS_Alert(CONS_ERROR, "Unlockable %u: Too many SECRET_ALTMUSICs associated with Level %s\n", i+1, mapheaderinfo[map]->lumpname);
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -103,7 +103,12 @@ public:
 | 
			
		|||
				return (1.f/encoremul);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return encoremul;
 | 
			
		||||
			if (!nightcoreable
 | 
			
		||||
			|| mapheaderinfo[gamemap-1]->encoremusname_size == 0)
 | 
			
		||||
			{
 | 
			
		||||
				// We only vape if the level doesn't have alternate tracks.
 | 
			
		||||
				return encoremul;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return 1.f;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -446,6 +446,8 @@ static void P_ClearSingleMapHeaderInfo(INT16 num)
 | 
			
		|||
 | 
			
		||||
	mapheaderinfo[num]->musname[0][0] = 0;
 | 
			
		||||
	mapheaderinfo[num]->musname_size = 0;
 | 
			
		||||
	mapheaderinfo[num]->encoremusname[0][0] = 0;
 | 
			
		||||
	mapheaderinfo[num]->encoremusname_size = 0;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < MAXMUSNAMES-1; i++)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -8194,6 +8196,9 @@ void P_ResetLevelMusic(void)
 | 
			
		|||
	UINT8 idx = 0;
 | 
			
		||||
 | 
			
		||||
	mapheader_t* mapheader = mapheaderinfo[gamemap - 1];
 | 
			
		||||
	UINT8 truesize = (encoremode && mapheader->encoremusname_size)
 | 
			
		||||
		? mapheader->encoremusname_size
 | 
			
		||||
		: mapheader->musname_size;
 | 
			
		||||
 | 
			
		||||
	// To keep RNG in sync, we will always pull from RNG, even if unused
 | 
			
		||||
	UINT32 random = P_Random(PR_MUSICSELECT);
 | 
			
		||||
| 
						 | 
				
			
			@ -8201,20 +8206,20 @@ void P_ResetLevelMusic(void)
 | 
			
		|||
	if (demo.playback)
 | 
			
		||||
	{
 | 
			
		||||
		// mapmusrng has already been set by the demo; just make sure it's valid
 | 
			
		||||
		if (mapmusrng >= mapheader->musname_size)
 | 
			
		||||
		if (mapmusrng >= truesize)
 | 
			
		||||
		{
 | 
			
		||||
			mapmusrng = 0;
 | 
			
		||||
		}
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (mapheader->musname_size > 1)
 | 
			
		||||
	if (truesize > 1)
 | 
			
		||||
	{
 | 
			
		||||
		UINT8 tempmapmus[MAXMUSNAMES], tempmapmus_size = 1, i;
 | 
			
		||||
 | 
			
		||||
		tempmapmus[0] = 0;
 | 
			
		||||
 | 
			
		||||
		for (i = 1; i < mapheader->musname_size; i++)
 | 
			
		||||
		for (i = 1; i < truesize; i++)
 | 
			
		||||
		{
 | 
			
		||||
			if (mapheader->cache_muslock[i-1] < MAXUNLOCKABLES
 | 
			
		||||
			&& !M_CheckNetUnlockByID(mapheader->cache_muslock[i-1]))
 | 
			
		||||
| 
						 | 
				
			
			@ -8260,7 +8265,12 @@ void P_LoadLevelMusic(void)
 | 
			
		|||
	mapheader_t* mapheader = mapheaderinfo[gamemap-1];
 | 
			
		||||
	const char *music = mapheader->musname[0];
 | 
			
		||||
 | 
			
		||||
	if (mapmusrng < mapheader->musname_size)
 | 
			
		||||
	if (encoremode && mapheader->encoremusname_size
 | 
			
		||||
	&& mapmusrng < mapheader->encoremusname_size)
 | 
			
		||||
	{
 | 
			
		||||
		music = mapheader->encoremusname[mapmusrng];
 | 
			
		||||
	}
 | 
			
		||||
	else if (mapmusrng < mapheader->musname_size)
 | 
			
		||||
	{
 | 
			
		||||
		music = mapheader->musname[mapmusrng];
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1292,6 +1292,11 @@ static void S_InsertMapIntoSoundTestSequence(UINT16 map, musicdef_t ***tail)
 | 
			
		|||
	{
 | 
			
		||||
		S_InsertMusicAtSoundTestSequenceTail(mapheaderinfo[map]->associatedmus[i], map, ALTREF_REQUIRESBEATEN, tail);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < mapheaderinfo[map]->encoremusname_size; i++)
 | 
			
		||||
	{
 | 
			
		||||
		S_InsertMusicAtSoundTestSequenceTail(mapheaderinfo[map]->encoremusname[i], map, i+MAXMUSNAMES, tail);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void S_PopulateSoundTestSequence(void)
 | 
			
		||||
| 
						 | 
				
			
			@ -1435,17 +1440,33 @@ static boolean S_SoundTestDefLocked(musicdef_t *def)
 | 
			
		|||
	&& !(header->records.mapvisited & MV_VISITED))
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	// Associated music only when completed
 | 
			
		||||
	if ((def->sequence.altref == ALTREF_REQUIRESBEATEN)
 | 
			
		||||
	&& !(header->records.mapvisited & MV_BEATEN))
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	if (def->sequence.altref != 0 && def->sequence.altref < header->musname_size)
 | 
			
		||||
	if (def->sequence.altref != 0)
 | 
			
		||||
	{
 | 
			
		||||
		// Alt music requires unlocking the alt
 | 
			
		||||
		if ((header->cache_muslock[def->sequence.altref - 1] < MAXUNLOCKABLES)
 | 
			
		||||
		&& gamedata->unlocked[header->cache_muslock[def->sequence.altref - 1]] == false)
 | 
			
		||||
			return true;
 | 
			
		||||
		if ((def->sequence.altref == ALTREF_REQUIRESBEATEN))
 | 
			
		||||
		{
 | 
			
		||||
			// Associated music only when completed
 | 
			
		||||
			if (!(header->records.mapvisited & MV_BEATEN))
 | 
			
		||||
				return true;
 | 
			
		||||
		}
 | 
			
		||||
		else if (def->sequence.altref < MAXMUSNAMES)
 | 
			
		||||
		{
 | 
			
		||||
			// Alt music requires unlocking the alt
 | 
			
		||||
			if ((header->cache_muslock[def->sequence.altref - 1] < MAXUNLOCKABLES)
 | 
			
		||||
			&& gamedata->unlocked[header->cache_muslock[def->sequence.altref - 1]] == false)
 | 
			
		||||
				return true;
 | 
			
		||||
		}
 | 
			
		||||
		else if (def->sequence.altref < MAXMUSNAMES*2)
 | 
			
		||||
		{
 | 
			
		||||
			// Encore!
 | 
			
		||||
			if (M_SecretUnlocked(SECRET_ENCORE, true) == false)
 | 
			
		||||
				return true;
 | 
			
		||||
 | 
			
		||||
			// Side B of the same CD
 | 
			
		||||
			if (def->sequence.altref > MAXMUSNAMES
 | 
			
		||||
			&& (header->cache_muslock[def->sequence.altref - (1 + MAXMUSNAMES)] < MAXUNLOCKABLES)
 | 
			
		||||
			&& gamedata->unlocked[header->cache_muslock[def->sequence.altref - (1 + MAXMUSNAMES)]] == false)
 | 
			
		||||
				return true;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Finally, do a full-fat map check.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue