Home   Help Search Login Register  

Author Topic: Detecting What Caused Damage to a Unit  (Read 2014 times)

0 Members and 1 Guest are viewing this topic.

Offline Lor

  • Members
  • *
Detecting What Caused Damage to a Unit
« on: 16 Jan 2008, 00:29:25 »
I'm creating a set of medic scripts.

When a unit takes damage, I need to know basically whether the damage was caused by a bullet, a grenade, or an explosion.

Is there any way at all to do this?

The hit event handler doesn't seem to return what caused the damage, and I can't think of any clever scripting hacks.

Anyone have any ideas?

Many thanks in advance!


Offline Loyalguard

  • Former Staff
  • ****
Re: Detecting What Caused Damage to a Unit
« Reply #1 on: 16 Jan 2008, 02:50:56 »
This is a rough idea, but this "might" be one way (assuming MP, otherwise public variables are just global instead).  This is only pseudo code, I can have actual code written in the morning:

UnitA is the "shooter" (has 'fired" event handler added to him)
UnitB is the "victim" (has "hit" event added to him)

UnitA "fires" a weapon.  The ammo type fired is stored as a global variable (local only on the client that controls UnitA) from _this select 4 according to the event handler.

UnitB is "hit" by something.  The object (unit) that caused the damage is _this select 1 according to the event handler. The event handler and broadcasts a public variable with the value of _this select 1.

A looping script on all clients checks the public variable against the name of the unit of the client it is running on (in this case UnitA) and if the same, it broadcasts a public variable with the value of of the global variable of the last known ammo fired.

UnitB's receives this public variable and proceeds with that as the most likely type of ammo that damaged it.

I know there are some potentially big holes in this concept (time delay bombs, damage from vehicles (they need their own fired event handlers), among others) but I can't think of any other way except maybe a looping nearObjects search to try to capture the types of objects of that were near the victim before the hit event handler was triggered but I am not sure that will work.

EDIT: Here is the code I came up with.  It is still theoretical and untested, I can't try it until tonight when I get home.  This code doesn not take into account the new public variable event handlers option in v. 1.09

UnitA Init Line:
Code: [Select]
this addEventHandler ["fired", {lastFiredAmmo = _this select 4}]; nul =  this execVM "lastFiredAmmo.sqf";The above adds a fired eventhandler to the unit that when triggered creates a global variable storing the last type of ammo fired by the unit.  The init also executes a looping script that uses the global variable in case a unit is hit by the ammo.
 
UnitB Init Line:
Code: [Select]
this addEventHandler ["hit", {lastHitBy = _this select 1; publicVariable "lastHitBy"; unitLastHit = _this select 0; newHit = true; publicVariable "newHit"; nul = this execVM "lastHitAmmo.sqf"}];The above adds a hit event handler to the unit that when triggered broadcasts a public variable to all units recording the last unit to hit someone.  The event handler broadcasts another public variable notifying all clients that a unit has been newly hit.  Lastly the event handler executes a script that determines what type of ammo last hit the unit.

init.sqf
Code: [Select]
// Initialize global variables for later use
lastFiredAmmo = "";
lastHitBy = "";
unitLastHit = "";
newHit = false;
lastFiredAmmo = "";
lastHitAmmo = "";

 
lastFiredAmmo.sqf:
Code: [Select]
_localUnitF = _this;
while {newHit} do
{
     if (lastHitBy == _localUnitF) then
     {
          publicVariable "lastFiredAmmo";
     }
};
The above script loops waiting for newHit to return true.  When it does it compares the unit that last hit someone with this unit. If they are the same a public variable is broadcast to all units with the type of ammo last fired.


lastHitAmmo.sqf
Code: [Select]
sleep .5;
_localUnitH = _this;
_localUnitH setVariable ["lastHitAmmo", lastFiredAmmo];
newHit = false;  publicVariable "newHit";
unitLastHit = "";
The above script is executed by the hit event handler.  It waits to make sure that lastFireAmmo.sqf has had time to broadcast lastFiredAmmo and then sets the value of lastFiredAmmo to the unit's object.  It then resets newHit and UnitLastHit for use by the next hit event.


Then when you need to find out what type of ammo last hit a unit for your medic script just use getVariable to retrieve it for that lastHitAmmo for that unit.  I have not worked with set/getVariable much so I can't be much help there.

If will test this later today to see if it works...but in the meantime...

SECOND EDIT: I sneaked home at lunch and tested it.  It works in the editor for a single unit with the hit event handler, so, this is encouraging.  I will test more extensively later trying to get it to work with multiple units.  In the meantime here is a demo mission as shown above.  The shooter has an M16 and an M9.  Shoot the civilian (try not to kill him) and then press 0-0-0 (Radio Juliet) to show the last known ammo to hit him.  Switch weapons and hit 0-0-0 again to see the difference.  It also works with grenades, I haven't tested satchels or other munitions.

(small error in the demo init. sqf.  Change llastFiredAmmo to lastFiredAmmo.  Sorry, doesnt' seem to affect the script and I will fix it later)
« Last Edit: 16 Jan 2008, 15:31:03 by Loyalguard »

Offline Lor

  • Members
  • *
Re: Detecting What Caused Damage to a Unit
« Reply #2 on: 16 Jan 2008, 19:06:27 »
Holy crap Loyalguard - thanks for all the work!

This looks great, and as you said, it definitely works.

Really, the HUGE question is whether or not this could be adjusted to detect if units are damaged by grenades, or vehicle explosions -- as really, all I need is to tell whether the cause of damage was "bullet", or "explosion".

Unfortunately, every solution I come up with would require the ability to check the type of object AFTER it has caused the damage, which doesn't seem to be possible without tracking -every- bullet fired and grenade thrown =/

Offline Loyalguard

  • Former Staff
  • ****
Re: Detecting What Caused Damage to a Unit
« Reply #3 on: 16 Jan 2008, 19:27:26 »
No problem, that's what we're here for ;)

There might be another way, but if won't likely not be accurate, it will need some testing.  You might be able to use the "damage" value of the event handler array to "help" determine the kind of damage.  If it is a value consistent with bullets, a bullet most likely caused the damage.  If it is a value consistent with explosions (harder to determine because "splash" values vary if I am not mistaken...let me do some testing.

Offline Lor

  • Members
  • *
Re: Detecting What Caused Damage to a Unit
« Reply #4 on: 16 Jan 2008, 19:43:23 »
Aha! Interesting idea! I'll do some testing of various damage values too real quick.

Edit: Unfortunately, it looks like the damage done by a bullet varies depending on the distance to the target - and is indistinguishable from e.g. splash damage from a grenade which varies too.

Edit 2: I just had another thought - what about a constantly looping script that checks to see if there's a bullet within 100 meters of the player (or more or less), and then if damage is taken within 0.3 seconds of a bullet being detected near the player, then it's PROBABLY that the damage was done by the bullet.

This would all depend on how fast the script can loop and how accurate the timings can be, and also what the chances are of bullets being near a player when a vehicle explodes/grenade goes off, and if the timing of the coincidence of the presence of the bullet and the actual damage can be sufficiently accurate to differentiate.

I will do some more tests =)
« Last Edit: 16 Jan 2008, 20:12:16 by bedges »

