Jump to content
militarypolice

Popup targets requiring Multiple hits and Target Moving

Recommended Posts

Hello!

 

I have 2 questions. One is a request of the sorts and another is help with a function.

 

1. I would like to create a script that will keep a popup target up until 2 hits are achieved. I know it would require "Hit" event handlers. But I do not know how to work with Event Handlers yet. I've done it once before, but was a long while ago. Any direction on that, would be great. I'm sure I can figure it out, I just need some help with a foundation!

 

2. I'm using BIS_animateMoveSmooth to create a smooth movement of popup targets. In single player it works just fine and is smooth. But, in multiplayer it does not work at all, well the animation doesn't play. I click the button to move a target closer and it's like it plays the animation on the server, but not to the clients. Once it seems like the animation is done on the server it then teleports the target to the right place for everyone, including the person who selected the button. I wonder if I need to execute it via a remoteexec? Below is the block of code I am using:

 

call{this addAction ["Move 0m", "[l3t, [l330m, l30m]] spawn BIS_animateMoveSmooth;"];
this addAction ["Move 35m", "[l3t, [l330m, l320m]] spawn BIS_animateMoveSmooth;"];
this addAction ["Move 30m", "[l3t, [l30m, l330m]] spawn BIS_animateMoveSmooth;"];}

 

Name of the target is "l3t" and it then moves to a rail that is named "l330m" or "l320m" etc. Any help on this would be greatly appreciated as well!

Share this post


Link to post
Share on other sites

Any help would be greatly appreciated! I found some scripts throughout Google, but I assume something has changed in the backend as those scripts do not work anymore... I am kinda desperate as I've been reading and reading and testing and testing and am just failing lol... I've been looking for something that can accomplish multiple hits on a popup target for a very long time!

 

A tutorial on how to create Hit MPEventHandlers or something would help too! I'm totally not trying to have someone do this for me. I would much rather learn, I just need to be pointed in the right direction!

 

Thanks!

Share this post


Link to post
Share on other sites

No need to use MP event handler. The Hit event handler executed where popups are local (most likely on server) should be enough.

 

The problem is to suppress the engine animation for popping up again, but I m on it...

Share this post


Link to post
Share on other sites
Posted (edited)

This is tested in init field of popup in SP only and working. Its a long thing and maybe there is a shorter solution. Should work in MP as well but not testet it there:

 if !(local this) exitWith {};
 
 this addEventHandler ["Hit", { 

 private _hit_num = 10;
 private _down_time = 5;

 params ["_unit"];
 
 private _phase = _unit animationPhase "Terc";
 
 if ( _phase isNotEqualTo 0 ) exitWith { };
 
 private ["_dummy"];
 
 private _hit_already = _unit getVariable ["saro_hit_num", 0];
 
 if ( _hit_already < _hit_num - 1) exitWith 
 {
  _unit setVariable ["saro_hit_num", (_hit_already + 1) ];
  _dummy = _unit spawn
  {
   sleep diag_deltaTime;
   _this animateSource ["Terc", 0];
  };
 };
 
 _dummy = [_unit, _down_time] spawn
 {
  params [ "_unit", "_down_time" ];
 
  private ["_phase"];
  
  private _down_start = 0;
  
  sleep diag_deltaTime;
  waitUntil
  {
   _phase = _unit animationPhase "Terc";
   
   if ( _phase isEqualTo 1 && _down_start isEqualTo 0 ) then { _down_start = diag_tickTime };
   
   _unit animateSource ["Terc", 1];
   _down_start > 0 and (diag_tickTime - _down_start) > _down_time
  };
  _unit animateSource ["Terc", 0];
  _unit setVariable ["saro_hit_num", 0];
 };
}];

you are able to adjust needed number of hits with variable _hit_num and the time the target is down with _down_time

 

Edited by sarogahtyp
minor changes
  • Like 2

Share this post


Link to post
Share on other sites
11 hours ago, sarogahtyp said:

This is tested in init field of popup in SP only and working. Its a long thing and maybe there is a shorter solution. Should work in MP as well but not testet it there:


 if !(local this) exitWith {};
 
 this addEventHandler ["Hit", { 

 private _hit_num = 10;
 private _down_time = 5;

 params ["_unit"];
 
 private _phase = _unit animationPhase "Terc";
 
 if ( _phase isNotEqualTo 0 ) exitWith { };
 
 private ["_dummy"];
 
 private _hit_already = _unit getVariable ["saro_hit_num", 0];
 
 if ( _hit_already < _hit_num - 1) exitWith 
 {
  _unit setVariable ["saro_hit_num", (_hit_already + 1) ];
  _dummy = _unit spawn
  {
   sleep diag_deltaTime;
   _this animateSource ["Terc", 0];
  };
 };
 
 _dummy = [_unit, _down_time] spawn
 {
  params [ "_unit", "_down_time" ];
 
  private ["_phase"];
  
  private _down_start = 0;
  
  sleep diag_deltaTime;
  waitUntil
  {
   _phase = _unit animationPhase "Terc";
   
   if ( _phase isEqualTo 1 && _down_start isEqualTo 0 ) then { _down_start = diag_tickTime };
   
   _unit animateSource ["Terc", 1];
   _down_start > 0 and (diag_tickTime - _down_start) > _down_time
  };
  _unit animateSource ["Terc", 0];
  _unit setVariable ["saro_hit_num", 0];
 };
}];

