diff --git a/addons/cargo/functions/fnc_paradropItem.sqf b/addons/cargo/functions/fnc_paradropItem.sqf index 961b2f7c36..2f9ae06336 100644 --- a/addons/cargo/functions/fnc_paradropItem.sqf +++ b/addons/cargo/functions/fnc_paradropItem.sqf @@ -6,6 +6,7 @@ * Arguments: * 0: Object * 1: Vehicle + * 2: Show Hint (default: true) * * Return Value: * Object unloaded @@ -16,7 +17,7 @@ * Public: No */ -params ["_item", "_vehicle"]; +params ["_item", "_vehicle", ["_showHint", true]]; TRACE_2("params",_item,_vehicle); private _loaded = _vehicle getVariable [QGVAR(loaded), []]; @@ -90,14 +91,16 @@ _itemObject setVelocity ((velocity _vehicle) vectorAdd ((vectorNormalized (vecto }, 1, [_itemObject]] call CBA_fnc_addPerFrameHandler; -[ +if (_showHint) then { [ - LSTRING(UnloadedItem), - getText (configFile >> "CfgVehicles" >> typeOf _itemObject >> "displayName"), - getText (configFile >> "CfgVehicles" >> typeOf _vehicle >> "displayName") - ], - 3 -] call EFUNC(common,displayTextStructured); + [ + LSTRING(UnloadedItem), + getText (configFile >> "CfgVehicles" >> typeOf _itemObject >> "displayName"), + getText (configFile >> "CfgVehicles" >> typeOf _vehicle >> "displayName") + ], + 3 + ] call EFUNC(common,displayTextStructured); +}; // Invoke listenable event ["ace_cargoUnloaded", [_item, _vehicle, "paradrop"]] call CBA_fnc_globalEvent; diff --git a/addons/zeus/CfgVehicles.hpp b/addons/zeus/CfgVehicles.hpp index 74095cb4a2..ace73e3bcd 100644 --- a/addons/zeus/CfgVehicles.hpp +++ b/addons/zeus/CfgVehicles.hpp @@ -186,6 +186,13 @@ class CfgVehicles { function = QFUNC(moduleLoadIntoCargo); icon = "a3\ui_f\data\IGUI\Cfg\Actions\loadVehicle_ca.paa"; }; + class GVAR(moduleCargoParadrop): GVAR(moduleBase) { + curatorCanAttach = 1; + category = QGVAR(AI); + displayName = CSTRING(moduleCargoParadrop_DisplayName); + function = QFUNC(moduleCargoParadrop); + icon = QPATHTOF(UI\Icon_Module_Zeus_ParadropCargo_ca.paa); + }; class GVAR(modulePatrolArea): GVAR(moduleBase) { curatorCanAttach = 1; category = QGVAR(AI); diff --git a/addons/zeus/XEH_PREP.hpp b/addons/zeus/XEH_PREP.hpp index 910b0db4d1..efa01be7d5 100644 --- a/addons/zeus/XEH_PREP.hpp +++ b/addons/zeus/XEH_PREP.hpp @@ -13,6 +13,7 @@ PREP(moduleAddSpareTrack); PREP(moduleAddSpareWheel); PREP(moduleAddOrRemoveFRIES); PREP(moduleCaptive); +PREP(moduleCargoParadrop); PREP(moduleConfigurePylons); PREP(moduleGarrison); PREP(moduleGlobalSetSkill); diff --git a/addons/zeus/config.cpp b/addons/zeus/config.cpp index 37cfa24dd4..932d5e09c8 100644 --- a/addons/zeus/config.cpp +++ b/addons/zeus/config.cpp @@ -54,7 +54,8 @@ class CfgPatches { }; class GVAR(cargo): ADDON { units[] = { - QGVAR(moduleLoadIntoCargo) + QGVAR(moduleLoadIntoCargo), + QGVAR(moduleCargoParadrop) }; }; class GVAR(repair): ADDON { diff --git a/addons/zeus/functions/fnc_moduleCargoParadrop.sqf b/addons/zeus/functions/fnc_moduleCargoParadrop.sqf new file mode 100644 index 0000000000..948a54a7a9 --- /dev/null +++ b/addons/zeus/functions/fnc_moduleCargoParadrop.sqf @@ -0,0 +1,71 @@ +#include "script_component.hpp" +/* + * Author: PabstMirror + * Commands the selected vehicle to paradrop all cargo at the specified location + * + * Arguments: + * 0: Module logic + * 1: Synchronized units + * 2: Activated + * + * Return Value: + * None + * + * Example: + * [LOGIC, [], true] call ace_zeus_fnc_moduleCargoParadrop + * + * Public: No + */ + +if (canSuspend) exitWith {[FUNC(moduleCargoParadrop), _this] call CBA_fnc_directCall;}; + +params ["_logic", "", "_activated"]; + +if ((!local _logic) || {!_activated}) exitWith {}; + +// Validate the module target +private _vehicle = attachedTo _logic; +private _pilot = driver _vehicle; +TRACE_4("moduleCargoParadrop placed",_logic,typeOf _vehicle,_pilot,typeOf _pilot); + +deleteVehicle _logic; // cleanup logic now, we just needed it to get the attached vehicle + +if (!(missionNamespace getVariable [QEGVAR(cargo,enable), false])) exitWith { + [LSTRING(RequiresAddon)] call FUNC(showMessage); +}; +if (isNull _vehicle) exitWith { + [LSTRING(NothingSelected)] call FUNC(showMessage); +}; +if (!(_vehicle isKindOf "Air")) exitWith { + [format ["%1 %2", localize "str_dn_aircraft", localize "str_msg_no_veh_select"]] call FUNC(showMessage); +}; +if ((!alive _vehicle) || {!alive _pilot}) exitWith { + [LSTRING(OnlyAlive)] call FUNC(showMessage); +}; +if ([_pilot] call EFUNC(common,isPlayer)) exitWith { + ["str_a3_cfgvehicles_moduleremotecontrol_f_errorPlayer"] call FUNC(showMessage); +}; +if ((_vehicle getVariable [QEGVAR(cargo,loaded), []]) isEqualTo []) exitWith { + [LSTRING(paradrop_noCargoLoaded)] call FUNC(showMessage); +}; + +[_vehicle, { + params ["_successful", "_vehicle", "_mousePosASL"]; + TRACE_3("getModuleDestination return",_successful,_vehicle,_mousePosASL); + + if ((!_successful) || {!alive _vehicle}) exitWith {}; + + private _pilot = driver _vehicle; + private _group = group _pilot; + + if ((!alive _vehicle) || {!alive _pilot} || {[_pilot] call EFUNC(common,isPlayer)}) exitWith {TRACE_2("invalid",_vehicle,_pilot);}; + + [_group] call CBA_fnc_clearWaypoints; + + private _wp = _group addWaypoint [ASLtoAGL _mousePosASL, 0]; + _wp setWaypointType "SCRIPTED"; + _wp setWaypointScript QPATHTOF(functions\DOUBLES(fnc,moduleCargoParadropWaypoint).sqf); + + TRACE_2("Waypoint Added",_wp,local _group); // Locality is handled by the waypoint + +}, localize LSTRING(moduleCargoParadrop_DisplayName), "\a3\ui_f\data\IGUI\Cfg\Cursors\select_target_ca.paa", [1,0,0,1], 45] call FUNC(getModuleDestination); diff --git a/addons/zeus/functions/fnc_moduleCargoParadropWaypoint.sqf b/addons/zeus/functions/fnc_moduleCargoParadropWaypoint.sqf new file mode 100644 index 0000000000..1b4e00960c --- /dev/null +++ b/addons/zeus/functions/fnc_moduleCargoParadropWaypoint.sqf @@ -0,0 +1,75 @@ +#include "script_component.hpp" +/* + * Author: PabstMirror + * Handles the paradrop cargo scripted waypoint (Scheduled Environment) + * + * Arguments: + * 0: Group + * 1: Waypoint Position + * + * Return Value: + * Waypoint Finished + * + * Example: + * [group, [0,0,0]] call ace_zeus_fnc_moduleCargoParadropWaypoint + * + * Public: No + */ + +params [["_vehicleGroup", grpNull, [grpNull]], ["_wpPos", [0, 0, 0], [[]], 3]]; +TRACE_2("moduleCargoParadropWaypoint",_vehicleGroup,_wpPos); + +private _vehicle = vehicle leader _vehicleGroup; +private _commander = driver _vehicle; +private _cargo = _vehicle getVariable [QEGVAR(cargo,loaded), []]; +if (!(_vehicle isKindOf "Air")) exitWith {WARNING_1("not in a air vehicle",typeOf _vehicle); true}; +if (_cargo isEqualTo []) exitWith {WARNING_1("no cargo",_cargo); true}; + +private _previousSpeedMode = speedMode _vehicleGroup; +private _nextMoveUpdate = -1; +private _closeEnoughTicks = 0; // should prevent aircraft from endlessly going in circles trying to hit a point + +// Start moving the vehicle to the drop off point +waitUntil { + sleep 0.1; + if ((!alive _vehicle) || {!alive _commander}) exitWith {true}; + + if (CBA_missionTime > _nextMoveUpdate) then { + private _heading = _vehicle getDir _wpPos; + private _movePos = _vehicle getPos [1000, _heading]; + TRACE_2("move",_vehicleGroup,_movePos); + _vehicle flyInHeight 150; + _vehicleGroup move _movePos; + _nextMoveUpdate = CBA_missionTime + 3; + }; + if ((_vehicle distance2D _wpPos) < 300) then {_closeEnoughTicks = _closeEnoughTicks + 1}; + private _leadDistance = _closeEnoughTicks * 3 + linearConversion [0, 300, (speed _vehicle), 50, 100, true]; + (_vehicle distance2D _wpPos) < _leadDistance +}; +TRACE_2("Finished primary movement",_vehicle distance2D _wpPos,_closeEnoughTicks); + +if ((!alive _vehicle) || {!alive _commander}) exitWith {TRACE_2("died",alive _vehicle, alive _commander); true}; +if (((getPos _vehicle) select 2) < 25) exitWith {TRACE_1("too low",getPos _vehicle); true}; + +// Fly level and straight +private _unloadFlightPos = _vehicle getRelPos [1000, 0]; +_vehicle flyInHeight 150; +_vehicleGroup setSpeedMode "LIMITED"; +_vehicleGroup move _unloadFlightPos; + +sleep 0.5; + +TRACE_2("Starting unload",_vehicle,_cargo); +{ + TRACE_1("cargo-paradropItem",_x); + [QEGVAR(cargo,paradropItem), [_x, _vehicle, false], _vehicle] call CBA_fnc_targetEvent; + sleep 1; +} forEach (+_cargo); // copy because array will be modified after each drop + +TRACE_1("Unload finished",_vehicle); + +sleep 0.5; +_vehicleGroup setSpeedMode _previousSpeedMode; + +TRACE_1("WP Done",_vehicle); +true diff --git a/addons/zeus/functions/fnc_moduleLoadIntoCargo.sqf b/addons/zeus/functions/fnc_moduleLoadIntoCargo.sqf index b13c0cc29b..7411c8ee9f 100644 --- a/addons/zeus/functions/fnc_moduleLoadIntoCargo.sqf +++ b/addons/zeus/functions/fnc_moduleLoadIntoCargo.sqf @@ -43,7 +43,7 @@ if (!alive _cargo) exitWith { params ["_successful", "_cargo", "_mousePosASL"]; if (!_successful) exitWith {}; - private _holder = (nearestObjects [ASLToAGL _mousePosASL, EGVAR(cargo,cargoHolderTypes), 5, true]) param [0, objNull]; // 2d distance search + private _holder = (nearestObjects [ASLToAGL _mousePosASL, EGVAR(cargo,cargoHolderTypes), 15, true]) param [0, objNull]; // 2d distance search if (isNull _holder) exitWith { [LSTRING(NothingSelected)] call FUNC(showMessage); }; diff --git a/addons/zeus/stringtable.xml b/addons/zeus/stringtable.xml index c841f28f91..2eb2efe2a5 100644 --- a/addons/zeus/stringtable.xml +++ b/addons/zeus/stringtable.xml @@ -1516,5 +1516,11 @@ "%1" menu menu "%1" + + Paradrop Cargo + + + No cargo loaded + diff --git a/addons/zeus/ui/Icon_Module_Zeus_ParadropCargo_ca.paa b/addons/zeus/ui/Icon_Module_Zeus_ParadropCargo_ca.paa new file mode 100644 index 0000000000..d1790a405b Binary files /dev/null and b/addons/zeus/ui/Icon_Module_Zeus_ParadropCargo_ca.paa differ