Game Development Community

Getting the value of %damage?

by Kirby Webber · in Torque Game Engine · 07/22/2005 (7:12 am) · 9 replies

Let me explain what it is I'm trying to accomplish for clarity:

I am working from the racing mod, so the vehicles in question (hover vehicles to be specific) are the player entity.

I have defined the necessary datablock and script functions to allow damage to be applied to the vehicle as well as energy consumption through turbo/ jetting functionality.

What I'm working toward is a type of sheild system - not unlike that of Tribes2 - where incoming damage is applied first to energy, after which any remaining damage is applied to the health of the craft.

I have defined an onImpact() function to handle collision with terrain/ interior objects, an onDamage() function which seems to be required by the engine, and a damage() function wherein any damage inflicted actually gets applied to the vehicle.

onImpact() -
//---------------------------------------------------------------
function HoverCycle::onImpact(%this, %obj, %collidedObject, %vec, %vecLen)
{
     %obj.damage(0, VectorAdd(%obj.getPosition(),%vec),
     %vecLen * %this.speedDamageScale, "Impact");
}

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

          // 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 player is dead, kill him!
     if (%obj.getDamageLevel() > 1.99) {
          %obj.setDamageState(Destroyed);
          onDestroyed();
     }
}

damage()-
//---------------------------------------------------------------
function HoverCycle::damage(%this, %obj, %sourceObject, %position, %damage,
%damageType)
{
     if (%obj.getEnergyLevel() > 0) {
     //Decrement energy before health - emulate sheilds
     %newEnergy = %obj.getEnergyLevel() - 80; //Should be - %damage
     %obj.setEnergyLevel(%newEnergy);
     
     //If we went below 0, fix it
     if (%obj.getEnergyLevel() < 0)
          %obj.setEnergyLevel(0);
     }
     
     if (%obj.getEnergyLevel() == 0)
          %obj.applyDamage(%damage);
     
     // Deal with client callbacks here because we don't have this
     // information in the onDamage or onDisable methods
     %client = %obj.client;
     %sourceClient = %sourceObject ? %sourceObject.client : 0;
     
     if (%obj.getDamageState() $= "Destroyed")
          %client.onDeath(%sourceObject, %sourceClient, %damageType, %location);
}

Now, as you can see above, the damage() function takes in an argument called %damage.

The first thing I'm doing is testing the object to ensure that it has energy - no problems so far.

If it does, then I decrement energy using %obj.setEnergyLevel(%value). Still no problems, except that I'm currently having to calcualte using a constant value.

For some reason, if I change the statement which calculates the remaining energy to - %newEnergy = %obj.getEnergyLevel - %damage; - nothing happens. It's as if %damage has no value assigned?

What makes this more confusing is that when %obj.applyDamage(%damage); gets called, the damage gets applied appropriately?! Obviously %damage has a value, but why can I not access it in a simple calcualtion?

~ Thanks in advance for any help.

#1
07/22/2005 (8:25 am)
Kirby

Have you defined a variable called speedDamageScale in the hovercycles datablock?

%veclen is multiplied by the %this.speedDamageScale variable in onImpact to give the amount of damage to apply.

I think that if you havent specified a value for speedDamageScale in the datablock then it will give zero which results in no damage?

For example, from my player.cs file, the player datablock has

...
   minImpactSpeed = 15;
   speedDamageScale = 0.9;
..

If I comment out the speedDamageScale then no damage is done on impact.
#2
07/22/2005 (8:40 am)
Yes I have. (Brought a copy of the script to work with me this morning so I could verify these types of issues before responding. ;)

From the rigid body information in the vehicle datablock:

speedDamageScale                = 0.008;

You see, if I strip away all of my conditions, and just call %obj.applyDamage(); directly, everything works fine.

Even using a hard-coded variable to decrement energy works and, when energy is at 0 the damage carries across to the vehicle health.

It's only when I try to use the %damage variable to calculate how much energy to decrement that nothing happens.

I spent upwards of 3 hours on this last night and it's still got me stumped. =\

[edit]

It may be pertinent to state that I'm working with HEAD (1.4).

You never know...
#3
07/22/2005 (8:58 am)
The only thing I can think of there is that the speedDamageScale value is quite small.

If damage was 80 then the result of the scale would give damage of 0.64

