diff --git a/addons/cargo/CfgVehicles.hpp b/addons/cargo/CfgVehicles.hpp index 8406028bf2..0dd59720dc 100644 --- a/addons/cargo/CfgVehicles.hpp +++ b/addons/cargo/CfgVehicles.hpp @@ -222,6 +222,8 @@ class CfgVehicles { }; class Heli_Transport_04_base_F: Helicopter_Base_H { + // note the double brackets are because loadmasterTurrets is an array of arrays / turret paths + GVAR(loadmasterTurrets)[] = {{1}}; GVAR(space) = 0; GVAR(hasCargo) = 0; }; diff --git a/addons/cargo/XEH_PREP.hpp b/addons/cargo/XEH_PREP.hpp index 9ccd0d587d..8224ec0029 100644 --- a/addons/cargo/XEH_PREP.hpp +++ b/addons/cargo/XEH_PREP.hpp @@ -14,6 +14,7 @@ PREP(makeLoadable); PREP(moduleMakeLoadable); PREP(moduleSettings); PREP(onMenuOpen); +PREP(paradropItem); PREP(startLoadIn); PREP(startUnload); PREP(unloadItem); diff --git a/addons/cargo/XEH_postInit.sqf b/addons/cargo/XEH_postInit.sqf index 58a009c9f5..6b7320d5ae 100644 --- a/addons/cargo/XEH_postInit.sqf +++ b/addons/cargo/XEH_postInit.sqf @@ -1,6 +1,7 @@ #include "script_component.hpp" ["ace_addCargo", {_this call FUNC(addCargoItem)}] call CBA_fnc_addEventHandler; +[QGVAR(paradropItem), {_this call FUNC(paradropItem)}] call CBA_fnc_addEventHandler; ["ace_loadCargo", { params ["_item", "_vehicle"]; diff --git a/addons/cargo/functions/fnc_initVehicle.sqf b/addons/cargo/functions/fnc_initVehicle.sqf index 2dfc8b796b..3b5571f260 100644 --- a/addons/cargo/functions/fnc_initVehicle.sqf +++ b/addons/cargo/functions/fnc_initVehicle.sqf @@ -48,6 +48,7 @@ private _condition = { }; private _statement = { GVAR(interactionVehicle) = _target; + GVAR(interactionParadrop) = false; createDialog QGVAR(menu); }; private _text = localize LSTRING(openMenu); @@ -55,3 +56,24 @@ private _icon = ""; private _action = [QGVAR(openMenu), _text, _icon, _statement, _condition] call EFUNC(interact_menu,createAction); [_type, 0, ["ACE_MainActions"], _action] call EFUNC(interact_menu,addActionToClass); + +// Add the paradrop self interaction for planes and helicopters +if (_vehicle isKindOf "Air") then { + private _condition = { + GVAR(enable) && {[_player, _target, []] call EFUNC(common,canInteractWith)} && { + private _turretPath = _player call CBA_fnc_turretPath; + (_player == (driver _target)) || // pilot + {(getNumber (([_target, _turretPath] call CBA_fnc_getTurret) >> "isCopilot")) == 1} || // coPilot + {_turretPath in (getArray (configFile >> "CfgVehicles" >> (typeOf _target) >> QGVAR(loadmasterTurrets)))}} // loadMaster turret from config + }; + private _statement = { + GVAR(interactionVehicle) = _target; + GVAR(interactionParadrop) = true; + createDialog QGVAR(menu); + }; + private _text = localize LSTRING(openMenu); + private _icon = ""; + + private _action = [QGVAR(openMenu), _text, _icon, _statement, _condition] call EFUNC(interact_menu,createAction); + [_type, 1, ["ACE_SelfActions"], _action] call EFUNC(interact_menu,addActionToClass); // self action on the vehicle +}; diff --git a/addons/cargo/functions/fnc_onMenuOpen.sqf b/addons/cargo/functions/fnc_onMenuOpen.sqf index a9f558ac76..852729e529 100644 --- a/addons/cargo/functions/fnc_onMenuOpen.sqf +++ b/addons/cargo/functions/fnc_onMenuOpen.sqf @@ -21,6 +21,10 @@ params ["_display"]; uiNamespace setVariable [QGVAR(menuDisplay), _display]; +if (GVAR(interactionParadrop)) then { + (_display displayCtrl 12) ctrlSetText (localize LSTRING(paradropButton)); +}; + [{ disableSerialization; private _display = uiNamespace getVariable QGVAR(menuDisplay); @@ -28,7 +32,7 @@ uiNamespace setVariable [QGVAR(menuDisplay), _display]; [_this select 1] call CBA_fnc_removePerFrameHandler; }; - if (isNull GVAR(interactionVehicle) || {ACE_player distance GVAR(interactionVehicle) >= 10}) exitWith { + if (isNull GVAR(interactionVehicle) || {(ACE_player distance GVAR(interactionVehicle) >= 10) && {(vehicle ACE_player) != GVAR(interactionVehicle)}}) exitWith { closeDialog 0; [_this select 1] call CBA_fnc_removePerFrameHandler; }; diff --git a/addons/cargo/functions/fnc_paradropItem.sqf b/addons/cargo/functions/fnc_paradropItem.sqf new file mode 100644 index 0000000000..deec93b95e --- /dev/null +++ b/addons/cargo/functions/fnc_paradropItem.sqf @@ -0,0 +1,93 @@ +/* + * Author: marc_book, commy2, CAA-Picard + * Unload and paradrop object from plane or helicopter. + * + * Arguments: + * 0: Object + * 1: Vehicle + * + * Return value: + * Object unloaded + * + * Example: + * [object, vehicle] call ace_cargo_fnc_paradropItem + * + * Public: No + */ +#include "script_component.hpp" + +params ["_item", "_vehicle"]; +TRACE_2("params",_item,_vehicle); + +private _loaded = _vehicle getVariable [QGVAR(loaded), []]; + +if !(_item in _loaded) exitWith {false}; + +// unload item from cargo +_loaded deleteAt (_loaded find _item); +_vehicle setVariable [QGVAR(loaded), _loaded, true]; + +private _cargoSpace = [_vehicle] call FUNC(getCargoSpaceLeft); +private _itemSize = [_item] call FUNC(getSizeItem); +_vehicle setVariable [QGVAR(space), (_cargoSpace + _itemSize), true]; + +(boundingBoxReal q2) params ["_bb1", "_bb2"]; +private _distBehind = ((_bb1 select 1) min (_bb2 select 1)) - 3; // 3 meters behind max bounding box +TRACE_1("",_distBehind); +private _posBehindVehicleAGL = _vehicle modelToWorld [0, _distBehind, -1]; + + +private _itemObject = if (_item isEqualType objNull) then { + detach _item; + // hideObjectGlobal must be executed before setPos to ensure light objects are rendered correctly + // do both on server to ensure they are executed in the correct order + [QGVAR(serverUnload), [_item, _posBehindVehicleAGL]] call CBA_fnc_serverEvent; + _item +} else { + private _newItem = createVehicle [_item, _posBehindVehicleAGL, [], 0, ""]; + _newItem setPosASL (AGLtoASL _posBehindVehicleAGL); + _newItem +}; + +_newItem setVelocity ((velocity _vehicle) vectorAdd ((vectorNormalized (vectorDir _vehicle)) vectorMultiply 10)); + +// open parachute and ir light effect +[{ + params ["_item"]; + + if (isNull _item || {getPos _item select 2 < 1}) exitWith {}; + + private _itemPosASL = getPosASL _item; + private _itemVelocity = velocity _item; + private _parachute = createVehicle ["B_Parachute_02_F", [0,0,0], [], 0, "CAN_COLLIDE"]; + + _item attachTo [_parachute, [0,0,0.2]]; + _parachute setPosASL _itemPosASL; + _parachute setVelocity _itemVelocity; + + private _light = "Chemlight_yellow" createVehicle [0,0,0]; + _light attachTo [_item, [0,0,0]]; + +}, [_itemObject], 0.7] call CBA_fnc_waitAndExecute; + +// smoke effect when crate landed +[{ + (_this select 0) params ["_item"]; + + if (isNull _item) exitWith { + [_this select 1] call CBA_fnc_removePerFrameHandler; + }; + + if (getPos _item select 2 < 1) then { + private _smoke = "SmokeshellYellow" createVehicle [0,0,0]; + _smoke attachTo [_item, [0,0,0]]; + + [_this select 1] call CBA_fnc_removePerFrameHandler; + }; + +}, 1, [_itemObject]] call CBA_fnc_addPerFrameHandler; + +// Invoke listenable event +["ace_cargoUnloaded", [_item, _vehicle, "paradrop"]] call CBA_fnc_globalEvent; + +true diff --git a/addons/cargo/functions/fnc_startUnload.sqf b/addons/cargo/functions/fnc_startUnload.sqf index 8f2dcfb2e2..8631449b9e 100644 --- a/addons/cargo/functions/fnc_startUnload.sqf +++ b/addons/cargo/functions/fnc_startUnload.sqf @@ -30,7 +30,37 @@ private _selected = (lbCurSel _ctrl) max 0; if (count _loaded <= _selected) exitWith {}; private _item = _loaded select _selected; //This can be an object or a classname string -// Start progress bar +if (GVAR(interactionParadrop)) exitWith { + // Start progress bar - paradrop + private _size = [_item] call FUNC(getSizeItem); + [ + 2.5 * _size, + [_item, GVAR(interactionVehicle), ACE_player], + { + (_this select 0) params ["_item", "_target", "_player"]; + [QGVAR(paradropItem), [_item, _target]] call CBA_fnc_localEvent; + }, + { + params ["_args", "", "", "_errorCode"]; // show warning if we failed because of flight conditions + if (_errorCode == 3) then { + _args params ["_item", "_target", "_player"]; + [localize LSTRING(unlevelFlightWarning)] call EFUNC(common,displayTextStructured); + }; + }, + localize LSTRING(UnloadingItem), + { + (_this select 0) params ["_item", "_target", "_player"]; + if ((acos ((vectorUp _target) select 2)) > 30) exitWith {false}; // check flight level + if (((getPos _target) select 2) < 25) exitWith {false}; // check height + if ((speed _target) < -5) exitWith {false}; // check reverse + true + }, + ["isNotSwimming", "isNotInside"] + ] call EFUNC(common,progressBar); +}; + + +// Start progress bar - normal ground unload if ([_item, GVAR(interactionVehicle), ACE_player] call FUNC(canUnloadItem)) then { private _size = [_item] call FUNC(getSizeItem); diff --git a/addons/cargo/menu.hpp b/addons/cargo/menu.hpp index aa23edd2e3..0a32d2bcdb 100644 --- a/addons/cargo/menu.hpp +++ b/addons/cargo/menu.hpp @@ -68,7 +68,7 @@ class GVAR(menu) { colorSelectBackground2[] = {0.3, 0.3, 0.3, 1.0}; }; class btnCancel: ACE_gui_buttonBase { - text = "Cancel"; + text = "$STR_DISP_CANCEL"; idc = 11; x = "13.1 * (((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX + (safezoneW - ((safezoneW / safezoneH) min 1.2))/2)"; y = "14.1 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + (safezoneY + (safezoneH - (((safezoneW / safezoneH) min 1.2) / 1.2))/2)"; diff --git a/addons/cargo/stringtable.xml b/addons/cargo/stringtable.xml index de5f7ab1e9..251220fd1c 100644 --- a/addons/cargo/stringtable.xml +++ b/addons/cargo/stringtable.xml @@ -201,5 +201,13 @@ Tamanho do objeto Размер объекта + + Airdrop + Türlast + + + Unlevel Flight + Schieflage + \ No newline at end of file