you are able to adjust needed number of hits with variable _hit_num and the time the target is down with _down_time

 

So this did work! Thank you very much for your time and interest!!

But, I'm seeing that if I want to create a shooting drill program, for targets to popup, it loses the hit event handler when they popup again.

 

So I have a program to select random targets and pop them up. The init.sqf file has nopop = true; within it. I removed:

 _dummy = [_unit, _down_time] spawn
 {
  params [ "_unit", "_down_time" ];
 
  private ["_phase"];
  
  private _down_start = 0;
  
  sleep diag_deltaTime;
  waitUntil
  {
   _phase = _unit animationPhase "Terc";
   
   if ( _phase isEqualTo 1 && _down_start isEqualTo 0 ) then { _down_start = diag_tickTime };
   
   _unit animateSource ["Terc", 1];
   _down_start > 0 and (diag_tickTime - _down_start) > _down_time
  };
  _unit animateSource ["Terc", 0];
  _unit setVariable ["saro_hit_num", 0];
 };
}];

from your script as it seemed to be popping up the target regardless of having nopop=true; within the init.sqf. The script I created for the shooting drill is this:

sleep 1;

_target = selectRandom [t1,t2,t3,t4,t5,t6,t7];
_target animate["terc", 0];
_target = selectRandom [t1,t2,t3,t4,t5,t6,t7];
_target animate["terc", 0];

sleep 4;

execVM "alldown.sqf";

(alldown.sqf just pops all targets down) That just runs when someone selects it from a computer via addaction. Add and take away when you want more then one target to popup. So, before running the program, multiple hits work and the targets do not go down unless the 2 hits are achieved. But once I run the program, it goes back to one hit.

 

Any ideas?

Share this post


Link to post
Share on other sites

Okay, so I did some playing around! I removed:

_unit animateSource ["Terc", 0];

from the script and now the program works and when they pop back up and it takes 2 shots to put the target back down!!

 

So, the only thing now, is to make something where the it can be executed via spawn or execVM with a oneliner as I will likely have hundreds of popup targets that will use this in my Training Map! That will make administration easy and will cut down on the SQM size!

 

Share this post


Link to post
Share on other sites

Okay! I've gotten it figured out!

 

I tried spawn, execVM and call and compile file routes. I do admit, I'm not 100% understanding of the variables. I'm a PowerSheller and understand variables and scoping very well. But, when it comes to arma, I guess I second guess myself.. But, what I've done, is created a foreach loop in the init file with your script:

 

_types = ["TargetP_Inf4_F","Land_TargetEpopup"];

for [{_i=0},{_i < (count _types)},{_i=_i+1}] do {
    _targets = getMarkerPos "target" nearObjects [_types select _i, 500];
    if (count _targets < 1) exitWith {
        systemChat "No Enemy were found.";  //exit if no targets have been found
    };
    {if (isServer) then { _x addEventHandler ["Hit", { 

 private _hit_num = 2;
 private _down_time = 0.1;

 params ["_unit"];
 
 private _phase = _unit animationPhase "Terc";
 
 if ( _phase isNotEqualTo 0 ) exitWith { };
 
 private ["_dummy"];
 
 private _hit_already = _unit getVariable ["saro_hit_num", 0];
 
 if ( _hit_already < _hit_num - 1) exitWith 
 {
  _unit setVariable ["saro_hit_num", (_hit_already + 1) ];
  _dummy = _unit spawn
  {
   sleep diag_deltaTime;
   _this animateSource ["Terc", 0];
  };
 };
 
 _dummy = [_unit, _down_time] spawn
 {
  params [ "_unit", "_down_time" ];
 
  private ["_phase"];
  
  private _down_start = 0;
  
  sleep diag_deltaTime;
  waitUntil
  {
   _phase = _unit animationPhase "Terc";
   
   if ( _phase isEqualTo 1 && _down_start isEqualTo 0 ) then { _down_start = diag_tickTime };
   
   _unit animateSource ["Terc", 1];
   _down_start > 0 and (diag_tickTime - _down_start) > _down_time
  };
  _unit setVariable ["saro_hit_num", 0];
 };
}];};} forEach _targets;
};

