Jump to content
Sign in to follow this  
spitfire007

Put a car in every garage on Altis via script

Recommended Posts

As per the subject I am trying code a script to put a car in every garage on Altis.

I am not quite sure how to go about it though.

My thinking is that I could use nearestBuilding then find out if it is a Land_i_Garage_V1_F (garage).

Then find out the orientation of the garage somehow ? and place a car in the garage with the same orientation.

Am I wasting my time trying to figure this out ?

Is it even possible to find out the position of the "hard coded" buildings in Arma 3 ?

Share this post


Link to post
Share on other sites

What's the garage's classname(s)? Dreadedentity made a loot spawning script, that stores a list of buildings ( all house buildings atm ) and their building positions (inside). You could alter that code, make it store a list of the desired garages instead. Also find out the most desireable building position(s) for said garage(s) and you're good to go.

Edited by Iceman77

Share this post


Link to post
Share on other sites

This will help you generate a list of classnames and positions:

car = vehicle player;
garages = [];

act = player addAction [
"Save",
'
	_trg = cursorTarget;
	_class = typeOf _trg;
	_pos = getPosWorld car;
	_mpos = _trg worldToModel _pos;
	_dir = (direction car) - (direction _trg);
	_arr = [_class,_mpos,_dir];

	_i = -1;
	{
		if(	_x select 0 == _class ) then {
			_i = _forEachIndex;
			garages set[_i,_arr];
		}
	} forEach garages;

	if (_i == -1) then {
		garages pushBack _arr;
	};

',
"",
10,
true,
true,
"",
'
	_show = false;
	_trg = cursorTarget;
	_class = typeOf _trg;
	if (_trg isKindOf "House") then {
		if ( {_x select 0 == _class} count garages > 0 ) then {
			_txt = format["Update %1", _class];
		} else {
			_txt = format["Save %1", _class];
		};
		_show = true;
		player setUserActionText[act,_txt];
	};
	_show
'
];

Here is how:

1. Spawn a car or place one in the editor

2. Get in the car

3. Press esc, copy the code above into the debug console and run it.

4. Drive your car to the next garage and park the car where you want it.

5. Get out, aim at the garage and use the action menu to save the position of the car (make sure, the action-name shows the right classname)

6. Get back into your car and drive to the next garage or building that you want to use. (1 vehicle position per building)

7. When you're done, enter "garages" in one of the bottom lines of the debug console and copy the contents of the variable.

Now you just need a script that uses this information to spawn vehicles, which is actually the easier part. ;)

Edited by Tajin
small fix

Share this post


Link to post
Share on other sites

Alternatively, (and not so precise I might add) spawn a random civ vehicle in each Land_i_Garage_V1_F garage, @ position 3 (kind of in the middle), within a given radius and facing outward. Cheers.

garageSpawn.sqf - From DreadedEntity's loot System FrameWork (Modified to the extreme by yours truely)

/*
****************
** Parameters **
****************
_this select 0 - <NUMBER> spawn radius
_this select 1 - <BOOL> debug markers ( OPTIONAL )

********************
** Usage Examples **
********************
[800, true] execVM "garageSpawn.sqf";
[600] execVM "garageSpawn.sqf";

*/

private ["_distanceToSpawn","_cfgArray","_positionArray","_buildingArray","_newMarker","_veh","_vehArray","_debug"];

_distanceToSpawn = [_this, 0, 300, [0]] call BIS_fnc_param;
_debug = [_this, 1, false, [true]] call BIS_fnc_param;

_vehArray = [];
_cfgArray = "( 
(getNumber (_x >> 'scope') >= 2) && 
{getNumber (_x >> 'side') == 3 && 
{getText (_x >> 'vehicleClass') in ['Car'] &&
{_vehArray pushBack ( configname _x );
	true}
	} 
} 
)" configClasses (configFile >> "CfgVehicles");

_positionArray = [];
_buildingArray = nearestObjects [player, ["Land_i_Garage_V1_F"], _distanceToSpawn];
{
_positionArray pushBack ([_x] call BIS_fnc_buildingPositions);	
}forEach _buildingArray;

