2023-09-12 18:58:10 +00:00
|
|
|
#include "..\script_component.hpp"
|
2021-10-12 09:33:05 +00:00
|
|
|
/*
|
2023-08-16 23:18:01 +00:00
|
|
|
* Author: tcvm
|
2024-02-05 18:54:51 +00:00
|
|
|
* Called per frame. Handles current unit state for attaching a rope to two vehicles.
|
2021-10-12 09:33:05 +00:00
|
|
|
*
|
|
|
|
* Arguments:
|
|
|
|
* 0: PFEH Args <ARRAY>
|
|
|
|
* 1: PFID <NUMBER>
|
|
|
|
*
|
|
|
|
* Return Value:
|
|
|
|
* None
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* [[],0]] call ace_towing_fnc_towStateMachinePFH
|
|
|
|
*
|
|
|
|
* Public: No
|
|
|
|
*/
|
|
|
|
params ["_args", "_handle"];
|
|
|
|
_args params ["_state", "_unit", "_parent", "_rope", "_length", "_ropeClass"];
|
|
|
|
|
2023-11-11 00:16:11 +00:00
|
|
|
private _wasSwimming = GVAR(isSwimming);
|
|
|
|
GVAR(isSwimming) = _unit call EFUNC(common,isSwimming);
|
|
|
|
|
|
|
|
// skip this frame to wait for weapon in hands
|
|
|
|
if (_wasSwimming && {!GVAR(isSwimming)}) exitWith {GVAR(putWeaponAwayNextFrame) = true;};
|
|
|
|
// move weapon to back in next frame
|
|
|
|
if (GVAR(putWeaponAwayNextFrame)) then {
|
|
|
|
if (currentWeapon _unit isNotEqualTo "") then {[_unit] call EFUNC(weaponselect,putWeaponAway)};
|
|
|
|
GVAR(putWeaponAwayNextFrame) = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
// block fire when swimming in wetsuit with weapon
|
|
|
|
if (GVAR(isSwimming) && {currentWeapon _unit isNotEqualTo ""}) then {
|
|
|
|
if (GVAR(blockFireEHID) == -1) then {
|
|
|
|
GVAR(blockFireEHID) = [_unit, "DefaultAction", {true}, {}] call EFUNC(common,addActionEventHandler);
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
if (GVAR(blockFireEHID) != -1) then {
|
|
|
|
[_unit, "DefaultAction", GVAR(blockFireEHID)] call EFUNC(common,removeActionEventHandler);
|
|
|
|
GVAR(blockFireEHID) = -1;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2021-10-12 09:33:05 +00:00
|
|
|
private _exitCondition = !(
|
|
|
|
(alive GVAR(attachHelper)) &&
|
2021-10-16 22:17:20 +00:00
|
|
|
{ alive _parent } &&
|
2021-10-12 09:33:05 +00:00
|
|
|
{ alive _unit } &&
|
2023-11-11 00:16:11 +00:00
|
|
|
{
|
|
|
|
currentWeapon _unit isEqualTo ""
|
|
|
|
|| {_unit call EFUNC(common,isSwimming)} // swimming in wetsuit forces weapon in hands
|
|
|
|
|| {getPosASLW _unit select 2 < -1.5} // walking-to-swimming animation in wetsuit lasts for 3 seconds
|
|
|
|
} &&
|
2021-10-12 09:33:05 +00:00
|
|
|
{ [_unit, objNull, [INTERACTION_EXCEPTIONS]] call EFUNC(common,canInteractWith) } &&
|
|
|
|
{ "unconscious" isNotEqualTo toLower animationState _unit } &&
|
2021-11-07 23:19:13 +00:00
|
|
|
{ !(_unit getVariable ["ACE_isUnconscious", false]) } &&
|
|
|
|
{ ACE_player == _unit }
|
2021-10-12 09:33:05 +00:00
|
|
|
);
|
|
|
|
|
2021-11-07 23:19:13 +00:00
|
|
|
if (_exitCondition && {_state < TOW_STATE_CANCEL}) then {
|
2021-10-12 09:33:05 +00:00
|
|
|
_state = TOW_STATE_CANCEL;
|
|
|
|
};
|
|
|
|
|
|
|
|
switch (_state) do {
|
|
|
|
case TOW_STATE_ATTACH_PARENT: {
|
2024-02-05 18:54:51 +00:00
|
|
|
// TRACE_2("state attach parent",_unit,_parent);
|
2021-10-12 09:33:05 +00:00
|
|
|
[_unit, _parent, objNull, objNull, [0, 0, 0], _length] call FUNC(attachRopePFH);
|
|
|
|
|
|
|
|
if (GVAR(canAttach) && { GVAR(mouseLeft) }) then {
|
|
|
|
_args set [0, TOW_STATE_ATTACH_CHILD];
|
2024-02-05 18:54:51 +00:00
|
|
|
// can't use unit hand because rope doesn't change position when hand moving
|
|
|
|
// can't use createVehicleLocal because rope can be non-local (like parent) and it must be attached to global vehicle
|
|
|
|
GVAR(helper) = createVehicle [QGVAR(helper), [0, 0, 0], [], 0, "CAN_COLLIDE"];
|
|
|
|
GVAR(helper) attachTo [_unit, [0, 0, 0], "LeftHand", true];
|
|
|
|
_rope = ropeCreate [_parent, _parent worldToModelVisual ASLtoAGL getPosASLVisual GVAR(attachHelper), GVAR(helper), [0, 0, 0], _length];
|
2021-10-12 09:33:05 +00:00
|
|
|
_args set [3, _rope];
|
|
|
|
};
|
|
|
|
|
2021-11-07 23:19:13 +00:00
|
|
|
if (GVAR(mouseRight) || GVAR(cancel)) then {
|
2021-10-12 09:33:05 +00:00
|
|
|
_args set [0, TOW_STATE_CANCEL];
|
2021-11-07 23:19:13 +00:00
|
|
|
GVAR(cancel) = false;
|
2021-10-12 09:33:05 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
case TOW_STATE_ATTACH_CHILD: {
|
2024-02-05 18:54:51 +00:00
|
|
|
// TRACE_3("state attach child",_unit,_parent,_rope);
|
2021-10-12 09:33:05 +00:00
|
|
|
[_unit, objNull, _parent, _rope, getPosASLVisual _rope, _length] call FUNC(attachRopePFH);
|
|
|
|
|
|
|
|
if (GVAR(canAttach) && { GVAR(mouseLeft) }) then {
|
|
|
|
_args set [0, TOW_STATE_ATTACH];
|
|
|
|
};
|
|
|
|
|
|
|
|
if (GVAR(mouseRight) || GVAR(cancel)) then {
|
|
|
|
_args set [0, TOW_STATE_CANCEL];
|
|
|
|
GVAR(cancel) = false;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
case TOW_STATE_ATTACH: {
|
|
|
|
TRACE_3("state attach",GVAR(attachHelper),_parent,_rope);
|
|
|
|
private _child = GVAR(attachHelper) getVariable [QGVAR(object), objNull];
|
|
|
|
private _relativeAttachPos = _child worldToModelVisual ASLtoAGL getPosASLVisual GVAR(attachHelper);
|
|
|
|
|
|
|
|
TRACE_3("child&pos",_parent,_child,_relativeAttachPos);
|
|
|
|
|
|
|
|
if (_child isEqualTo _parent) exitWith {
|
|
|
|
_args set [0, TOW_STATE_CANCEL];
|
|
|
|
ERROR_MSG("_child isEqualTo _parent");
|
|
|
|
};
|
|
|
|
|
2021-11-07 23:19:13 +00:00
|
|
|
if (GVAR(cancel)) exitWith {
|
|
|
|
_args set [0, TOW_STATE_CANCEL];
|
|
|
|
GVAR(cancel) = false;
|
|
|
|
};
|
|
|
|
|
2024-02-05 18:54:51 +00:00
|
|
|
detach GVAR(helper);
|
|
|
|
// can't delete GVAR(helper) without ropeDetach which requires local rope (==parent), so pass it to owner
|
|
|
|
if (isNull (_child getVariable [QGVAR(parent), objNull])) then {
|
|
|
|
[QGVAR(attachVehicles), [_parent, _child, _relativeAttachPos, _rope, GVAR(helper)]] call CBA_fnc_globalEvent;
|
|
|
|
} else {
|
|
|
|
[QGVAR(ropeAttachTo), [_child, _relativeAttachPos, _rope, GVAR(helper)], _parent] call CBA_fnc_targetEvent;
|
|
|
|
};
|
2021-10-12 09:33:05 +00:00
|
|
|
|
2024-02-05 18:54:51 +00:00
|
|
|
private _hookParent = createVehicle [QGVAR(hook), [0, 0, 0], [], 0, "CAN_COLLIDE"];
|
|
|
|
_hookParent attachTo [_parent, _parent worldToModelVisual ASLtoAGL getPosASLVisual _rope];
|
2021-10-12 09:33:05 +00:00
|
|
|
|
2024-02-05 18:54:51 +00:00
|
|
|
private _hook = createVehicle [QGVAR(hook), [0, 0, 0], [], 0, "CAN_COLLIDE"];
|
2021-10-12 09:33:05 +00:00
|
|
|
_hook attachTo [_child, _relativeAttachPos];
|
|
|
|
|
2024-02-05 18:54:51 +00:00
|
|
|
// use array to decrease public setVar count
|
|
|
|
private _hookVars = [_parent, _child, _rope, _ropeClass, _hookParent];
|
|
|
|
_hook setVariable [QGVAR(vars), _hookVars, true];
|
2021-10-12 09:33:05 +00:00
|
|
|
|
2024-02-05 18:54:51 +00:00
|
|
|
_hookParent setVariable [QGVAR(hook), _hook, true];
|
|
|
|
_rope setVariable [QGVAR(hook), _hook, true];
|
2021-10-12 09:33:05 +00:00
|
|
|
|
2024-02-05 18:54:51 +00:00
|
|
|
private _childParentHooks = _child getVariable [QGVAR(parentHooks), []];
|
|
|
|
_childParentHooks pushBack _hook;
|
|
|
|
_child setVariable [QGVAR(parentHooks), _childParentHooks, true];
|
2021-10-12 09:33:05 +00:00
|
|
|
|
2024-02-05 18:54:51 +00:00
|
|
|
private _parentChildHooks = _parent getVariable [QGVAR(childHooks), []];
|
|
|
|
_parentChildHooks pushBack _hook;
|
|
|
|
_parent setVariable [QGVAR(childHooks), _parentChildHooks, true];
|
2021-10-12 09:33:05 +00:00
|
|
|
|
|
|
|
_args set [0, TOW_STATE_CLEANUP];
|
|
|
|
};
|
|
|
|
case TOW_STATE_CANCEL: {
|
|
|
|
TRACE_1("state cancel",_rope);
|
2021-11-07 23:19:13 +00:00
|
|
|
if !(isNull _rope) then {
|
2024-02-05 18:54:51 +00:00
|
|
|
detach GVAR(helper);
|
|
|
|
deleteVehicle GVAR(helper);
|
2021-11-07 23:19:13 +00:00
|
|
|
ropeDestroy _rope;
|
|
|
|
};
|
2021-10-12 09:33:05 +00:00
|
|
|
[_unit, _ropeClass, true] call CBA_fnc_addItem;
|
|
|
|
_args set [0, TOW_STATE_CLEANUP];
|
2021-11-07 23:19:13 +00:00
|
|
|
GVAR(cancel) = false;
|
2023-05-01 17:39:22 +00:00
|
|
|
[QGVAR(ropeDeployCanceled), [_unit, _ropeClass]] call CBA_fnc_localEvent;
|
2021-10-12 09:33:05 +00:00
|
|
|
(localize LSTRING(canceled)) call CBA_fnc_notify;
|
|
|
|
};
|
|
|
|
case TOW_STATE_CLEANUP: {
|
|
|
|
TRACE_2("state cleanup",GVAR(attachHelper),_handle);
|
|
|
|
deleteVehicle GVAR(attachHelper);
|
|
|
|
[_handle] call CBA_fnc_removePerFrameHandler;
|
2024-02-05 18:54:51 +00:00
|
|
|
["MouseButtonDown", GVAR(onMouseButtonDownEHID)] call CBA_fnc_removeDisplayHandler;
|
2021-10-12 09:33:05 +00:00
|
|
|
_unit setVariable [QGVAR(hint), []];
|
|
|
|
call EFUNC(interaction,hideMouseHint);
|
2023-11-11 00:16:11 +00:00
|
|
|
if (GVAR(blockFireEHID) != -1) then {
|
|
|
|
[_unit, "DefaultAction", GVAR(blockFireEHID)] call EFUNC(common,removeActionEventHandler);
|
|
|
|
GVAR(blockFireEHID) = -1;
|
|
|
|
};
|
2021-10-12 09:33:05 +00:00
|
|
|
};
|
|
|
|
};
|