this way, I can control which targets are need to be hit multiple times and which ones do not. This route also doesnt touch the SQM file size either!

Let me know if you approve of this method? or if there is a better method?

Share this post


Link to post
Share on other sites

Okay, so everything works in SP and Hosted Multiplayer. But it doesn't work with Dedicated Servers. Do you know how I could fix that? This is how I am getting it to all of the Pop-up targets that need it:

_types = ["TargetP_Inf4_F"];

for [{_i=0},{_i < (count _types)},{_i=_i+1}] do {
    _targets = getMarkerPos "target" nearObjects [_types select _i, 15000];
    if (count _targets < 1) exitWith {
        systemChat "No Targets were found.";  //exit if no targets have been found
    };
    {if !(local _x) exitWith {}; _x addEventHandler ["Hit", { 

 private _hit_num = 2;
 private _down_time = 0.1;

 params ["_unit"];
 
 private _phase = _unit animationPhase "Terc";
 
 if ( _phase isNotEqualTo 0 ) exitWith { };
 
 private ["_dummy"];
 
 private _hit_already = _unit getVariable ["saro_hit_num", 0];
 
 if ( _hit_already < _hit_num - 1) exitWith 
 {
  _unit setVariable ["saro_hit_num", (_hit_already + 1) ];
  _dummy = _unit spawn
  {
   sleep diag_deltaTime;
   _this animateSource ["Terc", 0];
  };
 };
 
 _dummy = [_unit, _down_time] spawn
 {
  params [ "_unit", "_down_time" ];
 
  private ["_phase"];
  
  private _down_start = 0;
  
  sleep diag_deltaTime;
  waitUntil
  {
   _phase = _unit animationPhase "Terc";
   
   if ( _phase isEqualTo 1 && _down_start isEqualTo 0 ) then { _down_start = diag_tickTime };
   
   _unit animateSource ["Terc", 1];
   _down_start > 0 and (diag_tickTime - _down_start) > _down_time
  };
  _unit setVariable ["saro_hit_num", 0];
 };
}];} forEach _targets;
};

This is placed in the init.sqf file. Any ideas?

Share this post


Link to post
Share on other sites
Posted (edited)

I did not fully understand what you want to do exactly but I guess you need to enable/disable the EH behaviour related on actions taken by clients.

 

The important thing is to execute the event handler where the popups are local. This should be on server.

If you need other behaviour then the event handler provides then you have to remove the EH from those targets.

Therefore you should apply the EH everytime you need the behaviour and remove it after that.

If a client decides on which popups the EH should get applied then you have to remoteExec the EH on the server.

This can be done by first creating a sqf file with the EH. You could name it apply_EH.sqf

 

apply_EH.sqf

params ["_popup"];

//apply EH
private _eh_index = _popup addEventHandler ["Hit", { 

 private _hit_num = 10;
 private _down_time = 5;

 params ["_unit"];
 
 private _phase = _unit animationPhase "Terc";
 
 if ( _phase isNotEqualTo 0 ) exitWith { };
 
 private ["_dummy"];
 
 private _hit_already = _unit getVariable ["saro_hit_num", 0];
 
 if ( _hit_already < _hit_num - 1) exitWith 
 {
  _unit setVariable ["saro_hit_num", (_hit_already + 1) ];
  _dummy = _unit spawn
  {
   sleep diag_deltaTime;
   _this animateSource ["Terc", 0];
  };
 };
 
 _dummy = [_unit, _down_time] spawn
 {
  params [ "_unit", "_down_time" ];
 
  private ["_phase"];
  
  private _down_start = 0;
  
  sleep diag_deltaTime;
  waitUntil
  {
   _phase = _unit animationPhase "Terc";
   
   if ( _phase isEqualTo 1 && _down_start isEqualTo 0 ) then { _down_start = diag_tickTime };
   
   _unit animateSource ["Terc", 1];
   _down_start > 0 and (diag_tickTime - _down_start) > _down_time
  };
  _unit animateSource ["Terc", 0];
  _unit setVariable ["saro_hit_num", 0];
 };
}];

//store the EH index on popup to be able to remove the EH later
_popup setVariable ["saro_eh_index", _eh_index];

 

for one specific popup (I call it _one_popup here) chosen by a client to get the EH behaviour on it you can do now:

 

[_one_popup, "apply_EH.sqf"] remoteExec ["execVM", 2];

 

next thing you need a sqf file to remove that behaviour.

 

remove_EH.sqf

params [_popup];

//get the prior stored Index of the EH
private _eh_index = _popup getVariable "saro_eh_index";

// no index found, just leave
if (isNil "_eh_index") exitWith {};