Offline Loyalguard

  • Former Staff
  • ****
Re: Detecting What Caused Damage to a Unit
« Reply #5 on: 16 Jan 2008, 21:59:08 »
I actually tested last night something similar to what you proposed...I gave up early because the timing was hard to manage...I don't think the loop was fast enough...I will also look into it again as well.

Offline Mandoble

  • Former Staff
  • ****
    • Grunt ONE and MandoMissile suite
Re: Detecting What Caused Damage to a Unit
« Reply #6 on: 16 Jan 2008, 22:59:57 »
Put this into your init.sqf
Code: [Select]
grenade_bullet =
{
   (_this select 0) setVariable ["parts_damaged", ((_this select 0) getVariable "parts_damaged") + 1];
   if (((_this select 0) getVariable "parts_damaged") == 1) then
   {
      [_this select 0] spawn
      {
         Sleep 0.1;
         if ( ((_this select 0) getVariable "parts_damaged") > 2) then
         {
            (_this select 0) setVariable ["was_hit_by", "explosion"];
         }
         else
         {
            if (((_this select 0) getVariable "was_hit_by") == "nothing") then
            {
               (_this select 0) setVariable ["was_hit_by", "bullet"];
            };           
         };
         (_this select 0) setVariable ["parts_damaged", 0];
      };
   };
};

unit1 setVariable ["parts_damaged", 0];
unit1 setVariable ["was_hit_by", "nothing"];
unit1 addEventHandler ["Dammaged", grenade_bullet];


while {true} do
{
   waitUntil {damage unit1 > 0};
   hint format["Most representative damage caused by: %1", unit1 getVariable "was_hit_by"];
   Sleep 1;
};

Now add a unit in front of you named unit1
Try firing bullets at him or grenades, might be that is what you are looking for.
« Last Edit: 17 Jan 2008, 13:15:15 by Mandoble »

Offline Loyalguard

  • Former Staff
  • ****
Re: Detecting What Caused Damage to a Unit
« Reply #7 on: 16 Jan 2008, 23:22:03 »
Great idea! It should work because an explosion (grenade or bomb) usually damages more than one selectionName of a unit at a time whereas a bullet only damages one at a time.  Even if there are some cases where it an explosion only damages one, you could always consider that a "puncture" wound caused by shrapnel which would be treated like a bullet wound ;)
« Last Edit: 16 Jan 2008, 23:40:13 by Loyalguard »

Offline Lor

  • Members
  • *
Re: Detecting What Caused Damage to a Unit
« Reply #8 on: 17 Jan 2008, 00:25:03 »
That looks awesome Mandoble - I'll test this out and get back to you! =D

Offline Mandoble

  • Former Staff
  • ****
    • Grunt ONE and MandoMissile suite
Re: Detecting What Caused Damage to a Unit
« Reply #9 on: 17 Jan 2008, 13:18:13 »
Changed the code above a bit, so in case a unit gets hit by bullet and grenades, it stores the cause most representative of its current damage level, even if the grenade hit it before the bullet.

When the unit is healed, its "was_hit_by" internal variable should be reset again to "nothing". This is something your healing scripts should take care of.