- Modification of actions data structure to separate action parameters from children

- The action tree of each interaction point is parsed before drawing, pruning inactive actions
- Parent actions without statements or active children are not drawn, in order to reduce clutter
This commit is contained in:
Nicolás Badano 2015-03-02 23:29:57 -03:00
parent 094be22a19
commit 83572921ae
12 changed files with 230 additions and 195 deletions

View File

@ -5,7 +5,7 @@ ADDON = false;
PREP(addAction); PREP(addAction);
PREP(compileMenu); PREP(compileMenu);
PREP(compileMenuSelfAction); PREP(compileMenuSelfAction);
PREP(collectActiveChildren); PREP(collectActiveActionTree);
PREP(keyDown); PREP(keyDown);
PREP(keyDownSelfAction); PREP(keyDownSelfAction);
PREP(keyUp); PREP(keyUp);
@ -13,6 +13,7 @@ PREP(keyUpSelfAction);
PREP(removeAction); PREP(removeAction);
PREP(render); PREP(render);
PREP(renderIcon); PREP(renderIcon);
PREP(renderBaseMenu);
PREP(renderMenu); PREP(renderMenu);
PREP(rotateVectLine); PREP(rotateVectLine);
PREP(rotateVectLineGetMap); PREP(rotateVectLineGetMap);
@ -43,6 +44,4 @@ GVAR(startHoverTime) = diag_tickTime;
GVAR(iconCtrls) = []; GVAR(iconCtrls) = [];
GVAR(iconCount) = 0; GVAR(iconCount) = 0;
GVAR(uidCounter) = 0;
ADDON = true; ADDON = true;

View File

