Game Development Community

How do I run a script on Tick?

by eedok - Cody Hollis-Perdue · in Torque Game Engine · 04/09/2008 (9:50 am) · 9 replies

What I'm trying to do is modify the starter.fps to make it so when a player isn't moving their health regenerates, so I put this in player.cs under the server folder:
function Player::processTick( %this )
{
	echo("testing onTick");
	if(%this.getVelocity() == "0 0 0")
		%this.applyRepair(1);
}

So I checked my console and it looks like it wasn't being called at all so I added this to player.cc after Parent::processTick(move); in the processTick method:
Con::executef(mDataBlock,2,"processTick",scriptThis());

Would anyone be able to tell me where I went off track, or will I have to implement this in the C++ code?

#1
04/09/2008 (10:22 am)
You're on the right track (although raw per tick callbacks may be very performance expensive, since they happen every 32 milliseconds), but you are mapping the callback to the datablock of the Player, yet trying to receive the callback as the class itself.

You should try something like:

PlayerData::processTick(%this, %player)
{
 ...
}

Or, more appropriately, have one of these callback handlers for each possible datablock in your game.
#2
04/09/2008 (10:47 am)
Thanks, that works, I implemented a counter to make it only get called every 3 ticks(every tick made regeneration happen way too quickly), so I'm hoping that won't be too expensive.

So again thank you very much.
#3
04/09/2008 (11:04 am)
A better way to do this might be...
PlayerData::onVelocityStop( %this, %player )
{
     %player.repairSchedule = %player.schedule( 96, applyRepair );
}
 
PlayerData::onVelocityMoving( %this, %player )
{
     cancel( %player.repairSchedule );
}
... or something like that. The basic idea is that you add script callbacks that are infrequent then use a schedule to do the work at whatever rate is nessasary. C++ just needs to watch the state and fire off callbacks when they change.
#4
04/09/2008 (11:37 am)
I'll put that on my todo list to change it to that style, I just don't know enough torque yet to pull that off, thanks for the additional help, and maybe is there a place where I can learn the requisites to implement that?
#5
04/09/2008 (12:13 pm)
There really isn't some central database of knowlege that you would learn this in particular. Its just an experience thing.

It would be similar to what you've already done. In C++ near the end of Player::processTick()...
if ( isServerObject() )
{
   if ( mLastVelocity.isZero() && !mVelocity.isZero() )
      Con::executef(mDataBlock,2,"onVelocityMoving",scriptThis());
   else if ( !mLastVelocity.isZero() && mVelocity.isZero() )
      Con::executef(mDataBlock,2,"onVelocityStopped",scriptThis());
   
   mLastVelocity = mVelocity;
}
You would have to add mLastVelocity to the Player class header and initialize it in the constructor, but that's about it.
#6
04/09/2008 (12:48 pm)
Thanks, it's been changed
#7
04/13/2008 (5:01 pm)
In addition to this is there way to round down a vector, as I'm standing still and the health isn't regenerating like it should, and I run a getVelocity and it comes back with:
4.86798e-013 0 0

so is there a way to make values lower than 0.0001 round to 0?
#8
04/13/2008 (8:48 pm)
If a variable returns 4.86798e-013, according to my limited experience, it's an error from somewhere else in the code. Usually it is a conversion problem from one data type to another...Usually.

I could be wrong here.
#9
04/14/2008 (11:41 am)
Okay, I found the problem, but it's leading to another issue I'm having with what Tom helped me with, in my script I have this:
function regenerate(%player)
{
	echo("Regenerating...");
	if(%player.getDamageLevel() < 100)
		%player.applyRepair(1);
}
function PlayerData::onVelocityStopped( %this, %player )
{
	echo("stopped");
     %player.repairSchedule = schedule( 96,0, regenerate,%player);
}
 
function PlayerData::onVelocityMoving( %this, %player )
{
	echo("moving");
     cancel( %player.repairSchedule );
}

But it only seems to call regenerate once, instead of every 96ms while the player is stopped, what could be a cause of this?

EDIT: nvm I forgot to call schedule inside the regenerate function