CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

THEME.CPP (37242B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header: /CounterStrike/THEME.CPP 3     3/11/97 4:03p Joe_bostic $ */
     17 /***********************************************************************************************
     18  ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Command & Conquer                                            *
     22  *                                                                                             *
     23  *                    File Name : THEME.CPP                                                    *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : August 14, 1994                                              *
     28  *                                                                                             *
     29  *                  Last Update : August 12, 1996 [JLB]                                        *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   ThemeClass::AI -- Process the theme engine and restart songs.                             *
     34  *   ThemeClass::Base_Name -- Fetches the base filename for the theme specified.               *
     35  *   ThemeClass::From_Name -- Determines theme number from specified name.                     *
     36  *   ThemeClass::Full_Name -- Retrieves the full score name.                                   *
     37  *   ThemeClass::Is_Allowed -- Checks to see if the specified theme is legal.                  *
     38  *   ThemeClass::Next_Song -- Calculates the next song number to play.                         *
     39  *   ThemeClass::Play_Song -- Starts the specified song play NOW.                              *
     40  *   ThemeClass::Queue_Song -- Queues the song to the play queue.                              *
     41  *   ThemeClass::Scan -- Scans all scores for availability.                                    *
     42  *   ThemeClass::Set_Theme_Data -- Set the theme data for scenario and owner.                  *
     43  *   ThemeClass::Still_Playing -- Determines if music is still playing.                        *
     44  *   ThemeClass::Stop -- Stops the current theme from playing.                                 *
     45  *   ThemeClass::ThemeClass -- Default constructor for the theme manager class.                *
     46  *   ThemeClass::Theme_File_Name -- Constructs a filename for the specified theme.             *
     47  *   ThemeClass::Track_Length -- Calculates the length of the song (in seconds).               *
     48  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     49 
     50 #include	"function.h"
     51 #include	"theme.h"
     52 
     53 #ifndef WIN32
     54 extern short StreamLowImpact;
     55 #endif  //WIN32
     56 
     57 /*
     58 **	These are the actual filename list for the theme sample files.
     59 */
     60 ThemeClass::ThemeControl ThemeClass::_themes[THEME_COUNT] = {
     61 	{"BIGF226M",	TXT_THEME_BIGF,		0,		307,	true,		false,	true,	HOUSEF_ALLIES},
     62 	{"CRUS226M",	TXT_THEME_CRUS,		0,		222,	true,		false,	true,	HOUSEF_SOVIET},
     63 	{"FAC1226M",	TXT_THEME_FAC1,		0,		271,	true,		false,	true,	HOUSEF_ALLIES},
     64 	{"FAC2226M",	TXT_THEME_FAC2,		0,		328,	true,		false,	true,	HOUSEF_SOVIET},
     65 	{"HELL226M",	TXT_THEME_HELL,		0,		375,	true,		false,	true,	HOUSEF_ALLIES},
     66 	{"RUN1226M",	TXT_THEME_RUN1,		0,		312,	true,		false,	true,	HOUSEF_SOVIET},
     67 	{"SMSH226M",	TXT_THEME_SMSH,		0,		272,	true,		false,	true,	HOUSEF_ALLIES},
     68 	{"TREN226M",	TXT_THEME_TREN,		0,		312,	true,		false,	true,	HOUSEF_SOVIET},
     69 	{"WORK226M",	TXT_THEME_WORK,		0,		277,	true,		false,	true,	HOUSEF_ALLIES},
     70 	{"AWAIT",		TXT_THEME_AWAIT,		0,		259,	true,		false,	true,	HOUSEF_ALLIES},
     71 	{"DENSE_R",		TXT_THEME_DENSE_R,	0,		294,	true,		false,	true,	HOUSEF_ALLIES},
     72 	{"FOGGER1A",	TXT_THEME_FOGGER1A,	0,		297,	true,		false,	true,	HOUSEF_ALLIES},
     73 	{"MUD1A",		TXT_THEME_MUD1A,		0,		280,	true,		false,	true,	HOUSEF_ALLIES},
     74 	{"RADIO2",		TXT_THEME_RADIO2,		0,		237,	true,		false,	true,	HOUSEF_ALLIES},
     75 	{"ROLLOUT",		TXT_THEME_ROLLOUT,	0,		227,	true,		false,	true,	HOUSEF_ALLIES},
     76 	{"SNAKE",		TXT_THEME_SNAKE,		0,		277,	true,		false,	true,	HOUSEF_ALLIES},
     77 	{"TERMINAT",	TXT_THEME_TERMINAT,	0,		310,	true,		false,	true,	HOUSEF_ALLIES},
     78 	{"TWIN",			TXT_THEME_TWIN,		0,		229,	true,		false,	true,	HOUSEF_ALLIES},
     79 	{"VECTOR1A",	TXT_THEME_VECTOR1A,	0,		252,	true,		false,	true,	HOUSEF_ALLIES},
     80   	{"MAP",			TXT_THEME_MAP,			0,		63,	false,	true,		true,	HOUSEF_NONE},
     81 	{"SCORE",		TXT_THEME_SCORE,		0,		106,	false,	true,		true,	HOUSEF_NONE},
     82 	{"INTRO",		TXT_THEME_INTRO,		0,		205,	false,	true,		true,	HOUSEF_NONE},
     83 	{"CREDITS",		TXT_THEME_CREDITS,	0,		163,	false,	true,		true,	HOUSEF_NONE},
     84 
     85 	{"2ND_HAND",	TXT_THEME_2ND_HAND,	0,		268,	true,		false,	true,	HOUSEF_ALLIES|HOUSEF_SPAIN},
     86 	{"ARAZOID",		TXT_THEME_ARAZOID,	0,		257,	true,		false,	true,	HOUSEF_SOVIET|HOUSEF_SPAIN},
     87 	{"BACKSTAB",	TXT_THEME_BACKSTAB,	0,		278,	true,		false,	true,	HOUSEF_ALLIES|HOUSEF_SPAIN},
     88 	{"CHAOS2",		TXT_THEME_CHAOS2,		0,		250,	true,		false,	true,	HOUSEF_SOVIET|HOUSEF_SPAIN},
     89 	{"SHUT_IT",		TXT_THEME_SHUT_IT,	0,		261,	true,		false,	true,	HOUSEF_ALLIES|HOUSEF_SPAIN},
     90 	{"TWINMIX1",	TXT_THEME_TWINMIX1,	0,		222,	true,		false,	true,	HOUSEF_SOVIET|HOUSEF_SPAIN},
     91 	{"UNDER3",		TXT_THEME_UNDER3,		0,		246,	true,		false,	true,	HOUSEF_ALLIES|HOUSEF_SPAIN},
     92 	{"VR2",			TXT_THEME_VR2,			0,		255,	true,		false,	true,	HOUSEF_SOVIET|HOUSEF_SPAIN},
     93 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
     94 	{"BOG",			TXT_THEME_BOG,			0,		212,	true,		false,	true,	HOUSEF_ALLIES|HOUSEF_SPAIN},
     95 	{"FLOAT_V2",	TXT_THEME_FLOAT_V2,	0,		274,	true,		false,	true,	HOUSEF_SOVIET|HOUSEF_SPAIN},
     96 	{"GLOOM",		TXT_THEME_GLOOM,		0,		236,	true,		false,	true,	HOUSEF_ALLIES|HOUSEF_SPAIN},
     97 	{"GRNDWIRE",	TXT_THEME_GRNDWIRE,	0,		228,	true,		false,	true,	HOUSEF_SOVIET|HOUSEF_SPAIN},
     98 	{"RPT",			TXT_THEME_RPT,			0,		275,	true,		false,	true,	HOUSEF_ALLIES|HOUSEF_SPAIN},
     99 	{"SEARCH",		TXT_THEME_SEARCH,		0,		276,	true,		false,	true,	HOUSEF_SOVIET|HOUSEF_SPAIN},
    100 	{"TRACTION",	TXT_THEME_TRACTION,	0,		237,	true,		false,	true,	HOUSEF_ALLIES|HOUSEF_SPAIN},
    101 	{"WASTELND",	TXT_THEME_WASTELND,	0,		242,	true,		false,	true,	HOUSEF_SOVIET|HOUSEF_SPAIN},
    102 #endif
    103 };
    104 
    105 
    106 /***********************************************************************************************
    107  * ThemeClass::Base_Name -- Fetches the base filename for the theme specified.                 *
    108  *                                                                                             *
    109  *    This routine is used to retrieve a pointer to the base filename for the theme            *
    110  *    specified.                                                                               *
    111  *                                                                                             *
    112  * INPUT:   theme -- The theme number to convert into a base filename.                         *
    113  *                                                                                             *
    114  * OUTPUT:  Returns with a pointer to the base filename for the theme specified. If the        *
    115  *          theme number is invalid, then a pointer to "No Theme" is returned instead.         *
    116  *                                                                                             *
    117  * WARNINGS:   none                                                                            *
    118  *                                                                                             *
    119  * HISTORY:                                                                                    *
    120  *   05/29/1995 JLB : Created.                                                                 *
    121  *=============================================================================================*/
    122 char const * ThemeClass::Base_Name(ThemeType theme) const
    123 {
    124 	if (theme != THEME_NONE) {
    125 		return(_themes[theme].Name);
    126 	}
    127 	return("No theme");
    128 }
    129 
    130 
    131 /***********************************************************************************************
    132  * ThemeClass::ThemeClass -- Default constructor for the theme manager class.                  *
    133  *                                                                                             *
    134  *    This is the default constructor for the theme class object.                              *
    135  *                                                                                             *
    136  * INPUT:   none                                                                               *
    137  *                                                                                             *
    138  * OUTPUT:  none                                                                               *
    139  *                                                                                             *
    140  * WARNINGS:   none                                                                            *
    141  *                                                                                             *
    142  * HISTORY:                                                                                    *
    143  *   01/16/1995 JLB : Created.                                                                 *
    144  *=============================================================================================*/
    145 ThemeClass::ThemeClass(void) :
    146 	Current(-1),
    147 	Score(THEME_NONE),
    148 	Pending(THEME_NONE)
    149 {
    150 }
    151 
    152 
    153 /***********************************************************************************************
    154  * ThemeClass::Full_Name -- Retrieves the full score name.                                     *
    155  *                                                                                             *
    156  *    This routine will fetch and return with a pointer to the full name of the theme          *
    157  *    specified.                                                                               *
    158  *                                                                                             *
    159  * INPUT:   theme -- The theme to fetch the full name for.                                     *
    160  *                                                                                             *
    161  * OUTPUT:  Returns with a pointer to the full name for this score. This pointer may point to  *
    162  *          EMS memory.                                                                        *
    163  *                                                                                             *
    164  * WARNINGS:   none                                                                            *
    165  *                                                                                             *
    166  * HISTORY:                                                                                    *
    167  *   01/16/1995 JLB : Created.                                                                 *
    168  *=============================================================================================*/
    169 char const * ThemeClass::Full_Name(ThemeType theme) const
    170 {
    171 	if (theme >= THEME_FIRST && theme < THEME_COUNT) {
    172 		return(Text_String(_themes[theme].Fullname));
    173 	}
    174 	return(NULL);
    175 }
    176 
    177 
    178 /***********************************************************************************************
    179  * ThemeClass::AI -- Process the theme engine and restart songs.                               *
    180  *                                                                                             *
    181  *    This is a maintenance function that will restart an appropriate theme if the current one *
    182  *    has finished. This routine should be called frequently.                                  *
    183  *                                                                                             *
    184  * INPUT:   none                                                                               *
    185  *                                                                                             *
    186  * OUTPUT:  none                                                                               *
    187  *                                                                                             *
    188  * WARNINGS:   none                                                                            *
    189  *                                                                                             *
    190  * HISTORY:                                                                                    *
    191  *   09/08/1994 JLB : Created.                                                                 *
    192  *   01/23/1995 JLB : Picks new song just as it is about to play it.                           *
    193  *=============================================================================================*/
    194 void ThemeClass::AI(void)
    195 {
    196 	if (SampleType && !Debug_Quiet) {
    197 		if (ScoresPresent && Options.ScoreVolume != 0 && !Still_Playing() && Pending != THEME_NONE) {
    198 
    199 			/*
    200 			**	If the pending song needs to be picked, then pick it now.
    201 			*/
    202 			if (Pending == THEME_PICK_ANOTHER) {
    203 				Pending = Next_Song(Score);
    204 			}
    205 
    206 			/*
    207 			**	Start the song playing and then flag it so that a new song will
    208 			**	be picked when this one ends.
    209 			*/
    210 			Play_Song(Pending);
    211 			Pending = THEME_PICK_ANOTHER;
    212 		}
    213 		Sound_Callback();
    214 	}
    215 }
    216 
    217 
    218 /***********************************************************************************************
    219  * ThemeClass::Next_Song -- Calculates the next song number to play.                           *
    220  *                                                                                             *
    221  *    use this routine to figure out what song number to play. It examines the option settings *
    222  *    for repeat and shuffle so that it can return the correct value.                          *
    223  *                                                                                             *
    224  * INPUT:   theme -- The origin (last) index. The new value is related to this for all but     *
    225  *                   the shuffling method of play.                                             *
    226  *                                                                                             *
    227  * OUTPUT:  Returns with the song number for the next song to play.                            *
    228  *                                                                                             *
    229  * WARNINGS:   none                                                                            *
    230  *                                                                                             *
    231  * HISTORY:                                                                                    *
    232  *   01/16/1995 JLB : Created.                                                                 *
    233  *   01/19/1995 JLB : Will not play the same song twice when in shuffle mode.                  *
    234  *=============================================================================================*/
    235 ThemeType ThemeClass::Next_Song(ThemeType theme) const
    236 {
    237 	if (theme == THEME_NONE || theme == THEME_PICK_ANOTHER || (theme != THEME_QUIET && !_themes[theme].Repeat && !Options.IsScoreRepeat)) {
    238 		if (Options.IsScoreShuffle) {
    239 
    240 			/*
    241 			**	Shuffle the theme, but never pick the same theme that was just
    242 			**	playing.
    243 			*/
    244 			ThemeType newtheme;
    245 			do {
    246 				newtheme = Sim_Random_Pick(THEME_FIRST, THEME_LAST);
    247 			} while (newtheme == theme || !Is_Allowed(newtheme));
    248 			theme = newtheme;
    249 
    250 		} else {
    251 
    252 			/*
    253 			**	Sequential score playing.
    254 			*/
    255 			do {
    256 				theme++;
    257 				if (theme > THEME_LAST) {
    258 					theme = THEME_FIRST;
    259 				}
    260 			} while (!Is_Allowed(theme));
    261 		}
    262 	}
    263 	return(theme);
    264 }
    265 
    266 
    267 /***********************************************************************************************
    268  * ThemeClass::Queue_Song -- Queues the song to the play queue.                                *
    269  *                                                                                             *
    270  *    This routine will cause the current song to fade and the specified song to start. This   *
    271  *    is the normal and friendly method of changing the current song.                          *
    272  *                                                                                             *
    273  * INPUT:   theme -- The song to start playing. If -1 is passed in, then just the current song.*
    274  *                   is faded.                                                                 *
    275  *                                                                                             *
    276  * OUTPUT:  none                                                                               *
    277  *                                                                                             *
    278  * WARNINGS:   none                                                                            *
    279  *                                                                                             *
    280  * HISTORY:                                                                                    *
    281  *   01/16/1995 JLB : Created.                                                                 *
    282  *=============================================================================================*/
    283 void ThemeClass::Queue_Song(ThemeType theme)
    284 {
    285 	/*
    286 	**	If there is no score file present, then abort.
    287 	*/
    288 	if (!ScoresPresent) return;
    289 
    290 	/*
    291 	**	If there is no sound driver or sounds have been specifically
    292 	**	turned off, then abort.
    293 	*/
    294 	if (SampleType == 0 || Debug_Quiet) return;
    295 
    296 	/*
    297 	**	If the current score volumne is set to silent, then there is no need to play the
    298 	**	specified theme.
    299 	*/
    300 	if (Options.ScoreVolume == 0) return;
    301 
    302 	/*
    303 	**	If the pending theme is available to be set and the specified theme is valid, then
    304 	**	set the queued theme accordingly.
    305 	*/
    306 	if (Pending == THEME_NONE || Pending == THEME_PICK_ANOTHER || theme == THEME_NONE || theme == THEME_QUIET) {
    307 		Pending = theme;
    308 		if (Still_Playing()) {
    309 			Fade_Sample(Current, THEME_DELAY);
    310 		}
    311 	}
    312 }
    313 
    314 
    315 /***********************************************************************************************
    316  * ThemeClass::Play_Song -- Starts the specified song play NOW.                                *
    317  *                                                                                             *
    318  *    This routine is used to start the specified theme playing right now. If there is already *
    319  *    a theme playing, it is cut short so that this one may start.                             *
    320  *                                                                                             *
    321  * INPUT:   theme -- The theme number to start playing.                                        *
    322  *                                                                                             *
    323  * OUTPUT:  Returns with the sample play handle.                                               *
    324  *                                                                                             *
    325  * WARNINGS:   This cuts off any current song in a abrupt manner. Only use this routine when   *
    326  *             necessary.                                                                      *
    327  *                                                                                             *
    328  * HISTORY:                                                                                    *
    329  *   01/16/1995 JLB : Created.                                                                 *
    330  *=============================================================================================*/
    331 int ThemeClass::Play_Song(ThemeType theme)
    332 {
    333 	if (ScoresPresent && SampleType && !Debug_Quiet && Options.ScoreVolume != 0) {
    334 		Stop();
    335 		Score = theme;
    336 		if (theme != THEME_NONE && theme != THEME_QUIET) {
    337 			//PG StreamLowImpact = true;
    338 			Current = File_Stream_Sample_Vol(Theme_File_Name(theme), 0xFF, true);
    339 			//PG StreamLowImpact = false;
    340 		}
    341 	}
    342 	return(Current);
    343 }
    344 
    345 
    346 /***********************************************************************************************
    347  * ThemeClass::Theme_File_Name -- Constructs a filename for the specified theme.               *
    348  *                                                                                             *
    349  *    This routine will construct (into a static buffer) a filename that matches the theme     *
    350  *    number specified. This constructed filename is returned as a pointer. The filename will  *
    351  *    remain valid until the next call to this routine.                                        *
    352  *                                                                                             *
    353  * INPUT:   theme -- The theme number to convert to a filename.                                *
    354  *                                                                                             *
    355  * OUTPUT:  Returns with a pointer to the constructed filename for the specified theme number. *
    356  *                                                                                             *
    357  * WARNINGS:   none                                                                            *
    358  *                                                                                             *
    359  * HISTORY:                                                                                    *
    360  *   01/16/1995 JLB : Created.                                                                 *
    361  *   05/09/1995 JLB : Theme variation support.                                                 *
    362  *=============================================================================================*/
    363 char const * ThemeClass::Theme_File_Name(ThemeType theme)
    364 {
    365 	static char name[_MAX_FNAME+_MAX_EXT];
    366 
    367 	if (theme >= THEME_FIRST && theme < THEME_COUNT) {
    368 		_makepath(name, NULL, NULL, _themes[theme].Name, ".AUD");
    369 		return((char const *)(&name[0]));
    370 	}
    371 
    372 	return("");
    373 }
    374 
    375 
    376 /***********************************************************************************************
    377  * ThemeClass::Track_Length -- Calculates the length of the song (in seconds).                 *
    378  *                                                                                             *
    379  *    Use this routine to calculate the length of the song. The length is determined by        *
    380  *    reading the header of the song and dividing the sample rate into the sample length.      *
    381  *                                                                                             *
    382  * INPUT:   theme -- The song number to examine to find its length.                            *
    383  *                                                                                             *
    384  * OUTPUT:  Returns with the length of the specified theme. This length is in the form of      *
    385  *          seconds.                                                                           *
    386  *                                                                                             *
    387  * WARNINGS:   This routine goes to disk to fetch this information. Don't call frivolously.    *
    388  *                                                                                             *
    389  * HISTORY:                                                                                    *
    390  *   01/16/1995 JLB : Created.                                                                 *
    391  *=============================================================================================*/
    392 int ThemeClass::Track_Length(ThemeType theme) const
    393 {
    394 	if ((unsigned)theme < THEME_COUNT) {
    395 		return(_themes[theme].Duration);
    396 	}
    397 	return(0);
    398 }
    399 
    400 
    401 /***********************************************************************************************
    402  * ThemeClass::Stop -- Stops the current theme from playing.                                   *
    403  *                                                                                             *
    404  *    Use this routine to stop the current theme. After this routine is called, no more music  *
    405  *    will play until the Start() function is called.                                          *
    406  *                                                                                             *
    407  * INPUT:   none                                                                               *
    408  *                                                                                             *
    409  * OUTPUT:  none                                                                               *
    410  *                                                                                             *
    411  * WARNINGS:   none                                                                            *
    412  *                                                                                             *
    413  * HISTORY:                                                                                    *
    414  *   09/08/1994 JLB : Created.                                                                 *
    415  *=============================================================================================*/
    416 void ThemeClass::Stop(void)
    417 {
    418 	if (ScoresPresent && SampleType && !Debug_Quiet && Current != -1) {
    419 		Stop_Sample(Current);
    420 		Current = -1;
    421 		Score = THEME_NONE;
    422 		Pending = THEME_NONE;
    423 	}
    424 }
    425 
    426 
    427 void ThemeClass::Suspend(void)
    428 {
    429 	if (ScoresPresent && SampleType && !Debug_Quiet && Current != -1) {
    430 		Stop_Sample(Current);
    431 		Current = -1;
    432 		Pending = Score;
    433 		Score = THEME_NONE;
    434 	}
    435 }
    436 
    437 
    438 /***********************************************************************************************
    439  * ThemeClass::Still_Playing -- Determines if music is still playing.                          *
    440  *                                                                                             *
    441  *    Use this routine to determine if music is still playing.                                 *
    442  *                                                                                             *
    443  * INPUT:   none                                                                               *
    444  *                                                                                             *
    445  * OUTPUT:  bool; Is the music still audible?                                                  *
    446  *                                                                                             *
    447  * WARNINGS:   none                                                                            *
    448  *                                                                                             *
    449  * HISTORY:                                                                                    *
    450  *   12/20/1994 JLB : Created.                                                                 *
    451  *=============================================================================================*/
    452 int ThemeClass::Still_Playing(void) const
    453 {
    454 	if (ScoresPresent && SampleType && Current != -1 && !Debug_Quiet) {
    455 		return(Sample_Status(Current));
    456 	}
    457 	return(false);
    458 }
    459 
    460 
    461 /***********************************************************************************************
    462  * ThemeClass::Is_Allowed -- Checks to see if the specified theme is legal.                    *
    463  *                                                                                             *
    464  *    Use this routine to determine if a theme is allowed to be played. A theme is not allowed *
    465  *    if the scenario is too early for that score, or the score only is allowed in special     *
    466  *    cases.                                                                                   *
    467  *                                                                                             *
    468  * INPUT:   index -- The score the check to see if it is allowed to play.                      *
    469  *                                                                                             *
    470  * OUTPUT:  Is the specified score allowed to play in the normal score playlist?               *
    471  *                                                                                             *
    472  * WARNINGS:   none                                                                            *
    473  *                                                                                             *
    474  * HISTORY:                                                                                    *
    475  *   05/09/1995 JLB : Created.                                                                 *
    476  *   07/04/1996 JLB : Handles alternate playlist checking.                                     *
    477  *=============================================================================================*/
    478 bool ThemeClass::Is_Allowed(ThemeType index) const
    479 {
    480 	if ((unsigned)index >= THEME_COUNT) return(true);
    481 
    482 	/*
    483 	**	If the theme is not present, then it certainly isn't allowed.
    484 	*/
    485 	if (!_themes[index].Available) return(false);
    486 
    487 	/*
    488 	**	Only normal themes (playable during battle) are considered allowed.
    489 	*/
    490 	if (!_themes[index].Normal) return(false);
    491 
    492 	/*
    493 	**	If the theme is not allowed to be played by the player's house, then don't allow
    494 	**	it. If the player's house hasn't yet been determined, then presume this test
    495 	**	passes.
    496 	*/
    497 	if (PlayerPtr != NULL && ((1 << PlayerPtr->ActLike) & _themes[index].Owner) == 0) return(false);
    498 
    499 	/*
    500 	**	If the scenario doesn't allow this theme yet, then return the failure flag. The
    501 	**	scenario check only makes sense for solo play.
    502 	*/
    503 	if (Session.Type == GAME_NORMAL && Scen.Scenario < _themes[index].Scenario) return(false);
    504 
    505 	/*
    506 	**	Since all tests passed, return with the "is allowed" flag.
    507 	*/
    508 	return(true);
    509 }
    510 
    511 
    512 /***********************************************************************************************
    513  * ThemeClass::From_Name -- Determines theme number from specified name.                       *
    514  *                                                                                             *
    515  *    Use this routine to convert a name (either the base filename of the theme, or a partial  *
    516  *    substring of the full name) into the matching ThemeType value. Typical use of this is    *
    517  *    when parsing the INI file for theme control values.                                      *
    518  *                                                                                             *
    519  * INPUT:   name  -- Pointer to base filename of theme or a partial substring of the full      *
    520  *                   theme name.                                                               *
    521  *                                                                                             *
    522  * OUTPUT:  Returns with the matching theme number. If no match could be found, then           *
    523  *          THEME_NONE is returned.                                                            *
    524  *                                                                                             *
    525  * WARNINGS:   If a filename is specified the comparison is case insensitive. When scanning    *
    526  *             the full theme name, the comparison is case sensitive.                          *
    527  *                                                                                             *
    528  * HISTORY:                                                                                    *
    529  *   05/29/1995 JLB : Created.                                                                 *
    530  *=============================================================================================*/
    531 ThemeType ThemeClass::From_Name(char const * name) const
    532 {
    533 	if (name && strlen(name) > 0) {
    534 		/*
    535 		**	First search for an exact name match with the filename
    536 		**	of the theme. This is guaranteed to be unique.
    537 		*/
    538 		for (ThemeType theme = THEME_FIRST; theme < THEME_COUNT; theme++) {
    539 			if (stricmp(_themes[theme].Name, name) == 0) {
    540 				return(theme);
    541 			}
    542 		}
    543 
    544 		/*
    545 		**	If the filename scan failed to find a match, then scan for
    546 		**	a substring within the full name of the score. This might
    547 		**	yield a match, but is not guaranteed to be unique.
    548 		*/
    549 		for (ThemeType theme = THEME_FIRST; theme < THEME_COUNT; theme++) {
    550 			if (strstr(Text_String(_themes[theme].Fullname), name) != NULL) {
    551 				return(theme);
    552 			}
    553 		}
    554 	}
    555 
    556 	return(THEME_NONE);
    557 }
    558 
    559 
    560 /***********************************************************************************************
    561  * ThemeClass::Scan -- Scans all scores for availability.                                      *
    562  *                                                                                             *
    563  *    This routine should be called whenever a score mixfile is registered. It will scan       *
    564  *    to see if any score is unavailable. If this is the case, then the score will be so       *
    565  *    flagged in order not to appear on the play list. This condition is likely to occur       *
    566  *    when expansion mission disks contain a different score mix than the release version.     *
    567  *                                                                                             *
    568  * INPUT:   none                                                                               *
    569  *                                                                                             *
    570  * OUTPUT:  none                                                                               *
    571  *                                                                                             *
    572  * WARNINGS:   none                                                                            *
    573  *                                                                                             *
    574  * HISTORY:                                                                                    *
    575  *   01/04/1996 JLB : Created.                                                                 *
    576  *=============================================================================================*/
    577 void ThemeClass::Scan(void)
    578 {
    579 	for (ThemeType theme = THEME_FIRST; theme < THEME_COUNT; theme++) {
    580 		_themes[theme].Available = CCFileClass(Theme_File_Name(theme)).Is_Available();
    581 	}
    582 }
    583 
    584 
    585 
    586 /***********************************************************************************************
    587  * ThemeClass::Set_Theme_Data -- Set the theme data for scenario and owner.                    *
    588  *                                                                                             *
    589  *    This is an override function used to set a particular theme's initial scenario and       *
    590  *    owner values. Typically, the rules control file will be the source of calling this       *
    591  *    routine.                                                                                 *
    592  *                                                                                             *
    593  * INPUT:   theme    -- The theme to set these override values for.                            *
    594  *                                                                                             *
    595  *          scenario -- The first scenario when this theme becomes available on the play list. *
    596  *                                                                                             *
    597  *          owners   -- A bitfield representing the owners allowed to play this song.          *
    598  *                                                                                             *
    599  * OUTPUT:  none                                                                               *
    600  *                                                                                             *
    601  * WARNINGS:   none                                                                            *
    602  *                                                                                             *
    603  * HISTORY:                                                                                    *
    604  *   08/12/1996 JLB : Created.                                                                 *
    605  *=============================================================================================*/
    606 void ThemeClass::Set_Theme_Data(ThemeType theme, int scenario, int owners)
    607 {
    608 	if (theme != THEME_NONE) {
    609 		_themes[theme].Normal = true;
    610 		_themes[theme].Scenario = scenario;
    611 		_themes[theme].Owner = owners;
    612 	}
    613 }
    614