Skip to content

Commit

Permalink
Cargo - Add alternative unloading item from vehicle cargo (#8827)
Browse files Browse the repository at this point in the history
Co-authored-by: johnb432 <58661205+johnb432@users.noreply.github.com>
Co-authored-by: LinkIsGrim <salluci.lovi@gmail.com>
Co-authored-by: Grim <69561145+LinkIsGrim@users.noreply.github.com>
  • Loading branch information
4 people authored Feb 7, 2024
1 parent 6637a15 commit 8731bcc
Show file tree
Hide file tree
Showing 17 changed files with 506 additions and 50 deletions.
14 changes: 14 additions & 0 deletions addons/cargo/CfgEventHandlers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,17 @@ class Extended_PostInit_EventHandlers {
init = QUOTE(call COMPILE_SCRIPT(XEH_postInit));
};
};

class Extended_Killed_EventHandlers {
class CAManBase {
class ADDON {
killed = QUOTE((_this select 0) call FUNC(handleDeployInterrupt));
};
};
};

class Extended_DisplayLoad_EventHandlers {
class RscDisplayMission {
ADDON = QUOTE(_this call COMPILE_SCRIPT(XEH_missionDisplayLoad));
};
};
6 changes: 6 additions & 0 deletions addons/cargo/XEH_PREP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@ PREP(addCargoItem);
PREP(addCargoVehiclesActions);
PREP(canLoadItemIn);
PREP(canUnloadItem);
PREP(deployCancel);
PREP(deployConfirm);
PREP(getCargoSpaceLeft);
PREP(getNameItem);
PREP(getSelectedItem);
PREP(getSizeItem);
PREP(handleDestroyed);
PREP(handleDeployInterrupt);
PREP(handleScrollWheel);
PREP(initObject);
PREP(initVehicle);
PREP(loadItem);
Expand All @@ -16,6 +21,7 @@ PREP(removeCargoItem);
PREP(renameObject);
PREP(setSize);
PREP(setSpace);
PREP(startDeploy);
PREP(startLoadIn);
PREP(startUnload);
PREP(unloadCarryItem);
Expand Down
11 changes: 11 additions & 0 deletions addons/cargo/XEH_missionDisplayLoad.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "script_component.hpp"

params ["_display"];

_display displayAddEventHandler ["MouseZChanged", {(_this select 1) call FUNC(handleScrollWheel)}];
_display displayAddEventHandler ["MouseButtonDown", {
// Right clicking cancels deployment
if (_this select 1 == 1) then {
ACE_player call FUNC(handleDeployInterrupt);
};
}];
55 changes: 51 additions & 4 deletions addons/cargo/XEH_postInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
}] call CBA_fnc_addEventHandler;

["ace_unloadCargo", {
params ["_item", "_vehicle", ["_unloader", objNull]];
TRACE_3("UnloadCargo EH",_item,_vehicle,_unloader);
params ["_item", "_vehicle", ["_unloader", objNull], ["_place", []]];
TRACE_4("UnloadCargo EH",_item,_vehicle,_unloader,_place);

private _unloaded = [_item, _vehicle, _unloader] call FUNC(unloadItem); // returns true if successful
private _unloaded = [_item, _vehicle, _unloader, _place] call FUNC(unloadItem); // returns true if successful

// Show hint as feedback
private _hint = [LSTRING(unloadingFailed), LSTRING(unloadedItem)] select _unloaded;
Expand All @@ -36,13 +36,25 @@
};
}] call CBA_fnc_addEventHandler;

// Direction must be set before setting position according to wiki
[QGVAR(setDirAndUnload), {
params ["_item", "_emptyPosAGL", "_direction"];

_item setDir _direction;

[QGVAR(serverUnload), [_item, _emptyPosAGL]] call CBA_fnc_serverEvent;
}] call CBA_fnc_addEventHandler;

// 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), {
params ["_item", "_emptyPosAGL"];

_item hideObjectGlobal false;
_item setPosASL (AGLtoASL _emptyPosAGL);

[_item, "blockDamage", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
// Let objects remain invulernable for a short while after placement
[EFUNC(common,statusEffect_set), [_item, "blockDamage", QUOTE(ADDON), false], 2] call CBA_fnc_waitAndExecute;
}] call CBA_fnc_addEventHandler;

[QGVAR(paradropItem), {
Expand Down Expand Up @@ -166,3 +178,38 @@ if (isServer) then {
_bodyBag setVariable [QGVAR(customName), [_target, false, true] call EFUNC(common,getName), true];
}] call CBA_fnc_addEventHandler;
};

// Set variables, even on machines without interfaces, just to be safe
GVAR(selectedItem) = objNull;
GVAR(itemPreviewObject) = objNull;
GVAR(deployPFH) = -1;
GVAR(deployDistance) = -1;
GVAR(deployDirection) = 0;
GVAR(deployHeight) = 0;
GVAR(canDeploy) = false;

