Forum Jump :

Author Message


Posts: 131
Rank:


Level: Member

Country: us
Location:
Occupation:
Age: 22
In-game name: Joshua

 
#1 Posted at 2016-04-10 23:24        
     
I am creating a segment of a mission that needs to be entirely spawned in via a script (units, way-points, triggers, etc). At the same time, the placement of the units, way-points, triggers, etc needs to be precise. To do this I have created the mission file and then a second test mission. The test mission allows me to place down the units where I want them and run this script:
data = all3DENEntities;     //Gets all objects in 3DEN
_objects = data select 0;   //Gets only the objects (not way-points, groups, triggers, etc)
data = [];                  //Resets data
{                           //For each object, store its data and append it to the array 'data'
	_class = _x get3DENAttribute "ItemClass";
	_name = _x get3DENAttribute "Name";
	_pos = _x get3DENAttribute "position";
	_rot = _x get3DENAttribute "rotation";
	_lock = _x get3DENAttribute "lock";
	_sim = _x get3DENAttribute "enableSimulation";
	_dmg = _x get3DENAttribute "allowDamage";
	_stam = _x get3DENAttribute "enableStamina";
	data set[count data, [_class, _name, _pos, _rot, _lock, _sim, _dmg, _stam]];
}forEach _objects;
copyToClipboard str(data);  // Gives me that data!

This script gets all the units (I have relatively few triggers and way points, so I will code those by hand) and gives me their attributes (well most of them any how). After that it returns a list like so (this is only a sample of three entries, the whole thing is over 100 entries):

_objs = [
[["B_G_Offroad_01_armed_F"],[you],[[9561,15009.5,0]],[[358.091,1.985,177.057]],[0],[true],[false],[false]],
[["I_soldier_F"],[bravo0],[[9528.2,15432.5,0]],[[0,0,138.666]],[1],[true],[true],[true]],
[["Weapon_arifle_TRG21_F"],[],[[9608.86,15176.4,1.13617]],[[0,0,0]],[1],[true],[true],[true]]
];

Now we are getting to the meat of my problem. :)
So I have all this data and I can create the units with this script:

_units = [];
{
	_obj = (_x select 0 select 0) createVehicle [0,0,0];
	_obj setVehicleVarName str(_x select 1 select 0);
	_obj setPosATL (_x select 2 select 0);
	_obj setDir (_x select 3 select 0 select 2);
	_obj lock (_x select 4 select 0);
	_obj enableSimulation (_x select 5 select 0);
	_obj allowDamage (_x select 6 select 0);
	_obj enableStamina (_x select 7 select 0);
	_units set[count _units, _obj];
}forEach _objs;

That's all well and good but since I can't copy data, like what vehicle a unit is in and such, I need to add additional commands after that in the script. The issue is when I try to call a unit from that list above:

bravo0 disableAI "MOVE";

bravo0 is still walking around. The variable name of the unit (what you call the unit when you edit their attributes in the editor) is not bravo0. After looking at the setVehicleVarName command (line 3 of the spawn script), it only sets the string representation of the unit to what I assign it, not the variable name. I looked into using setVariable to see if the following was possible:

_obj setVariable [name, _x select 1 select 0];

From my testing, that didn't work. Is there a way to use setVariable or something else to do this?

If you need more info, or you can't follow, let me know.

Sorry for all the code, and for the acute among you, I did use a macro to remove the quotes around the unit's variable names in my list, otherwise bravo0 would be in a string in the list.


Author Message


Posts: 1189
Rank:


Level: Member

Country: tr
Location:
Occupation: Computer Science student
Age: 20
In-game name: Wak

 
#2 Posted at 2016-04-11 00:33        
     
For saving:
data = [];
{
    _entity = _x;
    _entityData = [];
    {
        _entityData append (_entity get3DENAttribute _x);
    } forEach ["name", "itemClass", "position", "rotation", "lock", "enableSimulation", "allowDamage", "enableStamina"];
         
    data pushBack _entityData;
} forEach (all3DENEntities select 0);
copyToClipboard str data;