{
_veh = createVehicle [_vehArray call BIS_fnc_selectRandom, ( _positionArray select _forEachIndex ) select 2, [], 0, "CAN_COLLIDE"];
_veh setDir (getDir (_buildingArray select _foreachindex) - 90);
if ( _debug ) then {
	_newMarker = createMarker [format ["marker%1", _forEachIndex], getPos _veh];
	_newMarker setMarkerShape "ICON";
	_newMarker setMarkerType "mil_dot"; 
};
}forEach _positionArray;

//Framework by DreadedEntity 
//I'll have to ask anybody that uses this code, or any parts of this code, to not delete these comments  

Note: Updated it. Also, you could pass some other object to the script as the center instead of hard coding player variable. I'll leave it for now.

Edited by Iceman77
Removed refresh loop to make things more straight forward

Share this post


Link to post
Share on other sites

You guys are gold.

Will give both methods a shot and report back.

edit:

The method Iceman made/adjusted works a treat.

@Tagin.

For some reason I get ["Land_i_Garage_V2_F",array,scalar]] this in the bottom line.

Out of bounds error ?

Edited by spitfire007

Share this post


Link to post
Share on other sites

If you don't mind spending a bit of time, using tajin's method, you can get very precise spawning positions. The quick and dirty I posted works okay for civ vehicles because they're smaller overall (the garage is tiny hehe). It doesn't place them exactly in the middle, but close enough.

Share this post


Link to post
Share on other sites
For some reason I get ["Land_i_Garage_V2_F",array,scalar]] this in the bottom line.

Out of bounds error ?

Did you get into the car before running the script?

Otherwise the script doesn't know which car to use.

Share this post


Link to post
Share on other sites

Yes I did ...

I made sure it said garage [new] before I pressed save .. but same result. Very late here and I may have made a mistake. Will have another go tomorrow.

@Iceman.

Thanks for the file debug is now working for me.

One thing I notice though is on Altis I placed a player right in the middle of the airfield and set the distance to 30000 like so.

[30000, true] spawn DREAD_fnc_lootSpawn;

But .. it does not cover the whole island.

And .. it lags the bejesus out of the load ... which I guess is to be expected :)

Share this post


Link to post
Share on other sites

Yeah. You may be better off passing a few different objects as centers to the script and checking shorter ranges. eg; spawn the vehicles in sectors of the map, and not all at once. I'd concentrate on the viable towns first and check short range a few times... My 2C

Share this post


Link to post
Share on other sites

Hmm no idea. Could easily be my mistake aswell, since I pulled that script out of thin air, without any testing.

I'll give it a try myself, when I get home.

Share this post


Link to post
Share on other sites

Example Altis: Spawning in sectors

We're now passing an array of objects (centers) to the script. Easy way to populate the towns without so much a performance hit like when searching a 30000m radius. Note: If there's no rush to spawn the vehicles, use a small 1 second sleep to spawn them one at a time if it's a performance hit.

Main Code:

/*
  ***************************************************************************
  ** Original Framework By DreadedEntity (modified extensively by Iceman77)**
  ***************************************************************************
   The original framework can be found @ http://forums.bistudio.com/showthread.php?184513-CODE-SNIPPET-The-simplest-loot-system-of-all-time

*****************
** Description **
*****************
Spawn random civilian vehicles in garages

   ****************
   ** Parameters **
   ****************
   _this select 0 - <NUMBER> spawn radius
_this select 1 - <ARRAY> of objects ( CENTERS )
   _this select 2 - <BOOL> debug markers ( OPTIONAL )

   ********************
   ** Usage Examples **
   ********************
   [200, [player], true] spawn DREAD_fnc_garageSpawn;
   [100, [obj1, obj2, obj3], true] spawn DREAD_fnc_garageSpawn;
[300, [obj4, obj8, obj26]] spawn DREAD_fnc_garageSpawn;

*/

private ["_radius","_centersArray","_debug","_vehArray","_cfgArray","_positionArray","_buildingArray"];

_radius = [_this, 0, 300, [0]] call BIS_fnc_param;
_centersArray = [_this, 1, [], [[]]] call BIS_fnc_param;
_debug = [_this, 2, false, [true]] call BIS_fnc_param;

