Jump to content
Sign in to follow this  
Woodpeckersam

Operators inside a string

Recommended Posts

Just wondering if anyone has any experience of getting operators that are inside a string to work.

This is the code I am trying to run, I want to name every single object, with their own number.

for "_i" from 0 to ((random 50) + 10) do
{
_pos = getMarkerPos "Agia_Marina";
_areasize = 150;
_position = [_pos, _areasize] call CBA_fnc_randPos;  
[color="#FF0000"][b]"Land_Tyres_F" createUnit [_position, group logicool,"this setPos [(getPos this select 0),(getPos this select 1),+0.5; this setDir (random 360); Tyre'+_i+' = this;"];[/b][/color]
};

The objects spawn no problems at all. They are placed randomly around an area also no problem at all. The init of the createUnit does have a problem, this is when I am trying to name the object.

I understand that it may be difficult/impossible to grab a number from a variable OUTSIDE the init, so I am just wondering... what can I do to give all these objects a name?

edit:

Sorry above is the wrong code, and I think I got the title for this post wrong :/

for "_i" from 0 to ((random 100) + 10) do
{
_pos = getMarkerPos "Agia_Marina";
_areasize = 150;
_position = [_pos, _areasize] call CBA_fnc_randPos;  
[color="#FF0000"]Tyres+_i = "Land_Tyres_F" createVehicle (_position);[/color]
//"Land_Tyres_F" createUnit [_position, group logicool,"this setPos [(getPos this select 0),(getPos this select 1),+0.5; this setDir (random 360); Tyre'+_i+' = this;"];
};

The above is the correct code. Since I had a backup I forgot which one I needed help on and it turns out that I dont need the object to be created with the name in it's init, I just wanted to know how I can identify each individual objects after spawn.

Edited by ArmASalt3

Share this post


Link to post
Share on other sites

Hey there, you would use format as an operator

for example

(format["Tyres%1",_i]) = "Land_Tyres_F" createVehicle (_position);

hope that helps :)

Share this post


Link to post
Share on other sites

Hey k0rd thanks for the response.

The code you posted, while logical it does not work. The game is throwing out this error:

2013-06-05%2020_00_54-Arma%203%20Alpha%20_D__Games_Steam_steamapps_common_Arma%203_arma3.exe_%20-showScriptError.png

Hmm...

Share this post


Link to post
Share on other sites

_tyre = "Land_Tyres_F" createVehicle (_position);
missionNameSpace setVariable [format["tyres%1",_i],_tyre];

setVariable uses a string to name the variable, so you can use format command on it to set the variable name

Share this post


Link to post
Share on other sites

ah, that makes more sense - thanks tuliq!

sorry about the bad info ArmASalt3

Share this post


Link to post
Share on other sites

You can do it with call compile.

call compile format ["Tyres%1 = 'Land_Tyres_F' createVehicle %2;", _i, _position];

But I would suggest to simply store all the objects within a list/array.

_list = [];

for "_i" from 0 to ((random 50) + 10) do
{
_pos = getMarkerPos "Agia_Marina";
_areasize = 150;
_position = [_pos, _areasize] call CBA_fnc_randPos;  
_tires = "Land_Tyres_F" createVehicle _position;

   _list set [count _list, _tires];
};

You would then be able to access each object with a foreach loop.

{
      //_x is now each tire contained in the array
} forEach _list;

Share this post


Link to post
Share on other sites