For loading:
_objs = [ /*...*/ ];
{
    _obj = call compile format ([
        ["%1 = createVehicle ['%2', %3, [], 0, 'CAN_COLLIDE']; %1", _x select 0, _x select 1, _x select 2],
        ["createVehicle ['%1', %2, [], 0, 'CAN_COLLIDE']", _x select 1, _x select 2]
    ] select ((_x select 0) isEqualTo ""));
    
    _obj setDir (_x select 3 select 2);
    _obj lock (_x select 4);
    _obj enableSimulation (_x select 5);
    _obj allowDamage (_x select 6);
    _obj enableStamina (_x select 7);
} forEach _objs;

Haven't tested the code, tell me if anything is wrong.

This post was edited by 654wak654 (2016-04-11 20:14, 613 days ago)

Sometimes I like to think as I started the whole "earplugs" thing.

W0lle: The only advice I can give you is: Do not try to understand BI. You will not succeed and it only makes your brain go boom. I would even go so far and say that not even they understand their own actions :-D.

#define getDamage getDammage

Advertisement


Author Message


Posts: 131
Rank:


Level: Member

Country: us
Location:
Occupation:
Age: 22
In-game name: Joshua

 
#3 Posted at 2016-04-11 02:28        
     
The refactored saving script works awesome! Its way more compact and I didn't know about the pushback command (I will need to refactor my other project that does a lot of array manipulation now... :).

The loading script is kinda troublesome though. I get one of two errors. When the name of the unit is not given (meaning its an empty string), I get the error: reserved word in expression. When I change the name of the last unit to have a value (i.e. "endOne"), I get the error: Type Any, Expected String. I tried filtering out the unnamed ones with an if statement, but I just got the Type Any error. The if statement is included below:

if(str(_x select 0) != str(""))then{
	_obj = call compile format ["%1 = createVehicle [%2, %3, [], 0, 'CAN_COLLIDE']; %1", _x select 0, _x select 1, _x select 2];
}else{
	_obj = call compile format ["_temp = createVehicle [%1, %2, [], 0, 'CAN_COLLIDE']; _temp", _x select 1, _x select 2];
};

Any idea on how to fix these errors?


Author Message


Posts: 1189
Rank:


Level: Member

Country: tr
Location:
Occupation: Computer Science student
Age: 20
In-game name: Wak

 
#4 Posted at 2016-04-11 03:48        
     
I updated my original post with a solution really similar to yours, it might work now. That condition is unnecessarily over-complicated btw.

Sometimes I like to think as I started the whole "earplugs" thing.

W0lle: The only advice I can give you is: Do not try to understand BI. You will not succeed and it only makes your brain go boom. I would even go so far and say that not even they understand their own actions :-D.

#define getDamage getDammage

Author Message


Posts: 1589
Rank:


Level: Member

Country: pf
Location: Tahiti
Occupation: too many Arma
Age: 57
In-game name: Kobayashi Maru

 
#5 Posted at 2016-04-11 17:29        
     
You should consider placing your units with Eden, which is a good tool for that, then, instead of "spawning" units with a script, just play with the possibility to hide/show units along with their disable/enable simulation.
That's the way some script writers drastically save FPS!

PLEASE CONTACT ME ON BI FORUMS FOR ANY SCRIPT / MOD QUESTION. TKS

Author Message


Posts: 131
Rank:


Level: Member

Country: us
Location:
Occupation:
Age: 22
In-game name: Joshua

 
#6 Posted at 2016-04-11 17:54        
     
@654wak654: I just tried it out, and its giving the 'type Any' error still but now its giving that error, weather or not it deals with an empty string.

With some testing, I discovered a few things.
-It appears that removing quotes around a unit's name prevents the error, but it doesn't spawn the unit either.
-If I wrap the first %1 in str() then it complains about missing a semicolon. Adding semicolons at the end of the second %1 still produced the error. Still no unit spawned in. Below I included the line with the first %1 wrapped in str() (04 in your code above):
["str(%1) = createVehicle [%2, %3, [], 0, 'CAN_COLLIDE']; %1", _x select 0, _x select 1, _x select 2],

Any ideas on how to fix the error or get it spawning in the units?

