Jump to content

Better building filling


Sgt_HARTMAN

Recommended Posts

Hello World, 

 

 

I don't know if it's the same with you, but with me, the units appear in groups, grouped into the same building. 

 

 

So I found a script in @Achilles Mods which allows to fill and distribute the units in the buildings.

 

I tried several times to integrate it into "fn_mainAOSpawnHandler.sqf" but nothing works.

 

According to you, is this script adaptable in "fn_mainAOSpawnHandler.sqf" (in this //=================Garrison inf===========================) ? or is it in another file? Or is it just not adaptable?

 

 

I will try to create a new .SQF file calling this function. If anyone has an idea to adapt it, I would be grateful

 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// AUTHOR: 			Kex
// DATE: 			12/26/17
// VERSION: 		AMAE.0.1.0
// DESCRIPTION:		Teleports units to random positions in nearby buildings.
//					Preferably orients them in such that they look out of windows.
//					They won't be able to move away till forceSpeed is set to -1.
//
// ARGUMENTS:		0: ARRAY - 3D position from where the building search starts.
//					1: ARRAY - Array of units which are used for the occupation.
//					2: SCALAR - Building search radius in meter (default: 150).
//					3: BOOLEAN - Only use positions inside buildings (default: false).
//					4: BOOLEAN - Distribute units evenly over closest buildings (default: false).
//
// RETURNS:			nothing
//
// Example:			[position leader _group, units _group] call Achilles_fnc_instantBuildingGarrison;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define GOOD_LOS			10
#define MEDIOCRE_LOS		3
#define EYE_HEIGHT			1.53
#define REL_REF_POS_LIST_HORIZONTAL		[[25,0,0],[0,25,0],[-25,0,0],[0,-25,0]]
#define REL_REF_POS_VERTICAL			[0,0,25]

// get arguments
params ["_AOpos", "_units", ["_searchRadius",150,[0]], ["_insideOnly",false,[false]], ["_fillEvenly",false,[false]]];

private _errorOccured = false;

// local function for checking whether positions are inside a building
private _fnc_isInsideBuilding =
{
	params ["_pos","_building"];
	_pos = ATLToASL _pos;
	_pos set [2, EYE_HEIGHT + (_pos select 2)];
	
	// if we have at least 3 walls and a roof, we are inside
	if (_building in (lineIntersectsObjs [_pos, _pos vectorAdd REL_REF_POS_VERTICAL])) then
	{
		{_building in (lineIntersectsObjs [_pos, _pos vectorAdd _x])} count REL_REF_POS_LIST_HORIZONTAL >= 3;
	}
	else
	{
		false;
	};
};

// get all near buildings and their positions inside
private _nearestBuildings = nearestObjects [_AOpos, ["building"], _searchRadius, true];
private _buildings = if (_searchRadius < 0) then {[_nearestBuildings select 0]} else {_nearestBuildings};
private _pos_nestedList = [];
{
	private _building = _x;
	private _pos_list = [_building] call BIS_fnc_buildingPositions;

	// filter positions that are already occupied or not inside if "inside only" is true.
	for "_i_pos" from (count _pos_list - 1) to 0 step -1 do
	{
		private _pos = _pos_list select _i_pos;
		if (count (_pos nearEntities [["Man"], 0.5]) > 0 or {_insideOnly and {not ([_pos, _building] call _fnc_isInsideBuilding)}}) then 
		{
			_pos_list deleteAt _i_pos;
		};
	};

	// filter buildings that do not offer valid positions
	if (not (_pos_list isEqualTo [])) then
	{
		_pos_nestedList pushBack _pos_list;
	};
} forEach _buildings;

for "AO-GarrisonInf-%1" from 0 to (count _units - 1) do
{
	private _unit = _units select AO-GarrisonInf-%1;
	private "_pos";
	private _n_building = count _pos_nestedList;
	
	if (_n_building > 0) then
	{
		if (_fillEvenly) then
		{
			// fill closest buildings by distributing the units randomly
			private _i_building = floor random _n_building;
			private _pos_list = _pos_nestedList select _i_building;
			private _i_pos = floor random count _pos_list;
			_pos = +(_pos_list select _i_pos);
			_pos_list deleteAt _i_pos;
			if (count _pos_list == 0) then {_pos_nestedList deleteAt _i_building};
		}
		else
		{
			// fill closest buildings one by one
			private _i_building = 0;
			private _pos_list = _pos_nestedList select _i_building;
			private _i_pos = floor random count _pos_list;
			_pos = +(_pos_list select _i_pos);
			_pos_list deleteAt _i_pos;
			if (count _pos_list == 0) then {_pos_nestedList deleteAt _i_building};
		};
		_unit setPosATL _pos;
		
		// rotate unit for a good line of sight
		private _eyePosASL = (ATLToASL _pos) vectorAdd [0,0,EYE_HEIGHT];
		private _startAngle = (round random 360);
        for "_angle" from _startAngle to (_startAngle + 360) step 10 do
		{
			// use angle finally if the line of sight is good
			private _relRefPos = [GOOD_LOS*sin(_angle), GOOD_LOS*cos(_angle), 0];
			if (not lineIntersects [_eyePosASL, _eyePosASL vectorAdd _relRefPos]) exitWith
			{
				_unit doWatch (_pos vectorAdd _relRefPos);
			};

			// use angle provisionally if the line of sight is mediocre
			private _relRefPos = [MEDIOCRE_LOS*sin(_angle), MEDIOCRE_LOS*cos(_angle), 0];
			if (not lineIntersects [_eyePosASL, _eyePosASL vectorAdd _relRefPos]) then
			{
				_unit doWatch (_pos vectorAdd _relRefPos);
			};
		};
	}
	else
	{
		// if we don't have sufficient building positions
		_errorOccured = true;
	};
	_unit forceSpeed 0;
};

if (_errorOccured) then
{
	[localize "STR_AMAE_DID_NOT_FIND_SUFFICIENT_FREE_POSITIONS"] call Achilles_fnc_showZeusErrorMessage;
};

fn_mainAOSpawnHandler.sqf

//=================Garrison inf===========================
[_AOpos, _radiusSize] spawn {
    params ["_AOpos", "_radiusSize"];
    private _grpList = [];
    private _milBuildingsarray = nearestObjects [_AOpos, ["house","building"], _radiusSize*0.5];
    sleep 0.5;
    private _milBuildingCount = count _milBuildingsarray;
    private _garrisongroupamount = 0;
	waitUntil {sleep 0.1; !isNil "MainFaction"};
    if (_milBuildingCount > 0) then{

        if (_milBuildingCount > 15) then{_milBuildingCount = 15;};

        for "_i" from 1 to _milBuildingCount do {
            private _infBuilding = selectRandom _milBuildingsarray;
            _milBuildingsarray = _milBuildingsarray - [_infBuilding];
            private _infbuildingpos = _infBuilding buildingPos -1;
            private _buildingposcount = count _infbuildingpos;
            if (_buildingposcount > 12 ) then {_buildingposcount = 12};

            _garrisongroupamount = _garrisongroupamount + 1;
            private _garrisongroup = createGroup east;
    		_grpList pushBack _garrisongroup;
            _garrisongroup setGroupIdGlobal [format ['AO-GarrisonInf-%1', _garrisongroupamount]];

            if (_buildingposcount > 0) then{
                for "_i" from 1 to _buildingposcount do {
                    private _unitpos = selectRandom _infbuildingpos;
                    _infbuildingpos = _infbuildingpos - [_unitpos];
                    private _unitArray = (missionConfigFile >> "unitList" >> MainFaction >> "units") call BIS_fnc_getCfgData;
                    private _unittype = selectRandom _unitArray;
                    private _unit = _garrisongroup createUnit [_unittype, _unitpos, [], 0, "CAN_COLLIDE"];
                    _unit disableAI "PATH";
                };
            };
            [units _garrisongroup] remoteExec ["AW_fnc_addToAllCurators", 2];

            { mainAOUnits pushBack _x; } forEach (units _garrisongroup);
            [units _garrisongroup] spawn derp_fnc_AISkill;
            {
            	_x setCombatMode "YELLOW";
            	_x setBehaviour "AWARE";
            } forEach _grpList;

            sleep 0.5;
        };
    };
    publicVariableServer "mainAOUnits";
};

[_AISkillUnitsArray] spawn {
    params ["_AISkillUnitsArray"];
	[_AISkillUnitsArray] call derp_fnc_AISkill;
};

[mainAOUnits] remoteExec ["AW_fnc_addToAllCurators", 2];
publicVariableServer "mainAOUnits";

{
	_x setCombatMode "YELLOW"; 
	_x setBehaviour "AWARE";
} forEach _grpList;


mainAOUnitsSpawnCompleted = true;
publicVariableServer "mainAOUnitsSpawnCompleted";

 

Thanks

Link to comment
Share on other sites

Could you describe the issue you're having a bit more?  Because the code from fn_mainAOSpawnHandler.sqf you've pasted here doesn't allow groups to be spawn into the same building. 

Before answering your question I have to point out the following: Achilles is released under the Creative Commons Attribution-NonCommercial-ShareAlike lincense.  Meaning that if you use their code you have to license their code under that license.  I&A3 is licensed under MIT.  So you'll have to explicitly license any file you put Achilles code in differently from I&A3.  So, you'll have no choice but to put that Achilles code into a separate file. 

Now for your question:

the goal of that Achilles function is to move an already spawned group into one or more buildings near a given position.  The I&A3 loops over a number of buildings in the AO and spawns a group (of max 12 units) in each one.  So is it possible to integrate that Achilles function?  Well, yes and no.  I wouldn't call it integration because of all the changes you have to make to make it work.  But you can most certainly get it working. 

Link to comment
Share on other sites

 

 

what I would like it is that the number of current unit is distributed in several buildings by covering a maximul the AO. The size of the groups has no importance, I just want to avoid a group of 12 men occupying a single house This is for working CQB techniques

Link to comment
Share on other sites

Well, in that case play with the following values in the AO spawn handler and you don't even need to integrate the function from Achilles:

 

On line 398: private _milBuildingsarray = nearestObjects [_AOpos, ["house","building"], _radiusSize*0.5];

Alter the *0.5 to how much % of the AO you want units to be able to garrison.  Currently units can only be garrisoned in the inner 50% of the AO, changing that value to 1 will make it the entire AO, changing it to for example 0.2 makes it only the inner 20% of the AO.

 

line 405: if (_milBuildingCount > 15) then{_milBuildingCount = 15;};

this value determines the maximum amount of buildings to be garrisoned and thus how many garrison groups there are.

 

line 412: if (_buildingposcount > 12 ) then {_buildingposcount = 12};

This is the upper limit of the amount of spots that will be garrisoned in a building.  And thus the maximum amount of units that will spawn in one building. 

 

You can additionally introduce a variable to keep track of the total amount of units actually spawned but that'll require a bit of editing.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Forum Statistics

    11.1k
    Total Topics
    66.5k
    Total Posts
×
×
  • Create New...