(sorry about the //comments on my code below, if you can stretch the web browser to the edge of your screen so the code can be read better)

_tyre = "Land_Tyres_F" createVehicle (_position);
missionNameSpace setVariable [format["tyres%1",_i],_tyre];

setVariable uses a string to name the variable, so you can use format command on it to set the variable name

That does make a lot of sense, thanks for that man

ah, that makes more sense - thanks tuliq!

sorry about the bad info ArmASalt3

Haha dont worry about it dude, the code you posted seemed logical, but obviously it did not work. I appreciate the help though!

You can do it with call compile.

call compile format ["Tyres%1 = 'Land_Tyres_F' createVehicle %2;", _i, _position];

But I would suggest to simply store all the objects within a list/array.

_list = [];

for "_i" from 0 to ((random 50) + 10) do
{
_pos = getMarkerPos "Agia_Marina";
_areasize = 150;
_position = [_pos, _areasize] call CBA_fnc_randPos;  
_tires = "Land_Tyres_F" createVehicle _position;

   _list set [count _list, _tires];
};

You would then be able to access each object with a foreach loop.

{
      //_x is now each tire contained in the array
} forEach _list;

Wow pretty advance stuff. Still in the learning phase even though i have been using the editor since OFP. If you see below, the completed script in which I have created a function from it, would what you have posted benefited me a lot more than what I have now?


[150, "Agia_Marina", 100,"Land_Garbage_square3_F","Garbage"] spawn fnc_ranPos;

The above code is calling the function, which is the code below.

private ["_pos","_areasize","_position","_randCode","_minNumber0f","_name","_type","_numberOf","_object","_random","_minNumberOf","_setName"];

_areasize = _this select 0;							//Size of the area to spawn the objects in
_type = _this select 1;								//Write in a Marker name or Unit/Object Name in quotes.
_numberOf = _this select 2;							//Sets the amount OR the Maximum amount of objects to spawn
_object = _this select 3;							//Set the object that you want to spawn in quotes.													
_setName = if (count _this > 4) then {_this select 4};		//Sets the name of all the objects by typing in the name you want in quotes.
_random = if (count _this > 5) then {_this select 5}; 			//Set to True if want random or False if not
_minNumberOf = if (count _this > 6) then {_this select 6};		//Sets a minimum number of objects to spawn

_minNumberOf = 0;
_random = false;

if (_random) then 
{
if (_minNumber0f > 0) then
	{
		_randCode = (_minNumberOf + (random _numberOf));
	} else
	{
		_randCode = (random _numberOf);
	}
} else 
{
	_randCode = _numberOf;
};

for "_i" from 0 to _randCode do
{
[b][color="#FF0000"]if (typeOf _type == "Marker") then {_pos = getPos _type;} else {_pos = getMarkerPos _type;};[/color][/b]
_position = [_pos, _areasize] call CBA_fnc_randPos;  
_name = _object createVehicle (_position);
_name setDir (random 360);
if (_setName == "") then {} else { missionNameSpace setVariable [format[_setName+"%1",_i],_name];}  
};

I do have a problem here... I am trying to figure out how to determine what _type is in the script. If it is a Marker, then do a getMarkerPos code else if it is not a marker do a getPos code

Any way to find out the type of entity (is that the right word for it?)

Share this post


Link to post
Share on other sites
switch (typeName _x) do {
//Markers
case ("STRING"): {
	_pos = getMarkerPos _x
};
//[pos, radius] or position [#, #, #]
case ("ARRAY"): {
	_pos = []
	{
		_pos set [_forEachIndex, _x select _forEachIndex];
	}forEach _x;
};
//Triggers, Units, Vehicles etc
case ("OBJECT"): {
	_pos = getPosATL _x;
};

Is one way todo it.

Share this post


Link to post
Share on other sites

Ah brilliant this is great stuff, thanks Larrow!

Ok so I have another issue, its been bugging me for a little while...

here is the updated code

private ["_pos","_areasize","_position","_randCode","_minNumber0f","_name","_type","_numberOf","_object","_random","_minNumberOf","_setName"];

_areasize = _this select 0;                                                            
//Size of the area to spawn the objects in

_type = _this select 1;                                                                    
//Write in a Marker name in quotes or Unit/Object Name without quotes.

_numberOf = _this select 2;                                                        
//Sets the amount OR the Maximum amount of objects to spawn

_object = _this select 3;                                                                
//Set the object that you want to spawn in quotes.                    

_setName = if (count _this > 4) then {_this select 4};        
//Sets the name of all the objects by typing in the name you want in quotes.

_random = if (count _this > 5) then {_this select 5};                 
//Set to True if want random or False if not

_minNumberOf = if (count _this > 6) then {_this select 6};        
//Sets a minimum number of objects to spawn

_minNumberOf = 0;
_random = false;

if (_random) then 
{
   if (_minNumberOf > 0) then
       {
           _randCode = (_minNumberOf + (random _numberOf));
       } else
       {
           _randCode = (random _numberOf);
       }
   } else 
   {
       _randCode = _numberOf;
   };

for "_i" from 0 to _randCode do
{
   switch (typeName _type) do {
       case ("STRING"): {
           _pos = getMarkerPos _type;
       };
       case ("ARRAY"): {
           _pos = [];
           {
               _pos set [_forEachIndex, _type select _forEachIndex];
           } forEach _type;
       };
       case ("OBJECT"): {
           _pos = getPosATL _type;
       };
   };

   _position = [_pos, _areasize] call CBA_fnc_randPos;  
   _name = _object createVehicle (_position);
   _name setDir (random 360);
   if (_setName == "") then {} else { missionNameSpace setVariable [format[_setName+"%1",_i],_name];}  
   };

You notice the text highlighted in BOLD RED? Well leaving that there would override the input spawned at the init. But when testing it, it spawns the object i want. But still the input at spawn has priority so I decided to move that highlighted code to the top, just underneath the Private code.

I test it in game, it does not spawn any objects....

If i remove the code, it still does not spawn any objects.

Does anyone know why? I put it there in case no one sets the Random to true and the minimum amount of objects to be spawned.

---------- Post added at 22:20 ---------- Previous post was at 22:10 ----------

Edit: I had no choice but to force the user to input data for all the indexes on the function.

fnc_ranPos = compile preprocessFile "Scripts\Functions\RanPos.sqf";

[150, Dude, 100,"Land_Tyres_F","Tyres",true,20] spawn fnc_ranPos;
[150, Dude, 30,"Land_GarbageWashingMachine_F","WMachine",false,0] spawn fnc_ranPos;

For example the second line I had to force it to not be random and have no minimum amount, which makes no sense to write all that because I only just want to spawn 30 Washing Machines, no random and obviously theres no need to write the minimum amount because not having a random will skip that part of the code.

private ["_pos","_areasize","_position","_randCode","_minNumber0f","_name","_type","_numberOf","_object","_random","_minNumberOf","_setName"];

_areasize = _this select 0;															
//Size of the area to spawn the objects in

_type = _this select 1;																	
//Write in a Marker name or Unit/Object Name in quotes.

_numberOf = _this select 2;														
//Sets the amount OR the Maximum amount of objects to spawn

_object = _this select 3;																
//Set the object that you want to spawn in quotes.					

_setName = _this select 4;		
//Sets the name of all the objects by typing in the name you want in quotes.

_random = _this select 5; 				
//Set to True if want random or False if not

_minNumberOf = _this select 6;		
//Sets a minimum number of objects to spawn

if (_random) then 
{
if (_minNumberOf > 0) then
	{
		_randCode = (_minNumberOf + (random _numberOf));
	} else
	{
		_randCode = (random _numberOf);
	}
} else 
{
	_randCode = _numberOf;
};

for "_i" from 0 to _randCode do
{
   switch (typeName _type) do {
	case ("STRING"): {
		_pos = getMarkerPos _type;
	};
	case ("ARRAY"): {
		_pos = [];
		{
			_pos set [_forEachIndex, _type select _forEachIndex];
		} forEach _type;
	};
	case ("OBJECT"): {
		_pos = getPosATL _type;
	};
};

_position = [_pos, _areasize] call CBA_fnc_randPos;  
_name = _object createVehicle (_position);
_name setDir (random 360);
if (_setName == "") then {} else { missionNameSpace setVariable [format[_setName+"%1",_i],_name];}  
};

Share this post


Link to post
Share on other sites

Hmm, have a look at bis_fnc_param. It is a function used inside a lot of BIS functions to handle function parameters.

---------- Post added at 01:04 ---------- Previous post was at 00:56 ----------

you should place the marker name / spawn pos as the first index of the passed array, and the model type second, or vice versa, since they are the most important parameters passed. Also, you can do away with the _minNumberOf var. Just pass _numberOf as an array if you want random amount of objects (like [4,19] four being the min, 19 the max), or as a number for an exact amount.

---------- Post added at 01:08 ---------- Previous post was at 01:04 ----------

Also, while I can see that having an option to name all your placed objects according to a formula is great, you might have an easier time just returning an array of all the created objects at the end of the function. then you could call it like this:

_myWonderfulArrayOfObjects = [YOUR ARGUMENTS] call fnc_ranPos 

_myWonderfulArrayOfObjects would then be an array of all the objects.

---------- Post added at 01:11 ---------- Previous post was at 01:08 ----------

For super easy-peasy mode, make the spawnpos parameter only accept a position array [x,y,z]. Then you don't have to rely on only using markers and units to spawn.

Share this post


Link to post
Share on other sites

there seem to be unnecessary loop in "ARRAY" case, could be simplified, can just copy array

instead of

 case ("ARRAY"): {
           _pos = [];
           {
               _pos set [_forEachIndex, _type select _forEachIndex];
           } forEach _type;
       };

use

 case ("ARRAY"): {
           _pos = +_type;
       };

Share this post


Link to post
Share on other sites

Thanks for everything guys, its been very informative and plus the script is working great. I did not use everything that was mentioned on here, but I hope you know that I took everything in, tried it out, mixed it around.

Here is the script. Anyone can use it to their benefit. Maybe some more advance scripter can edit/change the script so that one can make sure that for example the items will not be placed on roads, or inside buildings, or not within 5 meters of each other etc. You dont need to credit me, but please let me know if you change it, so I can look/see how you improved things (for my learning benefit).

// Init.sqf
fnc_ranPos = compile preprocessFile "Scripts\Functions\RanPos.sqf";

[ Dude , "Land_Tyres_F" , 150 , 20 , "Tyres" , true , 10 ] spawn fnc_ranPos;

// Scripts\Functions\RanPos.sqf
private ["_pos","_areasize","_position","_randCode","_minNumber0f","_name","_type","_numberOf","_object","_random","_minNumberOf","_setName"];

//Write in a Marker name or Unit/Object Name in quotes.
_type = _this select 0;																	

//Set the object that you want to spawn in quotes.		
_object = _this select 1;																

//Size of the area to spawn the objects in
_areasize = _this select 2;															

//Sets the amount OR the Maximum amount of objects to spawn		
_numberOf = _this select 3;														

//Sets the name of all the objects by typing in the name you want in quotes.		
_setName = _this select 4;		

//Set to True if want random or False if not	
_random = _this select 5; 				

//Sets a minimum number of objects to spawn
_minNumberOf = _this select 6;		

if (_random) then 
{
if (_minNumberOf > 0) then
	{
		_randCode = (_minNumberOf + (random _numberOf));
	} else
	{
		_randCode = (random _numberOf);
	}
} else 
{
	_randCode = _numberOf;
};

for "_i" from 0 to _randCode do
{
   switch (typeName _type) do {
	//If the _type is a string, then more than likely it is a marker
	case ("STRING"): {
		_pos = getMarkerPos _type;
	};
	//If it is an object, then it could be a unit/vehicle/gamelogic etc
	case ("OBJECT"): {
		_pos = getPosATL _type;
	};
};

 //CBA is required for this
_position = [_pos, _areasize] call CBA_fnc_randPos;  

//Create the named object to spawn, and set a random direction.
_name = _object createVehicle (_position);
_name setDir (random 360);

//I know the 2  codes below this comment are basically the same thing, 
//but I wanted to sort of put them in together as they seem to produce a nicer result that using one of them individually
_name setPos getPos _name;
_name setVectorUP (surfaceNormal [(getPosATL _name) select 0,(getPosATL _name) select 1]);  

//If there is no name, then exit, otherwise set a name for each object then exit.
if (_setName == "") then {exit;} else { missionNameSpace setVariable [format[_setName+"%1",_i],_name];}  
};

exit;

Share this post


Link to post
Share on other sites
You can do it with call compile.

call compile format ["Tyres%1 = 'Land_Tyres_F' createVehicle %2;", _i, _position];

But I would suggest to simply store all the objects within a list/array.

_list = [];

for "_i" from 0 to ((random 50) + 10) do
{
_pos = getMarkerPos "Agia_Marina";
_areasize = 150;
_position = [_pos, _areasize] call CBA_fnc_randPos;  
_tires = "Land_Tyres_F" createVehicle _position;

   _list set [count _list, _tires];
};

You would then be able to access each object with a foreach loop.

{
      //_x is now each tire contained in the array
} forEach _list;

Yeah this is the way you want to do it. Especially if you don't need to reference any single object, but you can deal with them as a batch. If you need to reference a unique element of your list specifically, you could store it separately, or store the index of the object in the array.

Share this post


Link to post
Share on other sites

if (_random) then 
{
   if (_minNumberOf > 0) then
       {
           _randCode = (_minNumberOf + (random _numberOf));
       } else
       {
           _randCode = (random _numberOf);
       }
   } else 
   {
       _randCode = _numberOf;
   }; 

This does not do what you want it to. If you have _numberOf = 20, _minNumberOf = 5,

_randCode = (5 + (19.99999)) = 24.99999 objects spawned, 19.99999 is the largest value possible of (random 20).

Fix

//Sets the amount OR the Maximum amount of objects to spawn (defaults to 1)
_numberOf = [_this,3,1,[0]] call BIS_fnc_param;

//Set to True if want random or False if not (defaults to false)
_random = [_this,5,false] call BIS_fnc_param;

//Sets a minimum number of objects to spawn (defaults to 0)
_minNumberOf = [_this,6,0,[0]] call BIS_fnc_param;

if (_random) then {
   _randCode = (floor (random (_numberOf - _minNumberOf))+1) + _minNumberOf;
}else{
_randCode = _numberOf;
};

Non CBA dependant fix. Swap

     //CBA is required for this
   _position = [_pos, _areasize] call CBA_fnc_randPos;  

   //Create the named object to spawn, and set a random direction.
   _name = _object createVehicle (_position);
   _name setDir (random 360); 

for

    //Create the named object to spawn, and set a random direction.
   _name = createVehicle [_object, _pos, [], _areasize];
   _name setDir (random 360);

I also agree with the others, setting a name for each object is a waste of resources, you would be better off passing an array of objects back to the user for them to deal with.

Edited by Larrow

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
Sign in to follow this  

×