AUDIO.CPP 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. /*
  2. ** Command & Conquer(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /* $Header: F:\projects\c&c\vcs\code\audio.cpv 2.17 16 Oct 1995 16:50:20 JOE_BOSTIC $ */
  19. /***********************************************************************************************
  20. *** 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 ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : Command & Conquer *
  24. * *
  25. * File Name : AUDIO.CPP *
  26. * *
  27. * Programmer : Joe L. Bostic *
  28. * *
  29. * Start Date : September 10, 1993 *
  30. * *
  31. * Last Update : May 4, 1995 [JLB] *
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * Is_Speaking -- Checks to see if the eva voice is still playing. *
  36. * Sound_Effect -- General purpose sound player. *
  37. * Sound_Effect -- Plays a sound effect in the tactical map. *
  38. * Speak -- Computer speaks to the player. *
  39. * Speak_AI -- Handles starting the EVA voices. *
  40. * Stop_Speaking -- Forces the EVA voice to stop talking. *
  41. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  42. #include "function.h"
  43. /***************************************************************************
  44. ** Controls what special effects may occur on the sound effect.
  45. */
  46. typedef enum {
  47. IN_NOVAR, // No variation or alterations allowed.
  48. IN_JUV, // Juvenile sound effect alternate option.
  49. IN_VAR, // Infantry variance response modification.
  50. } ContextType;
  51. static struct {
  52. char const *Name; // Digitized voice file name.
  53. int Priority; // Playback priority of this sample.
  54. ContextType Where; // In what game context does this sample exist.
  55. } SoundEffectName[VOC_COUNT] = {
  56. /*
  57. ** Special voices (typically associated with the commando).
  58. */
  59. {"BOMBIT1", 20, IN_NOVAR}, // VOC_RAMBO_PRESENT "I've got a present for ya"
  60. {"CMON1", 20, IN_NOVAR}, // VOC_RAMBO_CMON "c'mon"
  61. {"GOTIT1", 20, IN_NOVAR}, // VOC_RAMBO_UGOTIT "you got it" *
  62. {"KEEPEM1", 20, IN_NOVAR}, // VOC_RAMBO_COMIN "keep 'em commin'"
  63. {"LAUGH1", 20, IN_NOVAR}, // VOC_RAMBO_LAUGH "hahaha"
  64. {"LEFTY1", 20, IN_NOVAR}, // VOC_RAMBO_LEFTY "that was left handed" *
  65. {"NOPRBLM1", 20, IN_NOVAR}, // VOC_RAMBO_NOPROB "no problem"
  66. // {"OHSH1", 20, IN_NOVAR}, // VOC_RAMBO_OHSH "oh shiiiiii...."
  67. {"ONIT1", 20, IN_NOVAR}, // VOC_RAMBO_ONIT "I'm on it"
  68. {"RAMYELL1", 20, IN_NOVAR}, // VOC_RAMBO_YELL "ahhhhhhh"
  69. {"ROKROLL1", 20, IN_NOVAR}, // VOC_RAMBO_ROCK "time to rock and roll"
  70. {"TUFFGUY1", 20, IN_NOVAR}, // VOC_RAMBO_TUFF "real tuff guy" *
  71. {"YEAH1", 20, IN_NOVAR}, // VOC_RAMBO_YEA "yea" *
  72. {"YES1", 20, IN_NOVAR}, // VOC_RAMBO_YES "yes" *
  73. {"YO1", 20, IN_NOVAR}, // VOC_RAMBO_YO "yo"
  74. /*
  75. ** Civilian voices (technicians too).
  76. */
  77. {"GIRLOKAY", 20, IN_NOVAR}, // VOC_GIRL_OKAY
  78. {"GIRLYEAH", 20, IN_NOVAR}, // VOC_GIRL_YEAH
  79. {"GUYOKAY1", 20, IN_NOVAR}, // VOC_GUY_OKAY
  80. {"GUYYEAH1", 20, IN_NOVAR}, // VOC_GUY_YEAH
  81. /*
  82. ** Infantry and vehicle responses.
  83. */
  84. {"2DANGR1", 10, IN_VAR}, // VOC_2DANGER "negative, too dangerous"
  85. {"ACKNO", 10, IN_VAR}, // VOC_ACKNOWL "acknowledged"
  86. {"AFFIRM1", 10, IN_VAR}, // VOC_AFFIRM "affirmative"
  87. {"AWAIT1", 10, IN_VAR}, // VOC_AWAIT1 "awaiting orders"
  88. // {"BACKUP", 10, IN_VAR}, // VOC_BACKUP "send backup"
  89. // {"HELP", 10, IN_VAR}, // VOC_HELP "send help"
  90. {"MOVOUT1", 10, IN_VAR}, // VOC_MOVEOUT "movin' out"
  91. {"NEGATV1", 10, IN_VAR}, // VOC_NEGATIVE "negative"
  92. {"NOPROB", 10, IN_VAR}, // VOC_NO_PROB "not a problem"
  93. {"READY", 10, IN_VAR}, // VOC_READY "ready and waiting"
  94. {"REPORT1", 10, IN_VAR}, // VOC_REPORT "reporting"
  95. {"RITWAWA", 10, IN_VAR}, // VOC_RIGHT_AWAY "right away sir"
  96. {"ROGER", 10, IN_VAR}, // VOC_ROGER "roger"
  97. // {"SIR1", 10, IN_VAR}, // VOC_SIR1 "sir?"
  98. // {"SQUAD1", 10, IN_VAR}, // VOC_SQUAD1 "squad reporting"
  99. // {"TARGET1", 10, IN_VAR}, // VOC_PRACTICE "target practice"
  100. {"UGOTIT", 10, IN_VAR}, // VOC_UGOTIT "you got it"
  101. {"UNIT1", 10, IN_VAR}, // VOC_UNIT1 "unit reporting"
  102. {"VEHIC1", 10, IN_VAR}, // VOC_VEHIC1 "vehicle reporting"
  103. {"YESSIR1", 10, IN_VAR}, // VOC_YESSIR "yes sir"
  104. /*
  105. ** Sound effects that have a juvenile counterpart.
  106. */
  107. {"BAZOOK1", 1, IN_JUV}, // VOC_BAZOOKA Gunfire
  108. {"BLEEP2", 1, IN_JUV}, // VOC_BLEEP Clean metal bing
  109. {"BOMB1", 1, IN_JUV}, // VOC_BOMB1 Crunchy parachute bomb type explosion
  110. {"BUTTON", 1, IN_JUV}, // VOC_BUTTON Dungeon Master button click
  111. {"COMCNTR1", 10, IN_JUV}, // VOC_RADAR_ON Elecronic static with beeps
  112. {"CONSTRU2", 10, IN_JUV}, // VOC_CONSTRUCTION construction sounds
  113. {"CRUMBLE", 1, IN_JUV}, // VOC_CRUMBLE muffled crumble sound
  114. {"FLAMER2", 4, IN_JUV}, // VOC_FLAMER1 flame thrower
  115. {"GUN18", 4, IN_JUV}, // VOC_RIFLE rifle shot
  116. {"GUN19", 4, IN_JUV}, // VOC_M60 machine gun burst -- 6 rounds
  117. {"GUN20", 4, IN_JUV}, // VOC_GUN20 bat hitting heavy metal door
  118. {"GUN5", 4, IN_JUV}, // VOC_M60A medium machine gun burst
  119. {"GUN8", 4, IN_JUV}, // VOC_MINI mini gun burst
  120. {"GUNCLIP1", 1, IN_JUV}, // VOC_RELOAD gun clip reload
  121. {"HVYDOOR1", 5, IN_JUV}, // VOC_SLAM metal plates slamming together
  122. {"HVYGUN10", 1, IN_JUV}, // VOC_HVYGUN10 loud sharp cannon
  123. {"ION1", 1, IN_JUV}, // VOC_ION_CANNON partical beam
  124. {"MGUN11", 1, IN_JUV}, // VOC_MGUN11 alternate tripple burst
  125. {"MGUN2", 1, IN_JUV}, // VOC_MGUN2 M-16 tripple burst
  126. {"NUKEMISL", 1, IN_JUV}, // VOC_NUKE_FIRE long missile sound
  127. {"NUKEXPLO", 1, IN_JUV}, // VOC_NUKE_EXPLODE long but not loud explosion
  128. {"OBELRAY1", 1, IN_JUV}, // VOC_LASER humming star wars laser beam
  129. {"OBELPOWR", 1, IN_JUV}, // VOC_LASER_POWER warming-up sound of star wars laser beam
  130. {"POWRDN1", 1, IN_JUV}, // VOC_RADAR_OFF doom door slide
  131. {"RAMGUN2", 1, IN_JUV}, // VOC_SNIPER silenced rifle fire
  132. {"ROCKET1", 1, IN_JUV}, // VOC_ROCKET1 rocket launch variation #1
  133. {"ROCKET2", 1, IN_JUV}, // VOC_ROCKET2 rocket launch variation #2
  134. {"SAMMOTR2", 1, IN_JUV}, // VOC_MOTOR dentists drill
  135. {"SCOLD2", 1, IN_JUV}, // VOC_SCOLD cannot perform action feedback tone
  136. {"SIDBAR1C", 1, IN_JUV}, // VOC_SIDEBAR_OPEN xylophone clink
  137. {"SIDBAR2C", 1, IN_JUV}, // VOC_SIDEBAR_CLOSE xylophone clink
  138. {"SQUISH2", 1, IN_JUV}, // VOC_SQUISH2 crushing infantry
  139. {"TNKFIRE2", 1, IN_JUV}, // VOC_TANK1 sharp tank fire with recoil
  140. {"TNKFIRE3", 1, IN_JUV}, // VOC_TANK2 sharp tank fire
  141. {"TNKFIRE4", 1, IN_JUV}, // VOC_TANK3 sharp tank fire
  142. {"TNKFIRE6", 1, IN_JUV}, // VOC_TANK4 big gun tank fire
  143. {"TONE15", 0, IN_JUV}, // VOC_UP credits counting up
  144. {"TONE16", 0, IN_JUV}, // VOC_DOWN credits counting down
  145. {"TONE2", 1, IN_JUV}, // VOC_TARGET target sound
  146. {"TONE5", 10, IN_JUV}, // VOC_SONAR sonar echo
  147. {"TOSS", 1, IN_JUV}, // VOC_TOSS air swish
  148. {"TRANS1", 1, IN_JUV}, // VOC_CLOAK stealth tank
  149. {"TREEBRN1", 1, IN_JUV}, // VOC_BURN burning crackle
  150. {"TURRFIR5", 1, IN_JUV}, // VOC_TURRET muffled gunfire
  151. {"XPLOBIG4", 5, IN_JUV}, // VOC_XPLOBIG4 very long muffled explosion
  152. {"XPLOBIG6", 5, IN_JUV}, // VOC_XPLOBIG6 very long muffled explosion
  153. {"XPLOBIG7", 5, IN_JUV}, // VOC_XPLOBIG7 very long muffled explosion
  154. {"XPLODE", 1, IN_JUV}, // VOC_XPLODE long soft muffled explosion
  155. {"XPLOS", 4, IN_JUV}, // VOC_XPLOS short crunchy explosion
  156. {"XPLOSML2", 5, IN_JUV}, // VOC_XPLOSML2 muffled mechanical explosion
  157. /*
  158. ** Generic sound effects (no variations).
  159. */
  160. {"NUYELL1", 10, IN_NOVAR}, // VOC_SCREAM1 short infantry scream
  161. {"NUYELL3", 10, IN_NOVAR}, // VOC_SCREAM3 short infantry scream
  162. {"NUYELL4", 10, IN_NOVAR}, // VOC_SCREAM4 short infantry scream
  163. {"NUYELL5", 10, IN_NOVAR}, // VOC_SCREAM5 short infantry scream
  164. {"NUYELL6", 10, IN_NOVAR}, // VOC_SCREAM6 short infantry scream
  165. {"NUYELL7", 10, IN_NOVAR}, // VOC_SCREAM7 short infantry scream
  166. {"NUYELL10", 10, IN_NOVAR}, // VOC_SCREAM10 short infantry scream
  167. {"NUYELL11", 10, IN_NOVAR}, // VOC_SCREAM11 short infantry scream
  168. {"NUYELL12", 10, IN_NOVAR}, // VOC_SCREAM12 short infantry scream
  169. {"YELL1", 1, IN_NOVAR}, // VOC_YELL1 long infantry scream
  170. {"MYES1", 10, IN_NOVAR}, // VOC_YES "Yes?"
  171. {"MCOMND1", 10, IN_NOVAR}, // VOC_COMMANDER "Commander?"
  172. {"MHELLO1", 10, IN_NOVAR}, // VOC_HELLO "Hello?"
  173. {"MHMMM1", 10, IN_NOVAR}, // VOC_HMMM "Hmmm?"
  174. // {"MHASTE1", 10, IN_NOVAR}, // VOC_PROCEED1 "I will proceed, post haste."
  175. // {"MONCE1", 10, IN_NOVAR}, // VOC_PROCEED2 "I will proceed, at once."
  176. // {"MIMMD1", 10, IN_NOVAR}, // VOC_PROCEED3 "I will proceed, immediately."
  177. // {"MPLAN1", 10, IN_NOVAR}, // VOC_EXCELLENT1 "That is an excellent plan."
  178. // {"MPLAN2", 10, IN_NOVAR}, // VOC_EXCELLENT2 "Yes, that is an excellent plan."
  179. {"MPLAN3", 10, IN_NOVAR}, // VOC_EXCELLENT3 "A wonderful plan."
  180. // {"MACTION1", 10, IN_NOVAR}, // VOC_EXCELLENT4 "Astounding plan of action commander."
  181. // {"MREMARK1", 10, IN_NOVAR}, // VOC_EXCELLENT5 "Remarkable contrivance."
  182. {"MCOURSE1", 10, IN_NOVAR}, // VOC_OF_COURSE "Of course."
  183. {"MYESYES1", 10, IN_NOVAR}, // VOC_YESYES "Yes yes yes."
  184. {"MTIBER1", 10, IN_NOVAR}, // VOC_QUIP1 "Mind the Tiberium."
  185. // {"MMG1", 10, IN_NOVAR}, // VOC_QUIP2 "A most remarkable Metasequoia Glyptostroboides."
  186. {"MTHANKS1", 10, IN_NOVAR}, // VOC_THANKS "Thank you."
  187. {"CASHTURN", 1, IN_NOVAR}, // VOC_CASHTURN Sound of money being piled up.
  188. {"BLEEP2", 10, IN_NOVAR}, // VOC_BLEEPY3 Clean computer bleep sound.
  189. {"DINOMOUT", 10, IN_NOVAR}, // VOC_DINOMOUT Movin' out in dino-speak.
  190. {"DINOYES", 10, IN_NOVAR}, // VOC_DINOYES Yes Sir in dino-speak.
  191. {"DINOATK1", 10, IN_NOVAR}, // VOC_DINOATK1 Dino attack sound.
  192. {"DINODIE1", 10, IN_NOVAR}, // VOC_DINODIE1 Dino die sound.
  193. };
  194. /***********************************************************************************************
  195. * Sound_Effect -- Plays a sound effect in the tactical map. *
  196. * *
  197. * This routine is used when a sound effect occurs in the game world. It handles fading *
  198. * the sound according to distance. *
  199. * *
  200. * INPUT: voc -- The sound effect number to play. *
  201. * *
  202. * coord -- The world location that the sound originates from. *
  203. * *
  204. * OUTPUT: none *
  205. * *
  206. * WARNINGS: none *
  207. * *
  208. * HISTORY: *
  209. * 11/12/1994 JLB : Created. *
  210. * 01/05/1995 JLB : Reduces sound more dramatically when off screen. *
  211. *=============================================================================================*/
  212. void Sound_Effect(VocType voc, COORDINATE coord, int variation)
  213. {
  214. unsigned distance;
  215. CELL cell_pos;
  216. int pan_value;
  217. if (!Options.Volume || voc == VOC_NONE || !SoundOn || SampleType == SAMPLE_NONE) {
  218. return;
  219. }
  220. if (coord) {
  221. cell_pos = Coord_Cell(coord);
  222. }
  223. distance = 0xFF;
  224. pan_value = 0;
  225. if (coord && !Map.In_View(cell_pos)) {
  226. distance = Map.Cell_Distance(cell_pos, Coord_Cell(Map.TacticalCoord));
  227. distance = (unsigned int)MIN((int)distance, (int)MAP_CELL_W);
  228. distance = Cardinal_To_Fixed(MAP_CELL_W, distance);
  229. distance = MIN(distance, 0xFFu);
  230. distance ^= 0xFF;
  231. distance /= 2;
  232. distance = MAX(distance, 25);
  233. pan_value = Cell_X(cell_pos);
  234. pan_value -= Coord_XCell(Map.TacticalCoord) + (Lepton_To_Cell(Map.TacLeptonWidth) >> 1);
  235. if (ABS(pan_value) > Lepton_To_Cell(Map.TacLeptonWidth >> 1)) {
  236. pan_value *= 0x8000;
  237. pan_value /= (MAP_CELL_W >> 2);
  238. pan_value = Bound(pan_value, -0x7FFF, 0x7FFF);
  239. // pan_value = MAX((int)pan_value, (int)-0x7FFF);
  240. // pan_value = MIN((int)pan_value, 0x7FFF);
  241. } else {
  242. pan_value = 0;
  243. }
  244. }
  245. Sound_Effect(voc, (VolType)Fixed_To_Cardinal(distance, Options.Volume), variation, pan_value);
  246. }
  247. /***********************************************************************************************
  248. * Sound_Effect -- General purpose sound player. *
  249. * *
  250. * This is used for general purpose sound effects. These are sounds that occur outside *
  251. * of the game world. They do not have a corresponding game world location as their source. *
  252. * *
  253. * INPUT: voc -- The sound effect number to play. *
  254. * *
  255. * volume -- The volume to assign to this sound effect. *
  256. * *
  257. * OUTPUT: Returns with the sound handle (-1 if no sound was played). *
  258. * *
  259. * WARNINGS: none *
  260. * *
  261. * HISTORY: *
  262. * 11/12/1994 JLB : Created. *
  263. * 11/12/1994 JLB : Handles cache logic. *
  264. * 05/04/1995 JLB : Variation adjustments. *
  265. *=============================================================================================*/
  266. int Sound_Effect(VocType voc, VolType volume, int variation, signed short pan_value)
  267. {
  268. char name[_MAX_FNAME+_MAX_EXT]; // Working filename of sound effect.
  269. if (!Options.Volume || voc == VOC_NONE || !SoundOn || SampleType == SAMPLE_NONE) {
  270. return(-1);
  271. }
  272. /*
  273. ** Fetch a pointer to the sound effect data. Modify the sound as appropriate and desired.
  274. */
  275. char const * ext = ".AUD";
  276. if (Special.IsJuvenile && SoundEffectName[voc].Where == IN_JUV) {
  277. ext = ".JUV";
  278. } else {
  279. if (SoundEffectName[voc].Where == IN_VAR) {
  280. /*
  281. ** For infantry, use a variation on the response. For vehicles, always
  282. ** use the vehicle response table.
  283. */
  284. if (variation < 0) {
  285. if (ABS(variation) % 2) {
  286. ext = ".V00";
  287. } else {
  288. ext = ".V02";
  289. }
  290. } else {
  291. if (variation % 2) {
  292. ext = ".V01";
  293. } else {
  294. ext = ".V03";
  295. }
  296. }
  297. }
  298. }
  299. _makepath(name, NULL, NULL, SoundEffectName[voc].Name, ext);
  300. void const * ptr = MixFileClass::Retrieve(name);
  301. /*
  302. ** If the sound data pointer is not null, then presume that it is valid.
  303. */
  304. if (ptr) {
  305. return(Play_Sample(ptr, Fixed_To_Cardinal(SoundEffectName[voc].Priority, (int)volume), (int)volume, pan_value));
  306. }
  307. return(-1);
  308. }
  309. /*
  310. ** This elaborates all the EVA speech voices.
  311. */
  312. char const * Speech[VOX_COUNT] = {
  313. "ACCOM1", // mission accomplished
  314. "FAIL1", // your mission has failed
  315. "BLDG1", // unable to comply, building in progress
  316. "CONSTRU1", // construction complete
  317. "UNITREDY", // unit ready
  318. "NEWOPT1", // new construction options
  319. "DEPLOY1", // cannot deploy here
  320. "GDIDEAD1", // GDI unit destroyed
  321. "NODDEAD1", // Nod unit destroyed
  322. "CIVDEAD1", // civilian killed
  323. // "EVAYES1", // affirmative
  324. // "EVANO1", // negative
  325. // "UPUNIT1", // upgrade complete, new unit available
  326. // "UPSTRUC1", // upgrade complete, new structure available
  327. "NOCASH1", // insufficient funds
  328. "BATLCON1", // battle control terminated
  329. "REINFOR1", // reinforcements have arrived
  330. "CANCEL1", // canceled
  331. "BLDGING1", // building
  332. "LOPOWER1", // low power
  333. "NOPOWER1", // insufficient power
  334. "MOCASH1", // need more funds
  335. "BASEATK1", // our base is under attack
  336. "INCOME1", // incoming missile
  337. "ENEMYA", // enemy planes approaching
  338. "NUKE1", // nuclear warhead approaching
  339. // "RADOK1", // radiation levels are acceptable
  340. // "RADFATL1", // radiation levels are fatal
  341. "NOBUILD1", // unable to build more
  342. "PRIBLDG1", // primary building selected
  343. // "REPDONE1", // repairs completed
  344. "NODCAPT1", // Nod building captured
  345. "GDICAPT1", // GDI building captured
  346. // "SOLD1", // structure sold
  347. "IONCHRG1", // ion cannon charging
  348. "IONREDY1", // ion cannon ready
  349. "NUKAVAIL", // nuclear weapon available
  350. "NUKLNCH1", // nuclear weapon launched
  351. "UNITLOST", // unit lost
  352. "STRCLOST", // structure lost
  353. "NEEDHARV", // need harvester
  354. "SELECT1", // select target
  355. "AIRREDY1", // airstrike ready
  356. "NOREDY1", // not ready
  357. "TRANSSEE", // Nod transport sighted
  358. "TRANLOAD", // Nod transport loaded
  359. "ENMYAPP1", // enemy approaching
  360. "SILOS1", // silos needed
  361. "ONHOLD1", // on hold
  362. "REPAIR1", // repairing
  363. "ESTRUCX", // enemy structure destroyed
  364. "GSTRUC1", // GDI structure destroyed
  365. "NSTRUC1", // NOD structure destroyed
  366. "ENMYUNIT", // Enemy unit destroyed
  367. // "GUKILL1", // gold unit destroyed
  368. // "GSTRUD1", // gold structure destroyed
  369. // "GONLINE1", // gold player online
  370. // "GLEFT1", // gold player has departed
  371. // "GOLDKILT", // gold player destroyed
  372. // "GOLDWIN", // gold player is victorious
  373. // "RUKILL1", // red unit destroyed
  374. // "RSTRUD1", // red structure destroyed
  375. // "RONLINE1", // red player online
  376. // "RLEFT1", // red player has departed
  377. // "REDKILT", // red player destroyed
  378. // "REDWIN", // red player is victorious
  379. // "GYUKILL1", // grey unit destroyed
  380. // "GYSTRUD1", // grey structure destroyed
  381. // "GYONLINE", // grey player online
  382. // "GYLEFT1", // grey player has departed
  383. // "GREYKILT", // grey player destroyed
  384. // "GREYWIN", // grey player is victorious
  385. // "OUKILL1", // orange unit destroyed
  386. // "OSTRUD1", // orange structure destroyed
  387. // "OONLINE1", // orange player online
  388. // "OLEFT1", // orange player has departed
  389. // "ORANKILT", // orange player destroyed
  390. // "ORANWIN", // orange player is victorious
  391. // "GNUKILL1", // green unit destroyed
  392. // "GNSTRUD1", // green structure destroyed
  393. // "GNONLINE", // green player online
  394. // "GNLEFT1", // green player has departed
  395. // "GRENKILT", // green player destroyed
  396. // "GRENWIN", // green player is victorious
  397. // "BUKILL1", // blue unit destroyed
  398. // "BSTRUD1", // blue structure destroyed
  399. // "BONLINE1", // blue player online
  400. // "BLEFT1", // blue player has departed
  401. // "BLUEKILT", // blue player destroyed
  402. // "BLUEWIN" // blue player is victorious
  403. };
  404. static VoxType CurrentVoice = VOX_NONE;
  405. /***********************************************************************************************
  406. * Speak -- Computer speaks to the player. *
  407. * *
  408. * This routine is used to have the game computer (EVA) speak to the player. *
  409. * *
  410. * INPUT: voice -- The voice number to speak (see defines.h). *
  411. * *
  412. * OUTPUT: Returns with the handle of the playing speech (-1 if no voice started). *
  413. * *
  414. * WARNINGS: none *
  415. * *
  416. * HISTORY: *
  417. * 11/12/1994 JLB : Created. *
  418. *=============================================================================================*/
  419. void Speak(VoxType voice)
  420. {
  421. if (Options.Volume && SampleType != 0 && voice != VOX_NONE && voice != SpeakQueue && voice != CurrentVoice && SpeakQueue == VOX_NONE) {
  422. SpeakQueue = voice;
  423. }
  424. }
  425. /***********************************************************************************************
  426. * Speak_AI -- Handles starting the EVA voices. *
  427. * *
  428. * This starts the EVA voice talking as well. If there is any speech request in the queue, *
  429. * it will be started when the current voice is finished. Call this routine as often as *
  430. * possible (once per game tick is sufficient). *
  431. * *
  432. * INPUT: none *
  433. * *
  434. * OUTPUT: none *
  435. * *
  436. * WARNINGS: none *
  437. * *
  438. * HISTORY: *
  439. * 12/27/1994 JLB : Created. *
  440. *=============================================================================================*/
  441. void Speak_AI(void)
  442. {
  443. static VoxType _last = VOX_NONE;
  444. if (SampleType == 0) return;
  445. if (!Is_Sample_Playing(SpeechBuffer)) {
  446. CurrentVoice = VOX_NONE;
  447. if (SpeakQueue != VOX_NONE) {
  448. if (SpeakQueue != _last) {
  449. char name[_MAX_FNAME+_MAX_EXT];
  450. _makepath(name, NULL, NULL, Speech[SpeakQueue], ".AUD");
  451. if (CCFileClass(name).Read(SpeechBuffer, SPEECH_BUFFER_SIZE)) {
  452. Play_Sample(SpeechBuffer, 254, Options.Volume);
  453. }
  454. _last = SpeakQueue;
  455. } else {
  456. Play_Sample(SpeechBuffer, 254, Options.Volume);
  457. }
  458. SpeakQueue = VOX_NONE;
  459. }
  460. }
  461. }
  462. /***********************************************************************************************
  463. * Stop_Speaking -- Forces the EVA voice to stop talking. *
  464. * *
  465. * Use this routine to immediately stop the EVA voice from speaking. It also clears out *
  466. * the pending voice queue. *
  467. * *
  468. * INPUT: none *
  469. * *
  470. * OUTPUT: none *
  471. * *
  472. * WARNINGS: none *
  473. * *
  474. * HISTORY: *
  475. * 12/27/1994 JLB : Created. *
  476. *=============================================================================================*/
  477. void Stop_Speaking(void)
  478. {
  479. SpeakQueue = VOX_NONE;
  480. if (SampleType != 0) {
  481. Stop_Sample_Playing(SpeechBuffer);
  482. }
  483. }
  484. /***********************************************************************************************
  485. * Is_Speaking -- Checks to see if the eva voice is still playing. *
  486. * *
  487. * Call this routine when the EVA voice being played needs to be checked. A typical use *
  488. * of this would be when some action needs to be delayed until the voice has finished -- *
  489. * say the end of the game. *
  490. * *
  491. * INPUT: none *
  492. * *
  493. * OUTPUT: bool; Is the EVA voice still playing? *
  494. * *
  495. * WARNINGS: none *
  496. * *
  497. * HISTORY: *
  498. * 03/12/1995 JLB : Created. *
  499. *=============================================================================================*/
  500. bool Is_Speaking(void)
  501. {
  502. Speak_AI();
  503. if (SampleType != 0 && (SpeakQueue != VOX_NONE || Is_Sample_Playing(SpeechBuffer))) {
  504. return(true);
  505. }
  506. return(false);
  507. }