_vehArray = [];
_cfgArray = "( 
   (getNumber (_x >> 'scope') >= 2) && 
   {getNumber (_x >> 'side') == 3 && 
   {getText (_x >> 'vehicleClass') in ['Car'] &&
   {_vehArray pushBack ( configname _x );
       true}
       } 
   } 
)" configClasses (configFile >> "CfgVehicles");

{
_positionArray = [];
_buildingArray = nearestObjects [_x, ["Land_i_Garage_V1_F"], _radius];
{
	_positionArray pushBack ([_x] call BIS_fnc_buildingPositions);    
}forEach _buildingArray;

{
	private ["_veh","_newMarker"];
	_veh = createVehicle [_vehArray call BIS_fnc_selectRandom, ( _positionArray select _forEachIndex ) select 2, [], 0, "CAN_COLLIDE"];
	_veh setDir (getDir (_buildingArray select _foreachindex) - 90);
	if ( _debug ) then {
		_newMarker = createMarker [format ["marker%1", _forEachIndex], getPos _veh];
		_newMarker setMarkerShape "ICON";
		_newMarker setMarkerType "mil_dot"; 
	};
	sleep 1;
}forEach _positionArray;
sleep 1;
} forEach _centersArray;

//Framework by DreadedEntity 
//I'll have to ask anybody that uses this code, or any parts of this code, to not delete these comments  

Edited by Iceman77

Share this post


Link to post
Share on other sites

This should be pretty nice and at least kind of what you want

/*
USAGE: _handle = [P1, P2] execVM "garageFiller.sqf";
_handle = Anything you want
P1: Position (An array with 3 scalar elements) - The center point where you want to spawn cars
P2: Number - The radius outward you want the script to check for cars

EXAMPLE: _handle = [[0,0,0], 10000] execVM "garageFiller.sqf";
At [0,0,0] the script will check in a radius of 10km for garages and fill them
*/

private["_position","_radius","_allGarages","_car"];

_position = [_this, 0, [0,0,0], [[]]] call BIS_fnc_param;
_radius = [_this, 0, 0, [0]] call BIS_fnc_param;

_allGarages = nearestObjects [_position, ["Land_i_Garage_V1_F"], _radius];
{
_car = createVehicle ["YOURCARCLASSNAME", (_x modelToWorld [?, ?, ?]), [], 0, "CAN_COLLIDE"];
_car setDir (direction _x);
}forEach _allGarages;

Note the "YOURCARCLASSNAME" and modelToWorld [?,?,?]. I'm not sure what kind of car(s) you want to spawn (can be easily edited if you want to spawn more than one type) so you'll have to replace that and the second part I don't have arma open right now so I can't check the actual offset you should use to put the cars in. Save that into a script and make sure the code only runs ONCE

Hope that helps

Edited by DreadedEntity

Share this post


Link to post
Share on other sites

Meh, I just stuck with and recommended your framework :). I like using building positions, so you don't have to find perfect positions (find the correct MTW). May be using different type of garages etc etc. At any rate you could just spawn the vehicle at the building like you've done lol. Need to set it's direction though. And lets randomize vehicles too.

private["_position","_radius","_allGarages","_vehArray","_cfgArray","_class"];

_vehArray = [];
_cfgArray = "( 
   (getNumber (_x >> 'scope') >= 2) && 
   {getNumber (_x >> 'side') == 3 && 
   {getText (_x >> 'vehicleClass') in ['Car'] &&
   {_vehArray pushBack ( configname _x );
       true}
       } 
   } 
)" configClasses (configFile >> "CfgVehicles");

_position = [_this, 0, [0,0,0], [[]]] call BIS_fnc_param;
_radius = [_this, 1, 0, [0]] call BIS_fnc_param;

_allGarages = nearestObjects [_position, ["Land_i_Garage_V1_F"], _radius];
{
  _class = _vehArray call BIS_fnc_selectRandom;
  _veh = createVehicle [_class, (_x modelToWorld [0, 0, 0]), [], 0, "CAN_COLLIDE"];
  _veh setDir (getDir _x - 90);
}forEach _allGarages;  

Edited by Iceman77

Share this post


