Jnr4817 215 Posted June 1, 2016 I am wanting more than 1 plane at a time to be in the air, or working the pattern, or landing and taking off, at a time. Visiting multiple airports sleeping for a few minutes then moving to the next. I have figured it out with helos, but planes are different and difficult, due to the runways, ILS positions, and taxi positions. Landat is not always success, and waypoints are not perfect. ambflyby is great for flybys, but I want true ambient aircraft. thanks for the suggestion. Rather than trying to use the fsm directly, why not use a function such as BIS_fns_ambientFlyBy? ambFlyby = [getmarkerpos "startMarker", getmarkerpos "stopMarker", 100, "FULL", "B_Plane_CAS_01_F", WEST] call BIS_fnc_ambientFlyBy; Share this post Link to post Share on other sites
Jnr4817 215 Posted June 7, 2016 Where do I place this bit of ode to call the ambient flyby and how can I make it repeat? Rather than trying to use the fsm directly, why not use a function such as BIS_fns_ambientFlyBy? ambFlyby = [getmarkerpos "startMarker", getmarkerpos "stopMarker", 100, "FULL", "B_Plane_CAS_01_F", WEST] call BIS_fnc_ambientFlyBy; Share this post Link to post Share on other sites
kauppapekka 27 Posted June 13, 2016 BIS_fnc_taskState could use a fix. https://feedback.bistudio.com/T117691 Share this post Link to post Share on other sites
kauppapekka 27 Posted July 29, 2016 BIS_fnc_drawMinefields could use the newer allMines command, instead of shifting through allMissionObjects. Share this post Link to post Share on other sites
Grumpy Old Man 3545 Posted August 3, 2016 I humbly suggest to update BIS_fnc_selectRandomWeighted with this: /* Author: Joris-Jan van 't Land, optimized by Karel Moricky, modified by Grumpy Old Man Description: Function to select a random item from an array, taking into account item weights. The weights should be Numbers between 0 and 1, with a maximum precision of hundreds. Parameter(s): _this select 0: source Array (Array of Any Value) _this select 1: weights (Array of Numbers) Returns: Any Value selected item Example: [["apples","bananas","tractor"],[0.5,0.25,0.25]] call BIS_fnc_selectRandomWeighted TODO: [*] Algorithm is inefficient? */ params [["_array",[]],["_weights",[]]]; if !((count _array) isEqualTo (count _weights)) exitWith {"There must be at least as many elements in Weights (1) as there are in Array (0)!" call bis_fnc_error; nil}; _weightsTotal = 0; { _x = _x param [0,0,[0]]; _weightsTotal = _weightsTotal + _x; } count _weights; _weightCheck = _weightsTotal isEqualTo 0; _return = []; if (!_weightCheck) then { private ["_weighted"]; _weighted = []; { private ["_weight"]; _weight = _x / _weightsTotal; _weight = round (_weight * 100); for "_k" from 1 to _weight do { _weighted pushback _foreachindex; }; } foreach _weights; private ["_index"]; _index = selectRandom _weighted; _return = _array select _index; }; if (_weightCheck) then { ["The sum of weights must be larger than 0"] call bis_fnc_error; nil }; _return Using this: [["apples","bananas","tractor"],[0.5,0.25,0.25]] call BIS_fnc_selectRandomWeighted the original one runs at 0.237079 ms, my modified version runs at 0.0995 ms. Replaced the foreach loop with count, added isEqualTo checks, pushBack and replaced the "from 0 to _weighted -1" with "from 1 to _weighted". No idea how to squeeze more performance out of it other than taking a whole different approach, the current speed gain is impressive enough for me. Results for 100.000 iterations: Original one: [["tractor",24870],["apples",50116],["bananas",25014]] //23.589s My modification: [["bananas",24779],["apples",49939],["tractor",25282]] //10.005s Cheers 4 Share this post Link to post Share on other sites
pedeathtrian 99 Posted August 3, 2016 Even more humbly I suggest this (with a bit of algorithmical improvement): /* Author: Joris-Jan van 't Land, optimized by Karel Moricky, modified by Grumpy Old Man, a bit more optimized by pedeathtrian Description: Function to select a random item from an array, taking into account item weights. The weights should be Numbers between 0 and 1, with a maximum precision of hundreds. Parameter(s): _this select 0: source Array (Array of Any Value) _this select 1: weights (Array of Numbers) Returns: Any Value selected item Example: [["apples","bananas","tractor"],[0.5,0.25,0.25]] call BIS_fnc_selectRandomWeighted TODO: [*] Algorithm is inefficient? */ params [["_array",[]],["_weights",[]]]; if !((count _array) isEqualTo (count _weights)) exitWith {"There must be at least as many elements in Weights (1) as there are in Array (0)!" call BIS_fnc_error; nil}; _weightsTotal = 0; _wCheckFail = false; { _x = _x param [0,0,[0]]; if (_x < 0) exitWith {_wCheckFail = true}; _weightsTotal = _weightsTotal + _x; } count _weights; if (_wCheckFail) exitWith {"Non-negative weights expected!" call BIS_fnc_error; nil}; if (_weightsTotal isEqualTo 0) exitWith {"The sum of weights must be larger than 0" call BIS_fnc_error; nil}; _return = []; _wCheckFail = true; _rnd = random _weightsTotal; { if (_rnd < _x) exitWith {_wCheckFail = false; _return = _array select _forEachIndex}; _rnd = _rnd - _x; } forEach _weights; _return Or, alternatively, this (uses slightly different approach and binary search (could win on large arrays)) /* Author: Joris-Jan van 't Land, optimized by Karel Moricky, modified by Grumpy Old Man, a bit more optimized by pedeathtrian Description: Function to select a random item from an array, taking into account item weights. The weights should be Numbers between 0 and 1, with a maximum precision of hundreds. Parameter(s): _this select 0: source Array (Array of Any Value) _this select 1: weights (Array of Numbers) Returns: Any Value selected item Example: [["apples","bananas","tractor"],[0.5,0.25,0.25]] call BIS_fnc_selectRandomWeighted TODO: [*] Algorithm is inefficient? */ params [["_array",[]],["_weights",[]]]; _cnt = count _array; if !(_cnt isEqualTo (count _weights)) exitWith {"There must be at least as many elements in Weights (1) as there are in Array (0)!" call BIS_fnc_error; nil}; _weightsTotal = 0; _weightsCumulative = []; _wCheckFail = false; { _x = _x param [0,0,[0]]; if (_x < 0) exitWith {_wCheckFail = true}; _weightsTotal = _weightsTotal + _x; _weightsCumulative pushBack _weightsTotal; } count _weights; if (_wCheckFail) exitWith {"Non-negative weights expected!" call BIS_fnc_error; nil}; if (_weightsTotal isEqualTo 0) exitWith {"The sum of weights must be larger than 0" call BIS_fnc_error; nil}; _rnd = random _weightsTotal; _min = 0; while {(_cnt-_min) > 1} do { private _mid = floor ((_cnt+_min)/2); private _midW = _weightsCumulative select _mid; if (_rnd < _midW) then { _cnt = _mid; } else { _min = _mid }; }; _array select _cnt My stats of processing same input: 100000 calls (all ordered for ["apples","bananas","tractor"]): Original: [50079,24896,25025] // 34.3989 sec; avg 0.000343989 Grumpy Old Man's version: [50399,24966,24635] // 14.572 sec; avg 0.00014572" (as you can see my machine is slower, but ratio is kept the same). My version 1: [50021,25117,24862] // 3.66309 sec; avg 3.66309e-005 My version 2 (with bin. search; makes almost no difference to previous due to very short array): [50116,25032,24852] // 3.66199 sec; avg 3.66199e-005 I also decided if check input weights, then they should all be non-negative. UPD. Also, in my version you're freed from limitation "weights should be Numbers between 0 and 1, with a maximum precision of hundreds", they just should be non-negative (and preferably not causing sum overflow; and not sum to zero) 1 Share this post Link to post Share on other sites
Grumpy Old Man 3545 Posted August 3, 2016 Your first example runs for 0.0247 ms here, very nice. The second one throws an error in the line "_weightsCumulative pushBack _weightsTotal;" because count expects bool, add a true there and you're set. Second one runs 0.0311 ms with the bool error fixed. Very impressive. Cheers Share this post Link to post Share on other sites
Grumpy Old Man 3545 Posted August 12, 2016 Looks like KK added his own version of BIS_fnc_selectRandomWeighted to the devbranch, running at 0.0275 ms. Thanks for the improvement! Cheers Share this post Link to post Share on other sites
IndeedPete 1038 Posted August 20, 2016 Not exactly a function I use in that sense but one that is triggered through the ORBAT group module. When sync'ing the module to a unit, the ORBAT icon will follow it on the map. However, this also overwrites the given groupID with the content of the "text" attribute in the ORBAT entry. (Note that it is the "text" attribute, not the "textShort" one which would make much more sense IMO.) Untested suggestion to fix it, two altered lines marked in red: Grr, it overwrites my text formatting. Altered lines are 27 and 40. BIS_fnc_moduleStrategicMapORBAT _logic = _this param [0,objnull,[objnull]]; _units = _this param [1,[],[[]]]; _activated = _this param [2,true,[true]]; if (_activated) then { _pos = position _logic; _class = call compile (_logic getvariable "Path"); _parent = call compile (_logic getvariable "Parent"); _tags = _logic getvariable ["Tags",""]; _tiers = (call compile (_logic getvariable "Tiers")) call bis_fnc_parsenumber; if (isnil "_class") then {_class = configfile;}; if (isnil "_parent") then {_parent = _class;}; if (isnil "_tiers") then {_tiers = -1;}; _class = _class param [0,configfile,[configfile]]; _parent = _parent param [0,configfile,[configfile]]; _tags = call compile ("[" + _tags + "]"); _logic setvariable ["data",[_pos,_class,_parent,_tags,_tiers]]; //--- No Strategic Map connected - display in the main map if ({typeof _x == "ModuleStrategicMapInit_F"} count (synchronizedobjects _logic) == 0) then { _classParams = _class call bis_fnc_ORBATGetGroupParams; _text = _classParams select ("text" call bis_fnc_ORBATGetGroupParams); _textshort = _classParams select ("textshort" call bis_fnc_ORBATGetGroupParams); _texture = _classParams select ("texture" call bis_fnc_ORBATGetGroupParams); _size = _classParams select ("size" call bis_fnc_ORBATGetGroupParams); _sizeTexture = _classParams select ("sizeTexture" call bis_fnc_ORBATGetGroupParams); _textureSize = _classParams select ("textureSize" call bis_fnc_ORBATGetGroupParams); _color = _classParams select ("color" call bis_fnc_ORBATGetGroupParams); _iconSize = sqrt (_size + 1) * 26; //--- Assign the icon to a group if (count _units > 0) then { private ["_grp"]; _grp = group (_units select 0); if !(isnull _grp) then { _grp setgroupid [_textshort]; // Either this, or remove line entirely. _pos = [_grp]; }; }; _iconParams = [_texture,_color,_pos,_iconSize * _textureSize,_iconSize * _textureSize,0,"",false]; _sizeIconParams = if (_size >= 0) then {[_sizetexture,_color,_pos,_iconSize,_iconSize,0,"",false]} else {[]}; //--- Register icons _drawIcon = missionnamespace getvariable ["BIS_fnc_moduleStrategicMapORBAT_drawIcon",[]]; _drawIcon set [count _drawIcon,[_class,[_parent,_tags,_tiers],_iconParams,_classParams,_sizeIconParams]]; missionnamespace setvariable ["BIS_fnc_moduleStrategicMapORBAT_drawIcon",_drawIcon]; //--- Register ORBAT viewer on click event _ORBATonClick = missionnamespace getvariable ["BIS_fnc_moduleStrategicMapORBAT_ORBATonClick",[]]; _ORBATonClick set [count _ORBATonClick,_class]; _ORBATonClick set [ count _ORBATonClick, { disableserialization; [_this select 0,1,BIS_fnc_moduleStrategicMapORBAT_display select 0,BIS_fnc_moduleStrategicMapORBAT_drawIcon] spawn bis_fnc_strategicMapAnimate; true } ]; missionnamespace setvariable ["BIS_fnc_moduleStrategicMapORBAT_ORBATonClick",_ORBATonClick]; BIS_fnc_moduleStrategicMapORBAT_mouseClickDisable = false; //--- Initialize UI event handlers if (isnil {BIS_fnc_moduleStrategicMapORBAT_draw}) then { disableserialization; BIS_fnc_moduleStrategicMapORBAT_draw = { _control = _this select 0; _mousePos = missionnamespace getvariable ["BIS_fnc_moduleStrategicMapORBAT_mousePos",[0,0]]; _drawIcon = missionnamespace getvariable ["BIS_fnc_moduleStrategicMapORBAT_drawIcon",[]]; _overlay = missionnamespace getvariable ["BIS_fnc_ORBATAddGroupOverlay_groups",[]]; _selected = []; { scriptname "BIS_fnc_moduleStrategicMapORBAT_draw"; _class = _x select 0; _iconParams = +(_x select 2); _classParams = +(_x select 3); _sizeIconParams = +(_x select 4); _pos = _iconParams select 2; if (count _pos == 1) then { _pos = visibleposition leader (_pos select 0); _iconParams set [2,_pos]; _sizeIconParams set [2,_pos]; }; _mapPos = _control ctrlmapworldtoscreen _pos; _iconSize = _iconParams select 3; _isSelected = ((_mapPos distance _mousePos) / _iconSize) < 0.0007; if (_isSelected) then { _iconSize = _iconSize * 1.2; _iconParams set [3,_iconSize]; _iconParams set [4,_iconSize]; _selected = _x; }; _control drawicon _iconParams; //--- Draw size texture if (count _sizeIconParams > 0) then { if (_isSelected) then { _sizeIconSize = (_sizeIconParams select 3) * 1.2; _sizeIconParams set [3,_sizeIconSize]; _sizeIconParams set [4,_sizeIconSize]; }; _control drawIcon _sizeIconParams; }; //--- Draw custom textures _classID = _overlay find _class; if (_classID >= 0) then { _classOverlay = _overlay select (_classID + 1); _iconColor = _iconParams select 1; { if (typename _x == typename []) then { _xTexture = _x select 0; _xColor = +(_x select 1); _xWidth = _x select 2; _xHeight = _x select 3; _xAngle = _x select 4; _xText = _x select 5; _xShadow = _x select 6; //--- Read dynamic params passed as code if (typename _xColor == typename {}) then { _xColor = call _xColor; _xColor = _xColor param [0,[1,1,1,1],[[]]]; }; if (typename _xWidth == typename {}) then { _xWidth = call _xWidth; _xWidth = _xWidth param [0,1,[1]]; }; if (typename _xHeight == typename {}) then { _xHeight = call _xHeight; _xHeight = _xHeight param [0,1,[1]]; }; if (typename _xAngle == typename {}) then { _xAngle = call _xAngle; _xAngle = _xAngle param [0,0,[0]]; }; _xColor set [3,(_xColor select 3) * (_iconColor select 3)]; //--- Convert size to coeficients of original icon size _xWidth = _xWidth * _iconSize; _xHeight = _xHeight * _iconSize; //--- Draw _control drawicon [_xTexture,_xColor,[_pos select 0,_pos select 1],_xWidth,_xHeight,_xAngle,_xText,_xShadow]; }; } foreach _classOverlay; }; } foreach _drawIcon; if (count _selected > 0 && !BIS_fnc_moduleStrategicMapORBAT_mouseClickDisable) then { _class = _selected select 0; _classParams = _selected select 3; [_classParams,ctrlparent _control,_mousePos] call bis_fnc_ORBATTooltip; _control ctrlMapCursor ["Track","HC_overFriendly"]; } else { [[],ctrlparent _control] call bis_fnc_ORBATTooltip; _control ctrlMapCursor ["Track","Track"]; }; BIS_fnc_moduleStrategicMapORBAT_selected = _selected; }; BIS_fnc_moduleStrategicMapORBAT_mouse = { BIS_fnc_moduleStrategicMapORBAT_mousePos = [_this select 1,_this select 2]; }; //--- Add event handlers _fnc_addHandlers = { { _x spawn { disableserialization; waituntil {!isnull (finddisplay _this displayctrl 51)}; _control = finddisplay _this displayctrl 51; _control ctrladdeventhandler ["draw","_this call BIS_fnc_moduleStrategicMapORBAT_draw;"]; _control ctrladdeventhandler ["mousemoving","_this call BIS_fnc_moduleStrategicMapORBAT_mouse;"]; _control ctrladdeventhandler ["mouseholding","_this call BIS_fnc_moduleStrategicMapORBAT_mouse;"]; _control ctrladdeventhandler ["mousebuttonclick","['BIS_fnc_moduleStrategicMapORBAT',_this] spawn BIS_fnc_strategicMapMouseButtonClick;"]; }; } foreach [ getnumber (configfile >> "RscDisplayMainMap" >> "idd"), getnumber (configfile >> "RscDisplayGetReady" >> "idd"), getnumber (configfile >> "RscDisplayClientGetReady" >> "idd"), getnumber (configfile >> "RscDisplayServerGetReady" >> "idd") ]; }; [] spawn _fnc_addHandlers; addmissioneventhandler ["loaded",_fnc_addHandlers]; }; }; }; Will also spam the FT soon. Edit: FT Ticket - https://feedback.bistudio.com/T120008 Share this post Link to post Share on other sites
SilentSpike 84 Posted August 20, 2016 An easy function improvement: In BIS_fnc_locationDescription the nearestLocations command uses the player position to find locations to use as a reference for the supplied position. Surely it should use the supplied position instead? (Or you could use worldSize to make sure you get every location on the map if you wanted) 1 Share this post Link to post Share on other sites
killzone_kid 1330 Posted August 20, 2016 An easy function improvement: In BIS_fnc_locationDescription the nearestLocations command uses the player position to find locations to use as a reference for the supplied position. Surely it should use the supplied position instead? (Or you could use worldSize to make sure you get every location on the map if you wanted) Good catch! Share this post Link to post Share on other sites
JD Wang 352 Posted September 7, 2016 For purely selfish reason I've always thought BIS_fnc_buildingPositions would be even better if it differentiated between inside (with a roof and enclosing walls) and outside (balconies etc) Most of the time I use that function it's to place a unit inside a building, hidden in cover etc, but having them standing out on a balcony, or on a porch, or even under the roof at the petrol stations doesn't quite do the job. Sure I get why they're building positions, but it would be great to be able to exclude any that aren't enclosed. Share this post Link to post Share on other sites
Grumpy Old Man 3545 Posted December 4, 2016 Please take a look into BIS_fnc_enemyTargets and BIS_fnc_enemyDetected. BIS_fnc_enemyTargets: /* Author: Jiri Wainar Description: Return list of nearby enemy targets for given unit. Parameter(s): _this: unit that is inspected Returns: _targets:array (empty array if unit doesn't know about any enemy) Example: _targets:array = _unit call BIS_fnc_enemyTargets; _targets:array = [_unit(,_distance)] call BIS_fnc_enemyTargets; */ private["_pivot","_distance","_targets","_enemies","_enemySides","_side","_unit"]; _pivot = _this param [0,objNull,[objNull]]; _distance = _this param [1,300,[123]]; _targets = _pivot nearTargets _distance; _enemies = []; _enemySides = _pivot call BIS_fnc_enemySides; { _unit = (_x select 4); _side = (_x select 2); if ((_side in _enemySides) && (count crew _unit > 0)) then { if ((side driver _unit) in _enemySides) then { _enemies set [count _enemies, _unit]; }; }; } forEach _targets; _enemies BIS_fnc_enemyDetected: /* Author: Jiri Wainar Description: Return true if unit knows about nearby enemy unit or driven vehicle. Parameter(s): _this: unit that is inspected Returns: _knowsAboutEnemy:bool Example: _knowsAboutEnemy:bool = _unit call BIS_fnc_enemyDetected; _knowsAboutEnemy:bool = [_unit(,_distance)] call BIS_fnc_enemyDetected; */ count (_this call BIS_fnc_enemyTargets) > 0 The first one fails to return hostile vehicles without a driver, even if other positions are occupied by enemy units, the second one fails because of that. Using this as a temporary fix in my own missions, maybe someone comes up with a better solution: _unit = player; _enemySides = _unit call BIS_fnc_enemySides; _enemies = (_unit neartargets 2000) apply {_x select 4} select {side _x in _enemySides AND {count crew _x > 0}}; This runs for 0.0976 ms on my rig, compared to 0.145243 ms of the BIS function. Cheers Share this post Link to post Share on other sites
Grumpy Old Man 3545 Posted May 27, 2017 If this thread is still a thing: Possible improvement for BIS_fnc_numberDigits [random 10000] call BIS_fnc_numberDigits; //0.0538 ms toarray str random 10000 apply {parsenumber (tostring [_x])}; //0.01 ms 530% speed increase? Seems vast, or am I missing something? Cheers Share this post Link to post Share on other sites
R3vo 2654 Posted May 27, 2017 4 hours ago, Grumpy Old Man said: If this thread is still a thing: Possible improvement for BIS_fnc_numberDigits [random 10000] call BIS_fnc_numberDigits; //0.0538 ms toarray str random 10000 apply {parsenumber (tostring [_x])}; //0.01 ms 530% speed increase? Seems vast, or am I missing something? Cheers Without random it's even 900% for me. Good find! 1 Share this post Link to post Share on other sites
Grumpy Old Man 3545 Posted May 27, 2017 15 minutes ago, R3vo said: Without random it's even 900% for me. Good find! Currently optimizing some functions from my library (and for aircraft loadout dialog), getting rid of BI functions is a good idea most of the time, as you see. heh. Also I'm getting addicted to increasing performance, especially with such promising results. Shedding off the milliseconds like mad. Cheers Share this post Link to post Share on other sites
pedeathtrian 99 Posted May 27, 2017 (edited) 5 hours ago, Grumpy Old Man said: [random 10000] call BIS_fnc_numberDigits; //0.0538 ms toarray str random 10000 apply {parsenumber (tostring [_x])}; //0.01 ms Careful with fraction part. parseNumber parses decimal dot into zero, so for 12.34 you will get [1,2] for BIS_fnc_numberDigits and, surprise, [1,2,0,3,4] for parseNumber variant. UPD. If it only used for integers, this can be even faster: toarray str random 10000 apply {_x-48}; (decimal point converted to -2 in this variant) UPD2. And negatives! parseNumber parses minus sign into zero too. {_x-48} makes -3 out of minus sign. Not very comfy, but at least distinguishable from real number digits. Edited May 27, 2017 by pedeathtrian 1 Share this post Link to post Share on other sites
Grumpy Old Man 3545 Posted May 28, 2017 18 hours ago, pedeathtrian said: Careful with fraction part. parseNumber parses decimal dot into zero, so for 12.34 you will get [1,2] for BIS_fnc_numberDigits and, surprise, [1,2,0,3,4] for parseNumber variant. UPD. If it only used for integers, this can be even faster: toarray str random 10000 apply {_x-48}; (decimal point converted to -2 in this variant) UPD2. And negatives! parseNumber parses minus sign into zero too. {_x-48} makes -3 out of minus sign. Not very comfy, but at least distinguishable from real number digits. Removing the zeros from the array, nice. That's even faster, doing this with a set number it goes from 0.0079 ms using my attempt down to 0.0051 ms on my rig. Nice speed increase indeed! If you know the culprits and handle the outcome of a negative number when needed it's definitely the way to go! Cheers Share this post Link to post Share on other sites
killzone_kid 1330 Posted May 28, 2017 On 5/27/2017 at 5:41 AM, Grumpy Old Man said: or am I missing something? Yes 1234567 call BIS_fnc_numberDigits; //[1,2,3,4,5,6,7] toarray str 1234567 apply {parsenumber (tostring [_x])}; //[1,0,2,3,4,5,7,0,0,0,0,6] 1 Share this post Link to post Share on other sites