@Pierre: I am porting the incomplete mission over from the 2D editor. In the 2D editor, I tried using disable simulation and it still takes a massive performance hit (on my 4790K it gets 15-20FPS with 500m draw distance). This is just the first segment of many and it has ~200 objects. Not having the units on the map and spawning in 100-200 at a time makes it much more playable and believe it or not, this way is easier for me to understand. The player goes through several areas of the map. At each point I can spawn in the units just for that part. When the player leaves, I don't need to keep the units there and can delete them to save FPS.


Author Message


Posts: 1589
Rank:


Level: Member

Country: pf
Location: Tahiti
Occupation: too many Arma
Age: 57
In-game name: Kobayashi Maru

 
#7 Posted at 2016-04-11 18:08        
     
I'm not sure you did it like this.

Spawning/deleting is also the way I use for populate cities with civilians (with waypoints) or for randomizing enemy patrols.
It's hard to believe you need 200 units at the right place, right stance...
But, you can play on both faces:
- spawn units + waypoints when you don't need precise locations/stances...
- hideObjectGlobal / enableSimulation false where you need precise positions like in bunkers.

PLEASE CONTACT ME ON BI FORUMS FOR ANY SCRIPT / MOD QUESTION. TKS

Author Message


Posts: 131
Rank:


Level: Member

Country: us
Location:
Occupation:
Age: 22
In-game name: Joshua

 
#8 Posted at 2016-04-11 18:20        
     
I would disable simulation on the units until the player came in range (usually 1 or 2 kilometers). Also when I am referring to 100-200 objects, I am including tables, lanterns, empty and filled vehicles and units. Being able to selectively spawn in different parts of the mission also allows me to be much more detailed (add furniture to buildings, more empty vehicles, etc). Further more, because I was making so many objects in the 2D editor before, I was running into limits (group ones specifically, you can only have 144 groups per side, and lone units count as a group).

The beauty of what I am trying to do now is I will get the benefits of both strategies. Placing the units in 3DEN allows me to be precise and place a lot of objects. Then being able to store all that data in a script and spawn it in whenever allows it not be system intensive.


Author Message


Posts: 1189
Rank:


Level: Member

Country: tr
Location:
Occupation: Computer Science student
Age: 20
In-game name: Wak

 
#9 Posted at 2016-04-11 20:21        
     
I forgot to wrap the classnames in quotes, that was probably the problem. Updated my original post as usual.

Also there is no such thing as `str()`, it's not a method or a function, it's an sqf command. It should be `str <ANY>`.

Sometimes I like to think as I started the whole "earplugs" thing.

W0lle: The only advice I can give you is: Do not try to understand BI. You will not succeed and it only makes your brain go boom. I would even go so far and say that not even they understand their own actions :-D.

#define getDamage getDammage

Author Message


Posts: 131
Rank:


Level: Member

Country: us
Location:
Occupation:
Age: 22
In-game name: Joshua

 
#10 Posted at 2016-04-12 00:45        
     
That worked! I never would have figured that out on my own. Thanks so much for the help 654wak654!


Author Message


Posts: 1589
Rank:


Level: Member

Country: pf
Location: Tahiti
Occupation: too many Arma
Age: 57
In-game name: Kobayashi Maru

 
#11 Posted at 2016-04-13 01:15        
     
jshear95:
Placing the units in 3DEN allows me to be precise and place a lot of objects. Then being able to store all that data in a script and spawn it in whenever allows it not be system intensive.

Did you have a look at this future solution? You may wait for v1.58

This post was edited by Pierre MGI (2016-04-13 04:29, 612 days ago)

PLEASE CONTACT ME ON BI FORUMS FOR ANY SCRIPT / MOD QUESTION. TKS

Author Message


Posts: 131
Rank:


Level: Member

Country: us
Location:
Occupation:
Age: 22
In-game name: Joshua

 
#12 Posted at 2016-04-15 02:59        
     
Thank you for the tip Pierre. I will definitely look into that when it releases, however, I still believe that there is no amount of optimization quite like having the object not exist when you don't need it.

As for the script, here is the final version of the scripts (for future people that find this thread):

Data collection (Run this in the debug console in 3DEN):

comment "By 654wak654 and jshear95";
data = [];
{
    _entity = _x;
    _entityData = [];
    {
        _entityData append (_entity get3DENAttribute _x);
    } forEach ["name", "itemClass", "position", "rotation", "lock", "enableSimulation", "allowDamage", "enableStamina","unitName"];
         
    data pushBack _entityData;
} forEach (all3DENEntities select 0);
copyToClipboard str (data);

