THEME.CPP 36 KB

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