/* =========================================================================== Copyright (C) 2015 the OpenMoHAA team This file is part of OpenMoHAA source code. OpenMoHAA source code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. OpenMoHAA source code 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 OpenMoHAA source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ // soundman.cpp: Sound Manager // #include "g_local.h" #include "debuglines.h" #include "entity.h" #include "trigger.h" #include "player.h" #include "soundman.h" SoundManager SoundMan; /****************************************************************************** Sound Manager ******************************************************************************/ Event EV_SoundManager_AddSpeaker ( "addspeaker", EV_CONSOLE, NULL, NULL, "Add a new sound where the player is standing.", EV_NORMAL ); Event EV_SoundManager_AddRandomSpeaker ( "addrandomspeaker", EV_CONSOLE, NULL, NULL, "Add a new sound where the player is standing.", EV_NORMAL ); Event EV_SoundManager_AddMusicTrigger ( "addmusictrigger", EV_CONSOLE, NULL, NULL, "Add a new music trigger where the player is standing.", EV_NORMAL ); Event EV_SoundManager_AddReverbTrigger ( "addreverbtrigger", EV_CONSOLE, NULL, NULL, "Add a new reverb trigger where the player is standing.", EV_NORMAL ); Event EV_SoundManager_Replace ( "replace", EV_CONSOLE, NULL, NULL, "Replace the current sound position with the player's.", EV_NORMAL ); Event EV_SoundManager_Delete ( "delete", EV_CONSOLE, NULL, NULL, "Delete the current sound.", EV_NORMAL ); Event EV_SoundManager_MovePlayer ( "moveplayer", EV_CONSOLE, NULL, NULL, "Move the player to the current sound position.", EV_NORMAL ); Event EV_SoundManager_Next ( "next", EV_CONSOLE, NULL, NULL, "Go to the next sound.", EV_NORMAL ); Event EV_SoundManager_Previous ( "prev", EV_CONSOLE, NULL, NULL, "Go to the previous sound.", EV_NORMAL ); Event EV_SoundManager_Show ( "show", EV_CONSOLE, "E", "path", "Show all the sounds.", EV_NORMAL ); Event EV_SoundManager_ShowingSounds ( "_showing_sounds", EV_CONSOLE, NULL, NULL, "Internal event for showing the sounds.", EV_NORMAL ); Event EV_SoundManager_Hide ( "hide", EV_CONSOLE, NULL, NULL, "Hides the sounds.", EV_NORMAL ); Event EV_SoundManager_Save ( "save", EV_CONSOLE, NULL, NULL, "Saves the sounds.", EV_NORMAL ); Event EV_SoundManager_UpdateInput ( "updateinput", EV_CONSOLE, NULL, NULL, "Updates the current sound with user interface values.", EV_NORMAL ); Event EV_SoundManager_Reset ( "reset", EV_CONSOLE, NULL, NULL, "Resets the state of all sounds and triggers.", EV_NORMAL ); Event EV_SoundManager_GlobalTranslate ( "globaltranslate", EV_CONSOLE, "v", "translate_amount", "Translates all sounds and triggers by specified amount.", EV_NORMAL ); Event EV_SoundManager_SwitchFacet ( "switchfacet", EV_CONSOLE, NULL, NULL, "Switch the current facet that we are editing.", EV_NORMAL ); Event EV_SoundManager_PreviewReverb ( "previewreverb", EV_CONSOLE, NULL, NULL, "Test out the current reverb settings.", EV_NORMAL ); Event EV_SoundManager_ResetReverb ( "resetreverb", EV_CONSOLE, NULL, NULL, "reset the reverb settings to a normal.", EV_NORMAL ); CLASS_DECLARATION(Listener, SoundManager, NULL) { {&EV_SoundManager_AddSpeaker, &SoundManager::AddSpeaker }, {&EV_SoundManager_AddRandomSpeaker, &SoundManager::AddRandomSpeaker }, {&EV_SoundManager_AddMusicTrigger, &SoundManager::AddMusicTrigger }, {&EV_SoundManager_AddReverbTrigger, &SoundManager::AddReverbTrigger }, {&EV_SoundManager_Replace, &SoundManager::Replace }, {&EV_SoundManager_Delete, &SoundManager::Delete }, {&EV_SoundManager_MovePlayer, &SoundManager::MovePlayer }, {&EV_SoundManager_Next, &SoundManager::Next }, {&EV_SoundManager_Previous, &SoundManager::Previous }, {&EV_SoundManager_Show, &SoundManager::Show }, {&EV_SoundManager_ShowingSounds, &SoundManager::ShowingSounds }, {&EV_SoundManager_Hide, &SoundManager::Hide }, {&EV_SoundManager_Save, &SoundManager::Save }, {&EV_SoundManager_UpdateInput, &SoundManager::UpdateEvent }, {&EV_SoundManager_Reset, &SoundManager::ResetEvent }, {&EV_SoundManager_GlobalTranslate, &SoundManager::GlobalTranslateEvent}, {&EV_SoundManager_SwitchFacet, &SoundManager::SwitchFacetEvent }, {&EV_SoundManager_PreviewReverb, &SoundManager::PreviewReverbEvent }, {&EV_SoundManager_ResetReverb, &SoundManager::ResetReverbEvent }, {NULL, NULL } }; Player *SoundManager_GetPlayer(void) { assert(g_entities[0].entity && g_entities[0].entity->isSubclassOf(Player)); if (!g_entities[0].entity || !(g_entities[0].entity->isSubclassOf(Player))) { gi.Printf("No player found.\n"); return NULL; } return (Player *)g_entities[0].entity; } SoundManager::SoundManager() { currentFacet = 0; Reset(); } void SoundManager::Reset(void) { current = NULL; soundList.ClearObjectList(); } void SoundManager::UpdateUI(void) { if (current) { gi.cvar_set("snd_multifaceted", ""); gi.cvar_set("snd_currentfacet", ""); gi.cvar_set("snd_onetime", "0"); gi.cvar_set("snd_useangles", "0"); gi.cvar_set("snd_yaw", "0"); gi.cvar_set("snd_origin", va("%.2f %.2f %.2f", current->origin[0], current->origin[1], current->origin[2])); gi.cvar_set("snd_targetname", current->targetname.c_str()); if (current->isSubclassOf(TriggerSpeaker)) { TriggerSpeaker *speaker; speaker = (TriggerSpeaker *)current; if (speaker->volume != DEFAULT_VOL) { gi.cvar_set("snd_volume", va("%.1f", speaker->volume)); } else { gi.cvar_set("snd_volume", "Default"); } if (speaker->min_dist != DEFAULT_MIN_DIST) { gi.cvar_set("snd_mindist", va("%.1f", speaker->min_dist)); } else { gi.cvar_set("snd_mindist", "Default"); } // setup the sound gi.cvar_set("ui_pickedsound", speaker->Noise().c_str()); if (current->isSubclassOf(RandomSpeaker)) { RandomSpeaker *random; random = (RandomSpeaker *)current; gi.cvar_set("snd_mindelay", va("%.1f", random->mindelay)); gi.cvar_set("snd_maxdelay", va("%.1f", random->maxdelay)); gi.cvar_set("snd_channel", va("%d", random->channel)); gi.cvar_set("snd_chance", va("%.1f", random->chance)); gi.cvar_set("snd_type", "RandomSpeaker"); } else { gi.cvar_set("snd_type", "Speaker"); } } else if (current->isSubclassOf(TriggerMusic) || current->isSubclassOf(TriggerReverb)) { int multiFaceted; Trigger *trigger; trigger = (Trigger *)current; gi.cvar_set("snd_width", va("%.0f", trigger->maxs[0])); gi.cvar_set("snd_length", va("%.0f", trigger->maxs[1])); gi.cvar_set("snd_height", va("%.0f", trigger->maxs[2])); if (trigger->UsingTriggerDir()) { gi.cvar_set("snd_useangles", "1"); } else { gi.cvar_set("snd_useangles", "0"); } gi.cvar_set("snd_yaw", va("%.0f", trigger->angles[1])); multiFaceted = trigger->GetMultiFaceted(); if (multiFaceted) { if (multiFaceted == 1) { gi.cvar_set("snd_multifaceted", "North/South"); if (currentFacet) { gi.cvar_set("snd_currentfacet", "South"); } else { gi.cvar_set("snd_currentfacet", "North"); } } else { gi.cvar_set("snd_multifaceted", "East/West"); if (currentFacet) { gi.cvar_set("snd_currentfacet", "West"); } else { gi.cvar_set("snd_currentfacet", "East"); } } } else { gi.cvar_set("snd_multifaceted", "Not"); } if (current->isSubclassOf(TriggerMusic)) { TriggerMusic *music; music = (TriggerMusic *)trigger; gi.cvar_set("snd_type", "MusicTrigger"); if (music->oneshot) { gi.cvar_set("snd_onetime", "1"); } else { gi.cvar_set("snd_onetime", "0"); } if (!currentFacet) { gi.cvar_set("snd_currentmood", Director.GetString(music->current).c_str()); gi.cvar_set("snd_fallbackmood", Director.GetString(music->fallback).c_str()); } else { gi.cvar_set("snd_currentmood", Director.GetString(music->altcurrent).c_str()); gi.cvar_set("snd_fallbackmood", Director.GetString(music->altfallback).c_str()); } } else if (current->isSubclassOf(TriggerReverb)) { TriggerReverb *reverb; reverb = (TriggerReverb *)trigger; gi.cvar_set("snd_type", "ReverbTrigger"); if (reverb->oneshot) { gi.cvar_set("snd_onetime", "1"); } else { gi.cvar_set("snd_onetime", "0"); } if (!currentFacet) { gi.cvar_set("snd_reverbtypedisplay", EAXMode_NumToName(reverb->reverbtype)); gi.cvar_set("snd_reverbtype", va("%d", reverb->reverbtype)); gi.cvar_set("snd_reverblevel", va("%.2f", reverb->reverblevel)); } else { gi.cvar_set("snd_reverbtypedisplay", EAXMode_NumToName(reverb->altreverbtype)); gi.cvar_set("snd_reverbtype", va("%d", reverb->altreverbtype)); gi.cvar_set("snd_reverblevel", va("%.2f", reverb->altreverblevel)); } } } if (EventPending(EV_SoundManager_ShowingSounds)) { gi.cvar_set("snd_hiddenstate", "visible"); } else { gi.cvar_set("snd_hiddenstate", "hidden"); } gi.cvar_set("snd_speakernum", va("%d", soundList.IndexOfObject(current) - 1)); } } void SoundManager::UpdateRandomSpeaker(RandomSpeaker *speaker) { cvar_t *cvar; Vector tempvec; if (!speaker) { return; } // get origin cvar = gi.Cvar_Get("snd_origin", "", 0); sscanf(cvar->string, "%f %f %f", &tempvec[0], &tempvec[1], &tempvec[2]); speaker->setOrigin(tempvec); // get targetname cvar = gi.Cvar_Get("snd_targetname", "", 0); speaker->SetTargetName(cvar->string); // get volume cvar = gi.Cvar_Get("snd_volume", "", 0); if (str(cvar->string) == "Default") { speaker->SetVolume(DEFAULT_VOL); } else { speaker->SetVolume(cvar->value); } // get min_dist cvar = gi.Cvar_Get("snd_mindist", "", 0); if (str(cvar->string) == "Default") { speaker->SetMinDist(DEFAULT_MIN_DIST); } else { speaker->SetMinDist(cvar->value); } // get mindelay cvar = gi.Cvar_Get("snd_mindelay", "", 0); speaker->SetMinDelay(cvar->value); // get maxdelay cvar = gi.Cvar_Get("snd_maxdelay", "", 0); speaker->SetMaxDelay(cvar->value); // get chance cvar = gi.Cvar_Get("snd_chance", "", 0); speaker->SetChance(cvar->value); // get sound cvar = gi.Cvar_Get("ui_pickedsound", "", 0); if (cvar->string[0]) { speaker->SetNoise(cvar->string); speaker->ScheduleSound(); } } void SoundManager::UpdateSpeaker(TriggerSpeaker *speaker) { cvar_t *cvar; Vector tempvec; if (!speaker) { return; } // // make sure the speaker is an ambient speaker // speaker->ambient = true; // get origin cvar = gi.Cvar_Get("snd_origin", "", 0); sscanf(cvar->string, "%f %f %f", &tempvec[0], &tempvec[1], &tempvec[2]); speaker->setOrigin(tempvec); // get targetname cvar = gi.Cvar_Get("snd_targetname", "", 0); speaker->SetTargetName(cvar->string); // get volume cvar = gi.Cvar_Get("snd_volume", "", 0); if (str(cvar->string) == "Default") { speaker->SetVolume(DEFAULT_VOL); } else { speaker->SetVolume(cvar->value); } // get min_dist cvar = gi.Cvar_Get("snd_mindist", "", 0); if (str(cvar->string) == "Default") { speaker->SetMinDist(DEFAULT_MIN_DIST); } else { speaker->SetMinDist(cvar->value); } // get sound cvar = gi.Cvar_Get("ui_pickedsound", "", 0); if (cvar->string[0]) { speaker->SetNoise(cvar->string); speaker->StartSound(); } } void SoundManager::UpdateTriggerMusic(TriggerMusic *music) { cvar_t *cvar; str current; str fallback; str faceted; Vector tempvec; if (!music) { return; } // // go to a known state // music->SetOneShot(false); // no angle use music->useTriggerDir = false; // make sure it doesn't trigger music->triggerable = false; // get origin cvar = gi.Cvar_Get("snd_origin", "", 0); sscanf(cvar->string, "%f %f %f", &tempvec[0], &tempvec[1], &tempvec[2]); music->setOrigin(tempvec); // get targetname cvar = gi.Cvar_Get("snd_targetname", "", 0); music->SetTargetName(cvar->string); // get width cvar = gi.Cvar_Get("snd_width", "", 0); music->mins[0] = -cvar->value; music->maxs[0] = cvar->value; // get length cvar = gi.Cvar_Get("snd_length", "", 0); music->mins[1] = -cvar->value; music->maxs[1] = cvar->value; // get height cvar = gi.Cvar_Get("snd_height", "", 0); music->mins[2] = 0; music->maxs[2] = cvar->value; music->setSize(music->mins, music->maxs); // get current multi faceted ness cvar = gi.Cvar_Get("snd_multifaceted", "", 0); faceted = cvar->string; if (faceted == "North/South") { music->SetMultiFaceted(1); } else if (faceted == "East/West") { music->SetMultiFaceted(2); } else { music->SetMultiFaceted(0); } // get current mood cvar = gi.Cvar_Get("snd_currentmood", "", 0); current = cvar->string; // get fallback mood cvar = gi.Cvar_Get("snd_fallbackmood", "", 0); fallback = cvar->string; if (music->multiFaceted && currentFacet) { music->SetAltMood(current, fallback); } else { music->SetMood(current, fallback); } // get onetime cvar = gi.Cvar_Get("snd_onetime", "", 0); if (cvar->integer) { music->SetOneShot(true); } // get yaw cvar = gi.Cvar_Get("snd_yaw", "", 0); music->angles[YAW] = cvar->value; music->setAngles(); // get useangles cvar = gi.Cvar_Get("snd_useangles", "", 0); if (cvar->integer) { music->SetTriggerDir(music->angles[YAW]); } UpdateUI(); } void SoundManager::UpdateTriggerReverb(TriggerReverb *reverb) { cvar_t *cvar; int reverbtype; float reverblevel; str faceted; Vector tempvec; if (!reverb) { return; } // // go to a known state // reverb->SetOneShot(false); // no angle use reverb->useTriggerDir = false; // make sure it doesn't trigger reverb->triggerable = false; // get origin cvar = gi.Cvar_Get("snd_origin", "", 0); sscanf(cvar->string, "%f %f %f", &tempvec[0], &tempvec[1], &tempvec[2]); reverb->setOrigin(tempvec); // get targetname cvar = gi.Cvar_Get("snd_targetname", "", 0); reverb->SetTargetName(cvar->string); // get width cvar = gi.Cvar_Get("snd_width", "", 0); reverb->mins[0] = -cvar->value; reverb->maxs[0] = cvar->value; // get length cvar = gi.Cvar_Get("snd_length", "", 0); reverb->mins[1] = -cvar->value; reverb->maxs[1] = cvar->value; // get height cvar = gi.Cvar_Get("snd_height", "", 0); reverb->mins[2] = 0; reverb->maxs[2] = cvar->value; reverb->setSize(reverb->mins, reverb->maxs); // get current multi faceted ness cvar = gi.Cvar_Get("snd_multifaceted", "", 0); faceted = cvar->string; if (faceted == "North/South") { reverb->SetMultiFaceted(1); } else if (faceted == "East/West") { reverb->SetMultiFaceted(2); } else { reverb->SetMultiFaceted(0); } // get reverb type cvar = gi.Cvar_Get("snd_reverbtype", "", 0); reverbtype = cvar->integer; // get reverb level cvar = gi.Cvar_Get("snd_reverblevel", "", 0); reverblevel = cvar->value; if (reverb->multiFaceted && currentFacet) { reverb->SetAltReverb(reverbtype, reverblevel); } else { reverb->SetReverb(reverbtype, reverblevel); } // get onetime cvar = gi.Cvar_Get("snd_onetime", "", 0); if (cvar->integer) { reverb->SetOneShot(true); } // get yaw cvar = gi.Cvar_Get("snd_yaw", "", 0); reverb->angles[YAW] = cvar->value; reverb->setAngles(); // get useangles cvar = gi.Cvar_Get("snd_useangles", "", 0); if (cvar->integer) { reverb->SetTriggerDir(reverb->angles[YAW]); } UpdateUI(); } void SoundManager::UpdateEvent(Event *ev) { if (!current) { return; } if (current->isSubclassOf(RandomSpeaker)) { UpdateRandomSpeaker((RandomSpeaker *)current); } else if (current->isSubclassOf(TriggerSpeaker)) { UpdateSpeaker((TriggerSpeaker *)current); } else if (current->isSubclassOf(TriggerMusic)) { UpdateTriggerMusic((TriggerMusic *)current); } else if (current->isSubclassOf(TriggerReverb)) { UpdateTriggerReverb((TriggerReverb *)current); } } void SoundManager::AddSpeaker(Event *ev) { Player *player; Vector ang; Vector pos; player = SoundManager_GetPlayer(); if (player) { player->GetPlayerView(&pos, &ang); current = new TriggerSpeaker; current->setOrigin(pos); current->setAngles(ang); soundList.AddUniqueObject(current); Show(); } UpdateUI(); } void SoundManager::AddRandomSpeaker(Event *ev) { Player *player; Vector ang; Vector pos; player = SoundManager_GetPlayer(); if (player) { player->GetPlayerView(&pos, &ang); current = new RandomSpeaker; current->setOrigin(pos); current->setAngles(ang); soundList.AddUniqueObject(current); Show(); } UpdateUI(); } void SoundManager::AddMusicTrigger(Event *ev) { Player *player; Vector ang; player = SoundManager_GetPlayer(); if (player) { player->GetPlayerView(NULL, &ang); current = new TriggerMusic; // we grab the origin from the feet of the player current->setOrigin(player->origin); current->setAngles(ang); current->setSize(Vector("-16 -16 0"), Vector("16 16 64")); // make sure it doesn't trigger ((TriggerMusic *)current)->triggerable = false; soundList.AddUniqueObject(current); Show(); } UpdateUI(); } void SoundManager::AddReverbTrigger(Event *ev) { Player *player; Vector ang; player = SoundManager_GetPlayer(); if (player) { player->GetPlayerView(NULL, &ang); current = new TriggerReverb; // we grab the origin from the feet of the player current->setOrigin(player->origin); current->setAngles(ang); current->setSize(Vector("-16 -16 0"), Vector("16 16 64")); // make sure it doesn't trigger ((TriggerReverb *)current)->triggerable = false; soundList.AddUniqueObject(current); Show(); } UpdateUI(); } void SoundManager::Replace(Event *ev) { Player *player; Vector ang; Vector pos; player = SoundManager_GetPlayer(); if (current && player) { player->GetPlayerView(&pos, &ang); if (current->isSubclassOf(TriggerMusic) || current->isSubclassOf(TriggerReverb)) { current->setOrigin(player->origin); } else { current->setOrigin(pos); } current->setAngles(ang); } UpdateUI(); } void SoundManager::Delete(Event *ev) { int index = 0; if (!current) { return; } if (soundList.ObjectInList(current)) { index = soundList.IndexOfObject(current); // remove the speaker soundList.RemoveObject(current); } current->PostEvent(EV_Remove, 0); if ((index > 0) && (index < soundList.NumObjects())) { current = soundList.ObjectAt(index); CurrentGainsFocus(); } else { current = NULL; } UpdateUI(); } void SoundManager::MovePlayer(Event *ev) { Player *player; Vector pos; player = SoundManager_GetPlayer(); if (current && player) { player->GetPlayerView(&pos, NULL); if (current->isSubclassOf(TriggerMusic) || current->isSubclassOf(TriggerReverb)) { player->setOrigin(current->origin); } else { player->setOrigin(current->origin - pos + player->origin); } player->SetViewAngles(current->angles); } } void SoundManager::CurrentLostFocus(void) { if (current) { if (current->isSubclassOf(TriggerMusic) || current->isSubclassOf(TriggerReverb)) { current->PostEvent(EV_Trigger_SetTriggerable, 0.1f); } } } void SoundManager::CurrentGainsFocus(void) { if (current) { if (current->isSubclassOf(TriggerMusic) || current->isSubclassOf(TriggerReverb)) { current->ProcessEvent(EV_Trigger_SetNotTriggerable); } } } void SoundManager::Next(Event *ev) { int index; currentFacet = 0; if (current) { // // find current sound in container of sounds // index = soundList.IndexOfObject(current); if (index < soundList.NumObjects()) { index++; } else { index = 1; } CurrentLostFocus(); } else { index = 1; } if (index <= soundList.NumObjects()) { current = soundList.ObjectAt(index); CurrentGainsFocus(); UpdateUI(); } } void SoundManager::Previous(Event *ev) { int index; currentFacet = 0; if (current) { // // find current sound in container of sounds // index = soundList.IndexOfObject(current); if (index > 1) { index--; } else { index = soundList.NumObjects(); } CurrentLostFocus(); } else { index = 1; } if (index <= soundList.NumObjects()) { current = soundList.ObjectAt(index); CurrentGainsFocus(); UpdateUI(); } } void SoundManager::ResetEvent(Event *ev) { int i; Entity *ent; for (i = 1; i <= soundList.NumObjects(); i++) { ent = soundList.ObjectAt(i); if (ent->isSubclassOf(TriggerSpeaker)) { // nothing to reset } else if (ent->isSubclassOf(TriggerMusic)) { TriggerMusic *music; music = (TriggerMusic *)ent; music->SetOneShot(music->oneshot); } else if (ent->isSubclassOf(TriggerReverb)) { TriggerReverb *reverb; reverb = (TriggerReverb *)ent; reverb->SetOneShot(reverb->oneshot); } } } void SoundManager::GlobalTranslateEvent(Event *ev) { int i; Entity *ent; Vector amount; amount = ev->GetVector(1); for (i = 1; i <= soundList.NumObjects(); i++) { ent = soundList.ObjectAt(i); ent->addOrigin(amount); } } void SoundManager::SwitchFacetEvent(Event *ev) { if (current && current->isSubclassOf(Trigger)) { Trigger *trigger; trigger = (Trigger *)current; if (trigger->GetMultiFaceted() && !currentFacet) { currentFacet = 1; } else { currentFacet = 0; } } UpdateUI(); } void SoundManager::PreviewReverbEvent(Event *ev) { cvar_t *cvar; int reverbtype; float reverblevel; // get reverb type cvar = gi.Cvar_Get("snd_reverbtype", "", 0); reverbtype = cvar->integer; // get reverb level cvar = gi.Cvar_Get("snd_reverblevel", "", 0); reverblevel = cvar->value; if (g_entities[0].inuse && g_entities[0].client) { Player *client; client = (Player *)g_entities[0].entity; client->SetReverb(reverbtype, reverblevel); } } void SoundManager::ResetReverbEvent(Event *ev) { if (g_entities[0].inuse && g_entities[0].client) { Player *client; client = (Player *)g_entities[0].entity; client->SetReverb("Generic", 0); } } void SoundManager::ShowingSounds(Event *ev) { int i; Entity *ent; for (i = 1; i <= soundList.NumObjects(); i++) { ent = soundList.ObjectAt(i); if (ent->isSubclassOf(TriggerSpeaker)) { TriggerSpeaker *speaker; speaker = (TriggerSpeaker *)ent; if (current == ent) { if (speaker->volume != DEFAULT_VOL) { G_DrawDebugNumber(speaker->origin + Vector(0, 0, 10), speaker->volume, 0.5, 0, 1, 0, 2); } if (speaker->min_dist != DEFAULT_MIN_DIST) { G_DrawDebugNumber(speaker->origin + Vector(0, 0, 20), speaker->min_dist, 0.5, 0, 0, 1, 0); } // falloff circles if (speaker->min_dist != DEFAULT_VOL) { G_DebugCircle(speaker->origin, speaker->min_dist, 0, 1, 1, 1, true); G_DebugCircle(speaker->origin, 2 * speaker->min_dist, 0, 0.5, 0.5, 0.5, true); G_DebugCircle(speaker->origin, 4 * speaker->min_dist, 0, 0.25, 0.25, 0.25, true); } if (speaker->isSubclassOf(RandomSpeaker)) { RandomSpeaker *random; G_DebugPyramid(speaker->origin, 24, 1, 1, 0.5, 1); random = (RandomSpeaker *)ent; G_DrawDebugNumber(random->origin + Vector(0, 0, 30), random->mindelay, 0.5, 0.25, 0, 1, 1); G_DrawDebugNumber(random->origin + Vector(0, 0, 38), random->maxdelay, 0.5, 0.25, 0, 1, 1); G_DrawDebugNumber(random->origin + Vector(0, 0, 46), random->chance, 0.5, 0.25, 0, 1, 2); } else { G_DebugPyramid(speaker->origin, 24, 1, 1, 0, 1); } } else { if (speaker->isSubclassOf(RandomSpeaker)) { G_DebugPyramid(speaker->origin, 24, 1, 0, 1, 1); } else { G_DebugPyramid(speaker->origin, 24, 1, 0, 0, 1); } } } else if (ent->isSubclassOf(TriggerMusic)) { int facet; TriggerMusic *music; music = (TriggerMusic *)ent; if (current == ent) { if (music->oneshot) { G_DebugBBox(ent->origin, ent->mins, ent->maxs, 0, 1, 1, 1); } else { G_DebugBBox(ent->origin, ent->mins, ent->maxs, 1, 1, 0, 1); } } else { if (music->oneshot) { G_DebugBBox(ent->origin, ent->mins, ent->maxs, 0, 0.5, 0.5, 1); } else { G_DebugBBox(ent->origin, ent->mins, ent->maxs, 1, 0, 0, 1); } } if (music->useTriggerDir) { Vector org; org = ent->origin; org[2] += 0.5f * ent->maxs[2]; G_DebugArrow(org, music->GetTriggerDir(), 48, 0.5, 1, 1, 1); } facet = music->GetMultiFaceted(); if (facet) { if (current == ent) { G_DebugHighlightFacet( ent->origin, ent->mins, ent->maxs, (facet_t)(((facet - 1) << 1) + currentFacet), 1, 1, 1, 1 ); } else { G_DebugHighlightFacet( ent->origin, ent->mins, ent->maxs, (facet_t)(((facet - 1) << 1) + 0), 0.6f, 0.3f, 0.2f, 0.1f ); G_DebugHighlightFacet( ent->origin, ent->mins, ent->maxs, (facet_t)(((facet - 1) << 1) + 1), 0.6f, 0.3f, 0.2f, 0.1f ); } } } else if (ent->isSubclassOf(TriggerReverb)) { int facet; TriggerReverb *reverb; reverb = (TriggerReverb *)ent; if (current == ent) { if (reverb->oneshot) { G_DebugBBox(ent->origin, ent->mins, ent->maxs, 0.5, 0.5, 1, 1); } else { G_DebugBBox(ent->origin, ent->mins, ent->maxs, 0, 0.5, 1, 1); } } else { if (reverb->oneshot) { G_DebugBBox(ent->origin, ent->mins, ent->maxs, 0.5, 0, 1, 1); } else { G_DebugBBox(ent->origin, ent->mins, ent->maxs, 0, 0, 1, 1); } } if (reverb->useTriggerDir) { Vector org; org = ent->origin; org[2] += 0.5f * ent->maxs[2]; G_DebugArrow(org, reverb->GetTriggerDir(), 48, 0.5, 1, 1, 1); } facet = reverb->GetMultiFaceted(); if (facet) { if (current == ent) { G_DebugHighlightFacet( ent->origin, ent->mins, ent->maxs, (facet_t)(((facet - 1) << 1) + currentFacet), 1, 1, 1, 1 ); } else { G_DebugHighlightFacet( ent->origin, ent->mins, ent->maxs, (facet_t)(((facet - 1) << 1) + 0), 0.3f, 0.3f, 0.6f, 0.1f ); G_DebugHighlightFacet( ent->origin, ent->mins, ent->maxs, (facet_t)(((facet - 1) << 1) + 1), 0.3f, 0.3f, 0.6f, 0.1f ); } } } } PostEvent(EV_SoundManager_ShowingSounds, FRAMETIME); } void SoundManager::Show(void) { CurrentGainsFocus(); CancelEventsOfType(EV_SoundManager_ShowingSounds); PostEvent(EV_SoundManager_ShowingSounds, FRAMETIME); UpdateUI(); } void SoundManager::Show(Event *ev) { Show(); } void SoundManager::Hide(Event *ev) { CurrentLostFocus(); CancelEventsOfType(EV_SoundManager_ShowingSounds); UpdateUI(); } void SoundManager::Save(void) { Entity *ent; str buf; str filename; size_t i; // get the name of the sound file from the world filename = "maps/"; filename += level.mapname; for (i = filename.length() - 1; i >= 0; i--) { if (filename[i] == '.') { filename[i] = 0; break; } } filename += ".snd"; gi.Printf("Saving soundmanager file to '%s'...\n", filename.c_str()); buf = ""; buf += va("//\n"); buf += va("// Sound Manager File \"%s\", %d Sound Entities.\n", filename.c_str(), soundList.NumObjects()); buf += va("//\n"); // // save out normal TriggerSpeakers // buf += va("// TriggerSpeakers\n"); for (i = 1; i <= soundList.NumObjects(); i++) { TriggerSpeaker *speaker; ent = soundList.ObjectAt(i); if (!ent->isSubclassOf(TriggerSpeaker) || ent->isSubclassOf(RandomSpeaker)) { continue; } speaker = (TriggerSpeaker *)ent; // // start off the spawn command // buf += "spawn TriggerSpeaker"; // // set the targetname // if (ent->targetname != "") { buf += va(" targetname %s", ent->targetname.c_str()); } // // set the origin // buf += va(" origin \"%.2f %.2f %.2f\"", ent->origin.x, ent->origin.y, ent->origin.z); // // make the speaker ambient and on // buf += " spawnflags 1"; // // set the volume // if (speaker->volume != DEFAULT_VOL) { buf += va(" volume %.2f", speaker->volume); } // // set the mindist // if (speaker->min_dist != DEFAULT_MIN_DIST) { buf += va(" min_dist %.1f", speaker->min_dist); } // // save the sound // buf += va(" sound \"%s\"", speaker->Noise().c_str()); // // make sure it gets re-added to the sound manager // buf += " _addtosoundmanager 0"; buf += va("\n"); } // // save out RandomSpeakers // buf += va("// RandomSpeakers\n"); for (i = 1; i <= soundList.NumObjects(); i++) { RandomSpeaker *speaker; ent = soundList.ObjectAt(i); if (!ent->isSubclassOf(TriggerSpeaker) || !ent->isSubclassOf(RandomSpeaker)) { continue; } speaker = (RandomSpeaker *)ent; // // start off the spawn command // buf += "spawn RandomSpeaker"; // // set the targetname // if (ent->targetname != "") { buf += va(" targetname %s", ent->targetname.c_str()); } // // set the origin // buf += va(" origin \"%.2f %.2f %.2f\"", ent->origin.x, ent->origin.y, ent->origin.z); // // set the volume // if (speaker->volume != DEFAULT_VOL) { buf += va(" volume %.2f", speaker->volume); } // // set the mindist // if (speaker->min_dist != DEFAULT_MIN_DIST) { buf += va(" min_dist %.1f", speaker->min_dist); } // // set the channel // buf += va(" channel %d", speaker->channel); // // set the mindelay // buf += va(" mindelay %.2f", speaker->mindelay); // // set the maxdelay // buf += va(" maxdelay %.2f", speaker->maxdelay); // // set the chance // buf += va(" chance %.2f", speaker->chance); // // save the sound // buf += va(" sound \"%s\"", speaker->Noise().c_str()); // // make sure it gets re-added to the sound manager // buf += " _addtosoundmanager 0"; buf += va("\n"); } // // save out TriggerMusic // buf += va("// TriggerMusics\n"); for (i = 1; i <= soundList.NumObjects(); i++) { TriggerMusic *music; ent = soundList.ObjectAt(i); if (!ent->isSubclassOf(TriggerMusic)) { continue; } music = (TriggerMusic *)ent; // // start off the spawn command // buf += "spawn TriggerMusic"; // // set the targetname // if (ent->targetname != "") { buf += va(" targetname %s", ent->targetname.c_str()); } // // set the origin // buf += va(" origin \"%.2f %.2f %.2f\"", ent->origin.x, ent->origin.y, ent->origin.z); // // set the angle // if (music->useTriggerDir) { buf += va(" angle %.1f", AngleMod(ent->angles.y)); } // // set the oneshot // if (music->oneshot) { buf += " oneshot 0"; } // // set current // buf += va(" current %s", Director.GetString(music->current).c_str()); // // set fallback // buf += va(" fallback %s", Director.GetString(music->fallback).c_str()); if (music->GetMultiFaceted()) { // // save out multi faceted // buf += va(" multifaceted %d", music->GetMultiFaceted()); // // set alt current // buf += va(" altcurrent %s", Director.GetString(music->altcurrent).c_str()); // // set alt fallback // buf += va(" altfallback %s", Director.GetString(music->altfallback).c_str()); } // // set mins // buf += va(" _setmins \"%.2f %.2f %.2f\"", ent->mins.x, ent->mins.y, ent->mins.z); // // set maxs // buf += va(" _setmaxs \"%.2f %.2f %.2f\"", ent->maxs.x, ent->maxs.y, ent->maxs.z); // // make sure it gets re-added to the sound manager // buf += " _addtosoundmanager 0"; buf += va("\n"); } // // save out TriggerReverb // buf += va("// TriggerReverbs\n"); for (i = 1; i <= soundList.NumObjects(); i++) { TriggerReverb *reverb; ent = soundList.ObjectAt(i); if (!ent->isSubclassOf(TriggerReverb)) { continue; } reverb = (TriggerReverb *)ent; // // start off the spawn command // buf += "spawn TriggerReverb"; // // set the targetname // if (ent->targetname != "") { buf += va(" targetname %s", ent->targetname.c_str()); } // // set the origin // buf += va(" origin \"%.2f %.2f %.2f\"", ent->origin.x, ent->origin.y, ent->origin.z); // // set the angle // if (reverb->useTriggerDir) { buf += va(" angle %.1f", AngleMod(ent->angles.y)); } // // set the oneshot // if (reverb->oneshot) { buf += " oneshot 0"; } // // set reverb type // buf += va(" reverbtype %d", reverb->reverbtype); // // set reverb level // buf += va(" reverblevel %.2f", reverb->reverblevel); if (reverb->GetMultiFaceted()) { // // save out multi faceted // buf += va(" multifaceted %d", reverb->GetMultiFaceted()); // // set alt reverb type // buf += va(" altreverbtype %d", reverb->altreverbtype); // // set alt reverb level // buf += va(" altreverblevel %.2f", reverb->altreverblevel); } // // set mins // buf += va(" _setmins \"%.2f %.2f %.2f\"", ent->mins.x, ent->mins.y, ent->mins.z); // // set maxs // buf += va(" _setmaxs \"%.2f %.2f %.2f\"", ent->maxs.x, ent->maxs.y, ent->maxs.z); // // make sure it gets re-added to the sound manager // buf += " _addtosoundmanager 0"; buf += va("\n"); } buf += "end\n"; gi.FS_WriteFile(filename.c_str(), (void *)buf.c_str(), buf.length() + 1); gi.Printf("done.\n"); } void SoundManager::Save(Event *ev) { Save(); } void SoundManager::Load(void) { str filename; intptr_t i; // get the name of the sound file from the world filename = "maps/"; filename += level.mapname; for (i = filename.length() - 1; i >= 0; i--) { if (filename[i] == '.') { filename[i] = 0; break; } } filename += ".snd"; // If there isn't a script with the same name as the map, then don't try to load script if (gi.FS_ReadFile(filename.c_str(), NULL, true) != -1) { Reset(); Director.ExecuteThread(filename, ""); } } void SoundManager::AddEntity(Entity *ent) { if (ent) { soundList.AddUniqueObject(ent); } }