Link to post
Share on other sites
Need to set it's direction though.

Yep I thought of this just seconds after I posted it :p it's edited now

Share this post


Link to post
Share on other sites

@SpitFire - So... to continue our debugging and getting you all set, take a look @ post #12. Also take a look see at the latest "method". Please report back. I'd quite a bit of my time in tinkering with the original =). Like to know if it's feasible anyhow.

Share this post


Link to post
Share on other sites

Thanks for spending time on this.

It looks like it mostly works.

There seems to be some debug ... bug somewhere though.

https://www.dropbox.com/s/67plcc9iyai5wan/garageSpawner.Altis.zip?dl=0

For example.

If I put the player in the center of Kavala and set the radius to 500 all garages in Kavala are filled and show the debug dots.

However if I use an object to be the center and use the same radius, in the same position as the player in Kavala (or any other town I have tried), then all garages seem to be filled .. but only some of the debug dots show up.

Code for player standing in Kavala and object in Kavala.

[500, [obj1, obj2, obj3, obj4, obj5], true] spawn DREAD_fnc_garageSpawn;
[500, [player], true] spawn DREAD_fnc_garageSpawn;

(not using both calls together)

But, If I put the player at the central airfield and use a radius of 15000 it takes a long time but all garages on the whole island seem to fill correctly and the debug dots all show properly.

I am not sure what is going on.

Just one question about scripting if you don't mind.

When you spawned DREAD_fnc_garageSpawn why do you put DREAD at the start (apart from giving credit) and how does it know that that is infact fn_garagespawn.sqf ?

Nevermind .. I see it's in the functions.hpp

---------- Post added at 06:17 ---------- Previous post was at 05:06 ----------

@DreadedEntity

I just could not make yours spawn a car at all.

I just used 0,0,0 for ModelToWorld and called it with.

_handle = [[3758.21,13283.8,12.7194], 500] execVM "garageFiller.sqf";

I can't see why it wouldn't work .. but the [] are confusing the hell out of me.

_position = [_this, 0, [0,0,0], [[]]] call BIS_fnc_param;

Why are the empty brackets all there ?

Got it .. part of BIS_func_param. (not used to this new A3 thing yet)

Edit:

Ok .. I now see an error returned.

says [3758.21,13283.8,12.7194] is TYPE array, must be SCALAR, 0 used instead.

I think your arguments are messed up ? maybe ?

_handle = [[3758.21,13283.8,12.7194], 500] execVM "garageFiller.sqf";

is the call .. with position first as an array then the radius as scalar.

Then in the garagefiller.sqf they are ...

_position = [_this, 0, [0,0,0], [[]]] call BIS_fnc_param;

Radius first then position ?

Will mess around and see if I can fix it.

Edited by spitfire007

Share this post


Link to post
Share on other sites

Hey add me to steam btw. Good going btw m8. Bis_fnc_param lets you decide what types of arguments can be passed. ie; [], "", 1, true, objNull and even has a default value if the wrong type was being passed.

Share this post


Link to post
Share on other sites
@DreadedEntity

I just could not make yours spawn a car at all.

_position = [_this, 0, [0,0,0], [[]]] call BIS_fnc_param;
_radius = [_this, 0, 0, [0]] call BIS_fnc_param;

//SHOULD BE

_position = [_this, 0, [0,0,0], [[]], 3] call BIS_fnc_param;
_radius = [_this, 1, 0, [0]] call BIS_fnc_param;

radius was being overwritten because of my syntax error. After fixing that, worked like a dream! (also add -90 to the setDir command, all the cars sit in the garages sideways)

Share this post


Link to post
Share on other sites

Ahhh...

That did it.

Kind of makes it hard to get out of the garage though if you don't use -90 :)

_veh setDir (getDir (_buildingArray select _foreachindex) - 90);

Still a problem with it though.

It does not fill all the garages like the Iceman version.

Look at the garage at grid 256213 on the T Junction in Sophia.

Share this post


Link to post
Share on other sites
It does not fill all the garages like the Iceman version.

I traveled there and it seemed to fill the garage just fine? Please also be aware there there is not just "new" garages but there are also "damaged" garages, they have a different classname and the script will not fill them.

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  

×