//remove the EH
_popup removeEventHandler ["Hit", _eh_index];

//destroy the index variable on popup
_popup setVariable ["saro_eh_index", nil];

 

After that on the time a client decides to not need the EH behaviour anymore you can just do

 

[_one_popup, "remove_EH.sqf"] remoteExec ["execVM", 2];

 

not tested but should work...

Edited by sarogahtyp
finished post

Share this post


Link to post
Share on other sites

Okay, the code for the hits works! But it still doesnt work in Dedicated Servers. I tried with just "2" and I tried with "[0, -2] select isDedicated,true".

 

With "[0, -2] select isDedicated,true" the target would start to pop down and then half way through come back up for the second hit and once the second hit it would stay down. Also, it was very hit or miss, like it wouldnt do it for all targets. Just randomly some. But with just "2" it would not work at all.

 

This is the code I am using to put the remoteexec on every target needed (This is ran in the init.sqf file):

_types = ["TargetP_Inf4_F"];

for [{_i=0},{_i < (count _types)},{_i=_i+1}] do {
    _targets = getMarkerPos "target" nearObjects [_types select _i, 30000];
    if (count _targets < 1) exitWith {
        systemChat "No Enemy were found.";  //exit if no targets have been found
    };
    {[_x, "scripts\apply_EH.sqf"] remoteExec ["execVM", [0, -2] select isDedicated,true];} forEach _targets;
};

I think we are getting closer!

Share this post


Link to post
Share on other sites

I will try that! Quick question, so the Event handler doesn't stick if the "Enable Damage Button" in specials properties is checked. I was running through a program in single player and over time, the popup target was destroyed because of how many rounds was being used. I have a bunch of people who will be using these popup targets. To combat this, what we've done, is to just have Simulation on and have Damage off for popup targets. Is there a way to get the script to run while damage is off?

 

I will try the _x option right now and let you know!!

 

Also, seriously, thank you for your help! this is awesome!

Share this post


Link to post
Share on other sites

So, I tried it with _x:

_types = ["TargetP_Inf4_F"];

for [{_i=0},{_i < (count _types)},{_i=_i+1}] do {
    _targets = getMarkerPos "target" nearObjects [_types select _i, 30000];
    if (count _targets < 1) exitWith {
        systemChat "No Enemy were found.";  //exit if no targets have been found
    };
    {[_x, "scripts\apply_EH.sqf"] remoteExec ["execVM", _x];} forEach _targets;
};

and it did not work and went back to as if it was "2".

Share this post


Link to post
Share on other sites

I did not. But I just added the first block of code on that page. Ill test it in a second and let you know!

Share this post


Link to post
Share on other sites

If you'd like to take a look at the mission file:

http://www.575th.com/public/(U)_S3_Missions_PopUp_Target_Test.VR.rar

 

Also, in the remoteexec call, using [0,-2] works the best. It goes half way down, but then comes back up waiting for the second shot. But in single player, it doesnt go down until after the 2nd shot. Do you think this is a MP issue?

Share this post


Link to post
Share on other sites

@sarogahtyp
My favorite line from the script above,

_down_start > 0 and (diag_tickTime - _down_start) > _down_time

now that's how you return bool like a pro!

Thanks, man!

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

I helped him and I think we already fixed the problem. 

At least it looks like he has no more questions.

Share this post


Link to post
Share on other sites

Sorry about that! Its been a long week... But, thank you all for your help! For now this is fine and working! I've learned a lot and will try to implement things I've learned and continue to learn in the future!

Share this post


Link to post
Share on other sites

If anyone is interested, here is the main part of the solution:

[] call JF_fnc_Options;

player addEventHandler ["Fired",
  {
	   params ["_unit", "_weapon", "_muzzle", "_mode", "_ammo", "_magazine", "_projectile", "_gunner"];

     private _cTarget = cursorTarget;
     private _types = missionNamespace getVariable "types";

     if ((typeOf _cTarget) in _types) then {
       deleteVehicle _projectile;

       private _hit_already = _cTarget getVariable "saro_hit_num";
       private _phase = _cTarget animationSourcePhase "terc";

       if ( _hit_already < (HIT_NUM - 1)) then {
         _cTarget setVariable ["saro_hit_num", (_hit_already + 1), true];
       } else
       {
         _cTarget animateSource ["terc", 1.5];
         _cTarget setVariable ["saro_hit_num", 0, true];
       };

     hint parseText format ["<t color='#FFFFFF'>The Target <t color='#23D9C1'> %1 <t color='#FFFFFF'> has been hit <t color='#23D9C1'> %2 <t color='#FFFFFF'> times. </t>", _cTarget, _hit_already+1]; 

     };

  }
];

 

And here's the mission folder:

https://ufile.io/4dt0g2ke

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×