mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-20 20:50:58 +02:00
Quake 4 integrated with DoomRTX
This commit is contained in:
@@ -686,6 +686,8 @@ public:
|
||||
// all non-hardware initialization
|
||||
virtual void Init( void );
|
||||
|
||||
virtual idSoundSample* FindSample(const idStr& filename);
|
||||
|
||||
// shutdown routine
|
||||
virtual void Shutdown( void );
|
||||
virtual void ClearBuffer( void );
|
||||
@@ -716,6 +718,9 @@ public:
|
||||
// some tools, like the sound dialog, may be used in both the game and the editor
|
||||
// This can return NULL, so check!
|
||||
virtual idSoundWorld *GetPlayingSoundWorld( void );
|
||||
#ifdef QUAKE4
|
||||
virtual idSoundWorld* GetSoundWorldFromId(int worldId);
|
||||
#endif
|
||||
|
||||
virtual void BeginLevelLoad( void );
|
||||
virtual void EndLevelLoad( const char *mapString );
|
||||
|
||||
@@ -159,12 +159,31 @@ bool idSoundShader::ParseShader(idLexer& src) {
|
||||
int i;
|
||||
idToken token;
|
||||
|
||||
#ifdef QUAKE4
|
||||
parms.minDistance = 40.0f;
|
||||
parms.maxDistance = 400.0f;
|
||||
parms.volume = 1.0f;
|
||||
parms.attenuatedVolume = 0.0f;
|
||||
parms.shakes = 0.0f;
|
||||
parms.soundShaderFlags = 0;
|
||||
parms.soundClass = 0;
|
||||
parms.frequencyShift = 1.0f;
|
||||
parms.wetLevel = 0.0f;
|
||||
parms.dryLevel = 0.0f;
|
||||
|
||||
minFrequencyShift = 1.0f;
|
||||
maxFrequencyShift = 1.0f;
|
||||
|
||||
noShakes = false;
|
||||
frequentlyUsed = false;
|
||||
#else
|
||||
parms.minDistance = 1;
|
||||
parms.maxDistance = 10;
|
||||
parms.volume = 1;
|
||||
parms.shakes = 0;
|
||||
parms.soundShaderFlags = 0;
|
||||
parms.soundClass = 0;
|
||||
#endif
|
||||
|
||||
#ifdef PREY
|
||||
parms.subIndex = 0;
|
||||
@@ -201,9 +220,34 @@ bool idSoundShader::ParseShader(idLexer& src) {
|
||||
|
||||
// minimum number of sounds
|
||||
else if (!token.Icmp("minSamples")) {
|
||||
#ifdef QUAKE4
|
||||
const int requestedSamples = src.ParseInt();
|
||||
if (maxSamples < requestedSamples) {
|
||||
maxSamples = requestedSamples;
|
||||
}
|
||||
if (maxSamples > SOUND_MAX_LIST_WAVS) {
|
||||
maxSamples = SOUND_MAX_LIST_WAVS;
|
||||
}
|
||||
#else
|
||||
maxSamples = idMath::ClampInt(src.ParseInt(), SOUND_MAX_LIST_WAVS, maxSamples);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef QUAKE4
|
||||
// Raven: frequency shift range
|
||||
else if (!token.Icmp("frequencyshift")) {
|
||||
minFrequencyShift = src.ParseFloat();
|
||||
|
||||
if (!src.ExpectTokenString(",")) {
|
||||
src.FreeSource();
|
||||
return false;
|
||||
}
|
||||
|
||||
maxFrequencyShift = src.ParseFloat();
|
||||
parms.frequencyShift = minFrequencyShift;
|
||||
}
|
||||
#endif
|
||||
|
||||
// description
|
||||
else if (!token.Icmp("description")) {
|
||||
src.ReadTokenOnLine(&token);
|
||||
@@ -232,6 +276,23 @@ bool idSoundShader::ParseShader(idLexer& src) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef QUAKE4
|
||||
// Raven: indexed shake amplitude data
|
||||
else if (!token.Icmp("shakeData")) {
|
||||
if (!src.ExpectAnyToken(&token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int shakeIndex = atoi(token.c_str());
|
||||
|
||||
if (!src.ExpectAnyToken(&token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//SetShakeData(shakeIndex, token.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
// reverb -- parsed but unsupported
|
||||
else if (!token.Icmp("reverb")) {
|
||||
src.ParseFloat();
|
||||
@@ -249,6 +310,20 @@ bool idSoundShader::ParseShader(idLexer& src) {
|
||||
parms.volume = src.ParseFloat();
|
||||
}
|
||||
|
||||
#ifdef QUAKE4
|
||||
// Raven: volume specified in decibels, clamped to +10dB
|
||||
else if (!token.Icmp("volumeDb")) {
|
||||
float volumeDb = src.ParseFloat();
|
||||
|
||||
if (volumeDb > 10.0f) {
|
||||
common->Warning("Clamping volume of '%s' to +10dB (3 times louder)", GetName());
|
||||
volumeDb = 10.0f;
|
||||
}
|
||||
|
||||
parms.volume = idMath::dBToScale(volumeDb);
|
||||
}
|
||||
#endif
|
||||
|
||||
// leadinVolume is used to allow light breaking leadin sounds to be much louder than the broken loop
|
||||
else if (!token.Icmp("leadinVolume")) {
|
||||
leadinVolume = src.ParseFloat();
|
||||
@@ -400,6 +475,33 @@ bool idSoundShader::ParseShader(idLexer& src) {
|
||||
parms.soundShaderFlags |= SSF_OMNIDIRECTIONAL;
|
||||
}
|
||||
|
||||
#ifdef QUAKE4
|
||||
// Raven: allow doppler pitch shifting
|
||||
else if (!token.Icmp("useDoppler")) {
|
||||
parms.soundShaderFlags |= SSF_USEDOPPLER;
|
||||
}
|
||||
|
||||
// Raven: don't randomly seek into looping sounds
|
||||
else if (!token.Icmp("noRandomStart")) {
|
||||
parms.soundShaderFlags |= SSF_NO_RANDOMSTART;
|
||||
}
|
||||
|
||||
// Raven: marks VO directed at player/radio chatter
|
||||
else if (!token.Icmp("voForPlayer")) {
|
||||
parms.soundShaderFlags |= SSF_VO_FOR_PLAYER;
|
||||
}
|
||||
|
||||
// Raven: disable generated shake data
|
||||
else if (!token.Icmp("no_shakes")) {
|
||||
noShakes = true;
|
||||
}
|
||||
|
||||
// Raven: force expansion / keep hot
|
||||
else if (!token.Icmp("frequentlyUsed")) {
|
||||
frequentlyUsed = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// onDemand can't be a parms, because we must track all references and overrides would confuse it
|
||||
else if (!token.Icmp("onDemand")) {
|
||||
// no longer loading sounds on demand
|
||||
@@ -415,12 +517,6 @@ bool idSoundShader::ParseShader(idLexer& src) {
|
||||
}
|
||||
|
||||
// HumanHead/Prey: subtitle / subtitlecombat parser
|
||||
//
|
||||
// Supported examples based on the decompiled parser:
|
||||
// subtitle 1.5 "text"
|
||||
// subtitle2 c1 1.5 "text"
|
||||
// subtitlecombat c2 0.25 "combat text"
|
||||
// subtitlecombat3 c4 2.0 "combat text"
|
||||
else if (!token.Icmpn("subtitle", 8)) {
|
||||
const bool combatSubtitle = (token.Icmpn("subtitlecombat", 14) == 0);
|
||||
|
||||
@@ -482,19 +578,35 @@ bool idSoundShader::ParseShader(idLexer& src) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef QUAKE4
|
||||
if (soundSystemLocal.soundCache && numLeadins < maxSamples) {
|
||||
leadins[numLeadins] = soundSystem->FindSample(token.c_str());
|
||||
numLeadins++;
|
||||
}
|
||||
#else
|
||||
if (soundSystemLocal.soundCache && numLeadins < maxSamples) {
|
||||
#ifdef PREY
|
||||
// Prey behavior: do not run the Doom 3 VO language substitution path here.
|
||||
leadins[numLeadins] = soundSystemLocal.soundCache->FindSound(token.c_str(), onDemand);
|
||||
#else
|
||||
leadins[numLeadins] = soundSystemLocal.soundCache->FindSound(token.c_str(), onDemand);
|
||||
#endif
|
||||
numLeadins++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// the regular wave files
|
||||
else if (token.Find(".wav", false) != -1 || token.Find(".ogg", false) != -1) {
|
||||
#ifdef QUAKE4
|
||||
if (soundSystemLocal.soundCache && numEntries < maxSamples) {
|
||||
token.BackSlashesToSlashes();
|
||||
|
||||
entries[numEntries] = soundSystem->FindSample(token.c_str());
|
||||
if (entries[numEntries]) {
|
||||
numEntries++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (soundSystemLocal.soundCache && numEntries < maxSamples) {
|
||||
token.BackSlashesToSlashes();
|
||||
|
||||
@@ -526,6 +638,7 @@ bool idSoundShader::ParseShader(idLexer& src) {
|
||||
entries[numEntries] = soundSystemLocal.soundCache->FindSound(token.c_str(), onDemand);
|
||||
numEntries++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
else {
|
||||
@@ -534,9 +647,15 @@ bool idSoundShader::ParseShader(idLexer& src) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef QUAKE4
|
||||
// if (!soundSystem->GetInsideLevelLoad()) {
|
||||
// soundSystem->ValidateSoundShader(this);
|
||||
// }
|
||||
#else
|
||||
if (parms.shakes > 0.0f) {
|
||||
CheckShakesAndOgg();
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -680,3 +799,15 @@ const char *idSoundShader::GetSound( int index ) const {
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
#ifdef QUAKE4
|
||||
/*
|
||||
===============
|
||||
idSoundShader::IsVO_ForPlayer
|
||||
===============
|
||||
*/
|
||||
bool idSoundShader::IsVO_ForPlayer() const
|
||||
{
|
||||
return (parms.soundShaderFlags & SSF_VO_FOR_PLAYER) != 0;
|
||||
}
|
||||
#endif
|
||||
@@ -1642,4 +1642,24 @@ soundSubtitleList_t* idSoundSystemLocal::GetSubtitleList(int subIndex) {
|
||||
return &subtitleLists[listIndex];
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef QUAKE4
|
||||
idSoundWorld* idSoundSystemLocal::GetSoundWorldFromId(int worldId) {
|
||||
switch (worldId)
|
||||
{
|
||||
case SOUNDWORLD_GAME:
|
||||
case SOUNDWORLD_ANY:
|
||||
return session->sw;
|
||||
case SOUNDWORLD_MENU:
|
||||
return session->menuSoundWorld;
|
||||
|
||||
default:
|
||||
return session->sw;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
idSoundSample* idSoundSystemLocal::FindSample(const idStr& filename) {
|
||||
return soundCache->FindSound(filename, false);
|
||||
}
|
||||
+110
-7
@@ -56,6 +56,26 @@ static const int SSF_UNCLAMPED = BIT(7); // don't clamp calculated volumes at
|
||||
static const int SSF_NO_FLICKER = BIT(8); // always return 1.0 for volume queries
|
||||
static const int SSF_NO_DUPS = BIT(9); // try not to play the same sound twice in a row
|
||||
|
||||
#ifdef QUAKE4
|
||||
// sound classes are used to fade most sounds down inside cinematics, leaving dialog
|
||||
// flagged with a non-zero class full volume
|
||||
const int SOUND_CLASS_MUSICAL = 3;
|
||||
const int SOUND_MAX_CLASSES = 4;
|
||||
|
||||
static const int SSF_VO = BIT(10); // VO - direct a portion of the sound through the center channel (set automatically on shaders that contain files that start with "sound/vo/")
|
||||
static const int SSF_MUSIC = BIT(11); // Music - Muted when the player is playing his own music
|
||||
|
||||
// RAVEN BEGIN
|
||||
static const int SSF_USEDOPPLER = BIT(17); // allow doppler pitch shifting effects
|
||||
static const int SSF_NO_RANDOMSTART = BIT(18); // don't offset the start position for looping sounds
|
||||
static const int SSF_VO_FOR_PLAYER = BIT(12); // Notifies a funcRadioChatter that this shader is directed at the player
|
||||
static const int SSF_IS_VO = BIT(13); // this sound is VO
|
||||
static const int SSF_CAUSE_RUMBLE = BIT(14); // causes joystick rumble
|
||||
static const int SSF_CENTER = BIT(15); // sound through center channel only
|
||||
static const int SSF_HILITE = BIT(16); // display debug info for this emitter
|
||||
// RAVEN END
|
||||
#endif
|
||||
|
||||
#ifdef PREY
|
||||
static const int SSF_VOICEAMPLITUDE = BIT(10); // HUMANHEAD pdm: include in findamplitude queries
|
||||
static const int SSF_OMNI_WHEN_CLOSE = BIT(11); // HUMANHEAD pdm: make omni when within the mindistance
|
||||
@@ -74,15 +94,23 @@ static const int SSF_NOPORTALFLOW = BIT(13); // don't allow sounds to flow thro
|
||||
typedef struct {
|
||||
float minDistance;
|
||||
float maxDistance;
|
||||
float volume; // in dB, unfortunately. Negative values get quieter
|
||||
float volume;
|
||||
#ifdef QUAKE4
|
||||
float attenuatedVolume;
|
||||
#endif
|
||||
float shakes;
|
||||
int soundShaderFlags; // SSF_* bit flags
|
||||
int soundClass; // for global fading of sounds
|
||||
int soundShaderFlags;
|
||||
int soundClass;
|
||||
#ifdef QUAKE4
|
||||
float frequencyShift;
|
||||
float wetLevel;
|
||||
float dryLevel;
|
||||
#endif
|
||||
#ifdef PREY
|
||||
int subIndex; //HUMANHEAD rww - indices into the subtitle table
|
||||
int profanityIndex; // HUMANHEAD pdm
|
||||
float profanityDelay; // HUMANHEAD pdm
|
||||
float profanityDuration; // HUMANHEAD pdm
|
||||
int subIndex;
|
||||
int profanityIndex;
|
||||
float profanityDelay;
|
||||
float profanityDuration;
|
||||
#endif
|
||||
} soundShaderParms_t;
|
||||
|
||||
@@ -117,6 +145,13 @@ const int SOUNDCLASS_SPIRITWALK = 2;
|
||||
const int SOUNDCLASS_VOICE = 3;
|
||||
const int SOUNDCLASS_MUSIC = 4;
|
||||
const int SOUND_MAX_CLASSES = 5;
|
||||
#elif defined(QUAKE4)
|
||||
#define SOUNDWORLD_ANY -1
|
||||
#define SOUNDWORLD_NONE 0
|
||||
#define SOUNDWORLD_GAME 1
|
||||
#define SOUNDWORLD_MENU 2
|
||||
#define SOUNDWORLD_EDITOR 3
|
||||
#define SOUNDWORLD_MAX 4
|
||||
#else
|
||||
const int SOUND_MAX_CLASSES = 4;
|
||||
#endif
|
||||
@@ -156,6 +191,10 @@ public:
|
||||
|
||||
virtual bool CheckShakesAndOgg( void ) const;
|
||||
|
||||
#ifdef QUAKE4
|
||||
virtual bool IsVO_ForPlayer() const;
|
||||
#endif
|
||||
|
||||
private:
|
||||
friend class idSoundWorldLocal;
|
||||
friend class idSoundEmitterLocal;
|
||||
@@ -176,7 +215,16 @@ private:
|
||||
int numLeadins;
|
||||
idSoundSample * entries[SOUND_MAX_LIST_WAVS];
|
||||
int numEntries;
|
||||
#ifdef QUAKE4
|
||||
bool noShakes;
|
||||
bool frequentlyUsed;
|
||||
idStrList shakes;
|
||||
|
||||
float minFrequencyShift;
|
||||
float maxFrequencyShift;
|
||||
|
||||
int playCount;
|
||||
#endif
|
||||
private:
|
||||
void Init( void );
|
||||
bool ParseShader( idLexer &src );
|
||||
@@ -209,6 +257,11 @@ public:
|
||||
// the parms specified will be the default overrides for all sounds started on this emitter.
|
||||
// NULL is acceptable for parms
|
||||
virtual void UpdateEmitter( const idVec3 &origin, int listenerId, const soundShaderParms_t *parms ) = 0;
|
||||
#ifdef QUAKE4
|
||||
virtual void UpdateEmitter(const idVec3& origin, const idVec3& velocity, int listenerId, const soundShaderParms_t* parms) {
|
||||
UpdateEmitter(origin, listenerId, parms); // TODO implement velocity!
|
||||
}
|
||||
#endif
|
||||
|
||||
// returns the length of the started sound in msec
|
||||
virtual int StartSound( const idSoundShader *shader, const s_channelType channel, float diversity = 0, int shaderFlags = 0, bool allowSlow = true ) = 0;
|
||||
@@ -396,12 +449,62 @@ public:
|
||||
// is EAX support present - -1: disabled at compile time, 0: no suitable hardware, 1: ok, 2: failed to load OpenAL DLL
|
||||
virtual int IsEAXAvailable( void ) = 0;
|
||||
|
||||
virtual idSoundSample* FindSample(const idStr& filename) = 0;
|
||||
#ifdef PREY
|
||||
virtual int GetSubtitleIndex( const char *soundName ) = 0;
|
||||
virtual void SetSubtitleData( int subIndex, int subNum, const char *subText, float subTime, int subChannel ) = 0;
|
||||
virtual soundSub_t * GetSubtitle( int subIndex, int subNum ) = 0;
|
||||
virtual soundSubtitleList_t *GetSubtitleList( int subIndex ) = 0;
|
||||
#endif
|
||||
|
||||
#ifdef QUAKE4
|
||||
// jmarshall: Quake 4 specific code
|
||||
// RAVEN BEGIN
|
||||
// get a new emitter that can play sounds in this world
|
||||
virtual idSoundWorld* GetSoundWorldFromId(int worldId) = 0;
|
||||
|
||||
idSoundEmitter* EmitterForIndex(int worldId, int index) {
|
||||
return GetSoundWorldFromId(worldId)->EmitterForIndex(index);
|
||||
}
|
||||
|
||||
void FadeSoundClasses(int worldId, const int soundClass, const float to, const float over) {
|
||||
GetSoundWorldFromId(worldId)->FadeSoundClasses(soundClass, to, over);
|
||||
}
|
||||
|
||||
void PlayShaderDirectly(int worldId, const char* name, int channel = -1) {
|
||||
GetSoundWorldFromId(worldId)->PlayShaderDirectly(name, channel);
|
||||
}
|
||||
|
||||
virtual int AllocSoundEmitter(int worldId) {
|
||||
return GetSoundWorldFromId(worldId)->AllocSoundEmitter()->Index();
|
||||
}
|
||||
virtual void FreeSoundEmitter(int worldId, int handle, bool immediate) {
|
||||
|
||||
}
|
||||
|
||||
virtual void StopAllSounds(int worldId) {
|
||||
GetSoundWorldFromId(worldId)->StopAllSounds();
|
||||
}
|
||||
|
||||
virtual void SetActiveSoundWorld(bool val) { }
|
||||
|
||||
virtual void WriteToSaveGame(int worldId, idFile* savefile) {
|
||||
GetSoundWorldFromId(worldId)->WriteToSaveGame(savefile);
|
||||
}
|
||||
virtual void ReadFromSaveGame(int worldId, idFile* savefile) {
|
||||
GetSoundWorldFromId(worldId)->ReadFromSaveGame(savefile);
|
||||
}
|
||||
|
||||
void PlaceListener(const idVec3& origin, const idMat3& axis, const int listenerId, const int gameTime, const idStr& areaName) {
|
||||
GetSoundWorldFromId(SOUNDWORLD_GAME)->PlaceListener(origin, axis, listenerId, gameTime, areaName);
|
||||
}
|
||||
|
||||
virtual float CurrentShakeAmplitudeForPosition(int worldId, const int time, const idVec3& listenerPosition) {
|
||||
return GetSoundWorldFromId(worldId)->CurrentShakeAmplitudeForPosition(time, listenerPosition);
|
||||
}
|
||||
// RAVEN END
|
||||
// jmarshall end
|
||||
#endif
|
||||
};
|
||||
|
||||
extern idSoundSystem *soundSystem;
|
||||
|
||||
Reference in New Issue
Block a user