if (!hasInterface) exitWith {};

// Cancel object deployment if interact menu opened
["ace_interactMenuOpened", {ACE_player call FUNC(handleDeployInterrupt)}] call CBA_fnc_addEventHandler;

// Cancel deploy on player change. This does work when returning to lobby, but not when hard disconnecting
["unit", LINKFUNC(handleDeployInterrupt)] call CBA_fnc_addPlayerEventHandler;
["vehicle", {(_this select 0) call FUNC(handleDeployInterrupt)}] call CBA_fnc_addPlayerEventHandler;
["weapon", {(_this select 0) call FUNC(handleDeployInterrupt)}] call CBA_fnc_addPlayerEventHandler;

// When changing feature cameras, stop deployment
["featureCamera", {(_this select 0) call FUNC(handleDeployInterrupt)}] call CBA_fnc_addPlayerEventHandler;

// Handle falling unconscious while trying to deploy
["ace_unconscious", {(_this select 0) call FUNC(handleDeployInterrupt)}] call CBA_fnc_addEventHandler;

// Handle surrendering and handcuffing
["ace_captiveStatusChanged", {
params ["_unit", "_state"];

// If surrendered or handcuffed, stop deployment
if (_state) then {
_unit call FUNC(handleDeployInterrupt);
};
}] call CBA_fnc_addEventHandler;
39 changes: 39 additions & 0 deletions addons/cargo/functions/fnc_deployCancel.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include "..\script_component.hpp"
/*
* Author: Garth 'L-H' de Wet, Ruthberg, commy2, Smith
* Cancels unloading when deploying.
*
* Arguments:
* 0: Unit <OBJECT>
*
* Return Value:
* None
*
* Example:
* player call ace_cargo_fnc_deployCancel
*
* Public: No
*/

if (GVAR(deployPFH) == -1) exitWith {};

// Remove deployment pfh
GVAR(deployPFH) call CBA_fnc_removePerFrameHandler;
GVAR(deployPFH) = -1;

params ["_unit"];

