Jump to content
ObsceneNickname

Assign custom init to all spawned unit

Recommended Posts

Hello guys,

I've this piece of code which just is a "damage reduction" script.

this addEventHandler ["HandleDamage", {
  _unit = _this select 0;
  _selection = _this select 1;
  _damage = _this select 2;

  if (_selection == "?") exitWith {};

  _curDamage = damage _unit;
  if (_selection != "") then {_curDamage = _unit getHit _selection};
  _newDamage = _damage - _curDamage;

  _damage - _newDamage * 0.80
}];

Now, how can i assign this script to be used on all the units? I mean even spawned ones with various methods (Zeus, Alive mod, other spawn scripts) ?

I read I've to put this in my mission's description.ext

class Extended_Init_EventHandlers {
 class Man {
  init = "_this call (compile preprocessFileLineNumbers 'my_script.sqf')";
 };
};

and then just create the "my_script.sqf" file with the lines of code I want to put in all units' init (in this case the damage reduction script above-written).

But sadly this method didn't work for me.

Do you know how to assign a init to all spawned units? I'm so tired of manually edit all the unit xD

Thank you in advance.

Share this post


Link to post
Share on other sites
//description.ext
class Extended_InitPost_EventHandlers {
    class CAManBase {
        class initpost_units {
            serverInit = "[_this] call compile preprocessFileLineNumbers 'my_script.sqf'";
        };
    };
};



//my_script.sqf
params [["_unit",objNull,[objNull]]];

_unit addEventHandler ["HandleDamage", {

  _unit = _this select 0;
  _selection = _this select 1;
  _damage = _this select 2;

  if (_selection == "?") exitWith {};

  _curDamage = damage _unit;
  if (_selection != "") then {_curDamage = _unit getHit _selection};
  _newDamage = _damage - _curDamage;

  _damage - _newDamage * 0.80
}];

require CBA_A3 MOD

  • Like 2

Share this post


Link to post
Share on other sites

I appreciate the super fast help davidoss but sadly that didn't work :(

I tried it in a listening server (the one you can launch through the eden editor) and it doesn't work. It gives me on-screen errors.  (https://ibb.co/noBD6L here's a link to a screenshot of the in-game errors)

 

Share this post


Link to post
Share on other sites

My bad too many []

 

//description.ext
class Extended_InitPost_EventHandlers {
    class CAManBase {
        class initpost_units {
            serverInit = "_this call compile preprocessFileLineNumbers 'my_script.sqf'";
        };
    };
};



//my_script.sqf
params [["_unit",objNull,[objNull]]];

_unit addEventHandler ["HandleDamage", {

  _unit = _this select 0;
  _selection = _this select 1;
  _damage = _this select 2;

  if (_selection == "?") exitWith {};

  _curDamage = damage _unit;
  if (_selection != "") then {_curDamage = _unit getHit _selection};
  _newDamage = _damage - _curDamage;

  _damage - _newDamage * 0.80
}];

Anyway this should be an fuction  not a file because it will run multiple times.

  • Thanks 1

Share this post


Link to post
Share on other sites

davidoss, you're a hero! :D It worked perfectly! Thank you.

 

What do you mean by "this should be a function"? Can you help me "making" one? I fear I'm definitely too noob to understand that.

It seems you're super skilled in scripting, can i take advantage of that and ask you another thing regarding the eventHandler?

 

Thank you anyway :)

 

Share this post


Link to post
Share on other sites

There is a simple way, not requiring CBA:

 

in init.sqf:

 

[] spawn {
  while {true} do {
    _allUnits = (allUnits select {_x getVariable "ON_EH_HD"});
    {
       _x setVariable ["ON_EH_HD",true];
       _x addEventHandler ["HandleDamage", {
          params ["_unit","_selection","_damage"];
          if (_selection == "?") exitWith {};
          _curDamage = damage _unit;
          if (_selection != "") then {
            _curDamage = _unit getHit _selection
          };
          _newDamage = _damage - _curDamage;
          _damage - _newDamage * 0.80
       }]
    } forEach _allUnits;
    sleep 2;
  };
};

 

EDITED: There was a typo.

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
18 minutes ago, ObsceneNickname said:

Hello pierremgi, thank you for your answer.

which script should I use? which one is less "laggy"? :)

Did you experience "lag" with either?

 

Cheers

Share this post


Link to post
Share on other sites

You shouldn't see a great difference.

But the less laggy is "probably" adding the EH where and when you spawn the units.

 

in init.sqf:

ON_fnc_EH = compileFinal "
  params ['_unit'];

  _unit addEventHandler ['HandleDamage', { params ['_unit','_selection','_damage']; if (_selection == '?') exitWith {}; _curDamage = damage _unit; if (_selection != ' ') then { _curDamage = _unit getHit _selection }; _newDamage = _damage - _curDamage; _damage - _newDamage * 0.80 }]

