Game Development Community

Damage Animations

by Paul Clarke · in Torque Game Engine · 10/22/2008 (3:09 am) · 6 replies

Hey,
I'm fairly new to torque, and I've searched but haven't found a way to do this.
I was looking for a way to set up damage animations, so that when my player or AI gets shot/hit an animation will play of them being hurt and they will be unable to move for a few seconds.
I hope this request isn't too stupid, as I said above, I'm still new to this. Any help will be much appreciated.

#1
10/22/2008 (4:39 am)
Hi Paul,

For playing animations you'll want to look at the function;

function Armor::onDamage(%this, %obj, %delta) defined in server/scripts/player.cs

function Armor::onDamage(%this, %obj, %delta)
{
   // This method is invoked by the ShapeBase code whenever the 
   // object's damage level changes.
   if (%delta > 0 && %obj.getState() !$= "Dead") {

      // Increment the flash based on the amount.
      %flash = %obj.getDamageFlash() + ((%delta / %this.maxDamage) * 2);
      if (%flash > 0.75)
         %flash = 0.75;
      %obj.setDamageFlash(%flash);

      // If the pain is excessive, let's hear about it.
      if (%delta > 10)
         %obj.playPain();
   }
}

You can see at the end there if we are dealt more than 10points of damage it calls the playPain procedure which just plays an sound effect of being hurt, you could add you animation there, or straight into the onDamage() function if you always want to play it.

function Armor::onDamage(%this, %obj, %delta)
{
   // This method is invoked by the ShapeBase code whenever the 
   // object's damage level changes.
   if (%delta > 0 && %obj.getState() !$= "Dead") {

      // Increment the flash based on the amount.
      %flash = %obj.getDamageFlash() + ((%delta / %this.maxDamage) * 2);
      if (%flash > 0.75)
         %flash = 0.75;
      %obj.setDamageFlash(%flash);

      // If the pain is excessive, let's hear about it.
      if (%delta > 10)
         %obj.playPain();

      [b]%obj.setActionThread("name_of_animation");[/b]
   }
}

Obviously you'll want to replace the name_of_animation with whatever animation you wish to play.

Stopping them moving is a little more involved let me cover that seperately
#2
10/22/2008 (7:28 am)
Thanks Andy,
I got that working on my player, wasn't expecting it to be quite so simple.
I would still like to stop movement while the damage animation plays if possible.
#3
10/22/2008 (7:41 am)
I've several ideas on how you might freeze a player, one that springs to mind is using triggers and physicalzones.


1. Create a server/scripts/triggers.cs and make sure that it gets exec'd at the end of the onServerCreated() function in server/scripts/games.cs.

datablock TriggerData(FreezeTrigger)
{
   category     = "FreezeTrigger";
   tickPeriodMS = 100; // Every 10th of a second
};

function Trigger::AttachEffect( %Obj )
{

   %pzone = new PhysicalZone() {
      position     = vectorAdd( %Obj.getPosition() , "0 0 0" );
      rotation     = "1 0 0 0";
      scale        = "1 1 1";
      velocityMod  = "0";
      gravityMod   = "1";
      appliedForce = "0 0 0";
      polyhedron   = "0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 -1.0000000 0.0000000 0.0000000 0.0000000 1.0000000";
   };

   %obj.pzone = %pzone;
}


function FreezeTrigger::onEnterTrigger(%DB , %trigger , %Obj)
{
   %trigger.pzone.activate();
   %trigger.schedule( 5000, unFreezePlayer); // in 5000ms seconds unfreeze the player.
}

function FreezeTrigger::unFreezePlayer(%Trigger)
{
   %trigger.pzone.deactivate();
   %trigger.pzone.delete();
   %trigger.delete();
}




2. In the onDamage procedure mentioned above, create a trigger so something like:

function Armor::onDamage(%this, %obj, %delta)
{
   // This method is invoked by the ShapeBase code whenever the 
   // object's damage level changes.
   if (%delta > 0 && %obj.getState() !$= "Dead") {

      // Increment the flash based on the amount.
      %flash = %obj.getDamageFlash() + ((%delta / %this.maxDamage) * 2);
      if (%flash > 0.75)
         %flash = 0.75;
      %obj.setDamageFlash(%flash);

      // If the pain is excessive, let's hear about it.
      if (%delta > 10)
         %obj.playPain();

      %obj.setActionThread("name_of_animation");

      %trigger =  new Trigger() {
            position  = %obj.GetPosition();
            rotation  = "1 0 0 0";
            scale     = "1 1 1";
            polyhedron = "0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 -1.0000000 0.0000000 0.0000000 0.0000000 1.0000000";
            dataBlock = "FreezeTrigger";
         };     

        %trigger.attachEffect();
   }
}


Haven't had chance to see if that would work or not but give it a try.
#4
10/22/2008 (7:57 am)
To freeze an AI player it's even easier. Just set their movement speed to zero, and then schedule a restart. I use this method on my AI when they're firing weapons, so that they appear to actually aim and not just run-and-gun.

// [pseudo code]
function AiArmor::onDamage(%this, %obj, %delta)
{   
// This method is invoked by the ShapeBase code whenever the    // object's damage level changes.   
if (%delta > 0 && %obj.getState() !$= "Dead") 
{      
// Increment the flash based on the amount.      
%flash = %obj.getDamageFlash() + ((%delta / %this.maxDamage) * 2);      
if (%flash > 0.75)         
%flash = 0.75;      
%obj.setDamageFlash(%flash);      // If the pain is excessive, let's hear about it.      
if (%delta > 10)         
%obj.playPain();      
%obj.setActionThread("name_of_animation");

%this.setMoveSpeed(0.0);
%delay = 3;// or whatever you want

%this.schedule(%delay, restart);
}
}

function AIArmor::restart(%this)
{
%this.setMoveSpeed(1.0);
}

// [/pseudo code]
#5
10/22/2008 (1:42 pm)
If you have AFX as well, you can just set the animationLock. Nothing will override your custom anim until it's done playing.
#6
10/23/2008 (6:02 am)
Andy
I tried the code, it didn't seem to work, and caused a few problems with other animations freezing. I was in a hurry when I tried it though, so I may have done something wrong. I'll try it again later when I have some spare time.