Schedule not working!
by FruitBatInShades · in Technical Issues · 02/23/2005 (9:00 am) · 21 replies
NEWB ALERT!
I'm trying to get exploding glass. I have 2 models, one that has the animated explosion (Glass2) and one that is the glass after it has been exploded. I cannot get schedule to work to remove the sound or swap the datablock. If I swap the datablock directly in Glass2::damage, then the object swaps but the animation is never played. So i tried to use the schedule function to do this after the animation has finished but the SwapBlock function is never called.
The audioemitter is never destroyed either :(
Any pointers for a newb :)
I'm trying to get exploding glass. I have 2 models, one that has the animated explosion (Glass2) and one that is the glass after it has been exploded. I cannot get schedule to work to remove the sound or swap the datablock. If I swap the datablock directly in Glass2::damage, then the object swaps but the animation is never played. So i tried to use the schedule function to do this after the animation has finished but the SwapBlock function is never called.
The audioemitter is never destroyed either :(
Any pointers for a newb :)
datablock StaticShapeData(Glass2)
{
category = "DamageItems";
shapeFile = "~/data/shapes/glass2.dts";
maxDamage = 1;
destroyedLevel = 1;
};
datablock StaticShapeData(Glass3)
{
category = "DamageItems";
shapeFile = "~/data/shapes/glass3.dts";
};
function Glass2::create(%block)
{
%obj = new StaticShape()
{
dataBlock = %block;
};
return(%obj);
}
function Glass2::onCollision(%this,%obj,%collider)
{
echo("Glass2 collision");
}
function Glass2::damage(%this, %obj, %sourceObject, %position, %damage, %damageType)
{
echo("GlassTube::damage() obj=" @ %obj @ ", source=" @ %sourceObject @ ", damage=" @ %damage);
%obj.applyDamage("1");
%obj.playThread(0,"ambient");
%smashsound = new AudioEmitter()
{
position = %obj.position;
fileName = "~/data/sound/smash.ogg";
description = AudioClose3d; //for loud sound
};
//This schedules the audio emitter to delete itself when done playing the sound.
//If you use a longer sound, change the value of 1000 to a length of time long enough
//to finish your sound before deleting the emitter.
%this.schedule(1000,"KillSound",%smashsound);
}
function Glass2::onDamage(%this, %obj, %delta)
{
echo("GlassTube::onDamage() obj=" @ %obj @ ",delta=" @ %delta);
%this.schedule(500,"SwapBlock",Glass3);
}
function SwapBlock(%this, %block)
{
echo("Swapblock called");
%this.setDataBlock(%block);
}
#2
That doesn't woprk either. What object actually contains the schedule function? No errors are reported, but nothing ever happens! Is part of GameBaseData?
02/23/2005 (10:36 am)
Hi Stephen.That doesn't woprk either. What object actually contains the schedule function? No errors are reported, but nothing ever happens! Is part of GameBaseData?
#3
%this.schedule(1000,"KillSound",%smashsound);
to this...
%obj.schedule(1000,"KillSound",%smashsound);
And then you would need this function to handle it....
function Glass2::killSound(%obj, %smashsound)
{
}
02/23/2005 (10:47 am)
You are also using namespace schedules which may not be properly handled. For instance, you would need to alter this schedule...%this.schedule(1000,"KillSound",%smashsound);
to this...
%obj.schedule(1000,"KillSound",%smashsound);
And then you would need this function to handle it....
function Glass2::killSound(%obj, %smashsound)
{
}
#4
to get your existing schedule call to work, make your SwapBlock function belong to the datablock
function Glass2::SwapBlock(%this, %block)
{
...
}
------------------------------------------------------------------------------------------------------------
or, conversely, leave the function alone and use the general script function call for schedule (in onDamage):
schedule(500,0,"SwapBlock",%obj, Glass3);
Either one of those two approaches should work.
-----------------------------------------------------------------------------------------
Also, I don't see your KillSound method anywhere? it should be defined somewhere as belonging to the datablock since you are accessing it via the datablock:
function Glass2::KillSound(%this, %sound)
{
...
}
02/23/2005 (3:09 pm)
Bat,to get your existing schedule call to work, make your SwapBlock function belong to the datablock
function Glass2::SwapBlock(%this, %block)
{
...
}
------------------------------------------------------------------------------------------------------------
or, conversely, leave the function alone and use the general script function call for schedule (in onDamage):
schedule(500,0,"SwapBlock",%obj, Glass3);
Either one of those two approaches should work.
-----------------------------------------------------------------------------------------
Also, I don't see your KillSound method anywhere? it should be defined somewhere as belonging to the datablock since you are accessing it via the datablock:
function Glass2::KillSound(%this, %sound)
{
...
}
#5
02/23/2005 (3:38 pm)
Thanks guys. How do I dispose of an object like the sound, I don;t want to just add it to mission cleanup cos theres a lot going on. How do I dispose of it properly?
#6
It seems that event is fired recursively! Is there a way to specify it should fire only once?
02/23/2005 (5:16 pm)
I've tried those changes and now I get a full crash! Where am I going wrong? Its the call to SwapBlock thats crashing!echo("scheduling killsound");
schedule(100,0,"KillSound",%smashsound);
echo("scheduling Swapblock");
schedule(500,0,"SwapBlock",%obj, Glass3);
function SwapBlock(%this, %block)
{
echo("Swapblock called");
%this.setDataBlock(%block);
}
function KillSound(%this, %soundtokill)
{
echo("KillSound Called");
%soundtokill.delete();
}
[b]Console.log[/b]
scheduling killsound
scheduling Swapblock
GlassTube::damage() obj=1473, source=1506, damage=3.03052
scheduling killsound
scheduling Swapblock
KillSound Called
starter.fps/server/scripts/Glass.cs (0): Unable to find object: '' attempting to call function 'delete'
KillSound Called
starter.fps/server/scripts/Glass.cs (0): Unable to find object: '' attempting to call function 'delete'It seems that event is fired recursively! Is there a way to specify it should fire only once?
#7
Do this:
02/23/2005 (5:30 pm)
Kill Sound will continue to get called until you cancel the schedule.Do this:
%smashsound.scheduleId = schedule( 100, 0, "KillSound", %smashsound );
...
function KillSound( %soundtokill )
{
echo( "KillSound Called" );
cancel( %soundtokill.scheduleId );
%soundtokill.delete();
}It wasn't working the first time, because the schedule was putting %smashsound in the place of %this, and you were never canceling the schedule.
#8
02/23/2005 (5:31 pm)
Looks like you are missing a closing brace after your call to schedule(500,0,"SwapBlock",%obj, "Glass3");
#10
@Pat: Thanks :)
But if you look at the console dump above, %obj never gets passed or is out of scope when KillSound is called. Also Swapblock still crashes the engine :( When schedule is called %smashsound has an id, when KillSound is actually called 0 is passed as the ID!
02/23/2005 (5:39 pm)
That was just a cut and paste extract :)@Pat: Thanks :)
But if you look at the console dump above, %obj never gets passed or is out of scope when KillSound is called. Also Swapblock still crashes the engine :( When schedule is called %smashsound has an id, when KillSound is actually called 0 is passed as the ID!
#11
Take a closer look, you are passing the variable to "%this" and Pat has altered the function to only use "%soundtoKill". You were trying to delete a variable that didn't exist.
02/23/2005 (6:04 pm)
FruitTake a closer look, you are passing the variable to "%this" and Pat has altered the function to only use "%soundtoKill". You were trying to delete a variable that didn't exist.
#12
The sound should play 1 sec what i understand , why dont you use
%obj.playaudio(0,audiodescription) ?
And for the rest why not this
function Glass2::onDamage(%this, %obj, %delta)
{
schedule(500,0,"SwapBlock",%obj);
}
function SwapBlock(%obj)
{
%obj.setDataBlock(glass3);
}
02/23/2005 (8:57 pm)
@FruitThe sound should play 1 sec what i understand , why dont you use
%obj.playaudio(0,audiodescription) ?
And for the rest why not this
function Glass2::onDamage(%this, %obj, %delta)
{
schedule(500,0,"SwapBlock",%obj);
}
function SwapBlock(%obj)
{
%obj.setDataBlock(glass3);
}
#13
%obj.setDataBlock(glass3);
hardwires ONE possibility only where his method offers virtually unlimited possibilities.
02/23/2005 (9:09 pm)
Because this...%obj.setDataBlock(glass3);
hardwires ONE possibility only where his method offers virtually unlimited possibilities.
#14
But still depends on what he are after .
What i understand this swapblock is not somekind of global swap function.
02/23/2005 (9:12 pm)
Got it :)But still depends on what he are after .
What i understand this swapblock is not somekind of global swap function.
#15
To call a schedule with parameters
In each of these examples, when the schedule fires, the parameters in the call to 'someFunction' will be:
Unfortunatly TorqueScript does not, currently, have a concept of 'this' so that is the reason for the semi-hacked way of passing a reference to the current object in a script method. This will not always be the case, but for now that's the way it works.
02/23/2005 (9:28 pm)
Hopefully this will clear up some confusion...function SomeObject::someMethod( %this, %foo )
{
...
}To call a schedule with parameters
// Schedule someMethod to be executed on an instance of SomeObject %obj = new SomeObject(); %obj.schedule( 100, "someFunction", "foo argument" ); // Is the same as schedule( 100, %obj, "someFunction", "foo argument" ); // Is the same as schedule( 100, 0, "SomeObject::someFunction", %obj, "foo argument" );
In each of these examples, when the schedule fires, the parameters in the call to 'someFunction' will be:
%this = Sim Object Id of the SomeObject created %foo = "foo argument"
Unfortunatly TorqueScript does not, currently, have a concept of 'this' so that is the reason for the semi-hacked way of passing a reference to the current object in a script method. This will not always be the case, but for now that's the way it works.
#16
This cleared out some question marks in my head :)
Im not a coding guy so i really need clear examples like this.
Most of the time the problem is, so many good really skilled coders
give differnt approaches to the same problem.
Instead of giving a clear solution at once.
And the less skilled coders/semihackers like me comes and mess things up :)
02/23/2005 (9:43 pm)
Great Pat !This cleared out some question marks in my head :)
Im not a coding guy so i really need clear examples like this.
Most of the time the problem is, so many good really skilled coders
give differnt approaches to the same problem.
Instead of giving a clear solution at once.
And the less skilled coders/semihackers like me comes and mess things up :)
#17
@Pat: Thanks Pat, I was looking throught the docs but couldn't find any info on schedule other than the doxygen stuff which is useless on that function.
@Billy: I want to use the SwapBlock for a lot of stuff. We are using a lot of models that we WANT to swap at avrious points in their lifecycle. So having SwapBlock as a global function is what we're after. Same with killsound.
@everyone
I cannot get the swapBlock function to be called. It schedules, but never executes and no error message doesn't help me track down the problem :( Does anyone have any more ideas?
Swapblock is never called :(
02/24/2005 (3:02 am)
ARGGHHHHH. Still no swapblock calls, although no crash either ;)@Pat: Thanks Pat, I was looking throught the docs but couldn't find any info on schedule other than the doxygen stuff which is useless on that function.
@Billy: I want to use the SwapBlock for a lot of stuff. We are using a lot of models that we WANT to swap at avrious points in their lifecycle. So having SwapBlock as a global function is what we're after. Same with killsound.
@everyone
I cannot get the swapBlock function to be called. It schedules, but never executes and no error message doesn't help me track down the problem :( Does anyone have any more ideas?
Swapblock is never called :(
GlassTube::damage() obj=1473, source=1506, damage=10 GlassTube::onDamage() obj=1473,delta=1.000000 breaking glass scheduling killsound for item 1512 scheduling Swapblock for item 1473 GlassTube::damage() obj=1473, source=1506, damage=1.90956
//DTS with animation and collision
datablock StaticShapeData(Glass2)
{
category = "DamageItems";
shapeFile = "~/data/shapes/glass2.dts";
maxDamage = 1;
destroyedLevel = 1;
isBroken = false;
};
//DTS with no collision (after its broken)
datablock StaticShapeData(Glass3)
{
category = "DamageItems";
shapeFile = "~/data/shapes/glass3.dts";
};
//Functions to handle Glass2 operations
function Glass2::create(%block)
{
%obj = new StaticShape()
{
dataBlock = %block;
};
return(%obj);
}
function Glass2::onCollision(%this,%obj,%collider)
{
echo("Glass2 collision");
}
function Glass2::damage(%this, %obj, %sourceObject, %position, %damage, %damageType)
{
echo("GlassTube::damage() obj=" @ %obj @ ", source=" @ %sourceObject @ ", damage=" @ %damage);
//Apply damage and play smashing animation
%obj.applyDamage("1");
%obj.playThread(0,"ambient");
//only break glass if it isn't already broken
if (!%obj.isBroken)
{
echo("breaking glass");
//Set the broken flag
%obj.isBroken = true;
//create and play the smash sound
%smashsound = new AudioEmitter()
{
position = %obj.position;
fileName = "~/data/sound/smash.ogg";
description = AudioClose3d; //for loud sound
};
//This schedules the audio emitter to delete itself when done playing the sound.
//If you use a longer sound, change the value of 1000 to a length of time long enough
//to finish your sound before deleting the emitter.
echo("scheduling killsound for item" SPC %smashsound);
schedule(1000,0,"KillSound",%smashsound);
//Swap the DTS with the collision and animation for the
//DTS with no collision and no animation.
echo("scheduling Swapblock for item" SPC %obj);
schedule(1200,"SwapBlock",%obj, Glass3);
}
}
function Glass2::onDamage(%this, %obj, %delta)
{
echo("GlassTube::onDamage() obj=" @ %obj @ ",delta=" @ %delta);
}
//Swap one dtatblock for another so we can use different
//shapes at different points in the objects lifetime.
function SwapBlock(%this, %block)
{
echo("Swapblock called");
%this.setDataBlock(%block);
}
function KillSound(%soundtokill)
{
//Stop the schedule reoccuring
cancel( %soundtokill.scheduleId );
//remove sound from mission
%soundtokill.delete();
}
#18
and sending "Glass2" and "Glass3" to that to have their blocks created.
When you try to swap a block, if the block doesn't exist, it pretty much does nothing to stay fault tolerant. Check and see if that helps.
02/24/2005 (5:30 am)
First off, I don't see any indication of a "Glass3::create(%block)" function to even make the block. Second, I think you would be better off using...function StaticShapeData::create(%data)
{
// The mission editor invokes this method when it wants to create
// an object of the given datablock type.
%obj = new StaticShape()
{
dataBlock = %data;
};
return %obj;
}and sending "Glass2" and "Glass3" to that to have their blocks created.
When you try to swap a block, if the block doesn't exist, it pretty much does nothing to stay fault tolerant. Check and see if that helps.
#19
and when you call it you do:
And that will translate to this:
Things may not be working right, because when this method is called:
The object ID for a Glass2 object is going to be put into %block.
02/24/2005 (10:02 am)
You are still missing the purpose of %this. If you have a method (class member function) in script, you need to use the following format for the function declaration:function SomeObject::someMethod( %this, %arg1, %arg2, etc... )
and when you call it you do:
%someInstanceOfSomeObject.someMethod( "arg1", "arg2", etc... );
And that will translate to this:
SomeObject::someMethod( %someInstanceOfSomeObject, "arg1", "arg2", etc... );
Things may not be working right, because when this method is called:
Glass2::create(%block)
The object ID for a Glass2 object is going to be put into %block.
#20
This works well, even without the Explosion emitters.
02/24/2005 (10:21 pm)
Here is my code to do the same thing--a different way to do it. You just need to stuff your own particle emitters in (or not):datablock StaticShapeData(WindowA)
{
category = "windows";
shapeFile = "~/data/shapes/splody/window1.dts";
damageRadius = 10;
radiusDamage = 50;
damageType = WindowAdebris;
maxDamage = 5;
};
datablock StaticShapeData(Shards)
{
category = "windows";
shapeFile = "~/data/shapes/splody/shards.dts";
};
function WindowA::Damage(%theDatablock,%aWindow,%sourceObject,%pos,%damage,%damagetype)
{
%aWindow.applyDamage(%damage);
if(%aWindow.getDamageLevel() >= %theDatablock.maxDamage)
%theDatablock.Shatter( %aWindow, %pos, %sourceObject);
}
function WindowA::Shatter(%theDatablock, %aWindow, %position, %sourceObject)
{
if(%aWindow.exploded)
return;
%aWindow.exploded = true;
%smash= new Explosion()
{
datablock = GlassShatter;
position = %position;
};
MissionCleanup.add(%smash);
radiusDamage(%aWindow,%position,%theDatablock.damageRadius,
%theDatablock.radiusDamage,%sourceObject.damageType,%theDatablock.damageImpulse);
%aWindow.schedule(500, "delete");
%slivers = new StaticShape()
{
datablock = Shards;
position = %position;
};
MissionCleanup.add(%slivers);
}This works well, even without the Explosion emitters.
Torque 3D Owner Stephen Zepp
in Glass2::onDamage, you are using %this.schedule, which is calling schedule on the datablock. in functionSwapblock, you are receiving a %this parameter, which I am pretty sure is also the datablock (from the schedule), but then trying to set the datablock of a datablock (%this.setDataBlock, where %this is already a datablock).
Try changing the schedule line in Glass2::onDamage() to:
%obj.schedule(500,"SwapBlock", Glass3);
and see if that helps.
Also, you are doing the same thing (confusing datablock with object) in your Glass2::damage() function. Instead of using %this in that schedule, try %obj instead.