Game Development Community

Animating ShapeImage Nodes on Server?

by Matt Jolly · in Torque Game Engine Advanced · 02/03/2009 (12:55 pm) · 5 replies

See picture:
img3.imageshack.us/img3/5914/torquenodeproblemyu3.jpgI had to recreate the lines in Photoshop because they weren't saved when I took a screenshot.

I've implemented the simple melee system resource, but because my weapon swing animations and such are part of the weapon model and not the player, the ray I cast between damageStart and damageEnd is messed up (the ray resembles the blue line in the picture). I think this is due to the fact that ShapeImages are not animated on the server, but I can't figure out how exactly I can fix this. I've tried every variant of animate, animateNodeSubtrees, advanceTime, etc., nothing works.

Any help would be appreciated.

#1
02/03/2009 (1:30 pm)
Well, not an aswer to your question, but you could discard that part of the melee resource, and just detect a hit if the person was a) in range, and b) in the "strike zone"
#2
02/03/2009 (6:35 pm)
Yeah I've tried that, but it really just isn't very effective due to the variety of animations each weapon has.
#3
02/04/2009 (6:53 am)
You need mShapeInstance->advanceTime() to be called on the server as well. In Player::updateAnimation(F32 dt), replace this:

void Player::updateAnimation(F32 dt)
{
   if ((isGhost() || mActionAnimation.animateOnServer) && mActionAnimation.thread)
      mShapeInstance->advanceTime(dt,mActionAnimation.thread);
   if (mRecoilThread)
      mShapeInstance->advanceTime(dt,mRecoilThread);

   // If we are the client's player on this machine, then we need
   // to make sure the transforms are up to date as they are used
   // to setup the camera.
   if (isGhost())
   {
      if (getControllingClient())
      {
         updateAnimationTree(isFirstPerson());
         mShapeInstance->animate();
      }
      else
      {
         updateAnimationTree(false);
      }
   }
}

By this:
void Player::updateAnimation(F32 dt)
{
   if (mActionAnimation.thread)
      mShapeInstance->advanceTime(dt,mActionAnimation.thread);
   if (mRecoilThread)
      mShapeInstance->advanceTime(dt,mRecoilThread);

   // If we are the client's player on this machine, then we need
   // to make sure the transforms are up to date as they are used
   // to setup the camera.
   if (isGhost())
   {
      if (getControllingClient())
      {
         updateAnimationTree(isFirstPerson());
         mShapeInstance->animate();
      }
      else
      {
         updateAnimationTree(false);
      }
   }
}
#4
02/04/2009 (7:37 am)
Move the following code which was previously in ShapeBase::processTick:

for (int i = 0; i < MaxMountedImages; i++)
         if (mMountedImageList[i].dataBlock)
            UpdateImageRaycastDamage( TickSec, i );

To ShapeBase::updateImageState function just below the line:

image.delayTime -= dt;

This fix my problem and I hope that works for you too.
#5
02/04/2009 (12:46 pm)
I appreciate the help, but neither solution works. The server still doesn't animate the weapon nodes.

Edit: I found the bloody culprit. God, it's amazing how one condition can give me such a headache. In shapeImage.cpp, at line ~1413, I changed this:
if (isGhost()) {
      if (image.dataBlock->isAnimated) {
         image.animThread = image.shapeInstance->addThread();
         image.shapeInstance->setTimeScale(image.animThread,0);
      }
      if (image.dataBlock->hasFlash) {
         image.flashThread = image.shapeInstance->addThread();
         image.shapeInstance->setTimeScale(image.flashThread,0);
      }
      if (image.dataBlock->ambientSequence != -1) {
         image.ambientThread = image.shapeInstance->addThread();
         image.shapeInstance->setTimeScale(image.ambientThread,1);
         image.shapeInstance->setSequence(image.ambientThread,
                                          image.dataBlock->ambientSequence,0);
      }
      if (image.dataBlock->spinSequence != -1) {
         image.spinThread = image.shapeInstance->addThread();
         image.shapeInstance->setTimeScale(image.spinThread,1);
         image.shapeInstance->setSequence(image.spinThread,
                                          image.dataBlock->spinSequence,0);
      }
   }
to this
if (1) { //Change: Animate on server too (was isGhost())
      if (image.dataBlock->isAnimated) {
         image.animThread = image.shapeInstance->addThread();
         image.shapeInstance->setTimeScale(image.animThread,0);
      }
      if (image.dataBlock->hasFlash) {
         image.flashThread = image.shapeInstance->addThread();
         image.shapeInstance->setTimeScale(image.flashThread,0);
      }
      if (image.dataBlock->ambientSequence != -1) {
         image.ambientThread = image.shapeInstance->addThread();
         image.shapeInstance->setTimeScale(image.ambientThread,1);
         image.shapeInstance->setSequence(image.ambientThread,
                                          image.dataBlock->ambientSequence,0);
      }
      if (image.dataBlock->spinSequence != -1) {
         image.spinThread = image.shapeInstance->addThread();
         image.shapeInstance->setTimeScale(image.spinThread,1);
         image.shapeInstance->setSequence(image.spinThread,
                                          image.dataBlock->spinSequence,0);
      }
   }

Now my sword works!
'course this may not be enough to fix it from stock Torque, as my random animate(), advanceTime(), and countless other animation calls may have been required after all. Time to go back through and see what I can get rid of.

Edit: And these are the necessary animate calls (and is probably very brute-force, but ah well)
In shapeBase.cpp, in ShapeBase::processTick, make the following changes
advanceTime(TickSec); //add this
   if (isServerObject()) {
	   // Server only...
	   advanceThreads(TickSec);
	   updateServerAudio();
	   // SphyxGames -> Melee
	   for (int i = 0; i < MaxMountedImages; i++)
	   {
		   if (mMountedImageList[i].dataBlock != NULL)
		   {
			   //add these------------------------------------
			   mMountedImageList[i].shapeInstance->animate();
			   mMountedImageList[i].shapeInstance->animateNodeSubtrees(true);
			   mMountedImageList[i].shapeInstance->animateNodes(0);
			   //---------------------------------------------
			   UpdateImageRaycastDamage( TickSec, i );

		   }
	   }
	   // SphyxGames <- Melee