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