diff --git a/addons/attached_objects/XEH_PREP.hpp b/addons/attached_objects/XEH_PREP.hpp index 4e7ef7ea5..f29deb750 100644 --- a/addons/attached_objects/XEH_PREP.hpp +++ b/addons/attached_objects/XEH_PREP.hpp @@ -1,4 +1,7 @@ PREP(attach); +PREP(attachBone); +PREP(attachToSelection); PREP(detach); PREP(handleObjectEdited); +PREP(parseSelectionName); PREP(module); diff --git a/addons/attached_objects/functions/fnc_attachBone.sqf b/addons/attached_objects/functions/fnc_attachBone.sqf new file mode 100644 index 000000000..062e323d5 --- /dev/null +++ b/addons/attached_objects/functions/fnc_attachBone.sqf @@ -0,0 +1,91 @@ +#include "script_component.hpp" +/* + * Author: Ampersand + * Attaches the given objects to a parent object selected by Zeus. + * + * Arguments: + * 0: Objects + * 1: Is Bone + * + * Return Value: + * None + * + * Example: + * [_object] call zen_attached_objects_fnc_attachBone + * + * Public: No + */ + +[_this, { + params ["_successful", "_objects"]; + + if (!_successful) exitWith {}; + + curatorMouseOver params ["_type", "_entity"]; + if (_type isNotEqualTo "OBJECT") exitWith {}; + + // Prevent attaching object to itself + private _index = _objects find _entity; + + if (_index != -1 && {count _objects == 1}) exitWith { + [LSTRING(CannotAttachToSelf)] call EFUNC(common,showMessage); + }; + + _objects deleteAt _index; + + if (isNil QGVAR(modelSelections)) then { + GVAR(modelSelections) = createHashMap; + }; + + private _entries = GVAR(modelSelections) getOrDefaultCall [getText (configOf _entity >> "model"), { + private _turretsCfg = allTurrets _entity apply {[_entity, _x] call CBA_fnc_getTurret}; + private _selections = _entity selectionNames LOD_MEMORY select { + _entity selectionVectorDirAndUp [_x, LOD_MEMORY] isNotEqualTo [[0,0,0], [0,0,0]] + }; + [ + [""] + (_turretsCfg apply {getText (_x >> "memoryPointGunnerOptics")}) + _selections, + [""] + (_turretsCfg apply {configName _x}) + _selections apply {[_x] call FUNC(parseSelectionName)} + ] + }, true]; + + [LSTRING(AttachTo), [ + [ + "COMBO", + LSTRING(Bone), + _entries + ], + [ + "TOOLBOX", + [LSTRING(Orientation), LSTRING(Orientation_Description)], + [true, 1, 2, [LSTRING(Bone), LSTRING(Relative)]], + true + ] + ], { + params ["_values", "_args"]; + _values params ["_selection", "_isRelative"]; + _args params ["_objects", "_entity"]; + + if (_selection isEqualTo "") then { + { + private _dirAndUp = [_entity vectorWorldToModel vectorDir _x, _entity vectorWorldToModel vectorUp _x]; + _x attachTo [_entity]; + [QEGVAR(common,setVectorDirAndUp), [_x, _dirAndUp], _x] call CBA_fnc_targetEvent; + } forEach _objects; + } else { + { + [_x, _entity, _selection, _isRelative] call FUNC(attachToSelection); + } forEach _objects; + + private _hintPos = _entity modelToWorldVisual (_entity selectionPosition [_selection, LOD_MEMORY]); + _entity selectionVectorDirAndUp [_selection, LOD_MEMORY] params ["_selectionY", "_selectionZ"]; + [[ + ["ICON", [_hintPos, "\a3\ui_f\data\IGUI\Cfg\Targeting\LaserTarget_ca.paa"]], + ["LINE", [_hintPos, _entity vectorModelToWorldVisual _selectionY vectorMultiply 2 vectorAdd _hintPos, [0, 1, 0, 1]]], + ["LINE", [_hintPos, _entity vectorModelToWorldVisual _selectionZ vectorAdd _hintPos, [0, 0, 1, 1]]] + ], 3, _entity] call EFUNC(common,drawHint); + }; + + [LSTRING(ObjectsAttached), count _objects] call EFUNC(common,showMessage); + }, {}, [_objects, _entity]] call EFUNC(dialog,create); + +}, [], LSTRING(AttachTo)] call EFUNC(common,selectPosition); diff --git a/addons/attached_objects/functions/fnc_attachToSelection.sqf b/addons/attached_objects/functions/fnc_attachToSelection.sqf new file mode 100644 index 000000000..5d4d42569 --- /dev/null +++ b/addons/attached_objects/functions/fnc_attachToSelection.sqf @@ -0,0 +1,47 @@ +#include "script_component.hpp" +/* + * Author: Ampersand + * Attaches the child object to a selection on a parent object. + * + * Arguments: + * 0: Child + * 1: Parent + * 2: Selection + * 3: Relative True to maintain current relative orientation, false to match selection orientation + * + * Return Value: + * 0: Selection Position and Orientation For drawing hints + * + * Example: + * [_child] call zen_attached_objects_fnc_attachToSelection + * + * Public: No + */ + +params ["_child", "_parent", "_selection", ["_isRelative", true]]; + +if (!isNull attachedTo _child) then {detach _child;}; + +private _childPos = _parent worldToModel ASLToAGL getPosWorldVisual _child; +private _childY = _parent vectorWorldToModelVisual vectorDirVisual _child; +private _childZ = _parent vectorWorldToModelVisual vectorUpVisual _child; +private _childX = _childY vectorCrossProduct _childZ; + +private _selectionPos = _parent selectionPosition [_selection, LOD_MEMORY]; +private _offset = _childPos vectorDiff _selectionPos; +_parent selectionVectorDirAndUp [_selection, LOD_MEMORY] params ["_selectionY", "_selectionZ"]; +private _selectionX = _selectionY vectorCrossProduct _selectionZ; + +private _m = matrixTranspose [_selectionX, _selectionY, _selectionZ]; +private _pos = flatten ([_offset] matrixMultiply _m); +_child attachTo [_parent, _pos, _selection, true]; + +_child setVariable [QGVAR(attachedToSelection), _selection, true]; + +if (_isRelative) then { + [_childX, _childY, _childZ] matrixMultiply _m params ["", "_vY", "_vZ"]; + _child setVectorDirAndUp [_vY, _vZ]; + [QEGVAR(common,setVectorDirAndUp), [_child, [_vY, _vZ]], _child] call CBA_fnc_targetEvent; +}; + +[_selectionPos, _selectionY, _selectionZ] diff --git a/addons/attached_objects/functions/fnc_handleObjectEdited.sqf b/addons/attached_objects/functions/fnc_handleObjectEdited.sqf index f7a6697b4..c157b5c3b 100644 --- a/addons/attached_objects/functions/fnc_handleObjectEdited.sqf +++ b/addons/attached_objects/functions/fnc_handleObjectEdited.sqf @@ -21,7 +21,11 @@ params ["", "_object"]; // Update the position of attached objects relative to their parent object private _parentObject = attachedTo _object; -if (!isNull _parentObject && {isVehicleCargo _object != _parentObject}) then { +if (isNull _parentObject || {isVehicleCargo _object == _parentObject}) exitWith {}; + +private _selection = _object getVariable [QGVAR(attachedToSelection), ""]; + +if (_selection == "") then { private _offset = _parentObject worldToModel ASLtoAGL getPosWorld _object; private _dirAndUp = [vectorDir _object, vectorUp _object] apply {_parentObject vectorWorldToModel _x}; @@ -31,4 +35,6 @@ if (!isNull _parentObject && {isVehicleCargo _object != _parentObject}) then { _object attachTo [_parentObject, _offset]; [QEGVAR(common,setVectorDirAndUp), [_object, _dirAndUp], _object] call CBA_fnc_targetEvent; +} else { + [_object, _parentObject, _selection, true] call FUNC(attachToSelection); }; diff --git a/addons/attached_objects/functions/fnc_module.sqf b/addons/attached_objects/functions/fnc_module.sqf index b8a4d971d..f081b6a05 100644 --- a/addons/attached_objects/functions/fnc_module.sqf +++ b/addons/attached_objects/functions/fnc_module.sqf @@ -26,7 +26,7 @@ if (isNull _object) exitWith { // Start attaching if not already attached, otherwise detach if (isNull attachedTo _object) then { - [_object] call FUNC(attach); + [_object] call FUNC(attachBone); } else { [_object] call FUNC(detach); }; diff --git a/addons/attached_objects/functions/fnc_parseSelectionName.sqf b/addons/attached_objects/functions/fnc_parseSelectionName.sqf new file mode 100644 index 000000000..d9957be66 --- /dev/null +++ b/addons/attached_objects/functions/fnc_parseSelectionName.sqf @@ -0,0 +1,49 @@ +#include "script_component.hpp" +/* + * Author: Ampersand + * Attempt to translate Czech selection names. + * + * Arguments: + * 0: Selection Name + * + * Return Value: + * 0: Translated Name + * + * Example: + * [_selection] call zen_attached_objects_fnc_parseSelectionName + * + * Public: No + */ + +params ["_selection"]; + +{ + _selection = _selection regexReplace [_x, localize (LSTRING(Czech) + _x) + " "]; +} forEach [ + "hlavne", + "hlaven", + "kola", + "konec", + "leveho", + "leve", + "nabojnice", + "optika", + "osa", + "otoc", + "poklop", + "praveho", + "prave", + "predniho", + "raketa", + "slapek", + "slapky", + "smerovky", + "svetlo", + "vejskovky", + "velitele", + "veze", + "vez", + "vrtule" +]; + +(_selection splitString " _") joinString " " diff --git a/addons/attached_objects/functions/script_component.hpp b/addons/attached_objects/functions/script_component.hpp index 24f0d1da1..31cca736a 100644 --- a/addons/attached_objects/functions/script_component.hpp +++ b/addons/attached_objects/functions/script_component.hpp @@ -1 +1,3 @@ #include "\x\zen\addons\attached_objects\script_component.hpp" + +#define LOD_MEMORY 1e15 diff --git a/addons/attached_objects/initKeybinds.sqf b/addons/attached_objects/initKeybinds.sqf index abadcb817..e329c6046 100644 --- a/addons/attached_objects/initKeybinds.sqf +++ b/addons/attached_objects/initKeybinds.sqf @@ -5,6 +5,13 @@ }; }, {}, [DIK_A, [true, true, false]]] call CBA_fnc_addKeybind; // Default: CTRL + SHIFT + A +[[ELSTRING(main,DisplayName), LSTRING(DisplayName)], QGVAR(attachBone), [LSTRING(AttachBone), LSTRING(AttachBone_Description)], { + if (!isNull curatorCamera && {!GETMVAR(RscDisplayCurator_search,false)}) then { + SELECTED_OBJECTS call FUNC(attachBone); + true // handled + }; +}, {}, []] call CBA_fnc_addKeybind; // Default: Unbound + [[ELSTRING(main,DisplayName), LSTRING(DisplayName)], QGVAR(detach), [LSTRING(Detach), LSTRING(Detach_Description)], { if (!isNull curatorCamera && {!GETMVAR(RscDisplayCurator_search,false)}) then { SELECTED_OBJECTS call FUNC(detach); diff --git a/addons/attached_objects/stringtable.xml b/addons/attached_objects/stringtable.xml index a5b116256..79285b137 100644 --- a/addons/attached_objects/stringtable.xml +++ b/addons/attached_objects/stringtable.xml @@ -10,6 +10,24 @@ Attaches all selected objects to the specified parent object. + + Bone + + + Relative + + + Attach Objects to Bone + + + Attaches all selected objects to a bone on the specified parent object. + + + Orientation + + + Bone: match bone orientation (i.e. along gun barrel). Relative: maintain current orientation relative to bone. + Detach Objects @@ -47,5 +65,95 @@ 無法將物體附加到物體自己身上 Impossibile collegare l'oggetto a se stesso + + Barrel + + + Barrel + + + Wheel + + + End + + + Left + + + Left + + + Cartridge Case + + + Optics + + + Axis + + + Turn + + + Hatch + + + Right + + + Right + + + Nose + + + Pedals + + + Pedal + + + Rudder + + + Spike + + + Mark + + + Light + + + Elevator + + + Commander + + + Main + + + Turret + + + Turret + + + Rocket + + + Rotor + + + Muzzle + + + Aim Point + + + Rest + diff --git a/addons/modules/XEH_postInit.sqf b/addons/modules/XEH_postInit.sqf index 679f88cf6..8f55d4f32 100644 --- a/addons/modules/XEH_postInit.sqf +++ b/addons/modules/XEH_postInit.sqf @@ -115,12 +115,7 @@ if (isServer) then { }, _this] call CBA_fnc_execNextFrame; }] call CBA_fnc_addEventHandler; -[QGVAR(setRotation), { - params ["_object", "_pitch", "_roll", "_yaw"]; - - _object setDir _yaw; - [_object, _pitch, _roll] call BIS_fnc_setPitchBank; -}] call CBA_fnc_addEventHandler; +[QGVAR(setRotation), BIS_fnc_setObjectRotation] call CBA_fnc_addEventHandler; [QGVAR(moveToGunner), { params ["_unit", "_vehicle"]; diff --git a/addons/modules/functions/fnc_moduleRotateObject.sqf b/addons/modules/functions/fnc_moduleRotateObject.sqf index 04e2be298..2c3f4384f 100644 --- a/addons/modules/functions/fnc_moduleRotateObject.sqf +++ b/addons/modules/functions/fnc_moduleRotateObject.sqf @@ -35,5 +35,5 @@ private _yaw = [getDir _object] call CBA_fnc_simplifyAngle180; params ["_values", "_object"]; _values params ["_pitch", "_roll", "_yaw"]; - [QGVAR(setRotation), [_object, _pitch, _roll, _yaw], _object] call CBA_fnc_targetEvent; + [QGVAR(setRotation), [_object, [_yaw, _pitch, _roll]], _object] call CBA_fnc_targetEvent; }, {}, _object] call EFUNC(dialog,create);