@ -36,17 +36,18 @@ if((count _actions) == 0) then {
private "_entry"; private "_entry";
_entry = [ _entry = [
[
_displayName, _displayName,
_icon, _icon,
_position, _position,
_statement, _statement,
_condition, _condition,
_distance, _distance,
[], [false,false,false],
GVAR(uidCounter),
+ _fullPath + _fullPath
],
[]
]; ];
GVAR(uidCounter) = GVAR(uidCounter) + 1;
_actions pushBack _entry; _actions pushBack _entry;

View File

@ -0,0 +1,72 @@
/*
* Author: CAA-Picard
* Collect a entire tree of active actions
*
* Argument:
* 0: Object <OBJECT>
* 1: Original action tree <ARRAY>
*
* Return value:
* Active children <ARRAY>
*
* Public: No
*/
#include "script_component.hpp"
EXPLODE_2_PVT(_this,_object,_origAction);
EXPLODE_2_PVT(_origAction,_origActionData,_origActionChildren);
private ["_resultingAction","_target","_player","_activeChildren","_action","_actionData","_x"];
_target = _object;
_player = ACE_player;
// Return nothing if the action itself is not active
if !([_target, ACE_player] call (_origActionData select 4)) exitWith {
[]
};
_activeChildren = [];
// Collect children class actions
{
_action = [_object, _x] call FUNC(collectActiveActionTree);
if ((count _action) > 0) then {
_activeChildren pushBack _action;
};
} forEach _origActionChildren;
// Collect children object actions
{
_action = _x;
_actionData = _action select 0;
// Check if the action is children of the original action
if ((count (_actionData select 7)) == (count (_origActionData select 7) + 1)) then {
// Compare parent path to see if it's a suitable child
private "_isChild";
_isChild = true;
{
if !(_x isEqualTo ((_actionData select 7) select _forEachIndex)) exitWith {
_isChild = false;
};
} forEach (_origActionData select 7);
if (_isChild) then {
_action = [_object, _action] call FUNC(collectActiveActionTree);
if ((count _action) > 0) then {
_activeChildren pushBack _action;
};
};
};
} forEach GVAR(objectActions);
// If the original action has no statement, and no children, don't display it
if ((count _activeChildren) == 0 && ((_origActionData select 3) isEqualTo {})) exitWith {
// @todo: Account for showDisabled?
[]
};
[_origActionData, _activeChildren]

View File

@ -1,58 +0,0 @@
/*
* Author: CAA-Picard
* For a given action, collect all active children
*
* Argument:
* 0: Object <OBJECT>
* 1: Action data <ARRAY>
*
* Return value:
* Active children <ARRAY>
*
* Public: No
*/
#include "script_component.hpp"
EXPLODE_2_PVT(_this,_object,_parentAction);
private ["_activeChildren","_target","_player","_action"];
_activeChildren = [];
_target = _object;
_player = ACE_player;
// Collect children class actions
{
_action = _x;
if([_object, ACE_player] call (_action select 4)) then {
_activeChildren pushBack _action;
};
} forEach (_parentAction select 6);
// Collect children object actions
{
_action = _x;
// Check if the action is children of the selected menu
if ((count (_action select 8)) == (count (_parentAction select 8) + 1)) then {
// Compare parent path to see if it's a suitable child
private "_isChild";
_isChild = true;
{
if !(_x isEqualTo ((_action select 8) select _forEachIndex)) exitWith {
_isChild = false;
};
} forEach (_parentAction select 8);
if (_isChild) then {
if ([_target, ACE_player] call (_action select 4)) then {
_activeChildren pushBack _action;
};
};
};
} forEach GVAR(objectActions);
_activeChildren

View File

@ -45,8 +45,9 @@ _recurseFnc = {
// Add canInteract (including exceptions) and canInteractWith to condition // Add canInteract (including exceptions) and canInteractWith to condition
_condition = _condition + format [QUOTE( && {%1 call EGVAR(common,canInteract)} && {[ARR_2(ACE_player, _target)] call EFUNC(common,canInteractWith)} ), getArray (_entryCfg >> "exceptions")]; _condition = _condition + format [QUOTE( && {%1 call EGVAR(common,canInteract)} && {[ARR_2(ACE_player, _target)] call EFUNC(common,canInteractWith)} ), getArray (_entryCfg >> "exceptions")];
_showDisabled = getNumber (_entryCfg >> "showDisabled"); _showDisabled = (getNumber (_entryCfg >> "showDisabled")) > 0;
_enableInside = getNumber (_entryCfg >> "enableInside"); _enableInside = (getNumber (_entryCfg >> "enableInside")) > 0;
_canCollapse = (getNumber (_entryCfg >> "canCollapse")) > 0;
_fullPath = (+ _parentPath); _fullPath = (+ _parentPath);
_fullPath pushBack (configName _entryCfg); _fullPath pushBack (configName _entryCfg);
@ -55,18 +56,18 @@ _recurseFnc = {
_children = [_entryCfg, _fullPath] call _recurseFnc; _children = [_entryCfg, _fullPath] call _recurseFnc;
_entry = [ _entry = [
[
_displayName, _displayName,
_icon, _icon,
_selection, _selection,
_statement, _statement,
_condition, _condition,
_distance, _distance,
_children, [_showDisabled,_enableInside,_canCollapse],
GVAR(uidCounter),
_fullPath _fullPath
],
_children
]; ];
GVAR(uidCounter) = GVAR(uidCounter) + 1;
_actions pushBack _entry; _actions pushBack _entry;
}; };
}; };
@ -79,6 +80,7 @@ _actionsCfg = configFile >> "CfgVehicles" >> _objectType >> "ACE_Actions";
missionNamespace setVariable [_actionsVarName, [_actionsCfg, []] call _recurseFnc]; missionNamespace setVariable [_actionsVarName, [_actionsCfg, []] call _recurseFnc];
/* /*
[
[ [
[ [
"My Action", "My Action",
@ -87,9 +89,10 @@ missionNamespace setVariable [_actionsVarName, [_actionsCfg, []] call _recurseFn
{ (_this select 0) setVelocity [0,0,10]; }, { (_this select 0) setVelocity [0,0,10]; },
{ true }, { true },
1, 1,
[], [false,false,false]
uid,
["ACE_MainActions","TeamManagement","MyAction"] ["ACE_MainActions","TeamManagement","MyAction"]
],
[children actions]
] ]
] ]
*/ */

View File

