Damage FallOff. DMG over Distance
by Zorro Davis · in Torque Game Engine · 03/01/2014 (12:39 pm) · 6 replies
I am still new to scripting at the moment and I wanted to add a Damage FallOff or Damage over Distance effect to the Bulet Projectiles, which i was inspired by Battle Field 3 bullets. I attempted to kind of simulate damage over distance with this script:
/////////////////This is the OnFire:
function CarbineImage::onFire1(%this,%obj,%slot)
{
%obj.client.quantity["StatzFallOff"] = 6;
%obj.ShootTimerSchedule = schedule(10,%obj,ShootTimeLoop,%obj);
CarbineFired(%this,%obj,%slot);
}
///////////////The Function ShootTimeLoop:
function ShootTimeLoop(%obj)
{
%obj.client.quantity["StatzFallOff"] -= 0.01;
if(%obj.client.quantity["StatzFallOff"] >= 1)
{
%obj.ShootTimeSchedule = schedule(100,%obj,ShootTimeLoop,%obj);
}
else
{
%obj.client.quantity["StatzFallOff"] = 0;
cancel(%obj.ShootTimeSchedule);
}
}
///////////////The FallOff Function
function FallOff(%this, %obj, %col, %fade, %pos, %normal)
{
if(%obj.client.quantity["StatzFallOff"] > 4.5 && %obj.client.quantity["StatzFallOff"] < 6)
{
%damage = 100;
cancel(%obj.ShootTimeSchedule);
}
else if(%obj.client.quantity["StatzFallOff"] > 2 && %obj.client.quantity["StatzFallOff"] < 4.5)
{
%damage = 90;
cancel(%obj.ShootTimeSchedule);
}
else if(%obj.client.quantity["StatzFallOff"] > 0 && %obj.client.quantity["StatzFallOff"] < 2)
{
%damage = 50;
cancel(%obj.ShootTimeSchedule);
}
else if(%obj.client.quantity["StatzFallOff"] <= 0)
{
%obj.client.quantity["StatzFallOff"] = 0;
%damage = 40;
cancel(%obj.ShootTimeSchedule);
}
}
///////////////Projectile Damage function
function CarbineProjectile::damage(%this,%obj,%col,%fade,%pos,%normal)
{
FallOff(%this, %obj, %col, %fade, %pos, %normal);
echo("Damage :" SPC %damage);
%col.damage(%obj,%pos,%damage,%this.directDamageType);
parent::damage(%this, %obj, %col, %fade, %pos, %normal);
}
I later on figured that this set up is stupid because its unreliable and if I use a Full Auto weapon the value "%obj.client.quantity["StatzFallOff"]" would reset back to 6 which will make all the bullets (no matter how long they have been traveling) will be in the 100-90 range.
I began to think, if I can get the projectile lifetime maybe I can do something like:
Distance = Lifetime/Speed
then:
Damage = directDamage - Distance
Is there a callback or command that will callback how long a projectile has lived/Lifetime?
I know there is a better approach to this but I dont know how I would effectively calculate Damage over distance.
Any help is Lot of help to me.
/////////////////This is the OnFire:
function CarbineImage::onFire1(%this,%obj,%slot)
{
%obj.client.quantity["StatzFallOff"] = 6;
%obj.ShootTimerSchedule = schedule(10,%obj,ShootTimeLoop,%obj);
CarbineFired(%this,%obj,%slot);
}
///////////////The Function ShootTimeLoop:
function ShootTimeLoop(%obj)
{
%obj.client.quantity["StatzFallOff"] -= 0.01;
if(%obj.client.quantity["StatzFallOff"] >= 1)
{
%obj.ShootTimeSchedule = schedule(100,%obj,ShootTimeLoop,%obj);
}
else
{
%obj.client.quantity["StatzFallOff"] = 0;
cancel(%obj.ShootTimeSchedule);
}
}
///////////////The FallOff Function
function FallOff(%this, %obj, %col, %fade, %pos, %normal)
{
if(%obj.client.quantity["StatzFallOff"] > 4.5 && %obj.client.quantity["StatzFallOff"] < 6)
{
%damage = 100;
cancel(%obj.ShootTimeSchedule);
}
else if(%obj.client.quantity["StatzFallOff"] > 2 && %obj.client.quantity["StatzFallOff"] < 4.5)
{
%damage = 90;
cancel(%obj.ShootTimeSchedule);
}
else if(%obj.client.quantity["StatzFallOff"] > 0 && %obj.client.quantity["StatzFallOff"] < 2)
{
%damage = 50;
cancel(%obj.ShootTimeSchedule);
}
else if(%obj.client.quantity["StatzFallOff"] <= 0)
{
%obj.client.quantity["StatzFallOff"] = 0;
%damage = 40;
cancel(%obj.ShootTimeSchedule);
}
}
///////////////Projectile Damage function
function CarbineProjectile::damage(%this,%obj,%col,%fade,%pos,%normal)
{
FallOff(%this, %obj, %col, %fade, %pos, %normal);
echo("Damage :" SPC %damage);
%col.damage(%obj,%pos,%damage,%this.directDamageType);
parent::damage(%this, %obj, %col, %fade, %pos, %normal);
}
I later on figured that this set up is stupid because its unreliable and if I use a Full Auto weapon the value "%obj.client.quantity["StatzFallOff"]" would reset back to 6 which will make all the bullets (no matter how long they have been traveling) will be in the 100-90 range.
I began to think, if I can get the projectile lifetime maybe I can do something like:
Distance = Lifetime/Speed
then:
Damage = directDamage - Distance
Is there a callback or command that will callback how long a projectile has lived/Lifetime?
I know there is a better approach to this but I dont know how I would effectively calculate Damage over distance.
Any help is Lot of help to me.
About the author
#2
package ZLBullet_Pack
{
function Projectile::onAdd(%obj,%a,%b)
{
if(%obj.dataBlock.getID() == Carbineprojectile.getID())
{
%obj.startTime = $Sim::Time;
commandToClient(%obj.client,'startChargeBar', 100);
}
Parent::onAdd(%obj,%a,%b);
}
};
ActivatePackage(ZLBullet_Pack);
03/02/2014 (8:59 am)
So would adding a variable to the projectile go like this?:package ZLBullet_Pack
{
function Projectile::onAdd(%obj,%a,%b)
{
if(%obj.dataBlock.getID() == Carbineprojectile.getID())
{
%obj.startTime = $Sim::Time;
commandToClient(%obj.client,'startChargeBar', 100);
}
Parent::onAdd(%obj,%a,%b);
}
};
ActivatePackage(ZLBullet_Pack);
#3
just checked with
and got nothin in the console, so:
On the package bit, you should be able to replace any of the generic WeaponImage:: , ProjectileData:: methods with either a datablock specific or classname specific reference if you so choose. for instance:
03/02/2014 (1:36 pm)
couple things.just checked with
function BlunderbussProjectile::onAdd(%this,%obj)
{
error("projectiles have an onadd?");
}and got nothin in the console, so:
datablock ProjectileData( BlunderbussProjectile )
{...
falloffLoss = 2; //loose 2 points of damage every
falloffTime = 100; //100ms = 1/10 a second
damageFloor = 1; //with a minimum of this
...};
function WeaponImage::onFire(%this, %obj, %slot)
{...
if (%this.projectile.fallofftime != 0) %p.damageFalloffStartTime = $Sim::Time;
MissionCleanup.add(%p);
...}
function ProjectileData::onCollision(%this,%obj,%col,%fade,%pos,%normal,%hitbox)
{...
//subtract time alive
%dropoffmod = 0;
if (%obj.damageFalloffStartTime)
{
%timeAlive = $Sim::Time-%obj.damageFalloffStartTime;
%damagemod = %this.falloffLoss * (%timeAlive * 1000/%this.falloffTime);
%damage -= %damagemod;
if (%damage < %this.damageFloor) %damage = %this.damageFloor;
//error(%timeAlive SPC %damagemod SPC %damage);
}
...}Should give you enough values to use for fine-tuning (Or at least it seems to have done so this end. Thanks for the reminder. I should have popped something similar in our end a while back.)On the package bit, you should be able to replace any of the generic WeaponImage:: , ProjectileData:: methods with either a datablock specific or classname specific reference if you so choose. for instance:
datablock ProjectileData( BlunderbussProjectile )
{...
classname = "BlunderbussProjectileData";
...};
+
function BlunderbussProjectileData::onCollision(%this,%obj,%col,%fade,%pos,%normal,%hitbox)
{
error("BlunderbussProjectileData::onCollision");
Parent::onCollision(%this,%obj,%col,%fade,%pos,%normal,%hitbox);
}
#4
03/03/2014 (4:15 pm)
Why not just get the distance to the target using simple vector math and use that distance to reduce the damage? It would probably be less processor-intensive....
#5
03/03/2014 (4:31 pm)
Bullet drop, ricochet, and homing would distort a pure vector comparison, though Richard is right if you're just using the equivalent of raycasts (ie: no real motion from the bullet aside from forward till it hits something)
#6
03/03/2014 (6:37 pm)
Oh, now ricochet is a totally different matter - now we're talking materials and some considerably heavier math. There's a Mythbusters episode that goes into this topic pretty deeply out there somewhere....
Azaezel
Using something similar for our charged weapons this end:
function WeaponImage::onCharge(%this, %obj, %slot) { %obj.startTime = $Sim::Time; commandToClient(%obj.client,'startChargeBar', %this.maximumCharge); } function WeaponImage::onFire(%this, %obj, %slot) { if (%obj.startTime) { %modifier = $Sim::Time - %obj.startTime; //seconds if(%modifier > %this.maximumCharge) %modifier = %this.maximumCharge; if(%modifier < %this.minimumCharge) %modifier = %this.minimumCharge; commandToClient(%obj.client,'stopChargeBar', %this.maximumCharge); } else %modifier = 0.1;Depending on just how atomic you want it though, it might be better to hunt down the equivalent source entries and go that route.