Game Development Community

Seriously: Triggering Sounds = wtf?

by Thomas Shaw · in Torque Game Engine · 06/16/2005 (8:40 pm) · 9 replies

So I want to learn how to do sound triggers. Fine, I know better than to just come in and make a post without doing searches, and reading the documentation.

However, eventually every thread leads back to one source - http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=1934

Now that guy removed his tutorial on TRIGGERED SOUNDS (part 3 of his thing) in 2003!

So now it's time to come to the community. Can somebody do every SDK owner a favor and make a new resource on "This is how you trigger a sound and set up the datablock as such"? If you want to see my code so far I can post it, but its a waste of time because I can't get the sound to play.

There was another person who had this problem a long time ago and nobody ever resolved the issue with him, so I bumped his post last night (its in "Getting Started").

Anyway, please help!

#1
06/16/2005 (8:56 pm)
Can you explain more about what you want to do?

Would it be as simple as setting up an actual trigger in game to play a sound when triggered? So the trigger would make a call like...

$mySound = alxCreateSource("Sound",expandFilename("~/myfile/somewhere/test.wav"));
alxPlay ($mySound);

with "Sound" being the call to the audio datablock...

Maybe I'm just not understanding what you need and I'm over simplifying it.
#2
06/16/2005 (9:09 pm)
function Wickward::onCollision( %this, %obj, %col )
{
    echo( "Wickward::onCollision called" );
if (%col.getType() & $TypeMasks::PlayerObjectType) 
{
	$mySound = alxCreateSource("Sound",expandFilename("~/data/sound/wierd.wav"));
	alxPlay ($mySound);

	%obj.playThread(0,"alert");
	//%obj.playAudio(0, Wickwardnoise);
}
}

Let me explain. I have an animation I want to play when you walk into the box of this plant, its called the "Wickward". The above code is just my "onCollision" function, if you want to see the rest of it, let me know. Is that not doable? The sound still won't play.
#3
06/16/2005 (9:36 pm)
Update:

So I got it to work, and here is the code so everyone can see:

datablock TriggerData(WickwardTrigger)
{
    tickPeriodMS = 100;
};
function WickwardTrigger::onEnterTrigger( %this, %trigger, %obj )
{
      echo( "The Sound Has been CALLED!!!!11111" );
      serverPlay3D(Wickwardnoise,%obj.getTransform());
}


//----------------------------------------------------------------------------
// Wickwardnoise - jwoods
//----------------------------------------------------------------------------

datablock AudioProfile(Wickwardnoise)
{
	filename    = "~/data/sound/wierd.wav";
	description = AudioClose3d;
	preload = false;
};

I want to add one more piece of functionality to this. How can I make the trigger LOOP the sound as long as the player stays in the trigger. You know, play the sound over and over and immediately cease to make any noise when the player leaves the trigger?

Edit: btw a "while" function like this:

while (%obj.getType() & $TypeMasks::PlayerObjectType)

does not work!
#4
06/16/2005 (11:01 pm)
Set a variable and check the variable. If you move outside of the trigger, stop the sound. It's what you were trying to do, but in a different manner.

EDIT: Or do what Billy says in the next post.
#5
06/17/2005 (6:38 am)
What was wrong with //%obj.playAudio(0, Wickwardnoise); ?
then you can use %obj.stopAudio(0);
#6
06/17/2005 (10:20 am)
Will that cause it to loop until told to stop?
#7
06/17/2005 (11:44 am)
Yes if you use a looping description.
#8
06/17/2005 (11:55 am)
I think you can set looping in the datablock..

isLooping = true;
#9
06/23/2005 (6:31 pm)
Heh. I'm the guy who removed the tutorial--that was because of the inconsistencies of the sound system at that time.

In any case, I'm taking a slightly different approach:
a) the audioProfiles and dataBlock descriptions are stored in audioProfiles in the server/scripts folder (as Tim suggests you can control the looping etc there)

b) in server/scripts/triggers, I make the trigger function for entering the trigger; you could work with the onLeaveTrigger as well:
function someTrigger::onEnterTrigger(%this, %trigger, %obj)
{
   // Get the controlling client
   %client = %obj.client;

   // For now, don't let the AI players process the trigger
   if ((%obj.aiPlayer) || (%client.isAIControlled()))
      return;

   switch(true)
   {
      //AudioProfiles in server/scripts and played via common/client/scripts/triggerClients.cs
      case includedInString("k2qVoice_", %trigger.triggerTarget):  
         if (!alxIsPlaying(%trigger.triggerTarget))
         {
            commandToClient(%client, 'FireServerTrigger', %trigger.triggerTarget);
         }  

      default:
         commandToClient(%client, 'FireServerTrigger', %trigger.triggerTarget);
   }
}
c) in client/scripts/triggerClient.cs I pass the target to the client FireServer function; in this situation, I'm using the
global variables $BGMusicState and $K2QVoiceState to switch between the background music and the voice which is
activated when I run thru the trigger; I could overlay them but it seems get real confusing
function clientCmdFireServerTrigger(%target)
{
      case includedInString("k2qVoice_", %target):
           echo("---->fireServerTrigger alxPlay" SPC %target);

           switch($K2QVoiceState)
           { 
              case 0:

                 //V23 The reason not to use the approach below is because it
                 //    does not allow looping; need the profile approach instead
                 //alxStop($AudioTestHandle);
                 //if (!alxIsPlaying($AudioTestHandle))
                 //{
                 //   %temp = expandFilename(%target);
                 //   error("--->%temp = expandFilename(%target); = " SPC %temp);   
                 //   $AudioTestHandle = alxCreateSource("AudioChannel0", %temp);
                 //   alxPlay($AudioTestHandle);
                 //}
                 //alxPlay(%target);

                 alxStopAll();
                 alxPlay(%target);

                 $BGMusicState = 0;
                 $K2QVoiceState = 1;
d) in the mission file, the target is defined as part of the trigger
new Trigger(t_gracenote) {
         position = "494.914 -732.22 101.641";
         rotation = "0 0 -1 33.2316";
         scale = "1 1 1";
         dataBlock = "SomeTrigger";
         polyhedron = "0.00000 0.00000 0.00000 1.00000 0.00000 0.00000 0.00000 0.00000 1.00000 0.00000 1.00000 0.00000";
            triggerTarget = "k2qVoice_GraceNote";
            triggerDelay = "0";
      };

Maybe this will give you some other ideas :)