Game Development Community

Triggering Sound. A simple example.

by Jeff Osborn · in Torque Game Engine · 07/04/2005 (1:35 pm) · 6 replies

So, what I'm trying to do is pretty simple. I would like to have the player walk through an area that has some trigger zones set up for tutorials. When a player steps into a zone, I want an image of the tutorial 'genie' to pop up in the northeast corner of the screen and a voice-over to instruct the player in some facet of the game. The image part works just fine. The sound? Well...

The way I wanted it to work was to have a bunch of triggers that all use the same trigger logic, but can tell the trigger which sound to play based on the nameTag of the trigger (which I can set up when I create an instance of the TutorialTrigger in the game editor). Here is the complete code for '~/server/scripts/tutorial_triggers.cs':

datablock TriggerData(TutorialTrigger)
{
   tickPeriodMS = 100;
};

$Tutorial::sound::handle = 0;

function TutorialTrigger::onEnterTrigger(%this, %trigger, %obj)
{
   if ($pref::Tutorial::enabled)
   {
      if (%obj.client)
      {
         echo("The player has just entered a tutorial!");
         if (%obj.client.player)
         {
            echo("The player is in " @ %trigger.nameTag @ "!");
//            serverPlay3D(%trigger.nameTag, %trigger.getTransform());
//            commandToClient(%obj.client, 'StartTutorial', %trigger.nameTag);
            if ($Tutorial::sound::handle)
            {
               alxStop($Tutorial::sound::handle);
            }
            $Tutorial::sound::handle = 
               alxPlay(%trigger.nameTag, %trigger.getPosition());
//                  (%trigger.nametag @ "Emit").getPosition());
            TutorialGenie.visible = "1";
         }
      }
   }

   Parent::onEnterTrigger(%this, %trigger, %obj);
}

function TutorialTrigger::onLeaveTrigger(%this, %trigger, %obj)
{
   if ($pref::Tutorial::enabled)
   {
      if (%obj.client)
      {
         echo("The player has just left a tutorial!");
         if (%obj.client.player)
         {
            echo("The player has left " @ %trigger.nameTag @ "!");
//            commandToClient(%obj.client, 'EndTutorial', %trigger.nameTag);
            if ($Tutorial::sound::handle)
            {
               alxStop($Tutorial::sound::handle);
            }
            $Tutorial::sound::handle = 0;
            TutorialGenie.visible = "0";
         }
      }
   }

   Parent::onLeaveTrigger(%this, %trigger, %obj);
}

As you can see I've tried lots of over things (rituals) to get it to work also. As you can see from the commented-out code above, I've tried creating a clientCmdStartTutorial(%tutorial) function and clientCmdEndTutorial() on the client. No luck. I've tried a serverPlay3D() call. No luck.

What I get in the output log is the following:

The player has just entered a tutorial!
The player is in Tutorial1!
Unable to locate audio profile 'Tutorial1'

The AudioProfile I use is in '~/server/scripts/player.cs' (excerpt follows).

// Tutorials

datablock AudioProfile(Tutorial1)
{
   filename = "~/data/sound/talk/talkTutorial1.wav";
   description = "AudioClosest3d";
   preload = false;
};

Where does the AudioProfile have to reside for it to be recognized? Do I have to 'new' it? I've tried that with the same results (Unable to locate). Does it need to be over on the client side someplace? I've tried that too. No luck. Finney's book and the other forums don't help either. I've done just like they said. My example looks close enough to them that I can't figure out what is going on.

I understand that emitters don't need a newed instance of the datablock, they create an instance when the emitter is created, but do I need one here? I recently added music to the main menu of my app, and it required an instance of the AudioProfile in the ~/client/init.cs file. I tried putting a newed instance of Tutorial1 in there, too. No luck.

I'm using Torque 1.3. Thanks.

#1
07/04/2005 (2:52 pm)
This should really work !
You can place the AudioProfile anywhere , it doesnt matter.
Can you do a simple trigger like below and see if it works?

datablock AudioProfile(Test)
{
     filename = "~/data/sound/talk/talkTutorial1.wav";
     description = "AudioClosest3d";
     preload = false;
};

datablock TriggerData(TestTrigger)
{  
     tickPeriodMS = 100;
};

function TestTrigger::onEnterTrigger(%this, %trigger, %obj)
{
    $Tutorial::sound::handle =  alxPlay(%trigger.nameTag, %trigger.getPosition());
    Parent::onEnterTrigger(%this, %trigger, %obj);
}

function TestTrigger::onLeaveTrigger(%this, %trigger, %obj)
{

    alxStop($Tutorial::sound::handle);
    Parent::onLeaveTrigger(%this, %trigger, %obj);
}
#2
07/04/2005 (6:27 pm)
Yep, I did that. I even Hard-coded fthe name to be 'Tutorial1" ("Test" in your case) in the call to alxplay(). No luck. I took the trigger down to the bare bones-- no checking to see if the obj is a client or player. I left in the echo() calls and setting the UI image to visible to make sure the call was being made. No luck.

Actually, I've found that AudioProfiles can't just be declared anywhere. Your mileage my vary, but i've tried putting them in different files and voila! no sound. I've tried different sounds, ones that work just fine with emitters No luck. I've tried different profile names (Fubar, etc.)-- I have been VERY ritualistic about this. No luck.

I don't think the preload matters. The file is mono. i've changed some scripts to suit what I need to get what i need out of the engine, but nothing radical.

The example you posted, it works for you?

Thanks.
#3
07/05/2005 (7:21 am)
Ye it works !
For the Audioprofiles , i have my profiles all over really.
The only thing you need to load them before you use them.
And the preload doesnt matter either.
Do you write the audioprofilename in the trigger Nametag field ?
This should work, i tested it with a clean 1.3 SDK.
#4
07/05/2005 (7:53 am)
Yeah, putting the AudioProfile name in the nameTag element of the trigger instance is the trick. I thought it would be a pretty slick way to map the desired behavior from the trigger. I just can't get the sound to fire. It time to try more ritual-- I am going to try to kick alx in the butt a little by putting an alxStopAll() call in the trigger, maybe that will help. Even hard-coding another profile that I know works with an emitter is not working. Argh!

Funniest thing, all other sounds work-- emitters work (and I've got LOTS of them), the intro music that plays when the main menu is displayed (startup and bouncing out of a game)-- it all works. If it didn't I'd know that I was doing something basically wrong, but this is infuriating.

For the sake of pure chicken-killing (insert your favorite primitive ritual here if you don't want to harm chickens), I have reinstalled the 1.3 SDK, because I did patch a couple of things from the forums. Still no luck. Time to spread the chicken's entrails on the keyboard...
#5
07/05/2005 (5:09 pm)
I figured it out.

For the love of GOD don't name your trigger instance the same as the AudioProfile name!

So, when I created the trigger instance in the editor, I named it "Tutorial1", I also named the AudioProfile "Tutorial1' and gave the trigger instance the nameTag "Tutorial1". It seemed like voodoo to me, but I changed the name of the Trigger in the World Editor to "TutorialA" and the damned thing started working.

Note to self: Never name two objects the same thing EVER in Torque...
#6
07/06/2005 (12:25 am)
I could not see that , but im happy you made it :) !