// Enable running again
[_unit, "forceWalk", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
[_unit, "blockThrow", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);

// Delete placement dummy
deleteVehicle GVAR(itemPreviewObject);

// Remove mouse button actions
call EFUNC(interaction,hideMouseHint);

[_unit, "DefaultAction", _unit getVariable [QGVAR(deploy), -1]] call EFUNC(common,removeActionEventHandler);
_unit setVariable [QGVAR(deploy), -1];

_unit setVariable [QGVAR(isDeploying), false, true];
56 changes: 56 additions & 0 deletions addons/cargo/functions/fnc_deployConfirm.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include "..\script_component.hpp"
/*
* Author: Garth 'L-H' de Wet, Ruthberg, commy2, Smith
* Confirms unloading when deploying.
*
* Arguments:
* 0: Unit <OBJECT>
*
* Return Value:
* None
*
* Example:
* player call ace_cargo_fnc_deployConfirm
*
* Public: No
*/

if (GVAR(deployPFH) == -1) exitWith {};

params ["_unit"];

// Delete placement dummy and unload real item from cargo at dummy position
if (!isNull GVAR(itemPreviewObject) && {[GVAR(selectedItem), GVAR(interactionVehicle), _unit, false, true] call FUNC(canUnloadItem)}) then {
// Position is AGL for unloading event
private _position = ASLToAGL getPosASL GVAR(itemPreviewObject);
private _direction = getDir GVAR(itemPreviewObject);
private _duration = GVAR(loadTimeCoefficient) * (GVAR(selectedItem) call FUNC(getSizeItem));

// If unload time is 0, don't show a progress bar
if (_duration <= 0) exitWith {
["ace_unloadCargo", [GVAR(selectedItem), GVAR(interactionVehicle), _unit, [_position, _direction]]] call CBA_fnc_localEvent;
};

[
_duration,
[GVAR(selectedItem), GVAR(interactionVehicle), _unit, [_position, _direction]],
{
TRACE_1("deploy finish",_this);

["ace_unloadCargo", _this select 0] call CBA_fnc_localEvent;
},
{
TRACE_1("deploy fail",_this);
},
format [LLSTRING(unloadingItem), [GVAR(selectedItem), true] call FUNC(getNameItem), getText (configOf GVAR(interactionVehicle) >> "displayName")],
{
(_this select 0) params ["_item", "_vehicle", "_unit"];

[_item, _vehicle, _unit, false, true] call FUNC(canUnloadItem) // don't check for a suitable unloading position when deploying
},
["isNotSwimming"]
] call EFUNC(common,progressBar);
};

// Cleanup EHs and preview object
_unit call FUNC(deployCancel);
29 changes: 29 additions & 0 deletions addons/cargo/functions/fnc_getSelectedItem.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include "..\script_component.hpp"
/*
* Author: Glowbal, Smith
* Get selected item from cargo menu.
*
* Arguments:
* None
*
* Return Value:
* Classname of selected item or selected object <STRING> or <OBJECT> (default: nil)
*
* Example:
* call ace_cargo_fnc_getSelectedItem
*
* Public: No
*/

disableSerialization;

private _display = uiNamespace getVariable QGVAR(menuDisplay);

if (isNil "_display") exitWith {};

private _loaded = GVAR(interactionVehicle) getVariable [QGVAR(loaded), []];

if (_loaded isEqualTo []) exitWith {};

// This can be an object or a classname string
_loaded param [lbCurSel (_display displayCtrl 100), nil]
30 changes: 30 additions & 0 deletions addons/cargo/functions/fnc_handleDeployInterrupt.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "..\script_component.hpp"
/*
* Author: commy2, Smith
* Handle various interruption types.
*
* Arguments:
* 0: (New) unit <OBJECT>
* 1: Old unit (for player change) <OBJECT> (default: objNull)
*
* Return Value:
* None
*
* Example:
* player call ace_cargo_fnc_handleDeployInterrupt
*
* Public: No
*/

params ["_newPlayer", ["_oldPlayer", objNull]];
TRACE_2("params",_newPlayer,_oldPlayer);

if (!local _newPlayer) exitWith {};

if (_newPlayer getVariable [QGVAR(isDeploying), false]) then {
_newPlayer call FUNC(deployCancel);
};

if (_oldPlayer getVariable [QGVAR(isDeploying), false]) then {
_oldPlayer call FUNC(deployCancel);
};
58 changes: 58 additions & 0 deletions addons/cargo/functions/fnc_handleScrollWheel.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include "..\script_component.hpp"
/*
* Author: L-H, commy2, Smith
* Handles rotation of object to unload.
*
* Arguments:
* 0: Scroll amount <NUMBER>
*
* Return Value:
* If the scroll was handled <BOOL>
*
* Example:
* 1.2 call ace_cargo_fnc_handleScrollWheel
*
* Public: No
*/

if (GVAR(deployPFH) == -1) exitWith {false};

params ["_scrollAmount"];

private _deployedItem = GVAR(itemPreviewObject);

if (!CBA_events_control) then {
private _unit = ACE_player;

// Raise/lower
// Move deployed item 15 cm per scroll interval
_scrollAmount = _scrollAmount * 0.15;

private _position = getPosASL _deployedItem;
private _maxHeight = (_unit modelToWorldVisualWorld [0, 0, 0]) select 2;

_position set [2, ((_position select 2) + _scrollAmount min (_maxHeight + 1.5)) max _maxHeight];

// Move up/down object and reattach at current position
detach _deployedItem;

// Uses this method of selecting position because setPosATL did not have immediate effect
private _positionChange = _position vectorDiff (getPosASL _deployedItem);
private _selectionPosition = _unit worldToModel (ASLtoAGL getPosWorld _deployedItem);
_selectionPosition = _selectionPosition vectorAdd _positionChange;
_deployedItem attachTo [_unit, _selectionPosition];

// Reset the deploy direction
private _direction = _deployedItem getVariable [QGVAR(deployDirection_temp), 0];
_deployedItem setDir _direction;
} else {
// Rotate
private _direction = _deployedItem getVariable [QGVAR(deployDirection_temp), 0];
_scrollAmount = _scrollAmount * 10;
_direction = _direction + _scrollAmount;

_deployedItem setDir _direction;
_deployedItem setVariable [QGVAR(deployDirection_temp), _direction];
};

true
10 changes: 8 additions & 2 deletions addons/cargo/functions/fnc_initVehicle.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,17 @@ private _type = typeOf _vehicle;
private _config = configOf _vehicle;

// If vehicle had space given to it via eden/public, then override config hasCargo setting
private _hasCargoPublic = _vehicle getVariable [QGVAR(hasCargo), false];
private _hasCargoPublic = _item getVariable QGVAR(hasCargo);
private _hasCargoPublicDefined = !isNil "_canLoadPublic";

if (_hasCargoPublicDefined && {!(_hasCargoPublic isEqualType false)}) then {
WARNING_4("%1[%2] - Variable %3 is %4 - Should be bool",_item,_type,QGVAR(hasCargo),_hasCargoPublic);
};

private _hasCargoConfig = getNumber (_config >> QGVAR(hasCargo)) == 1;

// Nothing to do here if vehicle has no cargo space
if !(_hasCargoConfig || _hasCargoPublic) exitWith {};
if !((_hasCargoPublicDefined && {_hasCargoPublic in [true, 1]}) || {!_hasCargoPublicDefined && {_hasCargoConfig}}) exitWith {};

// Check if cargo is in cargo holder types (checked when trying to search for loadable objects)
private _addCargoType = GVAR(cargoHolderTypes) findIf {_type isKindOf _x} == -1;
Expand Down
Loading

0 comments on commit 8731bcc

Please sign in to comment.