diff options
| author | Felix Morgner <felix.morgner@gmail.com> | 2026-08-24 11:16:07 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@gmail.com> | 2026-08-24 11:16:07 +0200 |
| commit | c068f22329d5cc722622a2183bbb22eef2093df7 (patch) | |
| tree | 12d56c1aede67988a55e241364606bfbb4dba933 /src/parsec/aud_game.cpp | |
| download | openparsec-c068f22329d5cc722622a2183bbb22eef2093df7.tar.xz openparsec-c068f22329d5cc722622a2183bbb22eef2093df7.zip | |
Diffstat (limited to 'src/parsec/aud_game.cpp')
| -rw-r--r-- | src/parsec/aud_game.cpp | 2773 |
1 files changed, 2773 insertions, 0 deletions
diff --git a/src/parsec/aud_game.cpp b/src/parsec/aud_game.cpp new file mode 100644 index 0000000..49ad9ff --- /dev/null +++ b/src/parsec/aud_game.cpp @@ -0,0 +1,2773 @@ +/* + * PARSEC - High Level Audio Functions + * + * $Author: uberlinuxguy $ - $Date: 2004/09/15 12:25:21 $ + * + * Orginally written by: + * Copyright (c) Markus Hadwiger <msh@parsec.org> 1997-2000 + * Copyright (c) Clemens Beer <cbx@parsec.org> 1998-1999 + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// C library +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +// compilation flags/debug support +#include "config.h" +#include "debug.h" +#include "od_class.h" + +// general definitions +#include "general.h" +#include "objstruc.h" + +// global externals +#include "globals.h" + +// subsystem headers +#include "aud_defs.h" +#include "sys_subh.h" + +// mathematics header +#include "utl_math.h" + +// local module header +#include "aud_game.h" + +// proprietary module headers +#include "aud_supp.h" +#include "con_aux.h" +#include "e_events.h" +#include "obj_game.h" + + +// flags +//#define DISABLE_SELECT_SOUNDS +#define DIST_VOLUME +#define USE_SOUNDSOURCE_LIST +#define REALISTIC_VOLUME_DECREASE + + + +// critical voice numbers ----------------------------------------------------- +// +int SELECT_VOICE = 2; +int STREAM_VOICE_L = 0; +int STREAM_VOICE_R = 1; + + +// default audio file names and paths ----------------------------------------- +// +char menu_stream_name[ PATH_MAX + 1 ] = "menu.ogg"; +char intro_stream_name[ PATH_MAX + 1 ] = "jingle.ogg"; +char console_audio_stream_path[ PATH_MAX + 1 ] = ".\\music\\"; + + +// module local globals ------------------------------------------------------- +// +int g_nLightningsActive = 0; +struct DistVolumeInfo_s* g_pDistVolumeInfo[ NUMCHANNELS ]; // distance volume infos for each channel + + +// global volume -------------------------------------------------------------- +// +int GlobalVolume = AUD_MAX_VOLUME; + + +// ---------------------------------------------------------------------------- +// +#define JIM_COMMENT_VOICE GUN_SELECT_VOICE + + +// sample-channel relations for general ingame sounds ------------------------- +// +static sample_channel_info_s sample_channel_infos[] = { + + { SND_NAME_DROPMINE, NULL, -1, STD_VOICE, TRUE }, + { SND_NAME_DAZZLING_COLLECTED, SND_NAME_ENERGYEXTRA, -1, STD_VOICE, TRUE }, + { SND_NAME_THIEF_COLLECTED, SND_NAME_ENERGYEXTRA, -1, STD_VOICE, TRUE }, + { SND_NAME_AFTERBURNER_COLLECTED, SND_NAME_ENERGYEXTRA, -1, STD_VOICE, TRUE }, + { SND_NAME_INVISIBILITY_COLLECTED, SND_NAME_ENERGYEXTRA, -1, STD_VOICE, TRUE }, + { SND_NAME_INVUL_COLLECTED, SND_NAME_ENERGYEXTRA, -1, STD_VOICE, TRUE }, + { SND_NAME_DUMB_MISSILE_COLLECTED, SND_NAME_ENERGYEXTRA, -1, STD_VOICE, TRUE }, + { SND_NAME_GUIDE_MISSILE_COLLECTED, SND_NAME_ENERGYEXTRA, -1, STD_VOICE, TRUE }, + { SND_NAME_MINE_COLLECTED, SND_NAME_ENERGYEXTRA, -1, STD_VOICE, TRUE }, + { SND_NAME_ENERGYEXTRA, NULL, -1, ENERGYBOOSTED_VOICE, FALSE }, + { SND_NAME_ENERGYEXTRA, NULL, -1, STD_VOICE, TRUE }, + { SND_NAME_DAMAGE_REPAIRED, NULL, -1, STD_VOICE, TRUE }, + { SND_NAME_MAXED_OUT, NULL, -1, ENERGYBOOSTED_VOICE, TRUE }, + { SND_NAME_MAXED_OUT, NULL, -1, STD_VOICE, TRUE }, + { SND_NAME_SELECT1, NULL, -1, SELECT_VOICE, TRUE }, + { SND_NAME_SELECT2, NULL, -1, SELECT_VOICE, TRUE }, + { SND_NAME_SHIPDESTROYED, NULL, -1, DESTROYED_VOICE, TRUE }, + { SND_NAME_EXPLOSION, NULL, -1, EXPLOSION_VOICE, TRUE }, + { SND_NAME_LOWENERGY, NULL, -1, LOWENERGY_VOICE, FALSE }, + { SND_NAME_TARGETLOCKED, NULL, -1, LOCKED_VOICE, TRUE }, + { SND_NAME_BUTTONSLIDED, NULL, -1, STD_VOICE, FALSE }, + { SND_NAME_SCV_SLIDE_IN, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_SCV_SLIDE_OUT, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_MINEHIT, NULL, -1, EXPLOSION_VOICE, TRUE }, + { SND_NAME_LASER1, NULL, -1, LASER1_VOICE, TRUE }, + { SND_NAME_LASER2, NULL, -1, LASER1_VOICE, TRUE }, + { SND_NAME_LASER3, NULL, -1, LASER1_VOICE, TRUE }, + { SND_NAME_MISSILE1, NULL, -1, MISSILE1_VOICE, TRUE }, + { SND_NAME_MISSILE2, NULL, -1, MISSILE2_VOICE, TRUE }, + { SND_NAME_HELIX, NULL, -1, HELIX_VOICE, TRUE }, + { SND_NAME_TRACKING, NULL, -1, TRACKING_VOICE, TRUE }, + { SND_NAME_TRACKINGBEEP, NULL, -1, TRACKBEEP_VOICE, TRUE }, + { SND_NAME_NEWPLAYER, NULL, -1, NEWPLAYERJOINED_VOICE, TRUE }, + { SND_NAME_OPTIONS_SLIDE_IN, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_OPTIONS_SLIDE_OUT, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_SELECT_LASER1, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_SELECT_LASER2, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_SELECT_LASER3, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_SELECT_LASER4, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_SELECT_LASER5, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_SELECT_MISSILE1, NULL, -1, MISS_SELECT_VOICE, TRUE }, + { SND_NAME_SELECT_MISSILE2, NULL, -1, MISS_SELECT_VOICE, TRUE }, + { SND_NAME_SELECT_MISSILE3, NULL, -1, MISS_SELECT_VOICE, TRUE }, + { SND_NAME_SELECT_MISSILE4, NULL, -1, MISS_SELECT_VOICE, TRUE }, + { SND_NAME_COUNTDOWN1, NULL, -1, COUNTDOWN_VOICE, FALSE }, + { SND_NAME_COUNTDOWN2, NULL, -1, COUNTDOWN_VOICE, FALSE }, + { SND_NAME_COUNTDOWN3, NULL, -1, COUNTDOWN_VOICE, FALSE }, + { SND_NAME_COUNTDOWN4, NULL, -1, COUNTDOWN_VOICE, FALSE }, + { SND_NAME_COUNTDOWN5, NULL, -1, COUNTDOWN_VOICE, FALSE }, + { SND_NAME_SWITCH_GUN, NULL, -1, SELECT_VOICE, TRUE }, + { SND_NAME_SWITCH_MISSILE, NULL, -1, SELECT_VOICE, TRUE }, + { SND_NAME_THRUST, NULL, -1, THRUST_VOICE, FALSE }, + { SND_NAME_SLIDETHRUST, NULL, -1, SLIDETHRUST_VOICE, FALSE }, + { SND_NAME_INCOMING, NULL, -1, TRACKBEEP_VOICE, FALSE }, + { SND_NAME_BOOTING, NULL, -1, STD_VOICE, FALSE }, + { SND_NAME_LASERBEAM, NULL, -1, LASER1_VOICE, TRUE }, + { SND_NAME_ENEMYSHIELD_HIT, NULL, -1, ENEMY_HIT_VOICE, TRUE }, + { SND_NAME_ENEMYHULL_HIT, NULL, -1, ENEMY_HIT_VOICE, TRUE }, + { SND_NAME_PLAYERSHIELD_HIT, NULL, -1, ENEMY_HIT_VOICE, TRUE }, + { SND_NAME_PLAYERHULL_HIT, NULL, -1, ENEMY_HIT_VOICE, TRUE }, + { SND_NAME_LOW_SHIELDS, NULL, -1, LOWENERGY_VOICE, TRUE }, + { SND_NAME_ONE_KILL_LEFT, NULL, -1, ANNOUNCE_VOICE, TRUE }, + { SND_NAME_TWO_KILLS_LEFT, NULL, -1, ANNOUNCE_VOICE, TRUE }, + { SND_NAME_THREE_KILLS_LEFT, NULL, -1, ANNOUNCE_VOICE, TRUE }, + { SND_NAME_JIM_COMMENT_AFRAID_1, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_AFRAID_2, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_ANGRY_1, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_ANGRY_2, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_WEAPON_1, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_WEAPON_2, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_WEAPON_3, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_WEAPON_4, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_KILLED_1, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_KILLED_2, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_EAT_THIS_1, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_EAT_THIS_2, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_ENERGY, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_BORED_1, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_BORED_2, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_DECOY_COLLECTED, NULL, -1, MISS_SELECT_VOICE, TRUE }, + { SND_NAME_LASER_UPGRADE_COLLECTED, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_PHOTON_CANNON_COLLECTED, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_SWARM_MISSILES_COLLECTED, NULL, -1, MISS_SELECT_VOICE, TRUE }, + { SND_NAME_SKILL_AMAZING, NULL, -1, JIM_COMMENT_VOICE, TRUE }, + { SND_NAME_SKILL_BRILLIANT, NULL, -1, JIM_COMMENT_VOICE, TRUE }, + { SND_NAME_AFTERBURNER_ACTIVATE, NULL, -1, AFTERBURNER_VOICE, TRUE }, + { SND_NAME_AFTERBURNER_DEACTIVATE, NULL, -1, AFTERBURNER_VOICE, TRUE }, + { SND_NAME_PHOTON_LOADING, NULL, -1, PHOTON_CANNON_VOICE, TRUE }, + { SND_NAME_PHOTON_FIRING, NULL, -1, PHOTON_CANNON_VOICE, TRUE }, + { SND_NAME_SWARM_MISSILES, NULL, -1, SWARM_MISSILE_VOICE, TRUE }, + { SND_NAME_YOU_DID_IT, NULL, -1, ANNOUNCE_VOICE, TRUE }, + { SND_NAME_YOU_HAVE_LOST, NULL, -1, ANNOUNCE_VOICE, TRUE }, + { SND_NAME_MINE_DETECTOR, NULL, -1, TRACKBEEP_VOICE, TRUE }, + { SND_NAME_EMP_1, NULL, -1, EMP_VOICE, TRUE }, + { SND_NAME_EMP_2, NULL, -1, EMP_VOICE, TRUE }, + { SND_NAME_EMP_3, NULL, -1, EMP_VOICE, TRUE }, + { SND_NAME_TELEPORTER, NULL, -1, TRACKBEEP_VOICE, TRUE }, + + +}; + +enum { + + SCI_DROPMINE, + SCI_DAZZLING_COLLECTED, + SCI_THIEF_COLLECTED, + SCI_AFTERBURNER_COLLECTED, + SCI_INVISIBILITY_COLLECTED, + SCI_INVUL_COLLECTED, + SCI_DUMB_MISSILE_COLLECTED, + SCI_GUIDE_MISSILE_COLLECTED, + SCI_MINE_COLLECTED, + SCI_ENERGYEXTRA, + SCI_ENERGYEXTRA1, + SCI_DAMAGE_REPAIRED, + SCI_ENERGY_MAXED_OUT, + SCI_MAXED_OUT, + SCI_SELECT1, + SCI_SELECT2, + SCI_SHIPDESTROYED, + SCI_EXPLOSION, + SCI_LOWENERGY, + SCI_TARGETLOCKED, + SCI_BUTTONSLIDED, + SCI_SCV_SLIDE_IN, + SCI_SCV_SLIDE_OUT, + SCI_MINEHIT, + SCI_LASER1, + SCI_LASER2, + SCI_LASER3, + SCI_MISSILE1, + SCI_MISSILE2, + SCI_HELIX, + SCI_TRACKING, + SCI_TRACKINGBEEP, + SCI_NEWPLAYER, + SCI_OPTIONS_SLIDE_IN, + SCI_OPTIONS_SLIDE_OUT, + SCI_SELECT_LASER1, + SCI_SELECT_LASER2, + SCI_SELECT_LASER3, + SCI_SELECT_LASER4, + SCI_SELECT_LASER5, + SCI_SELECT_MISSILE1, + SCI_SELECT_MISSILE2, + SCI_SELECT_MISSILE3, + SCI_SELECT_MISSILE4, + SCI_COUNTDOWN1, + SCI_COUNTDOWN2, + SCI_COUNTDOWN3, + SCI_COUNTDOWN4, + SCI_COUNTDOWN5, + SCI_SWITCH_GUN, + SCI_SWITCH_MISSILE, + SCI_THRUST, + SCI_SLIDETHRUST, + SCI_INCOMING, + SCI_BOOTING, + SCI_LASERBEAM, + SCI_ENEMYSHIELD_HIT, + SCI_ENEMYHULL_HIT, + SCI_PLAYERSHIELD_HIT, + SCI_PLAYERHULL_HIT, + SCI_LOW_SHIELDS, + SCI_ONE_KILL_LEFT, + SCI_TWO_KILLS_LEFT, + SCI_THREE_KILLS_LEFT, + SCI_JIM_COMMENT_AFRAID_1, + SCI_JIM_COMMENT_AFRAID_2, + SCI_JIM_COMMENT_ANGRY_1, + SCI_JIM_COMMENT_ANGRY_2, + SCI_JIM_COMMENT_WEAPON_1, + SCI_JIM_COMMENT_WEAPON_2, + SCI_JIM_COMMENT_WEAPON_3, + SCI_JIM_COMMENT_WEAPON_4, + SCI_JIM_COMMENT_KILLED_1, + SCI_JIM_COMMENT_KILLED_2, + SCI_JIM_COMMENT_EAT_THIS_1, + SCI_JIM_COMMENT_EAT_THIS_2, + SCI_JIM_COMMENT_ENERGY, + SCI_JIM_COMMENT_BORED_1, + SCI_JIM_COMMENT_BORED_2, + SCI_DECOY_COLLECTED, + SCI_LASER_UPGRADE_COLLECTED, + SCI_PHOTON_CANNON_COLLECTED, + SCI_SWARM_MISSILES_COLLECTED, + SCI_SKILL_AMAZING, + SCI_SKILL_BRILLIANT, + SCI_AFTERBURNER_ACTIVATE, + SCI_AFTERBURNER_DEACTIVATE, + SCI_PHOTON_LOADING, + SCI_PHOTON_FIRING, + SCI_SWARM_MISSILES, + SCI_YOU_DID_IT, + SCI_YOU_HAVE_LOST, + SCI_MINE_DETECTOR, + SCI_EMP1, + SCI_EMP2, + SCI_EMP3, + SCI_TELEPORTER, + + SCI_NUM_SAMPLE_CHANNEL_INFOS +}; + +int NumSampleChannelInfos = SCI_NUM_SAMPLE_CHANNEL_INFOS; + + +// refframe delays for playing the specified sound ---------------------------- +// +#define MISSILE_SELECTED_SOUND_DELAY 300 +#define LASER_SELECTED_SOUND_DELAY 300 +#define COUNTDOWN_SOUND_DELAY 300 +#define SHIPDESTROYED_SOUND_DELAY 800 +#define EXPLOSION_SOUND_DELAY 400 +#define KILLSLEFT_SOUND_DELAY 500 +#define THRUST_SOUND_LIFETIME 60 +#define THRUST_FADEOUT_FRAMES 300 +#define DISTANCE_UPDATE_FRAMES ( FRAME_MEASURE_TIMEBASE / 10 ) +#define MAX_DISTANCE_VISIBLE 4096 +#define TARGET_LOCKED_REPEAT_RATE FRAME_MEASURE_TIMEBASE * 3 + + +// module local functions ----------------------------------------------------- +// +PRIVATE int AUDm_GetVolumeDistBased( DistVolumeInfo_s* pDistVolumeInfo ); +PRIVATE int AUDm_AddChannelSoundSource( int nChannel, DistVolumeInfo_s* pDistVolumeInfo ); +PRIVATE int AUDm_RemoveChannelSoundSource( int nChannel, GenObject* originator ); +PRIVATE int AUDm_WalkChannelSoundSources( void *param ); + + +// play sound effect "helix device" ------------------------------------------- +// +PRIVATE +void AUDm_HelixDevice() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_DAZZLING_COLLECTED ] ); +} + + +// play sound effect "lightning device" --------------------------------------- +// +PRIVATE +void AUDm_LightningDevice() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_THIEF_COLLECTED ] ); +} + + +// play sound effect "photon device" ------------------------------------------ +// +PRIVATE +void AUDm_PhotonDevice() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_PHOTON_CANNON_COLLECTED ] ); +} + + +// play sound effect "afterburner device" ------------------------------------- +// +PRIVATE +void AUDm_AfterBurnerDevice() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_AFTERBURNER_COLLECTED ] ); +} + + +// play sound effect "invisibility device" ------------------------------------ +// +PRIVATE +void AUDm_InvisibilityDevice() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_INVISIBILITY_COLLECTED ] ); +} + + +// play sound effect "invulnerability device" --------------------------------- +// +PRIVATE +void AUDm_InvulnerabilityDevice() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_INVUL_COLLECTED ] ); +} + + +// play sound effect "holo decoy device" -------------------------------------- +// +PRIVATE +void AUDm_HoloDecoyDevice() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_DECOY_COLLECTED ] ); +} + + +// play sound effect "laser upgrade" ------------------------------------------ +// +PRIVATE +void AUDm_LaserUpgradeDevice() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_LASER_UPGRADE_COLLECTED ] ); +} + + +// play sound effect "dumb missiles" ------------------------------------------ +// +PRIVATE +void AUDm_DumbMissiles() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_DUMB_MISSILE_COLLECTED ] ); +} + + +// play sound effect "guided missiles" ---------------------------------------- +// +PRIVATE +void AUDm_GuidedMissiles() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_GUIDE_MISSILE_COLLECTED ] ); +} + + +// play sound effect "proximity mines" ---------------------------------------- +// +PRIVATE +void AUDm_ProximityMine() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_MINE_COLLECTED ] ); +} + + +// play sound effect "swarm missiles" ----------------------------------------- +// +PRIVATE +void AUDm_SwarmMissiles() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_SWARM_MISSILES_COLLECTED ] ); +} + + +// play sound effect "extra collected" ---------------------------------------- +// +int AUD_ExtraCollected( int type ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + switch ( type ) { + + // helix cannon + case HELIX_DEVICE: + AUDm_HelixDevice(); + AUD_JimCommenting( JIM_COMMENT_WEAPON ); + break; + + // lightning device + case LIGHTNING_DEVICE: + AUDm_LightningDevice(); + AUD_JimCommenting( JIM_COMMENT_WEAPON ); + break; + + // afterburner device + case AFTERBURNER_DEVICE: + AUDm_AfterBurnerDevice(); + break; + + // cloak (invisibility) device + case INVISIBILITY_DEVICE: + AUDm_InvisibilityDevice(); + break; + + // photon cannon + case PHOTON_DEVICE: + AUDm_PhotonDevice(); + AUD_JimCommenting( JIM_COMMENT_WEAPON ); + break; + + // invulnerability device + case INVULNERABILITY_DEVICE: + AUDm_InvulnerabilityDevice(); + break; + + // holo decoy device + case DECOY_DEVICE: + AUDm_HoloDecoyDevice(); + break; + + // laser upgrade devices + case LASER_UPGRADE_1_DEVICE: + case LASER_UPGRADE_2_DEVICE: + AUDm_LaserUpgradeDevice(); + break; + + // dumb missile package + case MISSILE1TYPE: + AUDm_DumbMissiles(); + break; + + // guide missile package + case MISSILE4TYPE: + AUDm_GuidedMissiles(); + break; + + // swarm missiles package + case MISSILE5TYPE: + AUDm_SwarmMissiles(); + break; + + // proximity mine package + case MINE1TYPE: + AUDm_ProximityMine(); + break; + + default: + break; + } + + return TRUE; +} + + +// play sound effect "energy boosted" ----------------------------------------- +// +int AUD_EnergyBoosted() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_ENERGYEXTRA ] ); + return TRUE; +} + + +// play sound effect "damage repaired" ---------------------------------------- +// +int AUD_DamageRepaired() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_DAMAGE_REPAIRED ] ); + return TRUE; +} + + +// play sound effect "energy maxed out" --------------------------------------- +// +PRIVATE +void AUDm_EnergyMaxedOut() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_ENERGY_MAXED_OUT ] ); +} + + +// play sound effect "something maxed out" ------------------------------------ +// +int AUD_MaxedOut( int type ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + switch( type ) { + + case ENERGY_EXTRA_CLASS: + AUDm_EnergyMaxedOut(); + return TRUE; + + default: + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_MAXED_OUT ] ); + break; + } + + return TRUE; +} + + +// play sound effect "select click 1" ----------------------------------------- +// +int AUD_Select1() +{ + +#ifndef DISABLE_SELECT_SOUNDS + + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_SELECT1 ] ); + +#endif + + return TRUE; +} + + +// play sound effect "select click 2" ----------------------------------------- +// +int AUD_Select2() +{ + +#ifndef DISABLE_SELECT_SOUNDS + + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_SELECT2 ] ); + +#endif + + return TRUE; +} + + +// schedule event for delayed explosion --------------------------------------- +// +PRIVATE +int AUD_Explosion_Event( void* param ) +{ + int nVolume = (long) param; + ASSERT( ( nVolume >= AUD_MIN_VOLUME ) && ( nVolume <= AUD_MAX_VOLUME ) ); + + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + AUD_FETCHSAMPLE( sample_channel_infos[ SCI_EXPLOSION ].samplename ); + + if ( fetch_wave != NULL ) { + + // set the volume + fetch_params.volume = nVolume; + fetch_params.flags |= SOUNDPARAMS_VOLUME; + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( sample_channel_infos[ SCI_EXPLOSION ].channel, + fetch_wave, &fetch_params ); + + return TRUE; + + } else { + + return FALSE; + } +} + + +// play sound effect "ship destroyed" ----------------------------------------- +// +int AUD_ShipDestroyed( GenObject* objectpo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + +#define DISTANCE_BASED_EXPLOSION + +#ifdef DISTANCE_BASED_EXPLOSION + + AUD_FETCHSAMPLE( sample_channel_infos[ SCI_EXPLOSION ].samplename ); + + int nVolume; + + // check whether proper originator is set + if ( objectpo != NULL ) { + + // first we calculate the volume of the explosion based on the distance to the local ship + DistVolumeInfo_s DVI; + DVI.nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + DVI.nMinVolume = AUD_MIN_VOLUME; + DVI.fMaxVolumeDist = FLOAT_TO_GEOMV( 700 ); // distance for max. volume + DVI.fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + DVI.fRolloffscale = 1.0f; + DVI.pListener = MyShip; + DVI.pOriginator = objectpo; + + // get the volume + nVolume = AUDm_GetVolumeDistBased( &DVI ); + + } else { + + nVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? + fetch_params.volume : AUD_MAX_VOLUME; + } + + // now we schedule the event for playing the explosion sample + event_s* eventExplosion = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + eventExplosion->type = EVT_TYPE_SND_EXPLOSION_DELAY; + eventExplosion->callback = (event_callback_t) AUD_Explosion_Event; + eventExplosion->callback_params = (void*) nVolume; + eventExplosion->refframe_delay = EXPLOSION_SOUND_DELAY; + eventExplosion->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( eventExplosion ); + +#else // DISTANCE_BASED_EXPLOSION + + //FIXME: the explosion sample should be played by an event + //AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_EXPLOSION ] ); + + event_s* eventExplosion = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + eventExplosion->type = EVT_TYPE_SND_EXPLOSION_DELAY; + eventExplosion->callback = (event_callback_t) AUD_PlaySampleOnChannel; + eventExplosion->callback_params = &sample_channel_infos[ SCI_EXPLOSION ]; + eventExplosion->refframe_delay = EXPLOSION_SOUND_DELAY; + eventExplosion->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( eventExplosion ); + +#endif // DISTANCE_BASED_EXPLOSION + + event_s* eventShipDestroyed = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + eventShipDestroyed->type = EVT_TYPE_SND_COUNTDOWN; + eventShipDestroyed->callback = (event_callback_t) AUD_PlaySampleOnChannel; + eventShipDestroyed->callback_params = &sample_channel_infos[ SCI_SHIPDESTROYED ]; + eventShipDestroyed->refframe_delay = SHIPDESTROYED_SOUND_DELAY; + eventShipDestroyed->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( eventShipDestroyed ); + + return TRUE; +} + + +// play sound effect "low energy" --------------------------------------------- +// +int AUD_LowEnergy() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_LOWENERGY ] ); + return TRUE; +} + + +// refframe of last target lock ----------------------------------------------- +// +static refframe_t last_target_lock_ref = REFFRAME_INVALID; + + +// play sound effect "target locked" ------------------------------------------ +// +int AUD_Locked() +{ + refframe_t curref = SYSs_GetRefFrameCount(); + + // only play the "target locked" sample when enough time passed between play requests + if ( last_target_lock_ref != REFFRAME_INVALID ) { + if ( ( curref - last_target_lock_ref ) < TARGET_LOCKED_REPEAT_RATE ) { + return TRUE; + } + } + + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_TARGETLOCKED ] ); +// MSGOUT( "play target locked at %d ( diff: %d )", curref, curref - last_target_lock_ref ); + last_target_lock_ref = curref; + + return TRUE; +} + + +// play sound effect "menu buttin slided in" ---------------------------------- +// +int AUD_ButtonSlided() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_BUTTONSLIDED ] ); + return TRUE; +} + + +// play sound effect "spacecraft viewer slided in" ---------------------------- +// +int AUD_SpaceCraftViewerIn() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_SCV_SLIDE_IN ] ); + return TRUE; +} + + +// play sound effect "spacecraft viewer slided out" ---------------------------- +// +int AUD_SpaceCraftViewerOut() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_SCV_SLIDE_OUT ] ); + return TRUE; +} + + +// play sound effect "mine hit" ----------------------------------------------- +// +int AUD_MineCollision() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_MINEHIT ] ); + return TRUE; +} + + +// play sound effect "player has been killed" --------------------------------- +// +int AUD_PlayerKilled() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_MINEHIT ] ); + return TRUE; +} + + +// play sound effect "laser fired" -------------------------------------------- +// +int AUD_Laser( GenObject* objectpo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + // determine actual sound + int sci = SCI_LASER1; + dword objtype = objectpo ? objectpo->ObjectType : LASER1TYPE; + + audiowave_t fetchwave = NULL; + SoundParams_s fetchparams; + + switch ( objtype ) { + + case LASER1TYPE: + { + sci = SCI_LASER1; + AUD_FETCHSAMPLE( sample_channel_infos[ sci ].samplename ); + fetchwave = fetch_wave; + fetchparams = fetch_params; + } + break; + + case LASER2TYPE: + { + sci = SCI_LASER2; + AUD_FETCHSAMPLE( sample_channel_infos[ sci ].samplename ); + fetchwave = fetch_wave; + fetchparams = fetch_params; + } + break; + + case LASER3TYPE: + { + sci = SCI_LASER3; + AUD_FETCHSAMPLE( sample_channel_infos[ sci ].samplename ); + fetchwave = fetch_wave; + fetchparams = fetch_params; + } + break; + } + +#ifdef DIST_VOLUME + + if ( fetchwave != NULL ) { + + if ( ( objectpo != NULL ) && ( objectpo != MyShip ) ) { + + // set the info for changing the volume based on the distance + DistVolumeInfo_s DVI; + DVI.nMaxVolume = ( fetchparams.flags & SOUNDPARAMS_VOLUME ) ? fetchparams.volume : AUD_MAX_VOLUME; + DVI.nMinVolume = AUD_MIN_VOLUME; + DVI.fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + DVI.fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + DVI.fRolloffscale = 1.0f; + DVI.pListener = MyShip; + DVI.pOriginator = objectpo; + + // get the volume + fetchparams.volume = AUDm_GetVolumeDistBased( &DVI ); + fetchparams.flags |= SOUNDPARAMS_VOLUME; + } + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( sample_channel_infos[ sci ].channel, fetchwave, &fetchparams ); + } + + return TRUE; + +#else + + AUD_PlaySampleOnChannel( &sample_channel_infos[ sci ] ); + return TRUE; + +#endif // DIST_VOLUME + +} + + +// play sound effect "missile launched" --------------------------------------- +// +int AUD_Missile( GenObject *objectpo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + // determine actual sound + int sci = SCI_MISSILE1; + dword objtype = objectpo ? objectpo->ObjectType : MISSILE1TYPE; + + audiowave_t fetchwave = NULL; + SoundParams_s fetchparams; + + switch ( objtype ) { + + case MISSILE1TYPE: + { + sci = SCI_MISSILE1; + AUD_FETCHSAMPLE( sample_channel_infos[ sci ].samplename ); + fetchwave = fetch_wave; + fetchparams = fetch_params; + } + break; + + case MISSILE4TYPE: + { + sci = SCI_MISSILE2; + AUD_FETCHSAMPLE( sample_channel_infos[ sci ].samplename ); + fetchwave = fetch_wave; + fetchparams = fetch_params; + } + break; + } + +#ifdef DIST_VOLUME + + if ( fetchwave != NULL ) { + + if ( ( objectpo != NULL ) && ( objectpo != MyShip ) ) { + + // set the info for changing the volume based on the distance + DistVolumeInfo_s DVI; + DVI.nMaxVolume = ( fetchparams.flags & SOUNDPARAMS_VOLUME ) ? fetchparams.volume : AUD_MAX_VOLUME; + DVI.nMinVolume = AUD_MIN_VOLUME; + DVI.fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + DVI.fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + DVI.fRolloffscale = 1.0f; + DVI.pListener = MyShip; + DVI.pOriginator = objectpo; + + // get the volume + fetchparams.volume = AUDm_GetVolumeDistBased( &DVI ); + fetchparams.flags |= SOUNDPARAMS_VOLUME; + } + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( sample_channel_infos[ sci ].channel, fetchwave, &fetchparams ); + } + + return TRUE; + +#else + + AUD_PlaySampleOnChannel( &sample_channel_infos[ sci ] ); + return TRUE; + +#endif // DIST_VOLUME + +} + + +// play sound effect "drop mine" ---------------------------------------------- +// +int AUD_Mine( GenObject *objectpo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + int sci = SCI_DROPMINE; + +#ifdef DIST_VOLUME + + if ( ( objectpo != NULL ) && ( objectpo != MyShip ) ) { + + AUD_FETCHSAMPLE( sample_channel_infos[ sci ].samplename ); + + if ( fetch_wave != NULL ) { + + // set the info for changing the volume based on the distance + DistVolumeInfo_s DVI; + DVI.nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + DVI.nMinVolume = AUD_MIN_VOLUME; + DVI.fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + DVI.fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + DVI.fRolloffscale = 1.0f; + DVI.pListener = MyShip; + DVI.pOriginator = objectpo; + + // get the volume + fetch_params.volume = AUDm_GetVolumeDistBased( &DVI ); + fetch_params.flags |= SOUNDPARAMS_VOLUME; + } + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( sample_channel_infos[ sci ].channel, fetch_wave, &fetch_params ); + + } else { + AUD_PlaySampleOnChannel( &sample_channel_infos[ sci ] ); + } + + return TRUE; + +#else + + AUD_PlaySampleOnChannel( &sample_channel_infos[ sci ] ); + return TRUE; + +#endif // DIST_VOLUME + +} + + +// play sound effect "energy extra" ------------------------------------------- +// +int AUD_EnergyExtra() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_ENERGYEXTRA1 ] ); + return TRUE; +} + + +#ifdef DIST_VOLUME + +// calculate the volume based on the distance of two object ------------------- +PRIVATE +int AUDm_GetVolumeDistBased( DistVolumeInfo_s* pDistVolumeInfo ) +{ + // trivial case, when listener is the originator + if ( pDistVolumeInfo->pListener == pDistVolumeInfo->pOriginator ) { + return pDistVolumeInfo->nMaxVolume; + } + + Vector3 posListener, posOriginator; + Vector3 dist; + + ASSERT( pDistVolumeInfo != NULL ); + ASSERT( pDistVolumeInfo->pOriginator != NULL ); + + FetchTVector( pDistVolumeInfo->pListener->ObjPosition, &posListener ); + FetchTVector( pDistVolumeInfo->pOriginator->ObjPosition, &posOriginator ); + + VECSUB( &dist, &posOriginator, &posListener ); + + geomv_t len = VctLenX( &dist ); + geomv_t minvoldist = pDistVolumeInfo->fMinVolumeDist; + geomv_t maxvoldist = pDistVolumeInfo->fMaxVolumeDist; + + // default to max. volume + int nVolume = AUD_MAX_VOLUME; + + // check whether inside of sound sphere + if ( len <= minvoldist ) { + + // check trivial case: inside of max. volume sphere + if ( len <= maxvoldist ) { + nVolume = pDistVolumeInfo->nMaxVolume; + + } else { + +#ifdef REALISTIC_VOLUME_DECREASE + + // NOTE: this formula comes from the QMDX SDK documentation + // Applied_Volume = Volume / ( 1 + ( ( Range / minDistance ) - 1 ) * scale ) + + // calculate fraction inside sound sphere + geomv_t frac = GEOMV_1 + GEOMV_MUL( ( GEOMV_DIV ( len, maxvoldist ) - GEOMV_1 ), FLOAT_TO_GEOMV( pDistVolumeInfo->fRolloffscale ) ); + + nVolume = GEOMV_TO_INT( GEOMV_DIV( INT_TO_GEOMV( pDistVolumeInfo->nMaxVolume ), frac ) ); +#else + + // calculate fraction inside sound sphere + geomv_t frac = GEOMV_DIV( ( len - maxvoldist ), ( minvoldist - maxvoldist ) ); + + // calculate volume + nVolume = pDistVolumeInfo->nMaxVolume - GEOMV_TO_INT( GEOMV_MUL( INT_TO_GEOMV( pDistVolumeInfo->nMaxVolume - pDistVolumeInfo->nMinVolume ), frac ) ); + +#endif // REALISTIC_VOLUME_DECREASE + + } + + } else { + + nVolume = pDistVolumeInfo->nMinVolume; + + } + + return nVolume; +} + + +// callback for setting the distance-based volume of a channel ---------------- +// +PRIVATE +int AUDm_DistVolumeVoice( void* param ) +{ + DistVolumeInfo_s* pDistVolumeInfo = (DistVolumeInfo_s*) param; + ASSERT( pDistVolumeInfo != NULL ); + + // get the volume + int nVolume = AUDm_GetVolumeDistBased( pDistVolumeInfo ); + + // and set it on the channel + AUDs_SetVoiceVolume( pDistVolumeInfo->nChannel, nVolume ); + + // indicate event repetition + return TRUE; +} + + +// add a distance-volume info to list for the specified channel --------------- +// +PRIVATE +int AUDm_AddChannelSoundSource( int nChannel, DistVolumeInfo_s* pDistVolumeInfo ) +{ + ASSERT( ( nChannel >= 0 ) && ( nChannel < NUMCHANNELS ) ); + ASSERT( pDistVolumeInfo != NULL ); + + pDistVolumeInfo->next = g_pDistVolumeInfo[ nChannel ]; + g_pDistVolumeInfo[ nChannel ] = pDistVolumeInfo; + + return TRUE; +} + +// remove a distance-volume info from list for the specified channel ---------- +// +PRIVATE +int AUDm_RemoveChannelSoundSource( int nChannel, GenObject* originator ) +{ + ASSERT( ( nChannel >= 0 ) && ( nChannel < NUMCHANNELS ) ); + + DistVolumeInfo_s* pCurrent = g_pDistVolumeInfo[ nChannel ]; + DistVolumeInfo_s* pLast = NULL; + + for( ; pCurrent != NULL; ) { + + // we assume only one DistVolumeInfo_s per object per channel + if( pCurrent->pOriginator == originator ) { + if ( pLast != NULL ) { + pLast->next = pCurrent->next; + } else { + // remove head element + g_pDistVolumeInfo[ nChannel ] = pCurrent->next; + } + FREEMEM( pCurrent ); + + return TRUE; + } + + pLast = pCurrent; + pCurrent = pCurrent->next; + } + + return FALSE; +} + +// walk all sound sources for a specific channel and set the volume to the loudest one +PRIVATE +int AUDm_WalkChannelSoundSources( void *param ) +{ + int nChannel = (long)param; + + DistVolumeInfo_s* pCurrent = g_pDistVolumeInfo[ nChannel ]; + ASSERT( pCurrent != NULL ); + ASSERT( pCurrent->nChannel == nChannel ); + + int nVolume = 0; + + for( ; pCurrent != NULL; ) { + // get the volume + int nObjectVolume = AUDm_GetVolumeDistBased( pCurrent ); + nVolume = max( nVolume, nObjectVolume ); + + pCurrent = pCurrent->next; + } + + // and set it on the channel + AUDs_SetVoiceVolume( nChannel, nVolume ); + + return TRUE; +} + +#endif // DIST_VOLUME + + +// play sound effect "teleporter" --------------------------------------------- +// +int AUD_Teleporter( GenObject* teleporter ) +{ + // check whether we already play the sample + int stopped; + AUDs_GetVoiceStatus( TRACKBEEP_VOICE, &stopped ); + + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) { + if ( !stopped ) { + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( TRACKBEEP_VOICE, FALSE ); + } + return FALSE; + } + + AUD_FETCHSAMPLE( SND_NAME_TELEPORTER ); + + if ( stopped == 1 ) { + if ( fetch_wave != NULL ) { + + // set the info for changing the volume based on the distance + DistVolumeInfo_s* pDVI = (DistVolumeInfo_s*) ALLOCMEM( sizeof ( DistVolumeInfo_s ) ); + pDVI->nChannel = TRACKBEEP_VOICE; + pDVI->nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + pDVI->nMinVolume = AUD_MIN_VOLUME; + pDVI->fMaxVolumeDist = FLOAT_TO_GEOMV( 50 ); // distance for max. volume + pDVI->fMinVolumeDist = FLOAT_TO_GEOMV( MAX_VOLUME_DISTANCE_TELEPORTER ); // distance for min. volume + pDVI->fRolloffscale = 1.0f; + pDVI->pListener = MyShip; + pDVI->pOriginator = teleporter; + + // get the volume for starting the loop + fetch_params.volume = AUDm_GetVolumeDistBased( pDVI ); + fetch_params.flags |= SOUNDPARAMS_VOLUME; + + // check whether there is already a event for this + if ( g_pDistVolumeInfo[ TRACKBEEP_VOICE ] == NULL ) { + + // add the distance volume info to the list for the lightning channel + AUDm_AddChannelSoundSource( TRACKBEEP_VOICE, pDVI ); + + // add the event for changing the volume based on the distance + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_TELEPORTER_VOLUME; + event->callback = (event_callback_t) AUDm_WalkChannelSoundSources; + event->callback_params = (void*) TRACKBEEP_VOICE; + event->refframe_delay = DISTANCE_UPDATE_FRAMES; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_LOOP_INDEFINITE | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + } else { + + // add the distance volume info to the list for the lightning channel + AUDm_AddChannelSoundSource( TRACKBEEP_VOICE, pDVI ); + + } + + fetch_params.flags |= SOUNDPARAMS_LOOP; + fetch_params.start = 0; + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( TRACKBEEP_VOICE, fetch_wave, &fetch_params ); + + } + } + + return TRUE; +} + +// stop "teleporter" effect --------------------------------------------------- +// +int AUD_TeleporterOff( GenObject* teleporter ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + AUDm_RemoveChannelSoundSource( TRACKBEEP_VOICE, teleporter ); + + // check whether this was the last soundsource playing on the channel + if ( g_pDistVolumeInfo[ TRACKBEEP_VOICE ] == NULL ) { + + // remove the event for setting the volume + EVT_RemoveEventType( EVT_TYPE_SND_TELEPORTER_VOLUME ); + + // and stop playing, as no other soundsource is available anymore + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( TRACKBEEP_VOICE, FALSE ); + } + + return TRUE; +} + + +// play sound effect "lightning" ---------------------------------------------- +// +int AUD_Lightning( ShipObject *shippo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + AUD_FETCHSAMPLE( SND_NAME_LIGHTNING ); + + if ( fetch_wave != NULL ) { + +#ifdef DIST_VOLUME + + ASSERT( shippo != NULL ); + +#ifdef USE_SOUNDSOURCE_LIST + + // set the info for changing the volume based on the distance + DistVolumeInfo_s* pDVI = (DistVolumeInfo_s*) ALLOCMEM( sizeof ( DistVolumeInfo_s ) ); + pDVI->nChannel = LIGHTNING_VOICE; + pDVI->nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + pDVI->nMinVolume = AUD_MIN_VOLUME; + pDVI->fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + pDVI->fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + pDVI->fRolloffscale = 1.0f; + pDVI->pListener = MyShip; + pDVI->pOriginator = shippo; + + // get the volume for starting the loop + fetch_params.volume = AUDm_GetVolumeDistBased( pDVI ); + fetch_params.flags |= SOUNDPARAMS_VOLUME; + + // check whether there is already a event for this + if ( g_pDistVolumeInfo[ LIGHTNING_VOICE ] == NULL ) { + + // add the distance volume info to the list for the lightning channel + AUDm_AddChannelSoundSource( LIGHTNING_VOICE, pDVI ); + + // add the event for changing the volume based on the distance + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_LIGHTNING_VOLUME; + event->callback = (event_callback_t) AUDm_WalkChannelSoundSources; + event->callback_params = (void*) LIGHTNING_VOICE; + event->refframe_delay = DISTANCE_UPDATE_FRAMES; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_LOOP_INDEFINITE | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + } else { + + // add the distance volume info to the list for the lightning channel + AUDm_AddChannelSoundSource( LIGHTNING_VOICE, pDVI ); + + } +#else + if ( shippo != MyShip ) { + + // set the info for changing the volume based on the distance + DistVolumeInfo_s* pDVI = (DistVolumeInfo_s*) ALLOCMEM( sizeof ( DistVolumeInfo_s ) ); + pDVI->nChannel = LIGHTNING_VOICE; + pDVI->nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + pDVI->nMinVolume = AUD_MIN_VOLUME; + pDVI->fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + pDVI->fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + pDVI->fRolloffscale = 1.0f; + pDVI->pListener = MyShip; + pDVI->pOriginator = shippo; + + // get the volume for starting the loop + fetch_params.volume = AUDm_GetVolumeDistBased( pDVI ); + fetch_params.flags |= SOUNDPARAMS_VOLUME; + + // add the event for changing the volume based on the distance + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_LIGHTNING_VOLUME; + event->callback = (event_callback_t) AUDm_DistVolumeVoice; + event->callback_params = (void*) pDVI; + event->refframe_delay = DISTANCE_UPDATE_FRAMES; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOFREE_CALLBACK | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_LOOP_INDEFINITE | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + } + +#endif // USE_SOUNDSOURCE_LIST + +#endif //DIST_VOLUME + + fetch_params.flags |= SOUNDPARAMS_LOOP; + //FIXME: we need to set this to a reasonable value + fetch_params.start = 3648 * 2; + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( LIGHTNING_VOICE, fetch_wave, &fetch_params ); + } + + return TRUE; +} + + +// stop "lightning" effect ---------------------------------------------------- +// +int AUD_LightningOff( ShipObject* shippo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + +#ifdef DIST_VOLUME + +#ifdef USE_SOUNDSOURCE_LIST + + AUDm_RemoveChannelSoundSource( LIGHTNING_VOICE, shippo ); + + // check whether this was the last soundsource playing on the channel + if ( g_pDistVolumeInfo[ LIGHTNING_VOICE ] == NULL ) { + + // remove the event for setting the volume + EVT_RemoveEventType( EVT_TYPE_SND_LIGHTNING_VOLUME ); + + // and stop playing, as no other soundsource is available anymore + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( LIGHTNING_VOICE, FALSE ); + } + +#else // USE_SOUNDSOURCE_LIST + + // remove the event for setting the volume + EVT_RemoveEventType( EVT_TYPE_SND_LIGHTNING_VOLUME ); + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( LIGHTNING_VOICE, FALSE ); + +#endif // USE_SOUNDSOURCE_LIST + +#else // DIST_VOLUME + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( LIGHTNING_VOICE, FALSE ); + +#endif // DIST_VOLUME + + return TRUE; +} + + +// play sound effect "helix" -------------------------------------------------- +// +int AUD_Helix( ShipObject *shippo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + AUD_FETCHSAMPLE( sample_channel_infos[ SCI_HELIX ].samplename ); + + if ( fetch_wave != NULL ) { + +#ifdef DIST_VOLUME + + ASSERT( shippo != NULL ); + +#ifdef USE_SOUNDSOURCE_LIST + + // set the info for changing the volume based on the distance + DistVolumeInfo_s* pDVI = (DistVolumeInfo_s*) ALLOCMEM( sizeof ( DistVolumeInfo_s ) ); + pDVI->nChannel = HELIX_VOICE; + pDVI->nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + pDVI->nMinVolume = AUD_MIN_VOLUME; + pDVI->fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + pDVI->fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + pDVI->fRolloffscale = 1.0f; + pDVI->pListener = MyShip; + pDVI->pOriginator = shippo; + + // get the volume for starting the loop + fetch_params.volume = AUDm_GetVolumeDistBased( pDVI ); + fetch_params.flags |= SOUNDPARAMS_VOLUME; + + // check whether there is already a event for this + if ( g_pDistVolumeInfo[ HELIX_VOICE ] == NULL ) { + + // add the distance volume info to the list for the lightning channel + AUDm_AddChannelSoundSource( HELIX_VOICE, pDVI ); + + // add the event for changing the volume based on the distance + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_HELIX_VOLUME; + event->callback = (event_callback_t) AUDm_WalkChannelSoundSources; + event->callback_params = (void*) HELIX_VOICE; + event->refframe_delay = DISTANCE_UPDATE_FRAMES; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_LOOP_INDEFINITE | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + } else { + + // add the distance volume info to the list for the lightning channel + AUDm_AddChannelSoundSource( HELIX_VOICE, pDVI ); + + } + +#else // USE_SOUNDSOURCE_LIST + + if ( shippo != MyShip ) { + + // set the info for changing the volume based on the distance + DistVolumeInfo_s* pDVI = (DistVolumeInfo_s*) ALLOCMEM( sizeof ( DistVolumeInfo_s ) ); + pDVI->nChannel = HELIX_VOICE; + pDVI->nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + pDVI->nMinVolume = AUD_MIN_VOLUME; + pDVI->fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + pDVI->fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + pDVI->fRolloffscale = 1.0f; + pDVI->pListener = MyShip; + pDVI->pOriginator = shippo; + + // immediately set the volume for this channel + AUDm_DistVolumeVoice( pDVI ); + + // add the event for changing the volume based on the distance + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_HELIX_VOLUME; + event->callback = (event_callback_t) AUDm_DistVolumeVoice; + event->callback_params = (void*) pDVI; + event->refframe_delay = DISTANCE_UPDATE_FRAMES; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOFREE_CALLBACK | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_LOOP_INDEFINITE | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + } + +#endif // USE_SOUNDSOURCE_LIST + +#endif //DIST_VOLUME + + fetch_params.flags |= SOUNDPARAMS_LOOP; + fetch_params.start = 0; + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( HELIX_VOICE, fetch_wave, &fetch_params ); + + } + + return TRUE; +} + + +// stop sound effect "helix" -------------------------------------------------- +// +int AUD_HelixOff( ShipObject* shippo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + +#ifdef DIST_VOLUME + +#ifdef USE_SOUNDSOURCE_LIST + + AUDm_RemoveChannelSoundSource( HELIX_VOICE, shippo ); + + // check whether this was the last soundsource playing on the channel + if ( g_pDistVolumeInfo[ HELIX_VOICE ] == NULL ) { + + // remove the event for setting the volume + EVT_RemoveEventType( EVT_TYPE_SND_HELIX_VOLUME ); + + // and stop playing, as no other soundsource is available anymore + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( HELIX_VOICE, FALSE ); + } + +#else // USE_SOUNDSOURCE_LIST + + // remove the event for setting the volume + EVT_RemoveEventType( EVT_TYPE_SND_HELIX_VOLUME ); + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( HELIX_VOICE, FALSE ); + +#endif // USE_SOUNDSOURCE_LIST + +#else // DIST_VOLUME + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( HELIX_VOICE, TRUE ); + + +#endif // DIST_VOLUME + + return TRUE; +} + + + +// play sound effect "tracking" ----------------------------------------------- +// +int AUD_Tracking() +{ + //FIXME: + // currently not in use, therefore save time + // by not looking for it. + +// AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_TRACKING ] ); + + return TRUE; +} + + +// play sound effect "tracking beep" ------------------------------------------ +// +int AUD_TrackingBeep() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_TRACKINGBEEP ] ); + return TRUE; +} + + +// play sound effect "player joined" ------------------------------------------ +// +int AUD_NewPlayerJoined() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_NEWPLAYER ] ); + return TRUE; +} + + +// weapons index to weapons mask table ---------------------------------------- +// +//FIXME: gamecode !!! +int index_weapons_mask[ 5 ] = { + + WPMASK_CANNON_LASER, + WPMASK_CANNON_HELIX, + WPMASK_CANNON_LIGHTNING, + WPMASK_CANNON_PHOTON, + WPMASK_DEVICE_EMP, +}; + + +// play sound effect "laser changed" ------------------------------------------ +// +int AUD_SelectLaser( int sellaser ) +{ + ASSERT( ( sellaser >= 0 ) && ( sellaser < 5 ) ); + + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) { + return FALSE; + } + + // check if selected laser is available + if ( OBJ_DeviceAvailable( MyShip, index_weapons_mask[ sellaser ] ) ) { + + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_GUN_SELECT; + event->callback = (event_callback_t) AUD_PlaySampleOnChannel; + event->callback_params = &sample_channel_infos[ SCI_SELECT_LASER1 + sellaser ]; + event->refframe_delay = LASER_SELECTED_SOUND_DELAY; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + } else { + + // remove any previously issued event + EVT_RemoveEventType( EVT_TYPE_SND_GUN_SELECT ); + } + + // play the gun switching sample + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_SWITCH_GUN ] ); + + return TRUE; +} + + +// play sound effect "missile changed" ---------------------------------------- +// +int AUD_SelectMissile( int selmissile ) +{ + ASSERT( ( selmissile >= 0 ) && ( selmissile < 4 ) ); + + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + if ( ( ( selmissile == 0 ) && ( MyShip->NumMissls > 0 ) ) || + ( ( selmissile == 1 ) && ( MyShip->NumHomMissls > 0 ) ) || + ( ( selmissile == 2 ) && ( MyShip->NumMines > 0 ) ) || + ( ( selmissile == 3 ) && ( MyShip->NumPartMissls > 0 ) ) + ) { + + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_MISSILE_SELECT; + event->callback = (event_callback_t) AUD_PlaySampleOnChannel; + event->callback_params = &sample_channel_infos[ SCI_SELECT_MISSILE1 + selmissile ]; + event->refframe_delay = MISSILE_SELECTED_SOUND_DELAY; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + } else { + + // remove any previously issued event + EVT_RemoveEventType( EVT_TYPE_SND_MISSILE_SELECT ); + } + + // play the gun switching sample + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_SWITCH_MISSILE ] ); + + return TRUE; +} + + +// play sound effect for sliding in ------------------------------------------- +// +int AUD_SlideIn( int type ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + switch( type ) { + + case 0: + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_OPTIONS_SLIDE_IN ] ); + break; + + default: + break; + } + + return TRUE; +} + + +// play sound effect for sliding out ------------------------------------------ +// +int AUD_SlideOut( int type ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + switch( type ) { + + case 0: + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_OPTIONS_SLIDE_OUT ] ); + break; + + default: + break; + } + + return TRUE; +} + + +// play voice sample for missile countdown ------------------------------------ +// +int AUD_Countdown( int num ) +{ + if ( num < 1 || num > 5 ) + return FALSE; + + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + +// AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_COUNTDOWN1 + num - 1 ] ); + + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_COUNTDOWN; + event->callback = (event_callback_t) AUD_PlaySampleOnChannel; + event->callback_params = &sample_channel_infos[ SCI_COUNTDOWN1 + num - 1 ]; + event->refframe_delay = COUNTDOWN_SOUND_DELAY; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + return TRUE; +} + + +// struct for handling volume change on a specific channel -------------------- +// +struct ChannelVolumeChange_s { + + int nChannel; + int nVolume; + int nVolumeDelta; +}; + + +// callback function for fading out a specific voice -------------------------- +// +PRIVATE +int AUDm_FadeOutVoice( void* param ) +{ + ChannelVolumeChange_s* pChannelVolumeChange = (ChannelVolumeChange_s*)param; + ASSERT( pChannelVolumeChange != NULL ); + + // decrease the volume + pChannelVolumeChange->nVolume -= abs( pChannelVolumeChange->nVolumeDelta ); + + // and set the volume on the channel + if ( pChannelVolumeChange->nVolume > 0 ) { + + AUDs_SetVoiceVolume( pChannelVolumeChange->nChannel, pChannelVolumeChange->nVolume ); + + // indicate event repetition + return TRUE; + + } else { + + // stop playing the voice + AUDs_StopVoice( pChannelVolumeChange->nChannel, FALSE ); + + // indicate removal of the event + return FALSE; + } +} + + +// start playing the thrust sample -------------------------------------------- +// +int AUD_StartThrust( int type ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + int sci; + dword evttype; + + switch( type ) { + + case THRUST_TYPE_NORMAL: + sci = SCI_THRUST; + evttype = EVT_TYPE_SND_THRUST_FADEOUT; + break; + + case THRUST_TYPE_SLIDE: + sci = SCI_SLIDETHRUST; + evttype = EVT_TYPE_SND_SLIDETHRUST_FADEOUT; + break; + + default: + ASSERT( 0 ); + + } + + // fetch the sample + AUD_FETCHSAMPLE_EX( sample_channel_infos[ sci ].samplename, + sample_channel_infos[ sci ].sampleid ); + + // return, if not available + if ( fetch_pSampleInfo == NULL ) + return FALSE; + + // set the info for fading the volume on a channel + ChannelVolumeChange_s *pCVC = (ChannelVolumeChange_s*) + ALLOCMEM( sizeof ( ChannelVolumeChange_s ) ); + pCVC->nChannel = sample_channel_infos[ sci ].channel; + pCVC->nVolume = fetch_pSampleInfo->volume; + pCVC->nVolumeDelta = pCVC->nVolume / 5; + + // add the event for stopping the Thrust, this removes any previous event + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + event->type = evttype; + event->callback = (event_callback_t) AUDm_FadeOutVoice; + event->callback_params = (void*) pCVC; + event->refframe_delay = THRUST_SOUND_LIFETIME; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOFREE_CALLBACK | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_LOOP_INDEFINITE | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + // check whether we already play the sample + int stopped; + AUDs_GetVoiceStatus( sample_channel_infos[ sci ].channel, &stopped ); + + if ( stopped == 0 ) { + // set the volume to max + AUDs_SetVoiceVolume( sample_channel_infos[ sci ].channel, fetch_params.volume ); + return TRUE; + } + + + // enable looping of sample + fetch_params.flags |= SOUNDPARAMS_LOOP; + + if ( fetch_wave != NULL ) { + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( sample_channel_infos[ sci ].channel, + fetch_wave, &fetch_params ); + } + + return TRUE; +} + + +// callback function to stop a specific voice --------------------------------- +// +PRIVATE +int AUDm_EventStopVoice( void* param ) +{ + uintptr_t channel = (uintptr_t) param; + AUDs_StopVoice( (int) channel, FALSE ); + + return TRUE; +} + + +// play sample "incoming missile" --------------------------------------------- +// +int AUD_IncomingMissile( int looptime ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_INCOMING ] ); + + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_INCOMING_STOP; + event->callback = (event_callback_t) AUDm_EventStopVoice; + event->callback_params = (void *) sample_channel_infos[ SCI_INCOMING ].channel; + event->refframe_delay = looptime; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + return TRUE; +} + + +// flag whether sample "booting" is playing ----------------------------------- +// +static int booting_sample_playing = FALSE; + + +// play sample "booting" ------------------------------------------------------ +// +int AUD_BootOnBoardComputer() +{ + booting_sample_playing = + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_BOOTING ] ); + + return TRUE; +} + + +// make sure "booting" sample is not playing ---------------------------------- +// +int AUD_StopOnBoardComputer() +{ + if ( !booting_sample_playing ) + return FALSE; + + // stop playing the voice + AUDs_StopVoice( sample_channel_infos[ SCI_BOOTING ].channel, FALSE ); + booting_sample_playing = FALSE; + + return TRUE; +} + + +// start sample "laserbeam" --------------------------------------------------- +// +int AUD_StartLaserBeam() +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + // fetch the sample + AUD_FETCHSAMPLE_EX( sample_channel_infos[ SCI_LASERBEAM ].samplename, sample_channel_infos[ SCI_LASERBEAM ].sampleid ); + + // return, if not available + if ( fetch_pSampleInfo == NULL ) + return FALSE; + + // enable looping of sample + fetch_params.flags |= SOUNDPARAMS_LOOP; + + if ( fetch_wave != NULL ) { + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( sample_channel_infos[ SCI_LASERBEAM ].channel, fetch_wave, &fetch_params ); + } + + return TRUE; +} + + +// stop sample "laserbeam" ---------------------------------------------------- +// +int AUD_StopLaserBeam() +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + AUDs_StopVoice( sample_channel_infos[ SCI_LASERBEAM ].channel, FALSE ); + + return TRUE; +} + + +// play sound effect "enemy hit" ---------------------------------------------- +// +int AUD_EnemyShieldHit() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_ENEMYSHIELD_HIT ] ); + return TRUE; +} + + +// play sound effect "enemyhull hit" ------------------------------------------ +// +int AUD_EnemyHullHit() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_ENEMYHULL_HIT ] ); + return TRUE; +} + + +// play sound effect "playershield hit" --------------------------------------- +// +int AUD_PlayerShieldHit() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_PLAYERSHIELD_HIT ] ); + return TRUE; +} + + +// play sound effect "playerhull hit" ----------------------------------------- +// +int AUD_PlayerHullHit() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_PLAYERHULL_HIT ] ); + return TRUE; +} + + +// play sound effect "mine detector" ------------------------------------------ +// +int AUD_MineDetector() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_MINE_DETECTOR ] ); + return TRUE; +} + + +// play sound effect "low shields" -------------------------------------------- +// +int AUD_LowShields() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_LOW_SHIELDS ] ); + return TRUE; +} + + +// play sound effect "x kills left" ------------------------------------------- +// +int AUD_KillsLeft( int killsleft ) +{ + if ( ( killsleft < 1 ) || ( killsleft > 3 ) ) + return FALSE; + + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_KILLSLEFT; + event->callback = (event_callback_t) AUD_PlaySampleOnChannel; + event->callback_params = &sample_channel_infos[ SCI_ONE_KILL_LEFT + killsleft - 1 ]; + event->refframe_delay = KILLSLEFT_SOUND_DELAY; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + return TRUE; +} + + +// play afterburner activation sample ----------------------------------------- +// +int AUD_ActivateAfterBurner() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_AFTERBURNER_ACTIVATE ] ); + return TRUE; +} + + +// play afterburner deactivation sample --------------------------------------- +// +int AUD_DeactivateAfterBurner() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_AFTERBURNER_DEACTIVATE ] ); + return TRUE; +} + + +// play swarm missiles sample ------------------------------------------------- +// +int AUD_SwarmMissiles( Vertex3 *origin, GenObject *dummyobj ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + AUD_FETCHSAMPLE( sample_channel_infos[ SCI_SWARM_MISSILES ].samplename ); + + if ( fetch_wave != NULL ) { + +#ifdef DIST_VOLUME + +#ifdef USE_SOUNDSOURCE_LIST + + // set the info for changing the volume based on the distance + DistVolumeInfo_s* pDVI = (DistVolumeInfo_s*) ALLOCMEM( sizeof ( DistVolumeInfo_s ) ); + pDVI->nChannel = SWARM_MISSILE_VOICE; + pDVI->nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + pDVI->nMinVolume = AUD_MIN_VOLUME; + pDVI->fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + pDVI->fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + pDVI->fRolloffscale = 1.0f; + pDVI->pListener = MyShip; + pDVI->pOriginator = dummyobj; + + // get the volume for starting the loop + fetch_params.volume = AUDm_GetVolumeDistBased( pDVI ); + fetch_params.flags |= SOUNDPARAMS_VOLUME; + + // check whether there is already a event for this + if ( g_pDistVolumeInfo[ SWARM_MISSILE_VOICE ] == NULL ) { + + // add the distance volume info to the list for the lightning channel + AUDm_AddChannelSoundSource( SWARM_MISSILE_VOICE, pDVI ); + + // add the event for changing the volume based on the distance + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_SWARM_VOLUME; + event->callback = (event_callback_t) AUDm_WalkChannelSoundSources; + event->callback_params = (void*) SWARM_MISSILE_VOICE; + event->refframe_delay = DISTANCE_UPDATE_FRAMES; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_LOOP_INDEFINITE | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + } else { + + // add the distance volume info to the list for the lightning channel + AUDm_AddChannelSoundSource( SWARM_MISSILE_VOICE, pDVI ); + + } + +#else // USE_SOUNDSOURCE_LIST + + if ( shippo != MyShip ) { + + // set the info for changing the volume based on the distance + DistVolumeInfo_s* pDVI = (DistVolumeInfo_s*) ALLOCMEM( sizeof ( DistVolumeInfo_s ) ); + pDVI->nChannel = SWARM_MISSILE_VOICE; + pDVI->nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + pDVI->nMinVolume = AUD_MIN_VOLUME; + pDVI->fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + pDVI->fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + pDVI->fRolloffscale = 1.0f; + pDVI->pListener = MyShip; + pDVI->pOriginator = dummyobj; + + // immediately set the volume for this channel + AUDm_DistVolumeVoice( pDVI ); + + // add the event for changing the volume based on the distance + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_SWARM_VOLUME; + event->callback = (event_callback_t) AUDm_DistVolumeVoice; + event->callback_params = (void*) pDVI; + event->refframe_delay = DISTANCE_UPDATE_FRAMES; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOFREE_CALLBACK | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_LOOP_INDEFINITE | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + } + +#endif // USE_SOUNDSOURCE_LIST + +#endif //DIST_VOLUME + + fetch_params.flags |= SOUNDPARAMS_LOOP; + fetch_params.start = 0; + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( SWARM_MISSILE_VOICE, fetch_wave, &fetch_params ); + } + + return TRUE; +} + + +// stop swarm missiles sound effect ------------------------------------------- +// +int AUD_SwarmMissilesOff( GenObject *dummypo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + +#ifdef DIST_VOLUME + +#ifdef USE_SOUNDSOURCE_LIST + + AUDm_RemoveChannelSoundSource( SWARM_MISSILE_VOICE, dummypo ); + + // check whether this was the last soundsource playing on the channel + if ( g_pDistVolumeInfo[ SWARM_MISSILE_VOICE ] == NULL ) { + + // remove the event for setting the volume + EVT_RemoveEventType( EVT_TYPE_SND_SWARM_VOLUME ); + + // and stop playing, as no other soundsource is available anymore + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( SWARM_MISSILE_VOICE, FALSE ); + } + +#else // USE_SOUNDSOURCE_LIST + + // remove the event for setting the volume + EVT_RemoveEventType( EVT_TYPE_SND_SWARM_VOLUME ); + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( SWARM_MISSILE_VOICE, FALSE ); + +#endif // USE_SOUNDSOURCE_LIST + +#else // DIST_VOLUME + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( SWARM_MISSILE_VOICE, TRUE ); + + +#endif // DIST_VOLUME + + return TRUE; +} + + +// play photon cannon loading sound effect ------------------------------------ +// +int AUD_PhotonLoading( ShipObject *objectpo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + AUD_FETCHSAMPLE( sample_channel_infos[ SCI_PHOTON_LOADING ].samplename ); + + if ( fetch_wave != NULL ) { + +#ifdef DIST_VOLUME + +#ifdef USE_SOUNDSOURCE_LIST + + // set the info for changing the volume based on the distance + DistVolumeInfo_s* pDVI = (DistVolumeInfo_s*) ALLOCMEM( sizeof ( DistVolumeInfo_s ) ); + pDVI->nChannel = PHOTON_CANNON_VOICE; + pDVI->nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + pDVI->nMinVolume = AUD_MIN_VOLUME; + pDVI->fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + pDVI->fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + pDVI->fRolloffscale = 1.0f; + pDVI->pListener = MyShip; + pDVI->pOriginator = objectpo; + + // get the volume for starting the loop + fetch_params.volume = AUDm_GetVolumeDistBased( pDVI ); + fetch_params.flags |= SOUNDPARAMS_VOLUME; + + // check whether there is already a event for this + if ( g_pDistVolumeInfo[ PHOTON_CANNON_VOICE ] == NULL ) { + + // add the distance volume info to the list for the lightning channel + AUDm_AddChannelSoundSource( PHOTON_CANNON_VOICE, pDVI ); + + // add the event for changing the volume based on the distance + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_PHOTON_VOLUME; + event->callback = (event_callback_t) AUDm_WalkChannelSoundSources; + event->callback_params = (void*) PHOTON_CANNON_VOICE; + event->refframe_delay = DISTANCE_UPDATE_FRAMES; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_LOOP_INDEFINITE | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + } else { + + // add the distance volume info to the list for the lightning channel + AUDm_AddChannelSoundSource( PHOTON_CANNON_VOICE, pDVI ); + + } + +#else // USE_SOUNDSOURCE_LIST + + if ( shippo != MyShip ) { + + // set the info for changing the volume based on the distance + DistVolumeInfo_s* pDVI = (DistVolumeInfo_s*) ALLOCMEM( sizeof ( DistVolumeInfo_s ) ); + pDVI->nChannel = PHOTON_CANNON_VOICE; + pDVI->nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + pDVI->nMinVolume = AUD_MIN_VOLUME; + pDVI->fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + pDVI->fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + pDVI->fRolloffscale = 1.0f; + pDVI->pListener = MyShip; + pDVI->pOriginator = objectpo; + + // immediately set the volume for this channel + AUDm_DistVolumeVoice( pDVI ); + + // add the event for changing the volume based on the distance + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_PHOTON_VOLUME; + event->callback = (event_callback_t) AUDm_DistVolumeVoice; + event->callback_params = (void*) pDVI; + event->refframe_delay = DISTANCE_UPDATE_FRAMES; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOFREE_CALLBACK | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_LOOP_INDEFINITE | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + } + +#endif // USE_SOUNDSOURCE_LIST + +#endif //DIST_VOLUME + + fetch_params.flags |= SOUNDPARAMS_LOOP; + fetch_params.start = 0; + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( PHOTON_CANNON_VOICE, fetch_wave, &fetch_params ); + } + + return TRUE; + + +} + + +// stop photon cannon loading sound effect ------------------------------------ +// +int AUD_PhotonLoadingOff( ShipObject *objectpo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + +#ifdef DIST_VOLUME + +#ifdef USE_SOUNDSOURCE_LIST + + AUDm_RemoveChannelSoundSource( PHOTON_CANNON_VOICE, objectpo ); + + // check whether this was the last soundsource playing on the channel + if ( g_pDistVolumeInfo[ PHOTON_CANNON_VOICE ] == NULL ) { + + // remove the event for setting the volume + EVT_RemoveEventType( EVT_TYPE_SND_PHOTON_VOLUME ); + + // and stop playing, as no other soundsource is available anymore + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( PHOTON_CANNON_VOICE, FALSE ); + } + +#else // USE_SOUNDSOURCE_LIST + + // remove the event for setting the volume + EVT_RemoveEventType( EVT_TYPE_SND_PHOTON_VOLUME ); + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( PHOTON_CANNON_VOICE, FALSE ); + +#endif // USE_SOUNDSOURCE_LIST + +#else // DIST_VOLUME + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( PHOTON_CANNON_VOICE, TRUE ); + + +#endif // DIST_VOLUME + + return TRUE; +} + + +// play photon firing sample -------------------------------------------------- +// +int AUD_PhotonFiring( GenObject* objectpo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + + AUD_FETCHSAMPLE( sample_channel_infos[ SCI_PHOTON_FIRING ].samplename ); + +#ifdef DIST_VOLUME + + if ( fetch_wave != NULL ) { + + if ( ( objectpo != NULL ) && ( objectpo != MyShip ) ) { + + // set the info for changing the volume based on the distance + DistVolumeInfo_s DVI; + DVI.nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + DVI.nMinVolume = AUD_MIN_VOLUME; + DVI.fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + DVI.fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + DVI.fRolloffscale = 1.0f; + DVI.pListener = MyShip; + DVI.pOriginator = objectpo; + + // get the volume + fetch_params.volume = AUDm_GetVolumeDistBased( &DVI ); + fetch_params.flags |= SOUNDPARAMS_VOLUME; + } + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( sample_channel_infos[ SCI_PHOTON_FIRING ].channel, fetch_wave, &fetch_params ); + } + + return TRUE; + +#else + + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_PHOTON_FIRING ] ); + return TRUE; + +#endif // DIST_VOLUME + +} + + +// play emp sample ------------------------------------------------------------ +// +int AUD_EmpBlast( ShipObject *shippo, int level ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + int sci_id; + + switch ( level ) { + + case 0: + sci_id = SCI_EMP1; + break; + + case 1: + sci_id = SCI_EMP2; + break; + + case 2: + sci_id = SCI_EMP3; + break; + default: + return FALSE; + } + + AUD_FETCHSAMPLE( sample_channel_infos[ sci_id ].samplename ); + +#ifdef DIST_VOLUME + + if ( fetch_wave != NULL ) { + + if ( ( shippo != NULL ) && ( shippo != MyShip ) ) { + + // set the info for changing the volume based on the distance + DistVolumeInfo_s DVI; + DVI.nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + DVI.nMinVolume = AUD_MIN_VOLUME; + DVI.fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + DVI.fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + DVI.fRolloffscale = 1.0f; + DVI.pListener = MyShip; + DVI.pOriginator = shippo; + + // get the volume + fetch_params.volume = AUDm_GetVolumeDistBased( &DVI ); + fetch_params.flags |= SOUNDPARAMS_VOLUME; + } + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( sample_channel_infos[ sci_id ].channel, fetch_wave, &fetch_params ); + } + + return TRUE; + +#else + + AUD_PlaySampleOnChannel( &sample_channel_infos[ sci_id ] ); + return TRUE; + +#endif // DIST_VOLUME + +} + + +// play "You Did It" sample --------------------------------------------------- +// +int AUD_YouDidIt() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_YOU_DID_IT ] ); + return TRUE; +} + + +// play "You Have Lost" sample ------------------------------------------------ +// +int AUD_YouHaveLost() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_YOU_HAVE_LOST ] ); + return TRUE; +} + + +// play li comment sample ----------------------------------------------------- +// +int AUD_LiCommenting( int lcid ) +{ + if ( !AUX_ENABLE_FUNKY_AUDIO_COMMENTS ) + return TRUE; + + //TODO: + + return TRUE; +} + + +// play li comment sample ----------------------------------------------------- +// +int AUD_LiBabbling( int lbid ) +{ + if ( !AUX_ENABLE_FUNKY_AUDIO_COMMENTS ) + return TRUE; + + //TODO: + + return TRUE; +} + + +// tables for different types of jim comment samples -------------------------- +// +struct jim_comment_type_s { + + int sci; + int probability; + int delay; + int _mksiz16; +}; + +#define NUM_JIM_ANGRY 4 +jim_comment_type_s jim_angry[ NUM_JIM_ANGRY ] = { + { SCI_JIM_COMMENT_AFRAID_1, 25, 0 }, + { SCI_JIM_COMMENT_AFRAID_2, 25, 0 }, + { SCI_JIM_COMMENT_ANGRY_1, 25, 0 }, + { SCI_JIM_COMMENT_ANGRY_2, 25, 0 }, +}; + +#define NUM_JIM_WEAPON 2 +jim_comment_type_s jim_weapon[ NUM_JIM_WEAPON ] = { + { SCI_JIM_COMMENT_WEAPON_1, 50, 1000 }, + { SCI_JIM_COMMENT_WEAPON_2, 50, 1000 }, +}; + +#define NUM_JIM_KILLED 2 +jim_comment_type_s jim_killed[ NUM_JIM_KILLED ] = { + { SCI_JIM_COMMENT_KILLED_1, 50, 300 }, + { SCI_JIM_COMMENT_KILLED_2, 50, 300 }, +}; + +#define NUM_JIM_EATTHIS 2 +jim_comment_type_s jim_eatthis[ NUM_JIM_EATTHIS ] = { + { SCI_JIM_COMMENT_EAT_THIS_1, 50, 600 }, + { SCI_JIM_COMMENT_EAT_THIS_2, 50, 600 }, +}; + +#define NUM_JIM_ENERGY 1 +jim_comment_type_s jim_energy[ NUM_JIM_ENERGY ] = { + { SCI_JIM_COMMENT_ENERGY, 100, 800 }, +}; + +#define NUM_JIM_BORED 2 +jim_comment_type_s jim_bored[ NUM_JIM_BORED ] = { + { SCI_JIM_COMMENT_BORED_1, 50, 0 }, + { SCI_JIM_COMMENT_BORED_2, 50, 0 }, +}; + + +// standard random comment selection function --------------------------------- +// +PRIVATE +jim_comment_type_s *SelectCommentRandomly( jim_comment_type_s *tab, int tablen ) +{ + int selrand = RAND() % 100; + int sumrand = 0; + + for ( int sid = 0; sid < tablen; sid++ ) { + if ( selrand < ( tab[ sid ].probability + sumrand ) ) + return &tab[ sid ]; + sumrand += tab[ sid ].probability; + } + + return NULL; +} + + +// select angry comment depending on local damage ----------------------------- +// +PRIVATE +jim_comment_type_s *SelectCommentAngry( jim_comment_type_s *tab, int tablen ) +{ + ASSERT( NUM_JIM_ANGRY == 4 ); + + int selrand = RAND() % 100; + int threshold = (int)( (float)MyShip->MaxDamage * 0.80f ); + + if ( MyShip->CurDamage < threshold ) { + return ( selrand < 50 ) ? &jim_angry[ 0 ] : &jim_angry[ 1 ]; + } else { + return ( selrand < 50 ) ? &jim_angry[ 2 ] : &jim_angry[ 3 ]; + } +} + + +// table for jim comment samples ---------------------------------------------- +// +struct jim_comment_s { + + int probability; + int numentries; + jim_comment_type_s *table; + jim_comment_type_s *(*selfunc)( jim_comment_type_s *tab, int tablen ); +}; + +jim_comment_s jim_comments[] = { + + { 40, NUM_JIM_ANGRY, jim_angry, SelectCommentAngry }, + { 100, NUM_JIM_WEAPON, jim_weapon, SelectCommentRandomly }, + { 100, NUM_JIM_KILLED, jim_killed, SelectCommentRandomly }, + { 100, NUM_JIM_EATTHIS, jim_eatthis, SelectCommentRandomly }, + { 100, NUM_JIM_ENERGY, jim_energy, SelectCommentRandomly }, + { 60, NUM_JIM_BORED, jim_bored, SelectCommentRandomly }, +}; + +#define NUM_JIM_COMMENTS CALC_NUM_ARRAY_ENTRIES( jim_comments ) + + +// play jim comment sample ---------------------------------------------------- +// +int AUD_JimCommenting( int jcid ) +{ + ASSERT( ( jcid >= 0 ) && ( jcid < JIM_COMMENT_NUM_COMMENTS ) ); + ASSERT( NUM_JIM_COMMENTS == JIM_COMMENT_NUM_COMMENTS ); + + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return TRUE; + + if ( !AUX_ENABLE_FUNKY_AUDIO_COMMENTS ) + return TRUE; + + // probability that any comment will be played + int decisionrand = RAND() % 100; + if ( decisionrand >= jim_comments[ jcid ].probability ) + return TRUE; + + // let callback select the comment + jim_comment_type_s *dstcom = + (*jim_comments[ jcid ].selfunc)( jim_comments[ jcid ].table, jim_comments[ jcid ].numentries ); + if ( dstcom == NULL ) + return TRUE; + + // play the comment sample + if ( dstcom->delay == 0 ) { + + AUD_PlaySampleOnChannel( &sample_channel_infos[ dstcom->sci ] ); + + } else { + + event_s *event = (event_s *) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_COUNTDOWN; + event->callback = (event_callback_t) AUD_PlaySampleOnChannel; + event->callback_params = &sample_channel_infos[ dstcom->sci ]; + event->refframe_delay = dstcom->delay; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + } + + return TRUE; +} + + +// play jim babble sample ----------------------------------------------------- +// +int AUD_JimBabbling( int jbid ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return TRUE; + + if ( !AUX_ENABLE_FUNKY_AUDIO_COMMENTS ) + return TRUE; + + //TODO: + + return TRUE; +} + + +// play "amazing" sample ------------------------------------------------------ +// +int AUD_SkillAmazing() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_SKILL_AMAZING ] ); + return TRUE; +} + + +// play "brilliant" sample ---------------------------------------------------- +// +int AUD_SkillBrilliant() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_SKILL_BRILLIANT ] ); + return TRUE; +} + + +// module registration function ----------------------------------------------- +// +REGISTER_MODULE_INIT( AUD_GAME ) +{ + +#ifdef USE_SOUNDSOURCE_LIST + + for( int i = 0; i < NUMCHANNELS; i++ ) { + g_pDistVolumeInfo[ i ] = NULL; + } + +#endif // USE_SOUNDSOURCE_LIST + +} + + +// module deregistration function --------------------------------------------- +// +REGISTER_MODULE_KILL( AUD_GAME ) +{ + +#ifdef USE_SOUNDSOURCE_LIST + + // remove all remaining DistVolumeInfos + for ( int i = 0; i < NUMCHANNELS; i++ ) { + DistVolumeInfo_s* pCurrent = g_pDistVolumeInfo[ i ]; + + for( ; pCurrent != NULL; ) { + + DistVolumeInfo_s* pNext = pCurrent->next; + FREEMEM( pCurrent ); + pCurrent = pNext; + + } + g_pDistVolumeInfo[ i ] = NULL; + } + +#endif // USE_SOUNDSOURCE_LIST + +} + + + |