@ -42,8 +42,9 @@ _recurseFnc = {
// Add canInteract (including exceptions) and canInteractWith to condition // Add canInteract (including exceptions) and canInteractWith to condition
_condition = _condition + format [QUOTE( && {%1 call EGVAR(common,canInteract)} && {[ARR_2(ACE_player, _target)] call EFUNC(common,canInteractWith)} ), getArray (_entryCfg >> "exceptions")]; _condition = _condition + format [QUOTE( && {%1 call EGVAR(common,canInteract)} && {[ARR_2(ACE_player, _target)] call EFUNC(common,canInteractWith)} ), getArray (_entryCfg >> "exceptions")];
_showDisabled = getNumber (_entryCfg >> "showDisabled"); _showDisabled = (getNumber (_entryCfg >> "showDisabled")) > 0;
_enableInside = getNumber (_entryCfg >> "enableInside"); _enableInside = (getNumber (_entryCfg >> "enableInside")) > 0;
_canCollapse = (getNumber (_entryCfg >> "canCollapse")) > 0;
_fullPath = (+ _parentPath); _fullPath = (+ _parentPath);
_fullPath pushBack (configName _entryCfg); _fullPath pushBack (configName _entryCfg);
@ -52,18 +53,18 @@ _recurseFnc = {
_children = [_entryCfg, _fullPath] call _recurseFnc; _children = [_entryCfg, _fullPath] call _recurseFnc;
_entry = [ _entry = [
[
_displayName, _displayName,
_icon, _icon,
[0,0,0], [0,0,0],
_statement, _statement,
_condition, _condition,
10, //distace 10, //distace
_children, [_showDisabled,_enableInside,_canCollapse],
GVAR(uidCounter),
_fullPath _fullPath
],
_children
]; ];
GVAR(uidCounter) = GVAR(uidCounter) + 1;
_actions pushBack _entry; _actions pushBack _entry;
}; };
}; };
@ -74,18 +75,20 @@ private "_actionsCfg";
_actionsCfg = configFile >> "CfgVehicles" >> _objectType >> "ACE_SelfActions"; _actionsCfg = configFile >> "CfgVehicles" >> _objectType >> "ACE_SelfActions";
// Create a master action to base on self action // Create a master action to base on self action
_actions = [[ _actions = [
[
[
"Self Actions", "Self Actions",
"\a3\ui_f\data\IGUI\Cfg\Actions\eject_ca.paa", "\a3\ui_f\data\IGUI\Cfg\Actions\eject_ca.paa",
"Spine3", "Spine3",
{ true }, { true },
{ true }, { true },
10, 10,
[_actionsCfg, ["ACE_SelfActions"]] call _recurseFnc, [false,true,false],
GVAR(uidCounter),
["ACE_SelfActions"] ["ACE_SelfActions"]
],
[_actionsCfg, ["ACE_SelfActions"]] call _recurseFnc
] ]
]; ];
GVAR(uidCounter) = GVAR(uidCounter) + 1;
missionNamespace setVariable [_actionsVarName, _actions]; missionNamespace setVariable [_actionsVarName, _actions];

View File

@ -33,6 +33,5 @@ if(!GVAR(keyDownSelfAction)) then {
}; };
GVAR(selfMenuOffset) = (positionCameraToWorld [0, 0, 2]) vectorDiff (positionCameraToWorld [0, 0, 0]); GVAR(selfMenuOffset) = (positionCameraToWorld [0, 0, 2]) vectorDiff (positionCameraToWorld [0, 0, 0]);
//systemChat format ["GVAR(selfMenuOffset) %1",GVAR(selfMenuOffset)];
}; };
true true

View File

@ -24,7 +24,7 @@ _varName = [QGVAR(actions),QGVAR(selfActions)] select _typeNum;
_actions = _object getVariable [_varName, []]; _actions = _object getVariable [_varName, []];
{ {
if ((_x select 8) isEqualTo _fullPath) exitWith { if (((_x select 0) select 7) isEqualTo _fullPath) exitWith {
_actions deleteAt _forEachIndex; _actions deleteAt _forEachIndex;
}; };
} forEach _actions; } forEach _actions;

View File

