// // Copyright 2020 Electronic Arts Inc. // // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free // software: you can redistribute it and/or modify it under the terms of // the GNU General Public License as published by the Free Software Foundation, // either version 3 of the License, or (at your option) any later version. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed // in the hope that it will be useful, but with permitted additional restrictions // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT // distributed with this program. You should have received a copy of the // GNU General Public License along with permitted additional restrictions // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection /* $Header: /CounterStrike/AUDIO.CPP 1 3/03/97 10:24a Joe_bostic $ */ /*********************************************************************************************** *** 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 *** *********************************************************************************************** * * * Project Name : Command & Conquer * * * * File Name : AUDIO.CPP * * * * Programmer : Joe L. Bostic * * * * Start Date : September 10, 1993 * * * * Last Update : November 1, 1996 [JLB] * * * *---------------------------------------------------------------------------------------------* * Functions: * * Is_Speaking -- Checks to see if the eva voice is still playing. * * Sound_Effect -- General purpose sound player. * * Sound_Effect -- Plays a sound effect in the tactical map. * * Speak -- Computer speaks to the player. * * Speak_AI -- Handles starting the EVA voices. * * Speech_Name -- Fetches the name for the voice specified. * * Stop_Speaking -- Forces the EVA voice to stop talking. * * Voc_From_Name -- Fetch VocType from ASCII name specified. * * Voc_Name -- Fetches the name for the sound effect. * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "function.h" /* ** ** ** Win32lib stubs ** ** ** */ SFX_Type SoundType; Sample_Type SampleType; int File_Stream_Sample(char const *filename, BOOL real_time_start) { return 1; }; int File_Stream_Sample_Vol(char const *filename, int volume, BOOL real_time_start) { return 1; }; void __cdecl Sound_Callback(void) {}; void __cdecl far maintenance_callback(void) {}; void *Load_Sample(char const *filename) { return NULL; }; long Load_Sample_Into_Buffer(char const *filename, void *buffer, long size) { return 0; } long Sample_Read(int fh, void *buffer, long size) { return 0; }; void Free_Sample(void const *sample) {}; BOOL Audio_Init(HWND window, int bits_per_sample, BOOL stereo, int rate, int reverse_channels) { return 0; }; void Sound_End(void) {}; void Stop_Sample(int handle) {}; BOOL Sample_Status(int handle) { return 0; }; BOOL Is_Sample_Playing(void const * sample) { return 0; }; void Stop_Sample_Playing(void const * sample) {}; int Play_Sample(void const *sample, int priority, int volume, signed short panloc) { return 1; }; int Play_Sample_Handle(void const *sample, int priority, int volume, signed short panloc, int id) { return 1; }; int Set_Sound_Vol(int volume) { return 0; }; int Set_Score_Vol(int volume) { return 0; }; void Fade_Sample(int handle, int ticks) {}; int Get_Free_Sample_Handle(int priority) { return 1; }; int Get_Digi_Handle(void) { return 1; } long Sample_Length(void const *sample) { return 0; }; void Restore_Sound_Buffers(void) {}; BOOL Set_Primary_Buffer_Format(void) { return 0; }; BOOL Start_Primary_Sound_Buffer(BOOL forced) { return 0; }; void Stop_Primary_Sound_Buffer(void) {}; /*************************************************************************** ** Controls what special effects may occur on the sound effect. */ typedef enum { IN_NOVAR, // No variation or alterations allowed. IN_VAR // Infantry variance response modification. } ContextType; // static struct { // MBL 02.21.2019 // Had to name the struct for VS 2017 distributed build. ST - 4/10/2019 3:59PM struct SoundEffectNameStruct { char const * Name; // Digitized voice file name. int Priority; // Playback priority of this sample. ContextType Where; // In what game context does this sample exist. } SoundEffectName[VOC_COUNT] = { /* ** Civilian voices (technicians too). */ {"GIRLOKAY", 20, IN_NOVAR}, // VOC_GIRL_OKAY {"GIRLYEAH", 20, IN_NOVAR}, // VOC_GIRL_YEAH {"GUYOKAY1", 20, IN_NOVAR}, // VOC_GUY_OKAY {"GUYYEAH1", 20, IN_NOVAR}, // VOC_GUY_YEAH {"MINELAY1", 5, IN_VAR}, // VOC_MINELAY1 /* ** Infantry and vehicle responses. */ {"ACKNO", 20, IN_VAR}, // VOC_ACKNOWL "acknowledged" {"AFFIRM1", 20, IN_VAR}, // VOC_AFFIRM "affirmative" {"AWAIT1", 20, IN_VAR}, // VOC_AWAIT1 "awaiting orders" {"EAFFIRM1", 20, IN_NOVAR}, // VOC_ENG_AFFIRM Engineer: "affirmative" {"EENGIN1", 20, IN_NOVAR}, // VOC_ENG_ENG Engineer: "engineering" {"NOPROB", 20, IN_VAR}, // VOC_NO_PROB "not a problem" {"READY", 20, IN_VAR}, // VOC_READY "ready and waiting" {"REPORT1", 20, IN_VAR}, // VOC_REPORT "reporting" {"RITAWAY", 20, IN_VAR}, // VOC_RIGHT_AWAY "right away sir" {"ROGER", 20, IN_VAR}, // VOC_ROGER "roger" {"UGOTIT", 20, IN_VAR}, // VOC_UGOTIT "you got it" {"VEHIC1", 20, IN_VAR}, // VOC_VEHIC1 "vehicle reporting" {"YESSIR1", 20, IN_VAR}, // VOC_YESSIR "yes sir" {"DEDMAN1", 10, IN_NOVAR}, // VOC_SCREAM1 short infantry scream {"DEDMAN2", 10, IN_NOVAR}, // VOC_SCREAM3 short infantry scream {"DEDMAN3", 10, IN_NOVAR}, // VOC_SCREAM4 short infantry scream {"DEDMAN4", 10, IN_NOVAR}, // VOC_SCREAM5 short infantry scream {"DEDMAN5", 10, IN_NOVAR}, // VOC_SCREAM6 short infantry scream {"DEDMAN6", 10, IN_NOVAR}, // VOC_SCREAM7 short infantry scream {"DEDMAN7", 10, IN_NOVAR}, // VOC_SCREAM10 short infantry scream {"DEDMAN8", 10, IN_NOVAR}, // VOC_SCREAM11 short infantry scream {"DEDMAN10", 10, IN_NOVAR}, // VOC_YELL1 long infantry scream {"CHRONO2", 5, IN_NOVAR}, // VOC_CHRONO Chronosphere sound {"CANNON1", 1, IN_NOVAR}, // VOC_CANNON1 Cannon sound (medium). {"CANNON2", 1, IN_NOVAR}, // VOC_CANNON2 Cannon sound (short). {"IRONCUR9", 10, IN_NOVAR}, // VOC_IRON1 {"EMOVOUT1", 20, IN_NOVAR}, // VOC_ENG_MOVEOUT Engineer: "movin' out" {"SONPULSE", 10, IN_NOVAR}, // VOC_SONAR {"SANDBAG2", 5, IN_NOVAR}, // VOC_SANDBAG sand bag crunch {"MINEBLO1", 5, IN_NOVAR}, // VOC_MINEBLOW weird mine explosion {"CHUTE1", 1, IN_NOVAR}, // VOC_CHUTE1 Wind swoosh sound. {"DOGY1", 5, IN_NOVAR}, // VOC_DOG_BARK Dog bark. {"DOGW5", 10, IN_NOVAR}, // VOC_DOG_WHINE Dog whine. {"DOGG5P", 10, IN_NOVAR}, // VOC_DOG_GROWL2 Strong dog growl. {"FIREBL3", 1, IN_NOVAR}, // VOC_FIRE_LAUNCH Fireball launch sound. {"FIRETRT1", 1, IN_NOVAR}, // VOC_FIRE_EXPLODE Fireball explode sound. {"GRENADE1", 1, IN_NOVAR}, // VOC_GRENADE_TOSS Grenade toss. {"GUN11", 1, IN_NOVAR}, // VOC_GUN_5 5 round gun burst (slow). {"GUN13", 1, IN_NOVAR}, // VOC_GUN_7 7 round gun burst (fast). {"EYESSIR1", 20, IN_NOVAR}, // VOC_ENG_YES, Engineer: "yes sir" {"GUN27", 1, IN_NOVAR}, // VOC_GUN_RIFLE Rifle shot. {"HEAL2", 1, IN_NOVAR}, // VOC_HEAL Healing effect. {"HYDROD1", 1, IN_NOVAR}, // VOC_DOOR Hyrdrolic door. {"INVUL2", 1, IN_NOVAR}, // VOC_INVULNERABLE Invulnerability effect. {"KABOOM1", 1, IN_NOVAR}, // VOC_KABOOM1 Long explosion (muffled). {"KABOOM12", 1, IN_NOVAR}, // VOC_KABOOM12 Very long explosion (muffled). {"KABOOM15", 1, IN_NOVAR}, // VOC_KABOOM15 Very long explosion (muffled). {"SPLASH9", 5, IN_NOVAR}, // VOC_SPLASH water splash {"KABOOM22", 1, IN_NOVAR}, // VOC_KABOOM22 Long explosion (sharp). {"AACANON3", 1, IN_NOVAR}, {"TANDETH1", 10, IN_NOVAR}, {"MGUNINF1", 1, IN_NOVAR}, // VOC_GUN_5F 5 round gun burst (fast). {"MISSILE1", 1, IN_NOVAR}, // VOC_MISSILE_1 Missile with high tech effect. {"MISSILE6", 1, IN_NOVAR}, // VOC_MISSILE_2 Long missile launch. {"MISSILE7", 1, IN_NOVAR}, // VOC_MISSILE_3 Short missile launch. {"x", 1, IN_NOVAR}, {"PILLBOX1", 1, IN_NOVAR}, // VOC_GUN_5R 5 round gun burst (rattles). {"RABEEP1", 1, IN_NOVAR}, // VOC_BEEP Generic beep sound. {"RAMENU1", 1, IN_NOVAR}, // VOC_CLICK Generic click sound. {"SILENCER", 1, IN_NOVAR}, // VOC_SILENCER Silencer. {"TANK5", 1, IN_NOVAR}, // VOC_CANNON6 Long muffled cannon shot. {"TANK6", 1, IN_NOVAR}, // VOC_CANNON7 Sharp mechanical cannon fire. {"TORPEDO1", 1, IN_NOVAR}, // VOC_TORPEDO Torpedo launch. {"TURRET1", 1, IN_NOVAR}, // VOC_CANNON8 Sharp cannon fire. {"TSLACHG2", 10, IN_NOVAR}, // VOC_TESLA_POWER_UP Hum charge up. {"TESLA1", 10, IN_NOVAR}, // VOC_TESLA_ZAP Tesla zap effect. {"SQUISHY2", 10, IN_NOVAR}, // VOC_SQUISH Squish effect. {"SCOLDY1", 10, IN_NOVAR}, // VOC_SCOLD Scold bleep. {"RADARON2", 20, IN_NOVAR}, // VOC_RADAR_ON Powering up electronics. {"RADARDN1", 10, IN_NOVAR}, // VOC_RADAR_OFF B movie power down effect. {"PLACBLDG", 10, IN_NOVAR}, // VOC_PLACE_BUILDING_DOWN Building slam down sound. {"KABOOM30", 1, IN_NOVAR}, // VOC_KABOOM30 Short explosion (HE). {"KABOOM25", 10, IN_NOVAR}, // VOC_KABOOM25 Short growling explosion. {"x", 10, IN_NOVAR}, {"DOGW7", 10, IN_NOVAR}, // VOC_DOG_HURT Dog whine (loud). {"DOGW3PX", 10, IN_NOVAR}, // VOC_DOG_YES Dog 'yes sir'. {"CRMBLE2", 10, IN_NOVAR}, // VOC_CRUMBLE Building crumble. {"CASHUP1", 10, IN_NOVAR}, // VOC_MONEY_UP Rising money tick. {"CASHDN1", 10, IN_NOVAR}, // VOC_MONEY_DOWN Falling money tick. {"BUILD5", 10, IN_NOVAR}, // VOC_CONSTRUCTION Building construction sound. {"BLEEP9", 10, IN_NOVAR}, // VOC_GAME_CLOSED Long bleep. {"BLEEP6", 10, IN_NOVAR}, // VOC_INCOMING_MESSAGE Soft happy warble. {"BLEEP5", 10, IN_NOVAR}, // VOC_SYS_ERROR Sharp soft warble. {"BLEEP17", 10, IN_NOVAR}, // VOC_OPTIONS_CHANGED Mid range soft warble. {"BLEEP13", 10, IN_NOVAR}, // VOC_GAME_FORMING Long warble. {"BLEEP12", 10, IN_NOVAR}, // VOC_PLAYER_LEFT Chirp sequence. {"BLEEP11", 10, IN_NOVAR}, // VOC_PLAYER_JOINED Reverse chirp sequence. {"H2OBOMB2", 10, IN_NOVAR}, // VOC_DEPTH_CHARGE Distant explosion sound. {"CASHTURN", 10, IN_NOVAR}, // VOC_CASHTURN Airbrake. {"TUFFGUY1", 20, IN_NOVAR}, // VOC_TANYA_CHEW Tanya: "Chew on this" {"ROKROLL1", 20, IN_NOVAR}, // VOC_TANYA_ROCK Tanya: "Let's rock" {"LAUGH1", 20, IN_NOVAR}, // VOC_TANYA_LAUGH Tanya: "ha ha ha" {"CMON1", 20, IN_NOVAR}, // VOC_TANYA_SHAKE Tanya: "Shake it baby" {"BOMBIT1", 20, IN_NOVAR}, // VOC_TANYA_CHING Tanya: "Cha Ching" {"GOTIT1", 20, IN_NOVAR}, // VOC_TANYA_GOT Tanya: "That's all you got" {"KEEPEM1", 20, IN_NOVAR}, // VOC_TANYA_KISS Tanya: "Kiss it bye bye" {"ONIT1", 20, IN_NOVAR}, // VOC_TANYA_THERE Tanya: "I'm there" {"LEFTY1", 20, IN_NOVAR}, // VOC_TANYA_GIVE Tanya: "Give it to me" {"YEAH1", 20, IN_NOVAR}, // VOC_TANYA_YEA Tanya: "Yea?" {"YES1", 20, IN_NOVAR}, // VOC_TANYA_YES Tanya: "Yes sir?" {"YO1", 20, IN_NOVAR}, // VOC_TANYA_WHATS Tanya: "What's up." {"WALLKIL2", 5, IN_NOVAR}, // VOC_WALLKILL2 Crushing wall sound. {"x", 10, IN_NOVAR}, {"GUN5", 5, IN_NOVAR}, // VOC_TRIPLE_SHOT Three quick shots in succession. {"SUBSHOW1", 5, IN_NOVAR}, // VOC_SUBSHOW Submarine surface sound. {"EINAH1", 20, IN_NOVAR}, // VOC_E_AH, Einstien "ah" {"EINOK1", 20, IN_NOVAR}, // VOC_E_OK, Einstien "ok" {"EINYES1", 20, IN_NOVAR}, // VOC_E_YES, Einstien "yes" {"MINE1", 10, IN_NOVAR}, // VOC_TRIP_MINE mine explosion sound {"SCOMND1", 20, IN_NOVAR}, // VOC_SPY_COMMANDER Spy: "commander?" {"SYESSIR1", 20, IN_NOVAR}, // VOC_SPY_YESSIR Spy: "yes sir" {"SINDEED1", 20, IN_NOVAR}, // VOC_SPY_INDEED Spy: "indeed" {"SONWAY1", 20, IN_NOVAR}, // VOC_SPY_ONWAY Spy: "on my way" {"SKING1", 20, IN_NOVAR}, // VOC_SPY_KING Spy: "for king and country" {"MRESPON1", 20, IN_NOVAR}, // VOC_MED_REPORTING Medic: "reporting" {"MYESSIR1", 20, IN_NOVAR}, // VOC_MED_YESSIR Medic: "yes sir" {"MAFFIRM1", 20, IN_NOVAR}, // VOC_MED_AFFIRM Medic: "affirmative" {"MMOVOUT1", 20, IN_NOVAR}, // VOC_MED_MOVEOUT Medic: "movin' out" {"BEEPSLCT", 10, IN_NOVAR}, // VOC_BEEP_SELECT map selection beep {"SYEAH1", 20, IN_NOVAR}, // VOC_THIEF_YEA Thief: "yea?" {"ANTDIE", 20, IN_NOVAR}, // VOC_ANTDIE {"ANTBITE", 20, IN_NOVAR}, // VOC_ANTBITE {"SMOUT1", 20, IN_NOVAR}, // VOC_THIEF_MOVEOUT Thief: "movin' out" {"SOKAY1", 20, IN_NOVAR}, // VOC_THIEF_OKAY Thief: "ok" {"x", 20, IN_NOVAR}, {"SWHAT1", 20, IN_NOVAR}, // VOC_THIEF_WHAT Thief: "what" {"SAFFIRM1", 20, IN_NOVAR}, // VOC_THIEF_AFFIRM Thief: "affirmative" //ADDED VG 2/24/97 {"STAVCMDR", 20, IN_NOVAR}, {"STAVCRSE", 20, IN_NOVAR}, {"STAVYES", 20, IN_NOVAR}, {"STAVMOV", 20, IN_NOVAR}, {"BUZZY1", 20, IN_NOVAR}, {"RAMBO1", 20, IN_NOVAR}, {"RAMBO2", 20, IN_NOVAR}, {"RAMBO3", 20, IN_NOVAR}, #ifdef FIXIT_CSII // checked - ajw 9/28/98 {"MYES1", 20, IN_NOVAR}, // VOC_MECHYES1 Mechanic: "Yes sir!" {"MHOWDY1", 20, IN_NOVAR}, // VOC_MECHHOWDY1 Mechanic: "Howdy!" {"MRISE1", 20, IN_NOVAR}, // VOC_MECHRISE1 Mechanic: "Rise 'n shine!" {"MHUH1", 20, IN_NOVAR}, // VOC_MECHHUH1 Mechanic: "Huh?" {"MHEAR1", 20, IN_NOVAR}, // VOC_MECHHEAR1 Mechanic: "I Hear Ya!" {"MLAFF1", 20, IN_NOVAR}, // VOC_MECHLAFF1 Mechanic: guffaw {"MBOSS1", 20, IN_NOVAR}, // VOC_MECHBOSS1 Mechanic: "Sure Thing, Boss!" {"MYEEHAW1", 20, IN_NOVAR}, // VOC_MECHYEEHAW1 Mechanic: "Yee Haw!" {"MHOTDIG1", 20, IN_NOVAR}, // VOC_MECHHOTDIG1 Mechanic: "Hot Diggity Dog!" {"MWRENCH1", 20, IN_NOVAR}, // VOC_MECHWRENCH1 Mechanic: "I'll get my wrench." {"JBURN1", 20, IN_NOVAR}, // VOC_STBURN1 Shock Trooper: "Burn baby burn!" {"JCHRGE1", 20, IN_NOVAR}, // VOC_STCHRGE1 Shock Trooper: "Fully charged!" {"JCRISP1", 20, IN_NOVAR}, // VOC_STCRISP1 Shock Trooper: "Extra Crispy!" {"JDANCE1", 20, IN_NOVAR}, // VOC_STDANCE1 Shock Trooper: "Let's Dance!" {"JJUICE1", 20, IN_NOVAR}, // VOC_STJUICE1 Shock Trooper: "Got juice?" {"JJUMP1", 20, IN_NOVAR}, // VOC_STJUMP1 Shock Trooper: "Need a jump?" {"JLIGHT1", 20, IN_NOVAR}, // VOC_STLIGHT1 Shock Trooper: "Lights out!" {"JPOWER1", 20, IN_NOVAR}, // VOC_STPOWER1 Shock Trooper: "Power on!" {"JSHOCK1", 20, IN_NOVAR}, // VOC_STSHOCK1 Shock Trooper: "Shocking!" {"JYES1", 20, IN_NOVAR}, // VOC_STYES1 Shock Trooper: "Yesssss!" {"CHROTNK1", 20, IN_NOVAR}, // VOC_CHRONOTANK1 Chrono tank teleport {"FIXIT1", 20, IN_NOVAR}, // VOC_MECH_FIXIT1 Mechanic fixes something {"MADCHRG2", 20, IN_NOVAR}, // VOC_MAD_CHARGE MAD tank charges up {"MADEXPLO", 20, IN_NOVAR}, // VOC_MAD_EXPLODE MAD tank explodes {"SHKTROP1", 20, IN_NOVAR}, // VOC_SHOCK_TROOP1 Shock Trooper fires {"BEACON", 10, IN_NOVAR}, // VOC_BEACON Beacon sound. #endif }; // // External handlers. MBL 06.17.2019 // extern void On_Sound_Effect(int sound_index, int variation, COORDINATE coord, int house); // extern void On_Speech(int speech_index); MBL 02.06.2020 extern void On_Speech(int speech_index, HouseClass *house); extern void On_Ping(const HouseClass* player_ptr, COORDINATE coord); /*********************************************************************************************** * Voc_From_Name -- Fetch VocType from ASCII name specified. * * * * This will find the corresponding VocType from the ASCII string specified. It does this * * by finding a root filename that matches the string. * * * * INPUT: name -- Pointer to the ASCII string that will be converted into a VocType. * * * * OUTPUT: Returns with the VocType that matches the string specified. If no match could be * * found, then VOC_NONE is returned. * * * * WARNINGS: none * * * * HISTORY: * * 07/06/1996 JLB : Created. * *=============================================================================================*/ VocType Voc_From_Name(char const * name) { if (name == NULL) return(VOC_NONE); for (VocType voc = VOC_FIRST; voc < VOC_COUNT; voc++) { if (stricmp(name, SoundEffectName[voc].Name) == 0) { return(voc); } } return(VOC_NONE); } /*********************************************************************************************** * Voc_Name -- Fetches the name for the sound effect. * * * * This routine returns the descriptive name of the sound effect. Currently, this is just * * the root of the file name. * * * * INPUT: voc -- The VocType that the corresponding name is requested. * * * * OUTPUT: Returns with a pointer to the text string the represents the sound effect. * * * * WARNINGS: none * * * * HISTORY: * * 05/06/1996 JLB : Created. * *=============================================================================================*/ char const * Voc_Name(VocType voc) { if (voc == VOC_NONE) return("none"); return(SoundEffectName[voc].Name); } /*********************************************************************************************** * Sound_Effect -- Plays a sound effect in the tactical map. * * * * This routine is used when a sound effect occurs in the game world. It handles fading * * the sound according to distance. * * * * INPUT: voc -- The sound effect number to play. * * * * coord -- The world location that the sound originates from. * * * * variation -- This is the optional variation number to use when playing special * * sound effects that have variations. For normal sound effects, this * * parameter is ignored. * * * * house -- This specifies the optional house override value to use when playing * * sound effects that have a variation. If not specified, then the current * * player is examined for the house variation to use. * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 11/12/1994 JLB : Created. * * 01/05/1995 JLB : Reduces sound more dramatically when off screen. * * 09/15/1996 JLB : Revamped volume logic. * * 11/01/1996 JLB : House override control. * *=============================================================================================*/ void Sound_Effect(VocType voc, COORDINATE coord, int variation, HousesType house) { // // Intercept sound effect calls. MBL 06.17.2019 // On_Sound_Effect((int)voc, variation, coord, (int)house); #if 0 CELL cell_pos = 0; int pan_value; if (Debug_Quiet || Options.Volume == 0 || voc == VOC_NONE || !SoundOn || SampleType == SAMPLE_NONE) { return; } if (coord) { cell_pos = Coord_Cell(coord); } fixed volume = 1; pan_value = 0; if (coord && !Map.In_View(cell_pos)) { int distance = Distance(coord, Map.TacticalCoord) / CELL_LEPTON_W; fixed dfixed = fixed(distance, 128+64); dfixed.Sub_Saturate(1); volume = fixed(1) - dfixed; pan_value = Cell_X(cell_pos); pan_value -= Coord_XCell(Map.TacticalCoord) + (Lepton_To_Cell(Map.TacLeptonWidth) / 2); if (ABS(pan_value) > Lepton_To_Cell(Map.TacLeptonWidth / 2)) { pan_value *= 0x8000; pan_value /= (MAP_CELL_W >> 2); pan_value = Bound(pan_value, -0x7FFF, 0x7FFF); } else { pan_value = 0; } } Sound_Effect(voc, volume, variation, pan_value, house); #endif } /*********************************************************************************************** * Sound_Effect -- General purpose sound player. * * * * This is used for general purpose sound effects. These are sounds that occur outside * * of the game world. They do not have a corresponding game world location as their source. * * * * INPUT: voc -- The sound effect number to play. * * * * volume -- The volume to assign to this sound effect. * * * * variation -- This is the optional variation number to use when playing special * * sound effects that have variations. For normal sound effects, this * * parameter is ignored. * * * * house -- This specifies the optional house override value to use when playing * * sound effects that have a variation. If not specified, then the current * * player is examined for the house variation to use. * * * * OUTPUT: Returns with the sound handle (-1 if no sound was played). * * * * WARNINGS: none * * * * HISTORY: * * 11/12/1994 JLB : Created. * * 11/12/1994 JLB : Handles cache logic. * * 05/04/1995 JLB : Variation adjustments. * * 11/01/1996 JLB : House override control. * *=============================================================================================*/ int Sound_Effect(VocType voc, fixed volume, int variation, signed short pan_value, HousesType house) { // // Intercept sound effect calls. MBL 06.17.2019 // pan_value; COORDINATE coord = 0; On_Sound_Effect((int)voc, variation, coord, (int)house); #if 0 char name[_MAX_FNAME+_MAX_EXT]; // Working filename of sound effect. if (Debug_Quiet || Options.Volume == 0 || voc == VOC_NONE || !SoundOn || SampleType == SAMPLE_NONE) { return(-1); } /* ** Alter the volume according to the game volume setting. */ volume = volume * Options.Volume; /* ** Fetch a pointer to the sound effect data. Modify the sound as appropriate and desired. */ char const * ext = ".AUD"; if (SoundEffectName[voc].Where == IN_VAR) { /* ** If there is no forced house, then use the current player ** act like house. */ if (house == HOUSE_NONE) { house = PlayerPtr->ActLike; } /* ** Change the extension based on the variation and house accent requested. */ if (((1 << house) & HOUSEF_ALLIES) != 0) { /* ** For infantry, use a variation on the response. For vehicles, always ** use the vehicle response table. */ if (variation < 0) { if (ABS(variation) % 2) { ext = ".V00"; } else { ext = ".V02"; } } else { if (variation % 2) { ext = ".V01"; } else { ext = ".V03"; } } } else { if (variation < 0) { if (ABS(variation) % 2) { ext = ".R00"; } else { ext = ".R02"; } } else { if (variation % 2) { ext = ".R01"; } else { ext = ".R03"; } } } } _makepath(name, NULL, NULL, SoundEffectName[voc].Name, ext); void const * ptr = MFCD::Retrieve(name); /* ** If the sound data pointer is not null, then presume that it is valid. */ if (ptr != NULL) { volume.Sub_Saturate(1); return(Play_Sample(ptr, SoundEffectName[voc].Priority * volume, volume*256, pan_value)); } #endif return(-1); } /* ** This elaborates all the EVA speech voices. */ /*static PG*/ char const * Speech[VOX_COUNT] = { "MISNWON1", // VOX_ACCOMPLISHED mission accomplished "MISNLST1", // VOX_FAIL your mission has failed "PROGRES1", // VOX_NO_FACTORY unable to comply, building in progress "CONSCMP1", // VOX_CONSTRUCTION construction complete "UNITRDY1", // VOX_UNIT_READY unit ready "NEWOPT1", // VOX_NEW_CONSTRUCT new construction options "NODEPLY1", // VOX_DEPLOY cannot deploy here "STRCKIL1", // VOX_STRUCTURE_DESTROYED, structure destroyed "NOPOWR1", // VOX_INSUFFICIENT_POWER, insufficient power "NOFUNDS1", // VOX_NO_CASH insufficient funds "BCT1", // VOX_CONTROL_EXIT battle control terminated "REINFOR1", // VOX_REINFORCEMENTS reinforcements have arrived "CANCLD1", // VOX_CANCELED canceled "ABLDGIN1", // VOX_BUILDING building "LOPOWER1", // VOX_LOW_POWER low power "NOFUNDS1", // VOX_NEED_MO_MONEY insufficent funds "BASEATK1", // VOX_BASE_UNDER_ATTACK our base is under attack "NOBUILD1", // VOX_UNABLE_TO_BUILD unable to build more "PRIBLDG1", // VOX_PRIMARY_SELECTED primary building selected #ifdef FIXIT_CSII // checked - ajw 9/28/98 #ifdef ENGLISH "TANK01", // VOX_MADTANK_DEPLOYED M.A.D. Tank Deployed #else "none", #endif #else "none", #endif "none", // VOX_SOVIET_CAPTURED Allied building captured "UNITLST1", // VOX_UNIT_LOST unit lost "SLCTTGT1", // VOX_SELECT_TARGET select target "ENMYAPP1", // VOX_PREPARE enemy approaching "SILOND1", // VOX_NEED_MO_CAPACITY silos needed "ONHOLD1", // VOX_SUSPENDED on hold "REPAIR1", // VOX_REPAIRING repairing "none", "none", "AUNITL1", // VOX_AIRCRAFT_LOST airborne unit lost "none", "AAPPRO1", // VOX_ALLIED_FORCES_APPROACHING allied forces approaching "AARRIVE1", // VOX_ALLIED_APPROACHING allied reinforcements have arrived "none", "none", "BLDGINF1", // VOX_BUILDING_INFILTRATED building infiltrated "CHROCHR1", // VOX_CHRONO_CHARGING chronosphere charging "CHRORDY1", // VOX_CHRONO_READY chronosphere ready "CHROYES1", // VOX_CHRONO_TEST chronosphere test successful "CMDCNTR1", // VOX_HQ_UNDER_ATTACK command center under attack "CNTLDED1", // VOX_CENTER_DEACTIVATED control center deactivated "CONVYAP1", // VOX_CONVOY_APPROACHING convoy approaching "CONVLST1", // VOX_CONVOY_UNIT_LOST convoy unit lost "XPLOPLC1", // VOX_EXPLOSIVE_PLACED explosive charge placed "CREDIT1", // VOX_MONEY_STOLEN credits stolen "NAVYLST1", // VOX_SHIP_LOST naval unit lost "SATLNCH1", // VOX_SATALITE_LAUNCHED satalite launched "PULSE1", // VOX_SONAR_AVAILABLE sonar pulse available "none", "SOVFAPP1", // VOX_SOVIET_FORCES_APPROACHING soviet forces approaching "SOVREIN1", // VOX_SOVIET_REINFROCEMENTS soviet reinforcements have arrived "TRAIN1", // VOX_TRAINING training "AREADY1", // VOX_ABOMB_READY "ALAUNCH1", // VOX_ABOMB_LAUNCH "AARRIVN1", // VOX_ALLIES_N "AARRIVS1", // VOX_ALLIES_S "AARIVE1", // VOX_ALLIES_E "AARRIVW1", // VOX_ALLIES_W "1OBJMET1", // VOX_OBJECTIVE1 "2OBJMET1", // VOX_OBJECTIVE2 "3OBJMET1", // VOX_OBJECTIVE3 "IRONCHG1", // VOX_IRON_CHARGING "IRONRDY1", // VOX_IRON_READY "KOSYRES1", // VOX_RESCUED "OBJNMET1", // VOX_OBJECTIVE_NOT "FLAREN1", // VOX_SIGNAL_N "FLARES1", // VOX_SIGNAL_S "FLAREE1", // VOX_SIGNAL_E "FLAREW1", // VOX_SIGNAL_W "SPYPLN1", // VOX_SPY_PLANE "TANYAF1", // VOX_FREED "ARMORUP1", // VOX_UPGRADE_ARMOR "FIREPO1", // VOX_UPGRADE_FIREPOWER "UNITSPD1", // VOX_UPGRADE_SPEED "MTIMEIN1", // VOX_MISSION_TIMER "UNITFUL1", // VOX_UNIT_FULL "UNITREP1", // VOX_UNIT_REPAIRED "40MINR", // VOX_TIME_40 "30MINR", // VOX_TIME_30 "20MINR", // VOX_TIME_20 "10MINR", // VOX_TIME_10 "5MINR", // VOX_TIME_5 "4MINR", // VOX_TIME_4 "3MINR", // VOX_TIME_3 "2MINR", // VOX_TIME_2 "1MINR", // VOX_TIME_1 "TIMERNO1", // VOX_TIME_STOP "UNITSLD1", // VOX_UNIT_SOLD "TIMERGO1", // VOX_TIMER_STARTED "TARGRES1", // VOX_TARGET_RESCUED "TARGFRE1", // VOX_TARGET_FREED "TANYAR1", // VOX_TANYA_RESCUED "STRUSLD1", // VOX_STRUCTURE_SOLD "SOVFORC1", // VOX_SOVIET_FORCES_FALLEN "SOVEMP1", // VOX_SOVIET_SELECTED "SOVEFAL1", // VOX_SOVIET_EMPIRE_FALLEN "OPTERM1", // VOX_OPERATION_TERMINATED "OBJRCH1", // VOX_OBJECTIVE_REACHED "OBJNRCH1", // VOX_OBJECTIVE_NOT_REACHED "OBJMET1", // VOX_OBJECTIVE_MET "MERCR1", // VOX_MERCENARY_RESCUED "MERCF1", // VOX_MERCENARY_FREED "KOSYFRE1", // VOX_KOSOYGEN_FREED "FLARE1", // VOX_FLARE_DETECTED "COMNDOR1", // VOX_COMMANDO_RESCUED "COMNDOF1", // VOX_COMMANDO_FREED "BLDGPRG1", // VOX_BUILDING_IN_PROGRESS "ATPREP1", // VOX_ATOM_PREPPING "ASELECT1", // VOX_ALLIED_SELECTED "APREP1", // VOX_ABOMB_PREPPING "ATLNCH1", // VOX_ATOM_LAUNCHED "AFALLEN1", // VOX_ALLIED_FORCES_FALLEN "AAVAIL1", // VOX_ABOMB_AVAILABLE "AARRIVE1", // VOX_ALLIED_REINFORCEMENTS "SAVE1", // VOX_MISSION_SAVED "LOAD1" // VOX_MISSION_LOADED }; static VoxType CurrentVoice = VOX_NONE; /*********************************************************************************************** * Speech_Name -- Fetches the name for the voice specified. * * * * Use this routine to fetch the ASCII name of the speech id specified. Typical use of this * * would be to build a displayable list of the speech types. The trigger system uses this * * so that a speech type can be selected. * * * * INPUT: speech -- The speech type id to convert to ASCII string. * * * * OUTPUT: Returns with a pointer to the speech ASCII representation of the speech id type. * * * * WARNINGS: none * * * * HISTORY: * * 06/01/1996 JLB : Created. * *=============================================================================================*/ char const * Speech_Name(VoxType speech) { if (speech == VOX_NONE) return("none"); return(Speech[speech]); } /*********************************************************************************************** * Speak -- Computer speaks to the player. * * * * This routine is used to have the game computer (EVA) speak to the player. * * * * INPUT: voice -- The voice number to speak (see defines.h). * * * * OUTPUT: Returns with the handle of the playing speech (-1 if no voice started). * * * * WARNINGS: none * * * * HISTORY: * * 11/12/1994 JLB : Created. * *=============================================================================================*/ // void Speak(VoxType voice) // MBL 02.06.2020 void Speak(VoxType voice, HouseClass *house, COORDINATE coord) { // MBL 06.17.2019 if (voice == VOX_NONE) { return; } // // Intercept speech calls. MBL 06.17.2019 // // On_Speech((int)voice); // MBL 02.06.2020 On_Speech((int)voice, house); if (coord) { On_Ping(house, coord); } #if 0 if (!Debug_Quiet && Options.Volume != 0 && SampleType != 0 && voice != VOX_NONE && voice != SpeakQueue && voice != CurrentVoice && SpeakQueue == VOX_NONE) { SpeakQueue = voice; Speak_AI(); } #endif } /*********************************************************************************************** * Speak_AI -- Handles starting the EVA voices. * * * * This starts the EVA voice talking as well. If there is any speech request in the queue, * * it will be started when the current voice is finished. Call this routine as often as * * possible (once per game tick is sufficient). * * * * INPUT: none * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 12/27/1994 JLB : Created. * * 10/11/1996 JLB : Handles multiple speech buffers. * *=============================================================================================*/ void Speak_AI(void) { // MBL 06.17.2019 KO #if 0 static int _index = 0; if (Debug_Quiet || SampleType == 0) return; if (!Is_Sample_Playing(SpeechBuffer[_index])) { CurrentVoice = VOX_NONE; if (SpeakQueue != VOX_NONE) { /* ** Try to find a previously loaded copy of the EVA speech in one of the ** speech buffers. */ void const * speech = NULL; for (int index = 0; index < ARRAY_SIZE(SpeechRecord); index++) { if (SpeechRecord[index] == SpeakQueue) break; } /* ** If a previous copy could not be located, then load the requested ** voice into the oldest buffer available. */ if (speech == NULL) { _index = (_index + 1) % ARRAY_SIZE(SpeechRecord); char name[_MAX_FNAME+_MAX_EXT]; _makepath(name, NULL, NULL, Speech[SpeakQueue], ".AUD"); CCFileClass file(name); if (file.Is_Available() && file.Read(SpeechBuffer[_index], SPEECH_BUFFER_SIZE)) { speech = SpeechBuffer[_index]; SpeechRecord[_index] = SpeakQueue; } } /* ** Since the speech file was loaded, play it. */ if (speech != NULL) { Play_Sample(speech, 254, Options.Volume * 256); CurrentVoice = SpeakQueue; } SpeakQueue = VOX_NONE; } } #endif // MBL 06.18.2019 if (SpeakQueue != VOX_NONE) { // On_Speech((int)SpeakQueue); // MBL 02.06.2020 On_Speech((int)SpeakQueue, NULL); SpeakQueue = VOX_NONE; } } /*********************************************************************************************** * Stop_Speaking -- Forces the EVA voice to stop talking. * * * * Use this routine to immediately stop the EVA voice from speaking. It also clears out * * the pending voice queue. * * * * INPUT: none * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 12/27/1994 JLB : Created. * *=============================================================================================*/ void Stop_Speaking(void) { SpeakQueue = VOX_NONE; Stop_Sample_Playing(SpeechBuffer); } /*********************************************************************************************** * Is_Speaking -- Checks to see if the eva voice is still playing. * * * * Call this routine when the EVA voice being played needs to be checked. A typical use * * of this would be when some action needs to be delayed until the voice has finished -- * * say the end of the game. * * * * INPUT: none * * * * OUTPUT: bool; Is the EVA voice still playing? * * * * WARNINGS: none * * * * HISTORY: * * 03/12/1995 JLB : Created. * *=============================================================================================*/ bool Is_Speaking(void) { Speak_AI(); if (!Debug_Quiet && SampleType != 0 && (SpeakQueue != VOX_NONE || Is_Sample_Playing(SpeechBuffer))) { return(true); } return(false); }