You want to paste the data into an array set up like so:
_obj =;
Make sure to paste between the equals (=) and the semi colon (;).


The spawn part is this (run in an external script in the game):

/**
3DEN units spawn script
By jshear95 with the help of 654wak654
*/
{

	_obj = [];
	if(str(_x select 8) == str("Error: No unit")) then {		//If not an AI object spawn in
		_obj = call compile format ([
			["%1 = createVehicle ['%2', %3, [], 0, 'CAN_COLLIDE']; %1", _x select 0, _x select 1, _x select 2],
			["createVehicle ['%1', %2, [], 0, 'CAN_COLLIDE']", _x select 1, _x select 2]
		] select ((_x select 0) isEqualTo ""));
	}else{														//If an AI object
		_grp = "";
		switch (_x select 1 select [0,1]) do {					//Create a group for the side of the unit
			case("B"):{_grp = createGroup west;};
			case("b"):{_grp = createGroup west;};
			case("O"):{_grp = createGroup east;};
			case("o"):{_grp = createGroup east;};
			case("I"):{_grp = createGroup independent;};
			case("i"):{_grp = createGroup independent;};
			case("C"):{_grp = createGroup civilian;};
			case("c"):{_grp = createGroup civilian;};
		};
		_obj = call compile format ([							//Create an AI unit
			["'%2' createUnit [%3, _grp, "" %1 = this;""]", _x select 0, _x select 1, _x select 2, _grp],
			["'%1' createUnit [%2, _grp]", _x select 1, _x select 2, _grp]
		] select ((_x select 0) isEqualTo ""));
		_obj = (units _grp) select 0;
	};
	
    _obj setPosATL (_x select 2);								//Put unit in precise location
    _obj setDir (_x select 3 select 2);
    group _obj setFormDir (_x select 3 select 2);
    _obj lock (_x select 4);
    _obj enableSimulation (_x select 5);
    _obj allowDamage (_x select 6);
    _obj enableStamina (_x select 7);

} forEach _objs;

This script isn't guaranteed to be the most optimized and it will take a while to run with a lot of objects. To ensure play-ability while running the script, a sleep command can be put at the bottom of the forEach loop with a value of ~0.2 to stagger the load of spawning in units. Make sure to account for this extra time when spawning in the units so they don't pop-in in view of the player.

The reason I am adding this update is because while the script fixed by 654wak654 does spawn in all the objects, AI units do not get an AI, rather they spawn empty (think of placing an empty UAV, the riflemen and other units are like that). To remedy this, I get the unit's face, and if they have a face, I spawn them as AI rather than an empty vehicle.

This script is not perfect, for special things like grouping, setting AI values, inventory, moving units into vehicles etc, you will need to manually script all of that. Further more, when running the data gathering script in 3DEN, you must move all AI out of their vehicles in order to get vehicles to spawn propperly. Make sure the names of any AI you want to modify further have a name so you can properly refer to them later.

This script is not tested for multi-player. Feel free to optimize the script.

[Edit 5/1/2016]
-Added additional cases to group to account for outliers
-Updated how direction was set so AI stay facing that direction

This post was edited by jshear95 (2016-05-02 00:09, 593 days ago)


Author Message


Posts: 1589
Rank:


Level: Member

Country: pf
Location: Tahiti
Occupation: too many Arma
Age: 57
In-game name: Kobayashi Maru

 
#13 Posted at 2016-04-15 05:35        
     
Just my 2 cents:
You can directly:
copyToClipboard format ["_objs= %1;",data];
You should had stance for units (undefined for vehicle, there is no error possible)

This post was edited by Pierre MGI (2016-04-15 05:42, 610 days ago)

PLEASE CONTACT ME ON BI FORUMS FOR ANY SCRIPT / MOD QUESTION. TKS

Author Message


Posts: 131
Rank:


Level: Member

Country: us
Location:
Occupation:
Age: 22
In-game name: Joshua

 
#14 Posted at 2016-04-24 20:50        
     
I just your suggestion Pierre for another part of my mission, the format command limits the %1 to 8192 characters and truncates it after that length.