@ -22,7 +22,7 @@ GVAR(selfMenuScale) = (((worldToScreen (positionCameraToWorld [1,0,2])) select 0
//systemChat format ["selfMenuScale: %1", GVAR(selfMenuScale)]; //systemChat format ["selfMenuScale: %1", GVAR(selfMenuScale)];
GVAR(currentOptions) = []; GVAR(currentOptions) = [];
private ["_actionsVarName","_classActions","_objectActions","_target","_player","_actionItem","_active"]; private ["_actionsVarName","_classActions","_objectActions","_target","_player","_action","_actionData","_active"];
_player = ACE_player; _player = ACE_player;
if (GVAR(keyDown)) then { if (GVAR(keyDown)) then {
[] call FUNC(updateVecLineMap); [] call FUNC(updateVecLineMap);
@ -44,11 +44,11 @@ if (GVAR(keyDown)) then {
_actionsVarName = format [QGVAR(Act_%1), typeOf _target]; _actionsVarName = format [QGVAR(Act_%1), typeOf _target];
GVAR(objectActions) = _target getVariable [QGVAR(actions), []]; GVAR(objectActions) = _target getVariable [QGVAR(actions), []];
{ {
_actionItem = _x; _action = _x;
// Only render them directly if they are base level actions // Only render them directly if they are base level actions
if (count (_actionItem select 8) == 1) then { if (count ((_action select 0) select 7) == 1) then {
// Try to render the menu // Try to render the menu
if ([_target, _actionItem, false, [180, 360]] call FUNC(renderMenu)) then { if ([_target, _action] call FUNC(renderBaseMenu)) then {
_numInteractions = _numInteractions + 1; _numInteractions = _numInteractions + 1;
}; };
}; };
@ -57,9 +57,9 @@ if (GVAR(keyDown)) then {
// Iterate through base level class actions and render them if appropiate // Iterate through base level class actions and render them if appropiate
_classActions = missionNamespace getVariable [_actionsVarName, []]; _classActions = missionNamespace getVariable [_actionsVarName, []];
{ {
_actionItem = _x; _action = _x;
// Try to render the menu // Try to render the menu
if ([_target, _actionItem, false, [180, 360]] call FUNC(renderMenu)) then { if ([_target, _action] call FUNC(renderBaseMenu)) then {
_numInteractions = _numInteractions + 1; _numInteractions = _numInteractions + 1;
}; };
} forEach _classActions; } forEach _classActions;
@ -86,14 +86,10 @@ if (GVAR(keyDown)) then {
GVAR(objectActions) = _target getVariable [QGVAR(selfActions), []]; GVAR(objectActions) = _target getVariable [QGVAR(selfActions), []];
/* /*
{ {
_actionItem = _x; _action = _x;
// Only render them directly if they are base level actions // Only render them directly if they are base level actions
if (count (_actionItem select 8) == 1) then { if (count (_action select 7) == 1) then {
_active = [_target, ACE_player] call (_actionItem select 4); [_target, _action, 0, [180, 360]] call FUNC(renderMenu);
if (_active) then {
[_target, _actionItem, 0, [180, 360]] call FUNC(renderMenu);
};
}; };
} forEach GVAR(objectActions); } forEach GVAR(objectActions);
*/ */
@ -102,14 +98,10 @@ if (GVAR(keyDown)) then {
_actionsVarName = format [QGVAR(SelfAct_%1), typeOf _target]; _actionsVarName = format [QGVAR(SelfAct_%1), typeOf _target];
_classActions = missionNamespace getVariable [_actionsVarName, []]; _classActions = missionNamespace getVariable [_actionsVarName, []];
{ {
_actionItem = _x; _action = _x;
_active = [_target, ACE_player] call (_actionItem select 4);
if (_active) then {
//_pos = (ACE_player modelToWorld (ACE_player selectionPosition "spine3")) vectorAdd GVAR(selfMenuOffset) vectorAdd [0,0,0.25];
_pos = _cursorPos1 vectorAdd GVAR(selfMenuOffset); _pos = _cursorPos1 vectorAdd GVAR(selfMenuOffset);
[_target, _actionItem, true, [180, 360], _pos] call FUNC(renderMenu); [_target, _action, _pos] call FUNC(renderBaseMenu);
};
} forEach _classActions; } forEach _classActions;
}; };
}; };
@ -154,9 +146,10 @@ if(GVAR(keyDown) || GVAR(keyDownSelfAction)) then {
_foundTarget = true; _foundTarget = true;
GVAR(actionSelected) = true; GVAR(actionSelected) = true;
GVAR(selectedTarget) = (_closest select 0) select 0; GVAR(selectedTarget) = (_closest select 0) select 0;
GVAR(selectedAction) = ((_closest select 0) select 1) select 3; GVAR(selectedAction) = (((_closest select 0) select 1) select 0) select 3;
_misMatch = false; _misMatch = false;
_hoverPath = (_closest select 2); _hoverPath = (_closest select 2);
if((count GVAR(lastPath)) != (count _hoverPath)) then { if((count GVAR(lastPath)) != (count _hoverPath)) then {
_misMatch = true; _misMatch = true;
} else { } else {

View File

@ -0,0 +1,66 @@
/*
* Author: NouberNou and CAA-Picard
* Render the interaction menu for a base action
*
* Argument:
* 0: Object <OBJECT>
* 1: Action data <ARRAY>
* 2: 3D position <ARRAY> (Optional)
*
* Return value:
* Was the menu rendered <BOOL>
*
* Public: No
*/
#include "script_component.hpp"
private ["_distance","_pos","_weaponDir","_ref","_cameraPos","_sPos","_activeActionTree"];
EXPLODE_2_PVT(_this,_object,_baseAction);
EXPLODE_1_PVT(_baseAction,_actionData);
_distance = _actionData select 5;
// Obtain a 3D position for the action
if((count _this) > 2) then {
_pos = _this select 2;
} else {
if(typeName (_actionData select 2) == "ARRAY") then {
_pos = _object modelToWorld (_actionData select 2);
} else {
if ((_actionData select 2) == "weapon") then {
// Craft a suitable position for weapon interaction
_weaponDir = _object weaponDirection currentWeapon _object;
_ref = _weaponDir call EFUNC(common,createOrthonormalReference);
_pos = (_object modelToWorld (_object selectionPosition "righthand")) vectorAdd ((_ref select 2) vectorMultiply 0.1);
} else {
_pos = _object modelToWorld (_object selectionPosition (_actionData select 2));
};
};
};
// For non-self actions, exit if the action is too far away
_cameraPos = positionCameraToWorld [0, 0, 0];
if (GVAR(keyDown) && {_cameraPos distance _pos >= _distance}) exitWith {false};
// Exit if the action is behind you
_sPos = worldToScreen _pos;
if(count _sPos == 0) exitWith {false};
// Exit if the action is off screen
if ((_sPos select 0) < safeZoneXAbs || (_sPos select 0) > safeZoneXAbs + safeZoneWAbs) exitWith {false};
if ((_sPos select 1) < safeZoneY || (_sPos select 1) > safeZoneY + safeZoneH) exitWith {false};
// Collect active tree
// @todo: cache activeActionTree?
_activeActionTree = ([_object, _baseAction] call FUNC(collectActiveActionTree));
// Check if there's something left for rendering
if (count _activeActionTree == 0) exitWith {false};
//EXPLODE_2_PVT(_activeActionTree,_actionData,_actionChildren);
[_object, _activeActionTree, _pos, [180,360]] call FUNC(renderMenu);
true

View File

@ -40,7 +40,6 @@ if(count _sPos > 0) then {
if(_icon == "") then { if(_icon == "") then {
_icon = DEFAULT_ICON; _icon = DEFAULT_ICON;
}; };
//systemChat format ["Ctrl: %1, %2,%3", _text,_sPos select 0, _sPos select 1];
_text = format ["<img image='%1' color='%2' align='center'/><br/><t color ='%3' size='0.75' align='center'>%4</t>", _icon, _color, _color, _text]; _text = format ["<img image='%1' color='%2' align='center'/><br/><t color ='%3' size='0.75' align='center'>%4</t>", _icon, _color, _color, _text];
_ctrl ctrlSetStructuredText (parseText _text); _ctrl ctrlSetStructuredText (parseText _text);
_ctrl ctrlSetPosition [(_sPos select 0)-(0.2*SafeZoneW), (_sPos select 1)-(0.0095*SafeZoneW), 0.4*SafeZoneW, 0.035*SafeZoneW]; _ctrl ctrlSetPosition [(_sPos select 0)-(0.2*SafeZoneW), (_sPos select 1)-(0.0095*SafeZoneW), 0.4*SafeZoneW, 0.035*SafeZoneW];

View File

@ -1,70 +1,32 @@
/* /*
* Author: NouberNou and CAA-Picard * Author: NouberNou and CAA-Picard
* Render a interaction menu and it's children recursively * Render an interaction menu and it's children recursively
* *
* Argument: * Argument:
* 0: Object <OBJECT> * 0: Object <OBJECT>
* 1: Action data <ARRAY> * 1: Action data <ARRAY>
* 2: Was the condition already checked? <BOOL> * 2: 3D position <ARRAY>
* 3: Angle range available for rendering <ARRAY> * 3: Angle range available for rendering <ARRAY>
* 4: 3D position <ARRAY> (Optional)
* *
* Return value: * Return value:
* Was the menu rendered <BOOL> * None
* *
* Public: No * Public: No
*/ */
#include "script_component.hpp" #include "script_component.hpp"
private ["_distance", "_uid", "_pos", "_cameraPos", "_path", "_menuDepth", "_opacity", "_currentRenderDepth", "_radialOffset", "_active", "_x", "_offset", "_newPos", "_forEachIndex"]; private ["_menuInSelectedPath", "_path", "_menuDepth", "_currentRenderDepth", "_x", "_offset", "_newPos", "_forEachIndex"];
EXPLODE_4_PVT(_this,_object,_actionData,_wasConditionChecked,_angles); EXPLODE_4_PVT(_this,_object,_action,_pos,_angles);
EXPLODE_2_PVT(_action,_actionData,_activeChildren);
EXPLODE_2_PVT(_angles,_centerAngle,_maxAngleSpan); EXPLODE_2_PVT(_angles,_centerAngle,_maxAngleSpan);
_uid = _actionData select 7;
_distance = _actionData select 5;
// Obtain a 3D position for the action
if((count _this) > 4) then {
_pos = _this select 4;
} else {
if(typeName (_actionData select 2) == "ARRAY") then {
_pos = _object modelToWorld (_actionData select 2);
} else {
if ((_actionData select 2) == "weapon") then {
// Craft a suitable position for weapon interaction
_weaponDir = _object weaponDirection currentWeapon _object;
_ref = _weaponDir call EFUNC(common,createOrthonormalReference);
_pos = (_object modelToWorld (_object selectionPosition "righthand")) vectorAdd ((_ref select 2) vectorMultiply 0.1);
} else {
_pos = _object modelToWorld (_object selectionPosition (_actionData select 2));
};
};
};
// For non-self actions, exit if the action is too far away
_cameraPos = positionCameraToWorld [0, 0, 0];
if (GVAR(keyDown) && {_cameraPos distance _pos >= _distance}) exitWith {false};
// Exit if the action is behind you
_sPos = worldToScreen _pos;
if(count _sPos == 0) exitWith {false};
// Exit if the action is off screen
if ((_sPos select 0) < safeZoneXAbs || (_sPos select 0) > safeZoneXAbs + safeZoneWAbs) exitWith {false};
if ((_sPos select 1) < safeZoneY || (_sPos select 1) > safeZoneY + safeZoneH) exitWith {false};
// If the condition was not checked, check it and exit if needed
if (!_wasConditionChecked && {!([_target, ACE_player] call (_actionItem select 4))}) exitWith {false};
_menuDepth = (count GVAR(menuDepthPath)) - 1; _menuDepth = (count GVAR(menuDepthPath)) - 1;
// Store path to action // Store path to action
_path = [_object]; _path = [_object] + (_actionData select 7);
_path = _path + (_actionData select 8);
// Check if the menu is on the selected path // Check if the menu is on the selected path
private "_menuInSelectedPath";
_menuInSelectedPath = true; _menuInSelectedPath = true;
{ {
if (_forEachIndex >= (count GVAR(menuDepthPath))) exitWith { if (_forEachIndex >= (count GVAR(menuDepthPath))) exitWith {
@ -93,10 +55,6 @@ GVAR(currentOptions) pushBack [_this, _pos, _path];
// Exit without rendering children if it isn't // Exit without rendering children if it isn't
if !(_menuInSelectedPath) exitWith {true}; if !(_menuInSelectedPath) exitWith {true};
// Collect all active children actions
private "_activeChildren";
_activeChildren = [_object,_actionData] call FUNC(collectActiveChildren);
private ["_angleSpan","_angle"]; private ["_angleSpan","_angle"];
_angleSpan = _maxAngleSpan min (55 * ((count _activeChildren) - 1)); _angleSpan = _maxAngleSpan min (55 * ((count _activeChildren) - 1));
if (_angleSpan >= 305) then { if (_angleSpan >= 305) then {
@ -109,12 +67,12 @@ _angle = _centerAngle - _angleSpan / 2;
_player = ACE_player; _player = ACE_player;
_offset = [GVAR(vecLineMap), _angle] call FUNC(rotateVectLine); _offset = [GVAR(vecLineMap), _angle] call FUNC(rotateVectLine);
_mod = (0.15 max (0.15 * (_cameraPos distance _pos))) / GVAR(selfMenuScale); _mod = (0.15 max (0.15 * ((positionCameraToWorld [0, 0, 0]) distance _pos))) / GVAR(selfMenuScale);
_newPos = _pos vectorAdd (_offset vectorMultiply _mod); _newPos = _pos vectorAdd (_offset vectorMultiply _mod);
//drawLine3D [_pos, _newPos, [1,0,0,0.5]]; //drawLine3D [_pos, _newPos, [1,0,0,0.5]];
[_object, _x, true, [_angle, 140], _newPos] call FUNC(renderMenu); [_object, _x, _newPos, [_angle, 140]] call FUNC(renderMenu);
if (_angleSpan == 360) then { if (_angleSpan == 360) then {
_angle = _angle + _angleSpan / (count _activeChildren); _angle = _angle + _angleSpan / (count _activeChildren);