Game Development Community

Understanding Schedule() working, but not?

by Mike Rowley · in Torque Game Engine · 04/18/2008 (12:19 pm) · 5 replies

I'm trying to put some code together to fire a bullet from a static object. (not the crossbow)
I'm doing this by attempting to convert Ed Maurina's code for his fireballs to get things working.
So far, I have it working. I can call the fire function and it fires.
My problem is with scheduling it to repeat fire. Currently, I have it set to fire once every 9 seconds. The scedule function works, but loses the fire function. This is the part I don't understand. Why is it losing the fire function? I have tried my schedule before (as You will see) and after it.
Here's my code:

//***********************************************************
// Let's try this here and see if it works.
// Loses doFire() function
// Try it after doFire

// function ShootIt( %handle ) // My function to store the handle of my cannon object.
// {
//     %handle.doFire(true); // Let's fire a bullet
//     schedule( 9000, 0, ShootIt); // Schedule it to fire once every 9 seconds and repeat

//     }
// ******************************************************************
//					doFire() 
// ******************************************************************
//
function StaticShape::doFire( %handle ) {

        echo( "calling doFire");
        %handle.shootFireBall( FireBallProjectile , "0 0 1" , 20 );
        echo ("Firing Up" );
      //  schedule( 9000, 0, ShootIt(%handle));

}


// ******************************************************************
//					shootFireBall() 
// ******************************************************************
//
// 1. Create a projectile and fire in the direction and with velocity requested.
//
function StaticShape::shootFireBall( %marker, %projectile , %pointingVector , %velocity) 
{
   
    %bullet = new Projectile() {
        dataBlock        = %projectile;
        initialVelocity  = vectorScale( vectorNormalize(%pointingVector) , %velocity );
        initialPosition  = %marker.getWorldBoxCenter();
        sourceObject     = -1;
        sourceSlot       = -1;
        theMarker        = %marker;
    };

    %marker.bullet = %bullet;
    MissionCleanup.add(%bullet);
}

// Let's try this here and see if it works.

 function ShootIt( %handle )
 {
     %handle.doFire(true);
     schedule( 9000, 0, ShootIt);

     }

And here is my console:
calling doFire
Firing Up
scriptsAndAssets/server/scripts/test/myBullet.cs (219): Unable to find object: '' attempting to call function 'doFire'
[b]9 seconds later....[/b]
scriptsAndAssets/server/scripts/test/myBullet.cs (219): Unable to find object: '' attempting to call function 'doFire'
How is doFire getting lost?

Edit:
If I change the schedule to read: schedule( 9000, 0, ShootIt(%handle)); it crashes torque by shooting like a machine gun repeatedly.

#1
04/18/2008 (3:27 pm)
The right way to write the code would be.

schedule( 9000, 0, ShootIt, %handle );
#2
04/18/2008 (3:30 pm)
I should be either:

%handle.schedule(9000, 0, ShootIt);
shedule(9000, %handle, ShootIt);
#3
04/18/2008 (4:28 pm)
function ShootIt( %handle )
 {
     %handle = nameToId("Cannon1");
     %handle.doFire(true);
     schedule( 8000, 0, ShootIt, %handle);

     }

Thankyou both. This is what worked.
Once I started changing things to the way you two talked about, I started gettting messages that torque didn't know what object I was talking about. I remembered I needed to get the id of the object, so added it, and now it is working perfectly. Thanks again. Your help has helped me learn something new. :-)
#4
04/18/2008 (6:31 pm)
Just to clarify the use of the two different versions described above:

There are two types of functions that can be scheduled--global functions, and namespace methods. The technique Mike used above is by definition a global function, but as I'll discuss below, he really wants a namespace function, which we'll describe.

Global Function: A global function is a function that is not dependent on a particular object in most cases, and does not apply directly to a particular class of an object. Examples include things like onStartGame(), onMissionEnd(), and similar functions. Syntax for schedule for global functions is:

schedule ([i]time[/i], [i]referenceObject|0[/i], [i]globalFunction[/i], [i]optional params[/i]);

NameSpace Function: (more commonly known as script methods, or namespace methods) -- these functions are used on a particular object, and are reliant on both that object, and the data it contains. In the example above, ShapeBase::doFire() is a namespace method. Syntax for schedule for namespace functions is:

%objectID.schedule ([i]time[/i], [i]nameSpaceFunction[/i], [i]optional params[/i]);

Now, to the specific example, what worked for Mike is valid code, but it's a very unusual twist--in other words, it's a hack. The reason that it's a hack is because the ShootIt function is declared as a global function (no namespace), but requires an object to actually shoot--the "%handle" (as it turns out, we don't even use the actual value passed to us, but that's a different issue). Since the function is declared as a global function, he was forced to use the syntax for a global function, but here is a better example for how it should be set up:

// Let's try this here and see if it works.

 function ShapeBase::ShootIt( %handle )
{
     %handle.doFire(true);
     %handle.schedule(8000, ShootIt);
}
and since we have demonstrated that Cannon1 is a named object (the line that says %handle = nameToId("Cannon1"); ), we can call this namespace function by using:

Cannon1.ShootIt();

Subtle differences, but using global functions when a namespace function is more appropriate is normally considered a poor implementation choice for all sorts of Computer Science Theory reasons.
#5
04/18/2008 (6:41 pm)
Wow, thankyou Stephen. Now what i've been attempting makes more since.
I'll change my "hack" to more appropriate code. (as if any code I write Isn't a hack. :-D )