Have you tried echo(%damage); to see what values of damage you are getting?
#4
07/22/2005 (8:58 am)
You know, as I look at this, I find myself wondering...

Is it me, or does onImpact(); appear to be handing out 4 arguments and damage(); expecting 5?

(From onImpact()) -> Is'nt this 1 argument? VectorAdd(%obj.getPosition(),%vec)

Am I perhaps handing vectors to the %damage variable?

If so, why would applyDamage() not throw some type of error, or at least, not work properly?
#5
07/22/2005 (9:04 am)
Hmmm... we posted at the same time.

I hadn't thought of that David, but it's an interesting point.

My energy level is set to 100, but destroyedLevel is 2.0.

I think you're onto something.

I'll try multiplying the %damage value when I get home tonight and see what results I get.

And here I thought I'd been thorough. (C;
#6
07/22/2005 (9:16 am)
Off-topic: If you happen to solve your shield emulation, could you contact me? I've been attempting to emulate shields for my player by taking damage off the energy before the health bar and have been unsuccessful. :P
#7
07/22/2005 (9:46 am)
Chris, I should know by tonight whether or not this works, but ultimately, you're effectively looking at my solution.

Basically, this code block:

//---------------------------------------------------------------
function HoverCycle::damage(%this, %obj, %sourceObject, %position, %damage,
%damageType)
{
     if (%obj.getEnergyLevel() > 0) {
          //Decrement energy before health - emulate sheilds
          %newEnergy = %obj.getEnergyLevel() - 80; //Should be - %damage
          %obj.setEnergyLevel(%newEnergy);
     
          //If we went below 0, fix it
          if (%obj.getEnergyLevel() < 0)
          %obj.setEnergyLevel(0);
}

     if (%obj.getEnergyLevel() == 0)
          %obj.applyDamage(%damage);

...

Should read as follows:

//---------------------------------------------------------------
function HoverCycle::damage(%this, %obj, %sourceObject, %position, %damage,
%damageType)
{
     if (%obj.getEnergyLevel() > 0) {
          //Decrement energy before health - emulate sheilds
          [b]%newDamage = %damage * 100;
          %newEnergy = %obj.getEnergyLevel() - %newDamage;
          %damage = (%newDamage - %newEnergy)/100;[/b]
          %obj.setEnergyLevel(%newEnergy);
     
          //If we went below 0, fix it
          if (%obj.getEnergyLevel() < 0)
          %obj.setEnergyLevel(0);
...

Here's what I think is happening:

The vehicles health is on a very small scale, with a destroyedLevel of only 2.0. Energy, on the other hand is on a much larger scale.

In order to get the values comparable, I'll have to multiply %damage by 100 to get a whole number which can then be used to reduce the energy level.

Afterwards however, we want to take any remaining damage and apply it to the vehicle (assuming that the energy was completely drained.

In order to do that, we first subtract however much energy we used from the value, and then divide the result by 100 to get our value back within the range expected by the engine. Not doing so would rsult in instant death if you took damage beyond your sheilds.

You'll notice that the next if statement only activates when energy is set to zero, and then applies the value of %damage.

Beyond that, it's a matter of coding up some nifty FX for the sheild hit.

Who knows, if it works out, and there's enough interest, I may submit it as a resource or something. =)

[edit]

Of course, I could just increase the speedDamageScale, now that I think about it, and then increase the destroyedLevel to something larger.

~ Decisions... heh
#8
07/22/2005 (11:13 am)
I think the destroyedLevel is the amount of health left at which the object is destroyed.

So if you start off at 100 health and 100 energy, your small speedDamageScale would take ages to reduce health to a value of 2 when the object would be destroyed.

I would try making the speedDamageScale something like 0.8 and add a few echo("Damage: " @ %damage); lines in the script to see what values you are getting.
#9
07/22/2005 (11:23 am)
Yeah, that's what I'm realizing, although it appears that the engine counts damage upwards to the destroyed value. =\

So it's clear - destroyedLevel and MaxDamage were both set to 2.0. ;-) This required a very low speedDamageScale to avoid instant death on a single impact.

My thinking is that I can up the speedDamageScale, increase the destroyedLevel (and MaxDamage) and everything should work just fine.

I plan to try this out as soon as I get home.

I'll also add the echo command so I can track it.

Thanks for your help - I'm all but 100% positive you've nailed the problem. (C: