Jump to content
DeadCossack

Need to setVariable for spawned AI and vehicles

Recommended Posts

Hi guys, I am developing a pretty ambitious mission for ARMA3 singleplayer. I made a lot of spawns of enemy units to decrease CPU loading on my mission. But I have a serious issue, I can't find a way to give these groups and vehicles a variable names for my triggers to work in case of their elimination and so on. Here is an example of my spawn script:

 

_crewNE = [];
_offroad1 = [];
_mygroupNE = [];

if (isServer) then {

_crewNE = creategroup EAST; 
_OFFROAD1 = [getMarkerPos "vehicleNE", 140, "I_G_Offroad_01_F", _crewNE] call BIS_fnc_spawnVehicle;
_wp1 = _crewNE addWaypoint [(getmarkerpos "vNE"), 0];
_wp1 setWaypointType "TR UNLOAD";
_wp1 setWaypointSpeed "FULL";
_wp2 = _crewNE addWaypoint [(getmarkerpos "vNE1"), 0];
_wp2 setWaypointType "SAD";
_wp2 setWaypointSpeed "FULL";


_mygroupNE = [getmarkerpos "vehicleNE", RESISTANCE, ["I_C_Soldier_Bandit_5_F","I_C_Soldier_Bandit_1_F","I_C_Soldier_Para_8_F","    I_C_Soldier_Para_4_F","I_C_Soldier_Para_3_F","I_C_Soldier_Bandit_4_F"],[],[],[],[],[],180] call BIS_fnc_spawnGroup;
_wp1a = _mygroupNE addWaypoint [getmarkerpos "vNE1", 0];
{ _x setUnitPos "UP"; } forEach (units _mygroupNE);

sleep .5;
_mygroupNE1 = _mygroupNE;
{ _x assignAsCargo (_OFFROAD1 select 0); _x moveIncargo (_OFFROAD1 select 0);} foreach units _mygroupNE; 
};

Share this post


Link to post
Share on other sites

Take a look at vehicleVarName: https://community.bistudio.com/wiki/vehicleVarName

 

Here's a script for respawning a vehicle I picked up. Not my code at all, but I can't recall who wrote it to give credit but its theres lol. Take a look there and it might point you in the right direction.

 

Spoiler

_vehicle = _this select 0;

_respawntime = 15;

_facingofvehicle = getDir _vehicle;

_positionofvehicle = getPosATL _vehicle;

_vehicletype = typeOf _vehicle;

_vehicleName = vehicleVarName _vehicle;

 

//hint format ["%1\n%2\n%3\n%4\n%5\n%6",_vehicle,_respawntime,_facingofvehicle,_positionofvehicle,_vehicletype,_vehicleName];

if(isServer) then{

    while {true} do { //Loop forever

        if((!alive _vehicle) || (!canMove _vehicle)) then

        {

            waitUntil {count crew _vehicle == 0};

            deleteVehicle _vehicle;

            sleep _respawntime;

            _vehicle = _vehicletype createVehicle _positionofvehicle;

            _vehicle setPosATL _positionofvehicle;

            _vehicle setDir _facingofvehicle;

            missionNamespace setVariable [_vehicleName, _vehicle];

            publicVariable _vehicleName;

        };

        sleep 15;

    };

};

 

 

  • Like 1

Share this post


Link to post
Share on other sites

Not sure you take the problem by the right side. You can spawn units and make triggers working without any specific name for the units.

the question is about your trigger(s). How did you write it(them)?

Share this post


Link to post
Share on other sites
22 hours ago, XianGrim said:

Take a look at vehicleVarName: https://community.bistudio.com/wiki/vehicleVarName

 

Here's a script for respawning a vehicle I picked up. Not my code at all, but I can't recall who wrote it to give credit but its theres lol. Take a look there and it might point you in the right direction.

 

  Reveal hidden contents

_vehicle = _this select 0;

_respawntime = 15;

_facingofvehicle = getDir _vehicle;

_positionofvehicle = getPosATL _vehicle;

_vehicletype = typeOf _vehicle;

_vehicleName = vehicleVarName _vehicle;

 

//hint format ["%1\n%2\n%3\n%4\n%5\n%6",_vehicle,_respawntime,_facingofvehicle,_positionofvehicle,_vehicletype,_vehicleName];

if(isServer) then{

    while {true} do { //Loop forever

        if((!alive _vehicle) || (!canMove _vehicle)) then

        {

            waitUntil {count crew _vehicle == 0};

            deleteVehicle _vehicle;

            sleep _respawntime;

            _vehicle = _vehicletype createVehicle _positionofvehicle;

            _vehicle setPosATL _positionofvehicle;

            _vehicle setDir _facingofvehicle;

            missionNamespace setVariable [_vehicleName, _vehicle];

            publicVariable _vehicleName;

        };

        sleep 15;

    };

};

 

 

thanks, mate, I will try it out.

Share this post


Link to post
Share on other sites
15 hours ago, pierremgi said:

Not sure you take the problem by the right side. You can spawn units and make triggers working without any specific name for the units.

the question is about your trigger(s). How did you write it(them)?

 So, I will describe the situation. Protagonist and his teammates go to a certain area. Vehicle, full of Tangos, spawns and rides towards them. Fight starts. After a firefight(when all enemies r dead) I want my main character to get a hint about certain building. Entering this building will start a script, which changes a time of day. 

Reasons I need variable 4 vehicle ad enemy units:

- to lock a vehicle 3 protagonist and his crew(because of my mission's storytelling);

- to shoot a hint-trigger.(I don't want remaining  Tangos to attack my team, while my skiptime-script and a short cutscene are playing).

Share this post


Link to post
Share on other sites

Could you just use the "Seized by Blufor" condition in the trigger to fire your cutscene.sqf? When all the units are dead/have run away from the area, the cutscene plays?

Share this post


Link to post
Share on other sites
19 hours ago, XianGrim said:

Could you just use the "Seized by Blufor" condition in the trigger to fire your cutscene.sqf? When all the units are dead/have run away from the area, the cutscene plays?

Thanks for your reply, Xian. The thing is, that the area is empty by default. No opfor units. Then player and his team appear, their presence shoot spawnvehicle Trigger and opfor car starts approaching main character. The problem is, "Seized by BLUFOR" trigger will shoot, when Protagonist will enter my designated area, but his enemies won't spawn yet.

 

Share this post


Link to post
Share on other sites

you can add a condition. "seized by blufor" is just a preset condition. Add something like this way:

this && {side _x == EAST && _x inArea thisTrigger} count allUnits > 0

 

For your former question (adding a variable name on a spawned unit):

_OFFROAD1 = [getMarkerPos "vehicleNE", 140, "I_G_Offroad_01_F", _crewNE] call BIS_fnc_spawnVehicle;

 

You can just make the variable global (OFFROAD1 instead of _OFFROAD1). As you are in SP, this variable (then the vehicle) will be defined in any of your mission scripts:

OFFROAD1 = [getMarkerPos "vehicleNE", 140, "I_G_Offroad_01_F", _crewNE] call BIS_fnc_spawnVehicle;

 

Just to be exhaustive, you can use XianGrim method with setVehivleVarName but it's rather useful to respawn objects with their initial variable names:

_OFFROAD1 setVehicleVarName "OFFROAD1";

_OFFROAD1 call compile Format ["%1=_This","OFFROAD1"];

Now, your vehicle is "workable" as OFFROAD1.

 

 

  • Thanks 1

Share this post


Link to post
Share on other sites
2 hours ago, pierremgi said:

you can add a condition. "seized by blufor" is just a preset condition. Add something like this way:

this && {side _x == EAST && _x inArea thisTrigger} count allUnits > 0

 

For your former question (adding a variable name on a spawned unit):

_OFFROAD1 = [getMarkerPos "vehicleNE", 140, "I_G_Offroad_01_F", _crewNE] call BIS_fnc_spawnVehicle;

 

You can just make the variable global (OFFROAD1 instead of _OFFROAD1). As you are in SP, this variable (then the vehicle) will be defined in any of your mission scripts:

OFFROAD1 = [getMarkerPos "vehicleNE", 140, "I_G_Offroad_01_F", _crewNE] call BIS_fnc_spawnVehicle;

 

Just to be exhaustive, you can use XianGrim method with setVehivleVarName but it's rather useful to respawn objects with their initial variable names:

_OFFROAD1 setVehicleVarName "OFFROAD1";

_OFFROAD1 call compile Format ["%1=_This","OFFROAD1"];

Now, your vehicle is "workable" as OFFROAD1.

 

 

Much thanks to you, mr. pierremgi! But here is another trouble. The game sees OFFROAD1 as an Array, not an object. Any ideas why?(

Share this post


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

_OFFROAD1 call compile Format ["%1=_This","OFFROAD1"];

Do I have something in my eye or what is this that I'm seeing here?

"OFFROAD1 = _OFFROAD1"?
or "missionNamespace setVariable ["OFFROAD1", _OFFROAD1]"?

 

1 hour ago, DeadCossack said:

Much thanks to you, mr. pierremgi! But here is another trouble. The game sees OFFROAD1 as an Array, not an object. Any ideas why?(

 

Well.. https://community.bistudio.com/wiki/BIS_fnc_spawnVehicle returns Array.... So I guess that's why it's an array.

OFFROAD1 = ([getMarkerPos "vehicleNE", 140, "I_G_Offroad_01_F", _crewNE] call BIS_fnc_spawnVehicle) select 0;
OFFROAD1 setVehicleVarName "OFFROAD1"; 

 

 

  • Haha 1

Share this post


Link to post
Share on other sites

Thank you kindly, sir. But now I have another trouble(yeah I'm not good at this)

My OFFROAD1 is finally variablename, but my crew won't spawn in it, it spawns outside vehicle and won't assign to it -_-

23 minutes ago, Dedmen said:

Do I have something in my eye or what is this that I'm seeing here?

"OFFROAD1 = _OFFROAD1"?
or "missionNamespace setVariable ["OFFROAD1", _OFFROAD1]"?

 

 

Well.. https://community.bistudio.com/wiki/BIS_fnc_spawnVehicle returns Array.... So I guess that's why it's an array.


OFFROAD1 = ([getMarkerPos "vehicleNE", 140, "I_G_Offroad_01_F", _crewNE] call BIS_fnc_spawnVehicle) select 0;
OFFROAD1 setVehicleVarName "OFFROAD1"; 

 

 

 

Share this post


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

Thank you kindly, sir. But now I have another trouble(yeah I'm not good at this)

My OFFROAD1 is finally variablename, but my crew won't spawn in it, it spawns outside vehicle and won't assign to it -_-

 

 

 


_offroad = ([getMarkerPos "vehicleNE", 140, "I_G_Offroad_01_F", WEST] call BIS_fnc_spawnVehicle) select 0;
OFFROAD1 = _offroad select 0;
_crewNE = _offroad select 2;
OFFROAD1 setVehicleVarName "OFFROAD1"; 

How about that? The wiki page only shows a side being used. So I guess specifying a empty group might not work.

Share this post


Link to post
Share on other sites

Now I'm getting opposite error. Game expects Array, but gets Object -_-

5 hours ago, Dedmen said:

 

 



_offroad = ([getMarkerPos "vehicleNE", 140, "I_G_Offroad_01_F", WEST] call BIS_fnc_spawnVehicle) select 0;
OFFROAD1 = _offroad select 0;
_crewNE = _offroad select 2;
OFFROAD1 setVehicleVarName "OFFROAD1"; 

How about that? The wiki page only shows a side being used. So I guess specifying a empty group might not work.

 

Share this post


Link to post
Share on other sites
18 hours ago, DeadCossack said:

Now I'm getting opposite error. Game expects Array, but gets Object -_-

 

Ah crap. Please throw some stones at me.
Remove the "select 0" at the end of the first line.

Share this post


Link to post
Share on other sites

Sorry for the returned array with bis_fnc_spawnVehicle. My bad. For the setVehicleVarName, I'm sure you need to pass the name to the object and I wrote a working solution.

 

_OFFROAD1 =( [getMarkerPos "vehicleNE", 140, "I_G_Offroad_01_F", _crewNE] call BIS_fnc_spawnVehicle) select 0;

_OFFROAD1 setVehicleVarName "OFFROAD1";

_OFFROAD1 call compile Format ["%1=_this","OFFROAD1"];

I confirm.

@Dedmen: read compile. This makes the job.

 

Share this post


Link to post
Share on other sites
14 hours ago, pierremgi said:

@Dedmen: read compile. This makes the job.

 

Dude. Compile makes absolutely no sense here. And will kill the scripts performance for no reason.

"Format ["%1=_this","OFFROAD1"]" is constant. And literally evaluates to "OFFROAD1 = _this"
so you could have exactly the same as "_OFFROAD1 call {OFFROAD1 = _this}" which again makes no sense and is absolutely useless as it is exactly the same as

"OFFROAD1 = _OFFROAD1"

 

Also read the conversation above. The vehicle spawns empty with that code.

Share this post


Link to post
Share on other sites
2 hours ago, Dedmen said:

Dude. Compile makes absolutely no sense here. And will kill the scripts performance for no reason.

"Format ["%1=_this","OFFROAD1"]" is constant. And literally evaluates to "OFFROAD1 = _this"
so you could have exactly the same as "_OFFROAD1 call {OFFROAD1 = _this}" which again makes no sense and is absolutely useless as it is exactly the same as

"OFFROAD1 = _OFFROAD1"

 

Also read the conversation above. The vehicle spawns empty with that code.

 

Dude, the fact the vehicle spawns empty is not what I underlined here. Just mentioning a standard way to apply a variable name on an object.

 

When a vehicle is created and named in the editor, the name becomes both the variable containing the vehicle object and the string representation of the vehicle object. vehicleVarName on the other hand is only string representation of the object. So if you want to refer to the actual object by its vehicleVarName, an extra step needed to assign the object to a variable of the same name. For example to see and refer to offroad as myFerrari: _offroad setVehicleVarName "MyFerrari"; MyFerrari = _offroad;

But further step is not so evident. read discussion:

Compile here is a way to allocate a string as variable, referring to the object.

https://community.bistudio.com/wiki/Talk:setVehicleVarName

I'm not alone and i didn't invent this kind of code. Just talking about general case:

https://forums.bohemia.net/forums/topic/176372-change-variable-name-global-how/

https://forums.bohemia.net/forums/topic/191215-setvehiclevarname-and-remoteexec/

https://forums.bohemia.net/forums/topic/160361-set-name-of-vehicle-spawned-in/

http://www.arma3.fr/forum/viewtopic.php?f=13&t=916

https://www.reddit.com/r/armadev/comments/31x735/help_with_vehicle_variables_vanilla_arma_3_editor/

 

Share this post


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

 

Dude, the fact the vehicle spawns empty is not what I underlined here. Just mentioning a standard way to apply a variable name on an object.

 

When a vehicle is created and named in the editor, the name becomes both the variable containing the vehicle object and the string representation of the vehicle object. vehicleVarName on the other hand is only string representation of the object. So if you want to refer to the actual object by its vehicleVarName, an extra step needed to assign the object to a variable of the same name. For example to see and refer to offroad as myFerrari: _offroad setVehicleVarName "MyFerrari"; MyFerrari = _offroad;

But further step is not so evident. read discussion:

Compile here is a way to allocate a string as variable, referring to the object.

https://community.bistudio.com/wiki/Talk:setVehicleVarName

I'm not alone and i didn't invent this kind of code. Just talking about general case:

https://forums.bohemia.net/forums/topic/176372-change-variable-name-global-how/

https://forums.bohemia.net/forums/topic/191215-setvehiclevarname-and-remoteexec/

https://forums.bohemia.net/forums/topic/160361-set-name-of-vehicle-spawned-in/

http://www.arma3.fr/forum/viewtopic.php?f=13&t=916

https://www.reddit.com/r/armadev/comments/31x735/help_with_vehicle_variables_vanilla_arma_3_editor/

 

I know all that. You don't need to tell me that people write dumb code.

As I said. The "call compile format" is completely useless here.

I never said anything against having to assign it to a variable. I just don't want to teach beginners stupid nonsense code. If you teach then do it right please.

 

If you actually read the wiki page you linked... You would also see the guy saying that it doesn't make sense and is exactly the same as just writing "Test=This".

Thanks for telling me about the issue on the BI wiki. I'm fixing that now.

Actually.. Why did you copy a bad example from the Talk page. Ignoring the comment saying that it doesn't make sense. Instead of using the actual example from the real wiki page

https://community.bistudio.com/wiki/setVehicleVarName

Share this post


Link to post
Share on other sites

@pierremgi What you're doing is the equivalent to instead of just copying a PDF, printing it, then scanning it, then saving the scanned file under a different name. It makes no sense at all. Please stop copy-pasting code that you found somewhere unless you understand what it does.

  • Thanks 1
  • Confused 1

Share this post


Link to post
Share on other sites

@Dedmen and @baermitumlaut . I scripted some code to respawn any vehicle, saving their variable name (if any). I admit you are far more skilled for manipulation variables.

So please have a look and take time to correct my code, just the vehicle var name part of course, for the same result (I want to respawn some vehicles and their name without knowing them at start). It's a generic code to be applied in SP/MP.

Your comment and your way to do that will be appreciated. Tks.

Share this post


Link to post
Share on other sites

I didn't read through all of it, but I found the same issue there, in a similar variation. First you should know that you should avoid compile if you can, which is almost always the case (except for compiling files at game start of course), simply because it's slow and there's usually better alternatives. One of the few use cases of compile is compiling code that is saved in a config. Here is the line I'm referring to:

[_newVeh, compile Format ["%1=_This",_varName]] remoteExec ["call"];

You're trying to make sure the variable name refers to the same object on all machines. This line has two issues however:

  • you're using compile even though there are alternatives, which is a performance issue
  • you're transferring code over the network and then executing it, which is a security issue

The latter is particularily interesting. This line seems harmless at first, but it requires the server admin to allow using call with remoteExec, which is often blocked on public servers for a good reason. It allows an attacker to execute arbitrary code on any machine, which could be abused in various ways. You could for example try crashing the server this way.

Of course, you can't use = here, because the variable name isn't fixed. However, you can use setVariable:

missionNamespace setVariable [_varName, _newVeh, true];

 

Besides that, you have a large cluster of selects in one of the event handlers. You should replace it with params, which will look much nicer and more readable:

(_destroyed getVariable "MGIrespVehDATA") params [
    "_type",
    "_pos",
    "_side",
    "_fullOldCrew",
    "_varName",
    "_initDir"
];

That's getting a little off topic though.

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

Yes, thanks. Same remark on dedmen side. I'll correct the code with setVariable on missionNameSpace.

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

×