";

{_x call ON_fnc_EH} forEach allUnits;   // treating all existing units

 

then, for example:
_grp = [ getPos aPos, EAST, 5] call BIS_fnc_spawnGroup;

{_x call ON_fnc_EH} forEach units _grp;

 

But, to say the truth, I'm not using this method because I have many scripts spawning units and I do prefer treat them in init.sqf, without risk to forget this line somewhere.

 

EDITED:

Well, the problem, here, is that you're spawning on a PC (server, then not everywhere) and you want to run the EH on all PCs; So I forgot you have to remoteExec the call in this case!

{[_x, ON_fnc_EH] remoteExec ["call"] } forEach units _grp;

... not sure it's faster.

Share this post


Link to post
Share on other sites

I didn't notice lagg but I didn't perform yet a stress test with a lot of ai spawning at the same time. I'm a noob and ask you forgivness if I make dumb questions. I read somewhere scripts with "sleep *some number*"  should be avoided 'cause they just get spammed in a regular intervals but I'm absolutely not sure if this is the case with the pierremgi's script.

Share this post


Link to post
Share on other sites
25 minutes ago, ObsceneNickname said:

I didn't notice lagg but I didn't perform yet a stress test with a lot of ai spawning at the same time. I'm a noob and ask you forgivness if I make dumb questions. I read somewhere scripts with "sleep *some number*"  should be avoided 'cause they just get spammed in a regular intervals but I'm absolutely not sure if this is the case with the pierremgi's script.

 

There is no EH "entityCreated"... So you need to loop a check. Every 2 sec.  or even 4 sec. if you spawn your units out of combat area, that's fine.

There is plenty of considerations about scheduled code, sleep , waitUntil. ACE team push them at paroxysm, "banning" all shapes of scheduled event... just forgetting the called chain has also a limit. That's a policy : "my code is paramount, never mind the others".  IMHO.

  • Haha 1

Share this post


Link to post
Share on other sites

pierremgi, thank you for your clarifications. Your last post made me smile a bit :)

 

Since I wouldn't know how to find and how to edit the spawn scripts ( I use zeus and Alive mod principally for spawning ), I would use the first script kindly provided by davidoss or the second script (the one in the init.sfq) kindly provided by you :) I'm glad to hear that there's no need to avoid every form of scheduled code and I think the performance's advantages of one or another methods will be very hard to measure. :/

 

This regard, I've this:

if (!isServer) exitWith{};
//--- wait for world to initialize
sleep 60;
//--- allows to edit and see units only from own side
while {true} do {
    sleep 10;
    {
        if !((side _x) == west) then {
            z_west removeCuratorEditableObjects [[_x],true];    //removes editable enemy units and vehicles on map for zeus west
        };
        if !((side _x) == east) then {
            z_east removeCuratorEditableObjects [[_x],true];    //removes editable enemy units and vehicles on map for zeus east
        };
        if !((side _x) == independent) then {
            z_guer removeCuratorEditableObjects [[_x],true];    //removes editable enemy units and vehicles on map for zeus independent
        };
    } foreach allUnits + vehicles;
};

which is a script that hide from specific curators the objects that don't belong to his side. I would like to use this in some Zeus vs Zeus vs Zeus mission.

Can I use this script even with lowered sleep time or it should be converted in some way in order to use the EventHandler?

 

Thank you all

 

Share this post


Link to post
Share on other sites
Quote

Anyway this should be an fuction  not a file because it will run multiple times.

P.S. I'm still very confused about this :/

Share this post


Link to post
Share on other sites

Creating function using oldschool:

1.
Create directory called functions in your mission root
2.
Create directory called serverfnc in functions directory
3.
create file called fn_initunit.sqf in functions\serverfnc
4.

paste this code into file fn_initunit.sqf and save

params [["_unit",objNull,[objNull]]];

_unit addEventHandler ["HandleDamage", {

  _unit = _this select 0;
  _selection = _this select 1;
  _damage = _this select 2;

  if (_selection == "?") exitWith {};

  _curDamage = damage _unit;
  if (_selection != "") then {_curDamage = _unit getHit _selection};
  _newDamage = _damage - _curDamage;

  _damage - _newDamage * 0.80
}];

 

5. Paste this code to description.ext:

class CfgFunctions	{

	class MWF	{
	
		class serverfnc	{
		
			class initunit
			{
				preInit = 0;
				postInit = 0;
				preStart = 0;
				ext = ".sqf";
				headerType = 0;
				recompile = 0;
			};
		};
	};
};



class Extended_InitPost_EventHandlers {
    class CAManBase {
        class initpost_units {
            serverInit = "0  = _this spawn MWF_fnc_initunit";
        };
    };
};

 

  • Thanks 1

