diff --git a/addons/attach/$PBOPREFIX$ b/addons/attach/$PBOPREFIX$ index 1e4e48a4ca8..71a2f40af8c 100644 --- a/addons/attach/$PBOPREFIX$ +++ b/addons/attach/$PBOPREFIX$ @@ -1 +1 @@ -z\ace\Addons\laser \ No newline at end of file +z\ace\Addons\attach \ No newline at end of file diff --git a/addons/attach/CfgEventHandlers.hpp b/addons/attach/CfgEventHandlers.hpp index 5eca7fa129f..4c2b8b16ca1 100644 --- a/addons/attach/CfgEventHandlers.hpp +++ b/addons/attach/CfgEventHandlers.hpp @@ -1,5 +1,5 @@ class Extended_PreInit_EventHandlers { - class ADDON { - init = QUOTE( call COMPILE_FILE(XEH_preInit) ); - }; + class ADDON { + init = QUOTE( call COMPILE_FILE(XEH_preInit) ); + }; }; \ No newline at end of file diff --git a/addons/attach/CfgMagazines.hpp b/addons/attach/CfgMagazines.hpp index 293a075d708..282d36b9640 100644 --- a/addons/attach/CfgMagazines.hpp +++ b/addons/attach/CfgMagazines.hpp @@ -1,10 +1,10 @@ class CfgMagazines { - class CA_Magazine; - class B_IR_Grenade: CA_Magazine { - ACE_Attachable = 1; - }; - class SmokeShell; - class Chemlight_green: SmokeShell { - ACE_Attachable = 1; - }; + class CA_Magazine; + class B_IR_Grenade: CA_Magazine { + ACE_Attachable = 1; + }; + class SmokeShell; + class Chemlight_green: SmokeShell { + ACE_Attachable = 1; + }; }; \ No newline at end of file diff --git a/addons/attach/CfgVehicles.hpp b/addons/attach/CfgVehicles.hpp index a8653b9e068..bc1f52988a5 100644 --- a/addons/attach/CfgVehicles.hpp +++ b/addons/attach/CfgVehicles.hpp @@ -1,104 +1,147 @@ #define MACRO_ADDITEM(ITEM,COUNT) class _xx_##ITEM { \ - name = #ITEM; \ - count = COUNT; \ -}; + name = #ITEM; \ + count = COUNT; \ + }; + +#define MACRO_ATTACHTOVEHICLE \ + class ACE_Actions { \ + class GVAR(AttachVehicle) { \ + displayName = "$STR_ACE_Attach_AttachDetach"; \ + condition = QUOTE(([ARR_3(_player, _target, '')] call FUNC(canAttach))); \ + statement = QUOTE( [ARR_2(_player, _target)] call FUNC(openAttachUI);); \ + exceptions[] = {"ACE_Drag_isNotDragging"}; \ + showDisabled = 0; \ + priority = 0; \ + icon = PATHTOF(UI\attach_ca.paa); \ + distance = 4; \ + }; \ + class GVAR(DetachVehicle) { \ + displayName = "$STR_ACE_Attach_Detach"; \ + condition = QUOTE(([ARR_2(_player, _target)] call FUNC(canDetach))); \ + statement = QUOTE( [ARR_2(_player, _target)] call FUNC(detach) ); \ + exceptions[] = {"ACE_Drag_isNotDragging"}; \ + showDisabled = 0; \ + priority = 0; \ + icon = PATHTOF(UI\detach_ca.paa); \ + distance = 4; \ + }; \ + }; class CfgVehicles { - class Man; - class CAManBase: Man { - class ACE_SelfActions { - class ACE_Equipment { - class GVAR(Attach) { - displayName = "$STR_ACE_Attach_AttachDetach"; - condition = QUOTE( [_player, ''] call FUNC(canAttach) ); - statement = QUOTE( [_player] call FUNC(openAttachUI); ); - exceptions[] = {"ACE_Drag_isNotDragging"}; - showDisabled = 0; - priority = 5; - icon = PATHTOF(UI\attach_ca.paa); - hotkey = "T"; - }; - class GVAR(Detach) { - displayName = "$STR_ACE_Attach_Detach"; - condition = QUOTE( [_player] call FUNC(canDetach) ); - statement = QUOTE( [_player] call FUNC(detach) ); - exceptions[] = {"ACE_Drag_isNotDragging"}; - showDisabled = 0; - priority = 5; - icon = PATHTOF(UI\detach_ca.paa); - hotkey = "T"; + class LandVehicle; + class Car: LandVehicle { + MACRO_ATTACHTOVEHICLE + }; + class Tank: LandVehicle { + MACRO_ATTACHTOVEHICLE + }; + class Air; + class Helicopter: Air { + MACRO_ATTACHTOVEHICLE + }; + class Plane: Air { + MACRO_ATTACHTOVEHICLE + }; + class Ship; + class Ship_F: Ship { + MACRO_ATTACHTOVEHICLE + }; + + class Man; + class CAManBase: Man { + class ACE_SelfActions { + class ACE_Equipment { + class GVAR(Attach) { + displayName = "$STR_ACE_Attach_AttachDetach"; + condition = QUOTE(([ARR_3(_player, _player, '')] call FUNC(canAttach))); + statement = QUOTE( [ARR_2(_player, _player)] call FUNC(openAttachUI); ); + exceptions[] = {"ACE_Drag_isNotDragging"}; + showDisabled = 0; + priority = 5; + icon = PATHTOF(UI\attach_ca.paa); + hotkey = "T"; + }; + class GVAR(Detach) { + displayName = "$STR_ACE_Attach_Detach"; + condition = QUOTE(([ARR_2(_player, _player)] call FUNC(canDetach))); + statement = QUOTE( [ARR_2(_player, _player)] call FUNC(detach) ); + exceptions[] = {"ACE_Drag_isNotDragging"}; + showDisabled = 0; + priority = 5; + icon = PATHTOF(UI\detach_ca.paa); + hotkey = "T"; + }; + }; }; - }; }; - }; - class All; - class ACE_IR_Strobe_Effect: All { - scope = 1; - displayName = "IR Strobe"; - model = "\A3\Weapons_F\empty.p3d"; - simulation = "nvmarker"; + class All; + class ACE_IR_Strobe_Effect: All { + scope = 1; + displayName = "IR Strobe"; + model = "\A3\Weapons_F\empty.p3d"; + simulation = "nvmarker"; - class NVGMarker { - diffuse[] = {0,0,0}; - ambient[] = {0,0,0}; - brightness = 0.004; - name = "pozicni blik"; - drawLight = 1; - drawLightSize = 0.005; - drawLightCenterSize = 0.003; - activeLight = 0; - blinking=1; - dayLight = 0; - onlyInNvg = 1; - useFlare = 0; + class NVGMarker { + diffuse[] = {0,0,0}; + ambient[] = {0,0,0}; + brightness = 0.004; + name = "pozicni blik"; + drawLight = 1; + drawLightSize = 0.005; + drawLightCenterSize = 0.003; + activeLight = 0; + blinking=1; + dayLight = 0; + onlyInNvg = 1; + useFlare = 0; + }; + side = 7;//-1=NO_SIDE yellow box,3=CIV grey box,4=NEUTRAL yellow box,6=FRIENDLY green box,7=LOGIC no radar signature + accuracy = 1000; + cost = 0; + armor = 500; + threat[] = {0,0,0}; + nameSound = ""; + type = 0; + weapons[] = {}; + magazines[] = {}; + nvTarget = 1; + destrType = "DestructNo"; + brightness = 20; }; - side = 7;//-1=NO_SIDE yellow box,3=CIV grey box,4=NEUTRAL yellow box,6=FRIENDLY green box,7=LOGIC no radar signature - accuracy = 1000; - cost = 0; - armor = 500; - threat[] = {0,0,0}; - nameSound = ""; - type = 0; - weapons[] = {}; - magazines[] = {}; - nvTarget = 1; - destrType = "DestructNo"; - brightness = 20; - }; - class NATO_Box_Base; - class EAST_Box_Base; - class IND_Box_Base; - class FIA_Box_Base_F; + class NATO_Box_Base; + class EAST_Box_Base; + class IND_Box_Base; + class FIA_Box_Base_F; - class Box_NATO_Support_F: NATO_Box_Base { - class TransportItems { - MACRO_ADDITEM(ACE_IR_Strobe_Item,12) + class Box_NATO_Support_F: NATO_Box_Base { + class TransportItems { + MACRO_ADDITEM(ACE_IR_Strobe_Item,12) + }; }; - }; - class Box_East_Support_F: EAST_Box_Base { - class TransportItems { - MACRO_ADDITEM(ACE_IR_Strobe_Item,12) + class Box_East_Support_F: EAST_Box_Base { + class TransportItems { + MACRO_ADDITEM(ACE_IR_Strobe_Item,12) + }; }; - }; - class Box_IND_Support_F: IND_Box_Base { - class TransportItems { - MACRO_ADDITEM(ACE_IR_Strobe_Item,12) + class Box_IND_Support_F: IND_Box_Base { + class TransportItems { + MACRO_ADDITEM(ACE_IR_Strobe_Item,12) + }; }; - }; - class Box_FIA_Support_F: FIA_Box_Base_F { - class TransportItems { - MACRO_ADDITEM(ACE_IR_Strobe_Item,12) + class Box_FIA_Support_F: FIA_Box_Base_F { + class TransportItems { + MACRO_ADDITEM(ACE_IR_Strobe_Item,12) + }; }; - }; - class ACE_Box_Misc: Box_NATO_Support_F { - class TransportItems { - MACRO_ADDITEM(ACE_IR_Strobe_Item,12) + class ACE_Box_Misc: Box_NATO_Support_F { + class TransportItems { + MACRO_ADDITEM(ACE_IR_Strobe_Item,12) + }; }; - }; }; \ No newline at end of file diff --git a/addons/attach/CfgWeapons.hpp b/addons/attach/CfgWeapons.hpp index 65ca397ec94..8174f67b386 100644 --- a/addons/attach/CfgWeapons.hpp +++ b/addons/attach/CfgWeapons.hpp @@ -1,16 +1,16 @@ class CfgWeapons { - class ACE_ItemCore; - class InventoryItem_Base_F; + class ACE_ItemCore; + class InventoryItem_Base_F; - class ACE_IR_Strobe_Item: ACE_ItemCore { - displayName = "$STR_ACE_IrStrobe_Name"; - descriptionShort = "$STR_ACE_IrStrobe_Description"; - model = "\A3\weapons_F\ammo\mag_univ.p3d"; - picture = PATHTOF(UI\irstrobe_item.paa); - scope = 2; - ACE_attachable = 1; - class ItemInfo: InventoryItem_Base_F { - mass = 1; + class ACE_IR_Strobe_Item: ACE_ItemCore { + displayName = "$STR_ACE_IrStrobe_Name"; + descriptionShort = "$STR_ACE_IrStrobe_Description"; + model = "\A3\weapons_F\ammo\mag_univ.p3d"; + picture = PATHTOF(UI\irstrobe_item.paa); + scope = 2; + ACE_attachable = 1; + class ItemInfo: InventoryItem_Base_F { + mass = 1; + }; }; - }; }; \ No newline at end of file diff --git a/addons/attach/README.md b/addons/attach/README.md index 7ac36f109d4..5fb73d0645b 100644 --- a/addons/attach/README.md +++ b/addons/attach/README.md @@ -1,7 +1,8 @@ ace_attach ========== -Introducing the ability to attach various throwables to yourself to mark your position and assist in IFF. +Introducing the ability to attach various throwables to yourself or vehicles, to mark your position and assist in IFF. +Adds item `ACE_IR_Strobe_Item`. ## Maintainers @@ -11,3 +12,4 @@ The people responsible for merging changes to this component or answering potent - [esteldunedain](https://github.com/esteldunedain) - [bux578](https://github.com/bux578) - [KoffeinFlummi](https://github.com/KoffeinFlummi) +- [PabstMirror](https://github.com/PabstMirror) diff --git a/addons/attach/XEH_preInit.sqf b/addons/attach/XEH_preInit.sqf index 279ea4d4c72..63eb2e8438c 100644 --- a/addons/attach/XEH_preInit.sqf +++ b/addons/attach/XEH_preInit.sqf @@ -7,5 +7,7 @@ PREP(canAttach); PREP(canDetach); PREP(detach); PREP(openAttachUI); +PREP(placeApprove); +PREP(placeCancel); ADDON = true; diff --git a/addons/attach/config.cpp b/addons/attach/config.cpp index 4143f6eb44d..9accc9f253b 100644 --- a/addons/attach/config.cpp +++ b/addons/attach/config.cpp @@ -1,15 +1,15 @@ #include "script_component.hpp" class CfgPatches { - class ADDON { - units[] = {}; - weapons[] = {"ACE_IR_Strobe_Item"}; - requiredVersion = REQUIRED_VERSION; - requiredAddons[] = {"ace_common", "ace_interaction"}; - author[] = {"KoffeinFlummi", "eRazeri", "CAA-Picard"}; - authorUrl = "https://github.com/KoffeinFlummi/"; - VERSION_CONFIG; - }; + class ADDON { + units[] = {}; + weapons[] = {"ACE_IR_Strobe_Item"}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = {"ace_common", "ace_interaction"}; + author[] = {"KoffeinFlummi", "eRazeri", "CAA-Picard"}; + authorUrl = "https://github.com/KoffeinFlummi/"; + VERSION_CONFIG; + }; }; #include "CfgEventHandlers.hpp" diff --git a/addons/attach/functions/fnc_attach.sqf b/addons/attach/functions/fnc_attach.sqf index ab920c64282..9fd0cf79520 100644 --- a/addons/attach/functions/fnc_attach.sqf +++ b/addons/attach/functions/fnc_attach.sqf @@ -1,62 +1,88 @@ +/* + * Author: eRazeri and CAA-Picard + * Attach an item to the unit + * + * Arguments: + * 0: unit doing the attach (player) + * 1: vehicle that it will be attached to (player or vehicle) + * 2: Name of the attachable item + * + * Return Value: + * Nothing + * + * Example: + * Nothing + * + * Public: No + */ #include "script_component.hpp" -/* -Author: eRazeri and CAA-Picard +PARAMS_3(_unit,_attachToVehicle,_itemName); -Attach an item to the unit +//Sanity Check (_unit has item in inventory, not over attach limit) +if (!([_unit,_attachToVehicle,_itemName] call FUNC(canAttach))) exitWith {ERROR("Tried to attach, but check failed");}; -Arguments: -0: unit -1: Item name +_selfAttachPosition = [_unit, [-0.05,0,0.12], "rightshoulder"]; +_itemVehClass = ""; +_onAtachText = ""; -Return Value: -none -*/ +switch true do { +case (_itemName == "ACE_IR_Strobe_Item"): { + _itemVehClass = "ACE_IR_Strobe_Effect"; + _onAtachText = localize "STR_ACE_Attach_IrStrobe_Attached"; + _selfAttachPosition = [_unit,[0,-0.11,0.16],"pilot"]; //makes it attach to the head a bit better, shoulder is not good for visibility - eRazeri + }; +case (_itemName == "B_IR_Grenade"): { + _itemVehClass = "B_IRStrobe"; + _onAtachText = localize "STR_ACE_Attach_IrGrenade_Attached"; + }; +case (_itemName == "O_IR_Grenade"): { + _itemVehClass = "O_IRStrobe"; + _onAtachText = localize "STR_ACE_Attach_IrGrenade_Attached"; + }; +case (_itemName == "I_IR_Grenade"): { + _itemVehClass = "I_IRStrobe"; + _onAtachText = localize "STR_ACE_Attach_IrGrenade_Attached"; + }; +case (_itemName == "Chemlight_blue" or {_itemName == "Chemlight_green"} or {_itemName == "Chemlight_red"} or {_itemName == "Chemlight_yellow"}): { + _itemVehClass = _itemName; + _onAtachText = localize "STR_ACE_Attach_Chemlight_Attached"; + }; +}; -private ["_unit", "_itemName", "_attachedItem"]; +if (_itemVehClass == "") exitWith {ERROR("no _itemVehClass for Item");}; -_unit = _this select 0; -_itemName = _this select 1; +if (_unit == _attachToVehicle) then { //Self Attachment + _unit removeItem _itemName; // Remove item + _attachedItem = _itemVehClass createVehicle [0,0,0]; + _attachedItem attachTo _selfAttachPosition; + [_onAtachText] call EFUNC(common,displayTextStructured); + _attachToVehicle setVariable ["ACE_AttachedObjects", [_attachedItem], true]; + _attachToVehicle setVariable ["ACE_AttachedItemNames", [_itemName], true]; +} else { + GVAR(setupObject) = _itemVehClass createVehicleLocal [0,0,-10000]; + GVAR(setupObject) enableSimulationGlobal false; + GVAR(SetupPlacmentText) = _onAtachText; + GVAR(SetupPlacmentItem) = _itemName; + GVAR(SetupAttachVehicle) = _attachToVehicle; + GVAR(placer) = _unit; + [_unit, QGVAR(vehAttach), true] call EFUNC(common,setForceWalkStatus); -// Check if unit has an attached item -if (_unit getVariable [QGVAR(ItemName), ""] != "") exitWith {}; + [QGVAR(PlacementEachFrame),"OnEachFrame", { + private "_player"; + _player = ACE_player; + //Stop if player switch or player gets to far from vehicle + if ((GVAR(placer) != _player) || {(_player distance GVAR(SetupAttachVehicle)) > 7}) exitWith { + call FUNC(placeCancel); + }; + GVAR(pfeh_running) = true; + _pos = (ASLtoATL eyePos _player) vectorAdd (positionCameraToWorld [0,0,1] vectorDiff positionCameraToWorld [0,0,0]); + GVAR(setupObject) setPosATL _pos; + }] call BIS_fnc_addStackedEventHandler; -// Check if the unit still has the item -if !((_itemName in items _unit) or (_itemName in magazines _unit)) exitWith {}; + //had to delay the mouseHint, not sure why + [{[localize "STR_ACE_Attach_PlaceAction", localize "STR_ACE_Attach_CancelAction"] call EFUNC(interaction,showMouseHint)}, [], 0, 0] call EFUNC(common,waitAndExecute); -// Attach item -switch true do { - case (_itemName == "ACE_IR_Strobe_Item") : { - _attachedItem = "ACE_IR_Strobe_Effect" createVehicle [0,0,0]; - _attachedItem attachTo [_unit,[0,-0.11,0.16],"pilot"];//makes it attach to the head a bit better, shoulder is not good for visibility - eRazeri - [localize "STR_ACE_Attach_IrStrobe_Attached"] call EFUNC(common,displayTextStructured); - }; - case (_itemName == "B_IR_Grenade") : { - _attachedItem = "B_IRStrobe" createVehicle [0,0,0]; - _attachedItem attachTo [_unit,[-0.05,0,0.12],"rightshoulder"]; - [localize "STR_ACE_Attach_IrGrenade_Attached"] call EFUNC(common,displayTextStructured); - }; - case (_itemName == "O_IR_Grenade") : { - _attachedItem = "O_IRStrobe" createVehicle [0,0,0]; - _attachedItem attachTo [_unit,[-0.05,0,0.12],"rightshoulder"]; - [localize "STR_ACE_Attach_IrGrenade_Attached"] call EFUNC(common,displayTextStructured); - }; - case (_itemName == "I_IR_Grenade") : { - _attachedItem = "I_IRStrobe" createVehicle [0,0,0]; - _attachedItem attachTo [_unit,[-0.05,0,0.12],"rightshoulder"]; - [localize "STR_ACE_Attach_IrGrenade_Attached"] call EFUNC(common,displayTextStructured); - }; - case (_itemName == "Chemlight_blue" or {_itemName == "Chemlight_green"} or {_itemName == "Chemlight_red"} or {_itemName == "Chemlight_yellow"}) : { - _attachedItem = _itemName createVehicle [0,0,0]; - _attachedItem attachTo [_unit,[-0.05,0,0.12],"rightshoulder"]; - [localize "STR_ACE_Attach_Chemlight_Attached"] call EFUNC(common,displayTextStructured);; - }; - default { - if (true) exitWith {}; - }; + _unit setVariable [QGVAR(placeActionEH), [_unit, "DefaultAction", {GVAR(pfeh_running) AND !isNull (GVAR(setupObject))}, {call FUNC(placeApprove);}] call EFUNC(common,AddActionEventHandler)]; + _unit setVariable [QGVAR(cancelActionEH), [_unit, "MenuBack", {GVAR(pfeh_running) AND !isNull (GVAR(setupObject))}, {call FUNC(placeCancel);}] call EFUNC(common,AddActionEventHandler)]; }; - -// Remove item -_unit removeItem _itemName; -_unit setVariable [QGVAR(ItemName), _itemName, true]; -_unit setVariable [QGVAR(Item), _attachedItem, true]; diff --git a/addons/attach/functions/fnc_canAttach.sqf b/addons/attach/functions/fnc_canAttach.sqf index fe5191d7e28..ac646ef7009 100644 --- a/addons/attach/functions/fnc_canAttach.sqf +++ b/addons/attach/functions/fnc_canAttach.sqf @@ -1,21 +1,25 @@ -#include "script_component.hpp" - /* * Author: commy2 - * * Check if a unit can attach a specific item. - * - * Argument: - * 0: Unit that wants to attach the object (Object) - * 1: Name of the attachable item (String) - * - * Return value: - * Boolean (Bool) + * + * Arguments: + * 0: unit doing the attach (player) + * 1: vehicle that it will be attached to (player or vehicle) + * 2: Name of the attachable item + * + * Return Value: + * Boolean + * + * Example: + * Nothing + * + * Public: No */ +#include "script_component.hpp" -private ["_unit", "_item"]; +PARAMS_3(_unit,_attachToVehicle,_item); -_unit = _this select 0; -_item = _this select 1; +_attachLimit = if (_unit == _attachToVehicle) then {1} else {10}; +_attachedObjects = _attachToVehicle getVariable ["ACE_AttachedObjects", []]; -canStand _unit && {_unit getVariable [QGVAR(ItemName), ""] == ""} && {_item in (magazines _unit + items _unit + [""])} +canStand _unit && {alive _attachToVehicle} && {(count _attachedObjects) < _attachLimit} && {_item in ((magazines _unit) + (items _unit) + [""])} diff --git a/addons/attach/functions/fnc_canDetach.sqf b/addons/attach/functions/fnc_canDetach.sqf index 3ddfc6c11e4..d099d2035e8 100644 --- a/addons/attach/functions/fnc_canDetach.sqf +++ b/addons/attach/functions/fnc_canDetach.sqf @@ -1,19 +1,39 @@ -#include "script_component.hpp" - /* * Author: commy2 - * * Check if a unit has an item attached and if it can remove that item. - * - * Argument: - * 0: Unit that wants to detach something (Object) - * - * Return value: - * Boolean (Bool) + * + * Arguments: + * 0: unit doing the detaching (player) + * 1: vehicle that it will be detached from (player or vehicle) + * + * Return Value: + * Boolean + * + * Example: + * Nothing + * + * Public: No */ +#include "script_component.hpp" + +private ["_attachedObjects", "_inRange", "_unitPos", "_objectPos"]; + +PARAMS_2(_unit,_attachToVehicle); -private "_unit"; +_attachedObjects = _attachToVehicle getVariable ["ACE_AttachedObjects", []]; -_unit = _this select 0; +_inRange = false; +if (_unit == _attachToVehicle) then { + _inRange = (count _attachedObjects) > 0; +} else { + //Scan if unit is within range (using 2d distance) + _unitPos = getPos _unit; + _unitPos set [2,0]; + { + _objectPos = getPos _x; + _objectPos set [2, 0]; + if ((_objectPos distance _unitPos) < 4) exitWith {_inRange = true}; + } forEach _attachedObjects; +}; -canStand _unit && {_unit getVariable [QGVAR(ItemName), ""] != ""} +(canStand _unit) && _inRange && {alive _attachToVehicle} diff --git a/addons/attach/functions/fnc_detach.sqf b/addons/attach/functions/fnc_detach.sqf index 3ecac44d626..b18cec09bd3 100644 --- a/addons/attach/functions/fnc_detach.sqf +++ b/addons/attach/functions/fnc_detach.sqf @@ -1,63 +1,86 @@ -#include "script_component.hpp" - /* -Author: eRazeri and CAA-Picard + * Author: eRazeri and CAA-Picard + * Detach an item from a unit + * + * Arguments: + * 0: unit doing the attaching (player) + * 1: vehicle that it will be detached from (player or vehicle) + * + * Return Value: + * Nothing + * + * Example: + * Nothing + * + * Public: No + */ +#include "script_component.hpp" -Detach an item from a unit +private ["_itemName", "_count", "_attachedItem", "_fnc_detachDelay"]; -Arguments: -unit +PARAMS_2(_unit,_attachToVehicle); -Return Value: -none -*/ +_attachedObjectsArray = _attachToVehicle getVariable ["ACE_AttachedObjects", []]; +_attachedItemsArray = _attachToVehicle getVariable ["ACE_AttachedItemNames", []]; -private ["_unit", "_itemName", "_count", "_attachedItem", "_fnc_detachDelay"]; +_attachedObject = objNull; +_attachedIndex = -1; +_itemName = ""; -_unit = _this select 0; -_itemName = _unit getVariable [QGVAR(ItemName), ""]; -_attachedItem = _unit getVariable [QGVAR(Item), objNull]; +//Find closest attached object +_minDistance = 1000; +_unitPos = getPos _unit; +_unitPos set [2,0]; +{ + _objectPos = getPos _x; + _objectPos set [2, 0]; + if ((_objectPos distance _unitPos) < _minDistance) then { + _minDistance = (_objectPos distance _unitPos); + _attachedObject = _x; + _itemName = _attachedItemsArray select _forEachIndex; + _attachedIndex = _forEachIndex; + }; +} forEach _attachedObjectsArray; // Check if unit has an attached item -if (_itemName == "") exitWith {}; +if ((isNull _attachedObject) || {_itemName == ""}) exitWith {ERROR("Could not find attached object")}; // Add item to inventory _count = (count items _unit) + (count magazines _unit); _unit addItem _itemName; if ((count items _unit) + (count magazines _unit) <= _count) exitWith { - [localize "STR_ACE_Attach_Inventory_Full"] call EFUNC(common,displayTextStructured); + [localize "STR_ACE_Attach_Inventory_Full"] call EFUNC(common,displayTextStructured); }; if (_itemName == "B_IR_Grenade" or _itemName == "O_IR_Grenade" or _itemName == "I_IR_Grenade") then { - // Hack for dealing with X_IR_Grenade effect not dissapearing on deleteVehicle - detach _attachedItem; - _attachedItem setPos [getPos _unit select 0, getPos _unit select 1, ((getPos _unit select 2) - 1000)]; - // Delete attached item after 0.5 seconds - _fnc_detachDelay = { - deleteVehicle (_this select 0); - }; - [_fnc_detachDelay, [_attachedItem], 0.5, 0] call EFUNC(common,waitAndExecute); + // Hack for dealing with X_IR_Grenade effect not dissapearing on deleteVehicle + detach _attachedObject; + _attachedObject setPos [getPos _unit select 0, getPos _unit select 1, ((getPos _unit select 2) - 1000)]; + // Delete attached item after 0.5 seconds + _fnc_detachDelay = { + deleteVehicle (_this select 0); + }; + [_fnc_detachDelay, [_attachedObject], 0.5, 0] call EFUNC(common,waitAndExecute); } else { - // Delete attached item - deleteVehicle _attachedItem; + // Delete attached item + deleteVehicle _attachedObject; }; // Reset unit variables -_unit setVariable [QGVAR(ItemName),"", true]; -_unit setVariable [QGVAR(Item),nil, true]; +_attachedObjectsArray deleteAt _attachedIndex; +_attachedItemsArray deleteAt _attachedIndex; +_attachToVehicle setVariable ["ACE_AttachedObjects", _attachedObjectsArray, true]; +_attachToVehicle setVariable ["ACE_AttachedItemNames", _attachedItemsArray, true]; // Display message switch true do { - case (_itemName == "ACE_IR_Strobe_Item") : { - [localize "STR_ACE_Attach_IrStrobe_Detached"] call EFUNC(common,displayTextStructured); - }; - case (_itemName == "B_IR_Grenade" or _itemName == "O_IR_Grenade" or _itemName == "I_IR_Grenade") : { - [localize "STR_ACE_Attach_IrGrenade_Detached"] call EFUNC(common,displayTextStructured); - }; - case (_itemName == "Chemlight_blue" or {_itemName == "Chemlight_green"} or {_itemName == "Chemlight_red"} or {_itemName == "Chemlight_yellow"}) : { - [localize "STR_ACE_Attach_Chemlight_Detached"] call EFUNC(common,displayTextStructured); - }; - default { - if (true) exitWith {}; - }; +case (_itemName == "ACE_IR_Strobe_Item") : { + [localize "STR_ACE_Attach_IrStrobe_Detached"] call EFUNC(common,displayTextStructured); + }; +case (_itemName == "B_IR_Grenade" or _itemName == "O_IR_Grenade" or _itemName == "I_IR_Grenade") : { + [localize "STR_ACE_Attach_IrGrenade_Detached"] call EFUNC(common,displayTextStructured); + }; +case (_itemName == "Chemlight_blue" or {_itemName == "Chemlight_green"} or {_itemName == "Chemlight_red"} or {_itemName == "Chemlight_yellow"}) : { + [localize "STR_ACE_Attach_Chemlight_Detached"] call EFUNC(common,displayTextStructured); + }; }; diff --git a/addons/attach/functions/fnc_openAttachUI.sqf b/addons/attach/functions/fnc_openAttachUI.sqf index 97046fa80b2..6521e43fbe8 100644 --- a/addons/attach/functions/fnc_openAttachUI.sqf +++ b/addons/attach/functions/fnc_openAttachUI.sqf @@ -1,63 +1,67 @@ -#include "script_component.hpp" - /* - Author: Garth de Wet (LH) - - Description: - Opens the UI for attaching objects. + * Author: Garth de Wet (LH) + * Opens the UI for attaching objects. + * + * Arguments: + * 0: unit + * 1: target + * + * Return Value: + * Nothing + * + * Example: + * Nothing + * + * Public: No + */ +#include "script_component.hpp" - Parameters: - 0: OBJECT - unit +private ["_actions", "_attachables", "_item"]; - Returns: - Nothing +PARAMS_2(_unit,_target); - Example: - [player] call ACE_Attach_fnc_openAttachUI; -*/ -private ["_unit", "_actions", "_attachables", "_item"]; -_unit = _this select 0; +GVAR(attachTarget) = _target; _listed = []; _attachables = magazines _unit; _actions = [localize "STR_ACE_Attach_AttachDetach", localize "STR_ACE_Attach_Attach"] call EFUNC(interaction,prepareSelectMenu); { - if !(_x in _listed) then { - _item = ConfigFile >> "CfgMagazines" >> _x; - if (getNumber (_item >> "ACE_Attachable") == 1) then { - _actions = [ - _actions, - getText(_item >> "displayName"), - getText(_item >> "picture"), - _x - ] call EFUNC(interaction,addSelectableItem); + if !(_x in _listed) then { + _item = ConfigFile >> "CfgMagazines" >> _x; + if (getNumber (_item >> "ACE_Attachable") == 1) then { + _actions = [ + _actions, + getText(_item >> "displayName"), + getText(_item >> "picture"), + _x + ] call EFUNC(interaction,addSelectableItem); + }; + _listed pushBack _x; }; - _listed pushBack _x; - }; } forEach _attachables; _attachables = items _unit; { - if !(_x in _listed) then { - _item = ConfigFile >> "CfgWeapons" >> _x; - if (getNumber (_item >> "ACE_Attachable") == 1) then { - _actions = [ - _actions, - getText(_item >> "displayName"), - getText(_item >> "picture"), - _x - ] call EFUNC(interaction,addSelectableItem); + if !(_x in _listed) then { + _item = ConfigFile >> "CfgWeapons" >> _x; + if (getNumber (_item >> "ACE_Attachable") == 1) then { + _actions = [ + _actions, + getText(_item >> "displayName"), + getText(_item >> "picture"), + _x + ] call EFUNC(interaction,addSelectableItem); + }; + _listed pushBack _x; }; - _listed pushBack _x; - }; } forEach _attachables; [ - _actions, - { - [ACE_player, _this] call FUNC(attach); +_actions, +{ + [ACE_player, GVAR(attachTarget), _this] call FUNC(attach); call EFUNC(interaction,hideMenu); - }, - { +}, +{ call EFUNC(interaction,hideMenu); if !(profileNamespace getVariable [QEGVAR(interaction,AutoCloseMenu), false]) then {"Default" call EFUNC(interaction,openMenuSelf)}; - } +} ] call EFUNC(interaction,openSelectMenu); diff --git a/addons/attach/functions/fnc_placeApprove.sqf b/addons/attach/functions/fnc_placeApprove.sqf new file mode 100644 index 00000000000..ceb48de9b52 --- /dev/null +++ b/addons/attach/functions/fnc_placeApprove.sqf @@ -0,0 +1,110 @@ +/* + * Author: Pabst Mirror (based on Explosive attach by Garth de Wet (LH)) + * Approves placement of the lightObject, scans for an appropriate location and attaches + * + * Arguments: + * Nothing + * + * Return Value: + * Nothing + * + * Example: + * Nothing + * + * Public: No + */ +#include "script_component.hpp" + +private ["_setupObject", "_setupClassname", "_itemClassname", "_placementText", "_attachToVehicle", "_placer", "_startingPosition", "_startingOffset", "_distanceFromCenter", "_closeInUnitVector", "_keepGoingCloser", "_closeInDistance", "_endPosTestOffset", "_endPosTest", "_startingPosShifted", "_startASL", "_endPosShifted", "_endASL", "_attachedObject", "_currentObjects", "_currentItemNames"]; + + +if (GVAR(pfeh_running)) then { + [QGVAR(PlacementEachFrame),"OnEachFrame"] call BIS_fnc_removeStackedEventHandler; + GVAR(pfeh_running) = false; +}; + +_setupObject = GVAR(setupObject); +_setupClassname = typeOf _setupObject; +_itemClassname = GVAR(SetupPlacmentItem); +_placementText = GVAR(SetupPlacmentText); +_attachToVehicle = GVAR(SetupAttachVehicle); +_placer = GVAR(placer); + +GVAR(SetupPlacmentItem) = ""; +GVAR(SetupPlacmentText) = ""; +GVAR(setupObject) = objNull; +GVAR(SetupAttachVehicle) = objNull; +GVAR(placer) = objNull; + +[_placer, QGVAR(vehAttach), false] call EFUNC(common,setForceWalkStatus); +[_placer, "DefaultAction", _placer getVariable [QGVAR(placeActionEH), -1]] call EFUNC(common,removeActionEventHandler); +[_placer, "MenuBack", _placer getVariable [QGVAR(cancelActionEH), -1]] call EFUNC(common,removeActionEventHandler); +call EFUNC(interaction,hideMouseHint); + +//A player can release the attachObject with it floating in mid-air. +//This will use lineIntersectsWith to scan towards the center of the vehicle to find a collision +//ArmA's collision detection is of couse terrible and often misses collisions (difference between what we see and collision LOD) +//So it does multiple scans at slighly different angles +//This is VERY computationaly intensive, but doesn't happen that often. + +_startingPosition = _setupObject modelToWorld [0,0,0]; +_startingOffset = _attachToVehicle worldToModel _startingPosition; + +_distanceFromCenter = vectorMagnitude _startingOffset; +_closeInUnitVector = vectorNormalized (_startingOffset vectorFromTo [0,0,0]); +_keepGoingCloser = true; +_closeInDistance = 0; + +while {_keepGoingCloser} do { + if (_closeInDistance >= _distanceFromCenter) exitWith {}; + + _closeInDistance = _closeInDistance + 0.01; //10mm each step + _endPosTestOffset = _startingOffset vectorAdd (_closeInUnitVector vectorMultiply _closeInDistance); + _endPosTestOffset set [2, (_startingOffset select 2)]; + _endPosTest = _attachToVehicle modelToWorld _endPosTestOffset; + + { + _startingPosShifted = _startingPosition vectorAdd _x; + _startASL = if (surfaceIsWater _startingPosShifted) then {_startingPosShifted} else {ATLtoASL _startingPosShifted}; + { + _endPosShifted = _endPosTest vectorAdd _x; + _endASL = if (surfaceIsWater _startingPosShifted) then {_endPosShifted} else {ATLtoASL _endPosShifted}; + + //Uncomment to see the lazor show, and see how the scanning works: + drawLine3D [_startingPosShifted, _endPosShifted, [1,0,0,1]]; + + if (_attachToVehicle in lineIntersectsWith [_startASL, _endASL, _placer, _setupObject]) exitWith {_keepGoingCloser = false}; + } forEach [[0,0,0.045], [0,0,-0.045], [0,0.045,0], [0,-0.045,0], [0.045,0,0], [-0.045,0,0]]; + } forEach [[0,0,0], [0,0,0.05], [0,0,-0.05]]; +}; + +//Delete Local Placement Object +deleteVehicle _setupObject; + +//Checks +if ((_closeInDistance >= _distanceFromCenter) || (!([_placer,_attachToVehicle,_itemClassname] call FUNC(canAttach)))) exitWith { + TRACE_2("no valid spot found",_closeInDistance,_distanceFromCenter); + [localize "STR_ACE_Attach_Failed"] call EFUNC(common,displayTextStructured); +}; + +//Move it out slightly, for visability sake (better to look a little funny than be embedded//sunk in the hull) +_closeInDistance = (_closeInDistance - 0.0085); + +//Create New 'real' Object +_endPosTestOffset = _startingOffset vectorAdd (_closeInUnitVector vectorMultiply _closeInDistance); +_endPosTestOffset set [2, (_startingOffset select 2)]; +_attachedObject = _setupClassname createVehicle (getPos _placer); +_attachedObject attachTo [_attachToVehicle, _endPosTestOffset]; + +//Remove Item from inventory +_placer removeItem _itemClassname; + +//Add Object to ACE_AttachedObjects and ACE_AttachedItemNames +_currentObjects = _attachToVehicle getVariable ["ACE_AttachedObjects", []]; +_currentObjects pushBack _attachedObject; +_attachToVehicle setVariable ["ACE_AttachedObjects", _currentObjects, true]; +_currentItemNames = _attachToVehicle getVariable ["ACE_AttachedItemNames", []]; +_currentItemNames pushBack _itemClassname; +_attachToVehicle setVariable ["ACE_AttachedItemNames", _currentItemNames, true]; + +[_placementText] call EFUNC(common,displayTextStructured); diff --git a/addons/attach/functions/fnc_placeCancel.sqf b/addons/attach/functions/fnc_placeCancel.sqf new file mode 100644 index 00000000000..3abdf848bac --- /dev/null +++ b/addons/attach/functions/fnc_placeCancel.sqf @@ -0,0 +1,35 @@ +/* + * Author: Pabst Mirror (based on Explosive attach by Garth de Wet (LH)) + * Cancels placement of the lightObject + * + * Arguments: + * Nothing + * + * Return Value: + * Nothing + * + * Example: + * Nothing + * + * Public: No + */ +#include "script_component.hpp" + +if (GVAR(pfeh_running)) then { + [QGVAR(PlacementEachFrame),"OnEachFrame"] call BIS_fnc_removeStackedEventHandler; + GVAR(pfeh_running) = false; +}; +if (!isNull (GVAR(setupObject))) then { + deleteVehicle GVAR(setupObject); +}; + +[GVAR(placer), QGVAR(vehAttach), false] call EFUNC(common,setForceWalkStatus); +call EFUNC(interaction,hideMouseHint); +[GVAR(placer), "DefaultAction", GVAR(placer) getVariable [QGVAR(placeActionEH), -1]] call EFUNC(common,removeActionEventHandler); +[GVAR(placer), "MenuBack", GVAR(placer) getVariable [QGVAR(cancelActionEH), -1]] call EFUNC(common,removeActionEventHandler); + +GVAR(placer) = objNull; +GVAR(SetupPlacmentItem) = ""; +GVAR(SetupPlacmentText) = ""; +GVAR(setupObject) = objNull; +GVAR(SetupAttachVehicle) = objNull; diff --git a/addons/attach/stringtable.xml b/addons/attach/stringtable.xml index 877f26e6238..21577c55d38 100644 --- a/addons/attach/stringtable.xml +++ b/addons/attach/stringtable.xml @@ -1,5 +1,5 @@  - + @@ -146,5 +146,34 @@ Az infravörös jeladóval megjelölheted a helyzetedet úgy, hogy annak pulzáló fénye csak éjjellátó készülékkel látható. ИК строб позволяет сигнализировать свое местоположение через пульсирующий маяк, видимый только через ПНВ. + + Place + Platzieren + Colocar + Umieść + Placer + Položit + Colocar + Posiziona + Elhelyez + + + Cancel + Abbrechen + Cancelar + Anuluj + Annuler + Zrušit + Cancelar + Annulla + Mégse + + + Attach Failed + Échec du Attacher + Befestigen Fehlgeschlagen + Присоединить Ошибка + Error en Acoplar + \ No newline at end of file