Jump to content
Federico 76

Need help scripting with addaction to a classname [SOLVED]

Recommended Posts

Hello everyone, i'm trying to make my first script, so i've looked a bit into the introduction, i've put toghether all the notions i have on the subject, and that's what i managed to do:

 

Basically i'm trying to add a menu action to all police vans. The action itself is working fine when i use it into the init of the vehicle, but since multiple vans can be created during the mission, i need a way to affect them all.

 

That's what i've done until now:

 

- I have created an init.sqf file in my mission folder, and i've put this inside: 

[] execVM "myscript.sqf";

- Then i created another file called myscript.sqf, which looks like this:

{
params ["_unit"];

if (typeOf _unit isEqualTo "B_GEN_Van_02_vehicle_F") then
{
_unit enableVehicleCargo false;

_unit addAction 
[ 
 "Placeholder text", 
 { 
  params ["_target", "_caller", "_actionId", "_arguments"]; _target enableVehicleCargo true; _target lockCargo true; _target lockCargo [0, false]
 }, 
 nil,  
 1.5,  
 true,
 true, 
 "", 
 "(vehicleCargoEnabled _target) == false && count crew _target == 0", 
 5,  
 false,
 "",  
 "" 
];

_unit addAction 
[ 
 "Placeholder text 2", 
 { 
  params ["_target", "_caller", "_actionId", "_arguments"]; _target enableVehicleCargo false; _target lockCargo false
 }, 
 nil,  
 1.5,  
 true,
 true, 
 "", 
 "(vehicleCargoEnabled _target) == true && count crew _target == 0 && (getVehicleCargo _target) isEqualTo []", 
 5,  
 false,
 "",  
 "" 
]
}
};

The script does not give any error, but the action won't appear on the van... What am i doing wrong? I've also tried to search the forum a bit but i did't find exactly what i want.

I guess the error is in the first part of the script, when i try to tell to the machine what unit should be affected by the script. Looking on the internet i tried to mix and match a lot of combinations, but nothing worked.

Share this post


Link to post
Share on other sites

Hello!

Are you trying that only in editor and/or single player? Or it works fine in SP but not in MP/dedicated?
If multiplayer, the "problem" regarding addAction is related to that "Local vs. Global" stuff - so hardly anything related to addAction will do anything in multiplayer, even if it works in single player. Guys here have already helped me A LOT with it, and it will always need an extra work to try and get it working as we usually desire.

I will bring some workarounds that have worked for me - all of them after some nice tips I got here in forums, but some better approaches will arise from other users as well. But I think the most effective way would be to create an eventHandler 'GetInMan' inside your init.sqs/init Player that would execute your addAction once players get inside that specific police truck of yours.

For instance, this is part of what we have in a getInMan EH in a init, that will allow pilots to have permanent options to lock/unlock access to their copilot's seats. I know it's far from what you want, but at least for now it could give you some ideas.
Please also note that, for this case, we used getInMan, which has to deal with the "_unit" as a 'human" (regardless player or IA), and then checked for the type of vehicle to add the action to THE PLAYERS, and NOT to the vehicle. In your case, it might be more interesting to use EH 'getIn' and maybe add the action to the vehicles themselves.

 

Spoiler

 


_pClasses = [
						"I_E_Heli_light_03_dynamicLoadout_F",
						"I_Heli_light_03_dynamicLoadout_F"
						];
_hClasses = _pClasses;
_nearbyHs = nearestObjects [player, _hClasses, 5, false, false];

{
_hClass = typeOf _x;
if (
	(_hClass in _pClasses) &&
	(_position isEqualTo 'driver')
) then {
									lockOnAction =
									player addAction
									[
										"BLOCK Gunner", 
										{
											_currentHeli = (vehicle player);
											_currentHeli lockTurret [[0], true];
										},
										nil,
										-1,
										false,
										true,
										"",
										"_this == _target turretUnit [-1]",
										10,
										false
									];
									lockOffAction =
									player addAction
									[
											"ENABLE Gunner",
											{
											_currentHeli = (vehicle player);
											_currentHeli lockTurret [[0], false];
										},
										nil,
										-1,
										false,
										true,
										"",
										"_this == _target turretUnit [-1]",
										10,
										false
									];
};
} forEach _nearbyHs;

 

 

 

 

Share this post


Link to post
Share on other sites

First, get rid of the outer curly brackets in your script.

 

Second, you pass no params via execVM, so the param "_unit" in your script is nil. For example:

[] execVM "myscript.sqf";

//should be 

[this] execVM "myscript.sqf";
params ["_unit"];

// _unit is now whatever "this" is

 

Third, it's not a dynamic system. Your script ostensibly adds actions only to the vehicles that are being passed to it on execution. Your comments suggest you want all vehicles created during mission time to have these actions added.

 