Share this post


Link to post
Share on other sites
On 20/10/2018 at 7:16 AM, ObsceneNickname said:

if (!isServer) exitWith{};
//--- wait for world to initialize
sleep 60;
//--- allows to edit and see units only from own side
while {true} do {
    sleep 10;
    {
        if !((side _x) == west) then {
            z_west removeCuratorEditableObjects [[_x],true];    //removes editable enemy units and vehicles on map for zeus west
        };
        if !((side _x) == east) then {
            z_east removeCuratorEditableObjects [[_x],true];    //removes editable enemy units and vehicles on map for zeus east
        };
        if !((side _x) == independent) then {
            z_guer removeCuratorEditableObjects [[_x],true];    //removes editable enemy units and vehicles on map for zeus independent
        };
    } foreach allUnits + vehicles;
};

which is a script that hide from specific curators the objects that don't belong to his side. I would like to use this in some Zeus vs Zeus vs Zeus mission.

Can I use this script even with lowered sleep time or it should be converted in some way in order to use the EventHandler?

 

Thank you all

 

 

 

 

first, avoid a while{true} loop without spawning it. Then, your script is not blocked here and you can add lines of code after.

And.... here, there is no need to make a loop:
 

{
  _x addEventHandler ["CuratorGroupPlaced", {
    params ["_curator", "_group"];
    {_x removeCuratorEditableObjects [[units _group],true] } forEach (allCurators select {_x != _curator})
  }]
} forEach [z_west,z_east,z_guer];

More than this, you can place your code here:


 

{
  _x addEventHandler ["CuratorGroupPlaced", {
    params ["_curator", "_group"];
    {_x removeCuratorEditableObjects [[units _group],true]} forEach (allCurators select {_x != _curator});
    {_x addEventHandler ["HandleDamage", {
       params ["_unit","_selection","_damage"];
       if (_selection == "?") exitWith {};
       _curDamage = damage _unit;
       if (_selection != "") then {
         _curDamage = _unit getHit _selection };
         _newDamage = _damage - _curDamage;
         _damage - _newDamage * 0.80
       }]
     } forEach units _group;
  }]
} forEach [z_west,z_east,z_guer];

NOT TESTED.

The removeCuratorEditableObjects like scripted here has not interest (already done by Arma, so, see new version below)

 

second, waiting for world to initialize:

waitUntil {!isNil "BIS_fnc_init"};

the world, objects... are initialized but init.sqf not yet run in MP.
or even :

waitUntil {allPlayers >0};

 

 

 

 

 


 

  • Thanks 1

Share this post


Link to post
Share on other sites

I just want to say thank you again.

 

davidoss, your tutorial was retard-proof; I love that. <3 I did some test and it work very well.

 

pierremgi your "all in one" script looks very promising but I've still to test it. I will let you know soon for the sake of knowledge. :)

Share this post


Link to post
Share on other sites

I did some researches, as I never write for Zeus, and I think I understand what you are trying to do.

First of all, my scripts above have a useless part with removeCuratorEditableObjects. It seems to me Arma already forbid the manipulation of foreign objects (non placed by the current Zeus).

By the way, I discovered the difference between a curator (module, side logic) and a Zeus player (side player)...

Sorry for this late focus.

 

So, the script below

- remove the curator edited objects when not belonging to the side of the zeus' player.

- add any edited objects to an existing Zeus (not retroactive on already placed objects before Zeus JIP), if these objects have the same side of this Zeus.

 

{  
  _x addEventHandler ["CuratorObjectPlaced", {  
    params ["_curator", "_object"]; 
    _side = side _object;  
    if (_side != playerSide) then { 
      [_curator,[[vehicle _object],true]] remoteExec ["removeCuratorEditableObjects",2]; 
      { 
        [_x, [[vehicle _object],true]] remoteExec ["addCuratorEditableObjects",2] 
      } forEach (allcurators select {side (getassignedcuratorunit _x) == _side}) 
    };  
    _color = ["red","blue","green","white"] select (side _object call bis_fnc_sideId); 
    {_x forceFlagTexture ("\A3\Data_F\Flags\Flag_"+_color+"_CO.paa")} forEach crew _object; 
    {_x addEventHandler ["HandleDamage", {  
       params ["_unit","_selection","_damage"];  
       if (_selection == "?") exitWith {};  
       _curDamage = damage _unit;  
       if (_selection != "") then {  
         _curDamage = _unit getHit _selection };  
         _newDamage = _damage - _curDamage;  
         _damage - _newDamage * 0.80  
       }];
    } forEach crew _object;  
  }]  
} forEach allCurators;

Run it in init.sqf or any clients script.

TESTED

 

 

 

 

  • Like 3

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

×