a3_vemf_reloaded/exile_vemf_reloaded/functions/fn_findPos.sqf
2016-04-10 17:25:24 +02:00

233 lines
7.3 KiB
Plaintext

/*
Author: IT07
Description:
can find a location or pos randomly on the map where there are no players
Params:
_this select 0: STRING - Mode to use. Options: "loc" or "pos"
_this select 1: BOOLEAN - True if _pos needs to be a road
_this select 2: POSITION - Center for nearestLocations check
_this select 3: SCALAR - Distance in meters. Locations closer than that will be excluded
_this select 4: SCALAR - Max prefered distance in meters from center. If not achievable, further dest will be selected
_this select 5: SCALAR - Distance in meters to check from _cntr for players
_this select 6: STRING (optional) - Exact config name of mission override settings to load
Returns:
if mode = loc then: ARRAY - format [name of town/location, town position]
if mode = pos then POSITION
*/
private ["_settings","_locPos","_loc","_locName","_ret","_continue","_settings","_blackList","_usedLocs","_checkRange","_tooCloseRange","_maxPrefered","_skipDistance","_nonPopulated","_mode","_pos","_hasPlayers","_blackPos","_checkBlackPos"];
_ret = false;
// Define settings
_settings = [["nonPopulated","noMissionPos","missionDistance"]] call VEMFr_fnc_getSetting;
_nonPopulated = _settings param [0, 1, [0]];
_blackPos = _settings param [1, [], [[]]];
_missionDistance = _settings param [2, 3000, [0]];
_range = worldSize;
// Settings override system
_missionConfigName = param [6, "", [""]];
if not(_missionConfigName isEqualTo "") then
{
_nonPopulatedOverride = ([[_missionConfigName],["nonPopulated"]] call VEMFr_fnc_getSetting) select 0;
if not isNil"_nonPopulatedOverride" then
{
if not(_nonPopulatedOverride isEqualTo -1) then
{
_nonPopulated = _nonPopulatedOverride;
};
};
};
_checkBlackPos = false;
if (count _blackPos > 0) then
{
_checkBlackPos = true;
};
_mode = param [0, "", [""]];
if not(_mode isEqualTo "") then
{
_onRoad = param [1, false, [false]];
_roadRange = 5000;
_cntr = param [2, [], [[]]];
if (_cntr isEqualTypeArray [0,0,0]) then
{
_tooCloseRange = param [3, -1, [0]];
if (_tooCloseRange > -1) then
{
_maxPrefered = param [4, -1, [0]];
if (_maxPrefered > -1) then
{
_skipDistance = param [5, -1, [0]];
if (_skipDistance > -1) then
{
if (_mode isEqualTo "loc") then
{
// Get a list of locations close to _cntr (position of player)
_locs = nearestLocations [_cntr, ["CityCenter","Strategic","StrongpointArea","NameVillage","NameCity","NameCityCapital",if(_nonPopulated isEqualTo 1)then{"nameLocal","Area","BorderCrossing","Hill","fakeTown","Name","RockArea","ViewPoint"}], _range];
if (count _locs > 0) then
{
_usedLocs = uiNamespace getVariable "VEMFrUsedLocs";
_remLocs = [];
_blackListMapClasses = "true" configClasses (configFile >> "CfgVemfReloaded" >> "locationBlackLists");
_listedMaps = []; // Define
{ // Make a list of locationBlackLists's children
_listedMaps pushBack (configName _x);
} forEach _blackListMapClasses;
private ["_blackList"];
if (worldName in _listedMaps) then { _blackList = ([["locationBlackLists", worldName],["locations"]] call VEMFr_fnc_getSetting) select 0 };
if not(worldName in _listedMaps) then { _blackList = ([["locationBlackLists","Other"],["locations"]] call VEMFr_fnc_getSetting) select 0 };
{ // Check _locs for invalid locations (too close, hasPlayers or inBlacklist)
_hasPlayers = [locationPosition _x, _skipDistance] call VEMFr_fnc_checkPlayerPresence;
if _hasPlayers then
{
_remLocs pushBack _x;
};
if not _hasPlayers then
{
if _checkBlackPos then
{
private ["_locPos","_loc"];
_locPos = locationPosition _x;
_loc = _x;
{
if (count _x isEqualTo 2) then
{
_pos = _x param [0, [0,0,0], [[]]];
if not(_pos isEqualTo [0,0,0]) then
{
_range = _x param [1, 600, [0]];
if ((_pos distance _locPos) < _range) then
{
_remLocs pushBack _loc;
};
};
};
if not(count _x isEqualTo 2) then
{
["fn_findPos", 0, format["found invalid entry in mission blacklist: %1", _x]] spawn VEMFr_fnc_log;
};
} forEach _blackPos;
};
if ((text _x) in _blackList) then
{
_remLocs pushBack _x;
};
if not((text _x) in _blackList) then
{
if (_cntr distance (locationPosition _x) < _tooCloseRange) then
{
_remLocs pushBack _x;
};
if (_cntr distance (locationPosition _x) > _tooCloseRange) then
{
if (([text _x, locationPosition _x]) in _usedLocs) then
{
_remLocs pushBack _x;
};
};
};
if (count _usedLocs > 0) then
{
private ["_loc"];
_loc = _x;
{
if (((locationPosition _loc) distance (_x select 1)) < _missionDistance) then
{
_remLocs pushBack _loc;
};
} forEach _usedLocs;
};
};
} forEach _locs;
{ // Remove all invalid locations from _locs
_index = _locs find _x;
_locs deleteAt _index;
} forEach _remLocs;
// Check what kind of distances we have
_far = []; // Further than _maxPrefered
_pref = []; // Closer then _maxPrefered
{
_dist = _cntr distance (locationPosition _x);
if (_dist > _maxPrefered) then
{
_far pushBack _x;
};
if (_dist < _maxPrefered) then
{
_pref pushBack _x;
};
} forEach _locs;
// Check if there are any prefered locations. If yes, randomly select one
if (count _pref > 0) then
{
_loc = selectRandom _pref;
};
// Check if _far has any locations and if _pref is empty
if (count _far > 0) then
{
if (count _pref isEqualTo 0) then
{
_loc = selectRandom _far;
};
};
// Validate _locs just to prevent the .RPT from getting spammed
if (count _locs > 0) then
{
// Return Name and POS
_ret = [text _loc, locationPosition _loc];
(uiNamespace getVariable "VEMFrUsedLocs") pushBack _ret;
};
};
};
if (_mode isEqualTo "pos") then
{
_valid = false;
for "_p" from 1 to 10 do
{
if (_ret isEqualType true) then
{
if not _ret then
{
_pos = [_cntr, _tooCloseRange, -1, 2, 0, 50, 0] call BIS_fnc_findSafePos;
if _onRoad then
{
_roads = _pos nearRoads _roadRange;
if (count _roads > 0) then
{
private ["_closest","_dist"];
_closest = ["", _roadRange];
{ // Find the closest road
_dist = _x distance _pos;
if (_dist < (_closest select 1)) then
{
_closest = [_x, _dist];
};
} forEach _roads;
_pos = position (_closest select 0);
};
};
_hasPlayers = [_pos, _skipDistance] call VEMFr_fnc_checkPlayerPresence;
if not(_hasPlayers) then
{
_ret = _pos;
};
};
};
};
};
};
};
};
};
};
_ret