Since addAction is local, we want to run your code on each player's machine. Running it on the server is unnecessary. We can use initPlayerLocal.sqf for this.

 

initPlayerLocal.sqf:

while {true} do {
	sleep 10;
	{
		if ((typeOf _x) in ["B_GEN_Van_02_vehicle_F"]) then {
			if (!(_x getVariable ["FED_hasActions", false])) then {
				_x setVariable ["FED_hasActions", true];
				
				_unit enableVehicleCargo false;
				_unit addAction 
				[ 
					"Placeholder text", 
					{ 
						params ["_target", "_caller", "_actionId", "_arguments"]; _target enableVehicleCargo true; _target lockCargo true; _target lockCargo [0, false]
					}, 
					nil,  
					1.5,  
					true,
					true, 
					"", 
					"(vehicleCargoEnabled _target) == false && count crew _target == 0", 
					5,  
					false,
					"",  
					"" 
				];

				_unit addAction 
				[ 
					"Placeholder text 2", 
					{ 
						params ["_target", "_caller", "_actionId", "_arguments"]; _target enableVehicleCargo false; _target lockCargo false
					}, 
					nil,  
					1.5,  
					true,
					true, 
					"", 
					"(vehicleCargoEnabled _target) == true && count crew _target == 0 && (getVehicleCargo _target) isEqualTo []", 
					5,  
					false,
					"",  
					"" 
				]
			};
		};
	} forEach vehicles;
};

There is likely a more performance-optimal way to do this. Also, untested.

 

To explain:

if ((typeOf _x) in ["B_GEN_Van_02_vehicle_F"]) then {

Now instead of a 1:1 comparison, we can add actions to multiple classes, just add them to the array:

if ((typeOf _x) in ["B_GEN_Van_02_vehicle_F", "B_GEN_Van_02_transport_F", "B_GEN_Offroad_01_covered_F"]) then {

 

Also:

if (!(_x getVariable ["FED_hasActions", false])) then {
	_x setVariable ["FED_hasAction", true];

We don't want to add actions to a vehicle that already has them, so we set a variable on each vehicle as it receives its actions. Now, when we iterate through vehicles every 10 seconds, the vehicles that already have actions are ignored.

 

 

  • Like 1

Share this post


Link to post
Share on other sites

Ok, thanks JCataclisma and Harzach for your help!

If everything fails i'll look for a workaround like Cataclisma suggested, for now i'm trying the solution suggested by Harzach, that's the result:

 

- First i had to change the "_unit"  that i put in my script to "_x", otherwhise i get the "undefined variable" error and it won't work at all.

- Then it seems to work, exept for this part:

if (!(_x getVariable ["FED_hasActions", false])) then {
	_x setVariable ["FED_hasAction", true];

In fact, the game keeps duplicating the action again and again.

 

I tried to remove the "!" in the beginning, but then the script won't work at all... So i'll try to play around with "getVariable" and "setVariable", maybe i can get it to work somehow.

Share this post


Link to post
Share on other sites

I did it! Luckly it was just a little typo made by Harzach :

"FED_hasActions" has the plural "s" and "FED_hasAction" doesn't.

 

I'll post the corret form of the script in case someone needs it.

 

initPlayerLocal.sqf

while {true} do {
	sleep 10;
	{
		if ((typeOf _x) in ["B_GEN_Van_02_vehicle_F"]) then {
			if (!(_x getVariable ["FED_hasAction", false])) then {
				_x setVariable ["FED_hasAction", true];
				
				_x enableVehicleCargo false;
				_x addAction 
				[ 
					"Placeholder text", 
					{ 
						params ["_target", "_caller", "_actionId", "_arguments"]; _target enableVehicleCargo true; _target lockCargo true; _target lockCargo [0, false]
					}, 
					nil,  
					1.5,  
					true,
					true, 
					"", 
					"(vehicleCargoEnabled _target) == false && count crew _target == 0", 
					5,  
					false,
					"",  
					"" 
				];

				_x addAction 
				[ 
					"Placeholder text 2", 
					{ 
						params ["_target", "_caller", "_actionId", "_arguments"]; _target enableVehicleCargo false; _target lockCargo false
					}, 
					nil,  
					1.5,  
					true,
					true, 
					"", 
					"(vehicleCargoEnabled _target) == true && count crew _target == 0 && (getVehicleCargo _target) isEqualTo []", 
					5,  
					false,
					"",  
					"" 
				]
			};
		};
	} forEach vehicles;
};

 

Thanks everyone for helping!

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
15 minutes ago, Federico 76 said:

just a little typo made by Harzach

 

It's expected, see my signature.

 

Glad you're sorted!

  • Like 1
  • Haha 1

Share this post


Link to post
Share on other sites
3 hours ago, Alleged Accomplice said:

Could I put put isKindOf Car in there to make it work on any vehicle?

Any vehicle? or land vehicle or car only?

For cars (isKindOf "car")


 

comment "Prepare the addActions unlocking / locking vehicles. Don't forget, in multiplayer, the vehicles can switch owner, so the remoteExec";
MGI_actLockPax = ["unlockPaxAndCargo",{
    params ["_veh", "_plyr", "_id"];
    call {
        if ((_veh actionParams _id) #0 == "unlockPaxAndCargo") exitWith {
            _veh setUserActionText [_id,"lockPaxAndCargo"];
            [_veh,FALSE] remoteExec ["lockCargo",_veh,_veh];
            [_veh,TRUE] remoteExec ["enableVehicleCargo",_veh,_veh];
        };
        _veh setUserActionText [_id,"unlockPaxAndCargo"];
        [_veh,TRUE] remoteExec ["lockCargo",_veh,_veh];
        [_veh,FALSE] remoteExec ["enableVehicleCargo",_veh,_veh];
    };
},nil,6,FALSE,TRUE,"",""];

comment " feel free to do what you want with edited vehicles";
{_x lockCargo TRUE; _x enableVehicleCargo FALSE; _x addAction MGI_actLockPax} forEach (vehicles select {_x isKindOf "car"});

comment " wait for any new object created, filter for car, apply code on them (here locked by default)";
addMissionEventHandler ["EntityCreated", {
    params ["_entity"];
    if (_entity isKindOf "car") then {
        _entity lockCargo TRUE;
        _entity enableVehicleCargo FALSE;
        _entity addAction MGI_actLockPax;
        _entity addEventHandler ["respawn",{_entity addAction MGI_actLockPax}];
    };
}];

 

 

  • Like 1

Share this post


Link to post
Share on other sites
3 minutes ago, pierremgi said:

Any vehicle? or land vehicle or car only?

For cars (isKindOf "car")


 


comment "Prepare the addActions unlocking / locking vehicles. Don't forget, in multiplayer, the vehicles can switch owner, so the remoteExec";
MGI_actLockPax = ["unlockPaxAndCargo",{
    params ["_veh", "_plyr", "_id"];
    call {
        if ((_veh actionParams _id) #0 == "unlockPaxAndCargo") exitWith {
            _veh setUserActionText [_id,"lockPaxAndCargo"];
            [_veh,FALSE] remoteExec ["lockCargo",_veh,_veh];
            [_veh,TRUE] remoteExec ["enableVehicleCargo",_veh,_veh];
        };
        _veh setUserActionText [_id,"unlockPaxAndCargo"];
        [_veh,TRUE] remoteExec ["lockCargo",_veh,_veh];
        [_veh,FALSE] remoteExec ["enableVehicleCargo",_veh,_veh];
    };
},nil,6,FALSE,TRUE,"",""];

comment " feel free to do what you want with edited vehicles";
{_x lockCargo TRUE; _x enableVehicleCargo FALSE; _x addAction MGI_actLockPax} forEach (vehicles select {_x isKindOf "car"});

comment " wait for any new object created, filter for car, apply code on them (here locked by default)";
addMissionEventHandler ["EntityCreated", {
    params ["_entity"];
    if (_entity isKindOf "car") then {
        _entity lockCargo TRUE;
        _entity enableVehicleCargo FALSE;
        _entity addAction MGI_actLockPax;
        _entity addEventHandler ["respawn",{_entity addAction MGI_actLockPax}];
    };
}];

So the answer is yes from what you wrote and coded and yes I meant land vehicles. All of them that I know of go back to car.

 

 

Share this post


Link to post
Share on other sites

That's interesting, i'm trying to understand how the eventhandler works, just to see what i can do with it... But it gives me an error: "Error GIAR pre stack size violation". I'm not sure what i am doing wrong.

For now i'm just testing a simple code based on what pierremgi suggested:

 

 

addMissionEventHandler ["EntityCreated", {
    params ["_entity"];
    if (_entity isKindOf "car") then {
        _entity lockCargo TRUE;
        _entity enableVehicleCargo FALSE;
    };
}];

Maybe i'm putting it into the wrong file... Should it be a initServer.sqf, a normal script, a initPlayerServer.sqf, or what?

Share this post


Link to post
Share on other sites

This code work (in initPlayerLocal.sqf or even init.sqf)...

InitServer.sqf is ok if you spawn the vehicle on server.

 

initPlayerServer.sqf is not really good for that because it runs multiple times on server (at JIP).... depending on where your vehicles are spawning in fact. If you want to lock them, I guess they spawn locally, so initPlayerLocal is better.

 

Anyway, your error can be issued from some other script... Not sure this one is the culprit.

  • Like 1

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

×