Jump to content
Sign in to follow this  
Schalldampfer

Circular BIS_fnc_findSafePos

Recommended Posts

I modified the BIS_fnc_findSafePos to find the safe position in a circular area, which I use in my server.
(The original one searches positions in a square area, which is different from the description in https://community.bistudio.com/wiki/BIS_fnc_findSafePos )
I need it because mission systems spawn missions at the edge of the map, which is too far from any players.

Spoiler

scriptName "Functions\misc\fn_findSafePos.sqf";
/*
    File: findSafePos.sqf
    Author: Joris-Jan van 't Land
    Edited by Schalldampfer

    Description:
    Function to retrieve and dynamic position in the world according to several parameters.

    Parameter(s):
    _this select 0: center position (Array)
                        Note: passing [] (empty Array), the world's safePositionAnchor entry will be used.
    _this select 1: minimum distance from the center position (Number)
    _this select 2: maximum distance from the center position (Number)
                        Note: passing -1, the world's safePositionRadius entry will be used.
    _this select 3: minimum distance from the nearest object (Number)
    _this select 4: water mode (Number)
                        0: cannot be in water
                        1: can either be in water or not
                        2: must be in water
    _this select 5: maximum terrain gradient (average altitude difference in meters - Number)
    _this select 6: shore mode (Number):
                        0: does not have to be at a shore
                        1: must be at a shore
    _this select 7: (optional) blacklist (Array of Arrays):
                        (_this select 7) select X: Top-left and bottom-right coordinates of blacklisted area (Array)
    _this select 8: (optional) default positions (Array of Arrays):
                        (_this select 8) select 0: default position on land (Array)
                        (_this select 8) select 1: default position on water (Array)
    
    Returns:
    Coordinate array with a position solution.
    
    TODO:
    * Maybe allow passing several combinations of position, min and max dist ... so that you can 
    avoid several things?
    * Interpretation of minDist / maxDist is wrong. It's not true distance that is used. Too bad?
*/

scopeName "main";

private ["_pos", "_minDist", "_maxDist", "_objDist", "_waterMode", "_maxGradient", "_shoreMode", "_defaultPos", "_blacklist"];
_pos = _this select 0;
_minDist = _this select 1;
_maxDist = _this select 2;
_objDist = _this select 3;
_waterMode = _this select 4;
_maxGradient = _this select 5;
_shoreMode = _this select 6;

if (_shoreMode == 0) then {_shoreMode = false} else {_shoreMode = true};

_blacklist = [];
if ((count _this) > 7) then 
{
    _blacklist = _this select 7;
};

_defaultPos = [];
if ((count _this) > 8) then 
{
    _defaultPos = _this select 8;
};

//See if default world values should be used.
if ((count _pos) == 0) then 
{
    _pos = getArray(configFile >> "CfgWorlds" >> worldName >> "safePositionAnchor");
};
if ((count _pos) == 0) exitWith {debugLog "Log: [findSafePos] No center position was passed!"; []}; //TODO: instead return defaults below.

if (_maxDist == -1) then 
{
    _maxDist = getNumber(configFile >> "CfgWorlds" >> worldName >> "safePositionRadius");
};

//TODO: Validate parameters.

private ["_newPos", "_posX", "_posY"];
_newPos = [];
_posX = _pos select 0;
_posY = _pos select 1;


//Limit the amount of attempts at finding a good location.
private ["_attempts"];
_attempts = 0;
while {_attempts < 1000} do
{
    private ["_newX", "_newY", "_testPos", "_rad", "_dist"];
    _dist = _minDist + random (_maxDist - _minDist);
    _rad = random 360;
    _newX = _posX + _dist * (cos _rad);
    _newY = _posY + _dist * (sin _rad);
    _testPos = [_newX, _newY];

    //Blacklist check.
    //TODO: Do not use function when the blacklist is empty?
    if (!([_testPos, _blacklist] call BIS_fnc_isPosBlacklisted)) then
    {
        if (!((count (_testPos isFlatEmpty [_objDist, 0, _maxGradient, _objDist max 5, _waterMode, _shoreMode, objNull])) == 0)) then 
        {
            _newPos = _testPos;
            breakTo "main";
        };
    };

    _attempts = _attempts + 1;
};

//No position was found, use defaults.
if ((count _newPos) == 0) then
{
    if (_waterMode == 0) then
    {
        if ((count _defaultPos) > 0) then 
        {
            _newPos = _defaultPos select 0;
        } 
        else 
        {
            //Use world Armory default position:
            _newPos = getArray(configFile >> "CfgWorlds" >> worldName >> "Armory" >> "positionStart");
        };
    }
    else
    {
        if ((count _defaultPos) > 1) then 
        {
            _newPos = _defaultPos select 1;
        } 
        else 
        {
            //Use world Armory default water position:
            _newPos = getArray(configFile >> "CfgWorlds" >> worldName >> "Armory" >> "positionStartWater");
        };
    };
};

if ((count _newPos) == 0) then 
{
    //Still nothing was found, use world center positions.
    _newPos = getArray(configFile >> "CfgWorlds" >> worldName >> "centerPosition");
};

//diag_log format["BIS_fnc_findSafePos: %2 <- %1",_this,_newPos];

_newPos

BIS_fnc_findSafePos = compile preprocessFileLineNumbers "\z\addons\dayz_server\compile\BIS_fnc\fn_findSafePos.sqf";bis_fnc_findsafepos.jpg

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

  • Advertisement
  • Supporters
  • Discord

×
×
  • Create New...