ACE3/addons/towing/functions/fnc_towStateMachinePFH.sqf
Dystopian 74be4f1503
Towing - Fix swimming issues (#9401)
* Fix swimming issues

* Fix fire with rope in hand
2023-11-10 21:16:11 -03:00

185 lines
6.7 KiB
Plaintext

#include "..\script_component.hpp"
/*
* Author: tcvm
* Called per frame. Handles current unit state for attaching a rope to two vehicles
*
* 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"];
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;
};
};
private _exitCondition = !(
(alive GVAR(attachHelper)) &&
{ alive _parent } &&
{ alive _unit } &&
{
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
} &&
{ [_unit, objNull, [INTERACTION_EXCEPTIONS]] call EFUNC(common,canInteractWith) } &&
{ "unconscious" isNotEqualTo toLower animationState _unit } &&
{ !(_unit getVariable ["ACE_isUnconscious", false]) } &&
{ ACE_player == _unit }
);
if (_exitCondition && {_state < TOW_STATE_CANCEL}) then {
_state = TOW_STATE_CANCEL;
};
switch (_state) do {
case TOW_STATE_ATTACH_PARENT: {
TRACE_2("state attach parent",_unit,_parent);
[_unit, _parent, objNull, objNull, [0, 0, 0], _length] call FUNC(attachRopePFH);
if (GVAR(canAttach) && { GVAR(mouseLeft) }) then {
_args set [0, TOW_STATE_ATTACH_CHILD];
_rope = ropeCreate [_parent, _parent worldToModelVisual ASLtoAGL getPosASLVisual GVAR(attachHelper), _length];
[GVAR(attachHelper), [0, 0, 0]] ropeAttachTo _rope;
_args set [3, _rope];
};
if (GVAR(mouseRight) || GVAR(cancel)) then {
_args set [0, TOW_STATE_CANCEL];
GVAR(cancel) = false;
};
};
case TOW_STATE_ATTACH_CHILD: {
TRACE_3("state attach child",_unit,_parent,_rope);
[_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");
};
if (GVAR(cancel)) exitWith {
_args set [0, TOW_STATE_CANCEL];
GVAR(cancel) = false;
};
[QGVAR(setTowParent), [_parent, _child], _parent] call CBA_fnc_targetEvent;
GVAR(attachHelper) ropeDetach _rope;
[_child, _relativeAttachPos] ropeAttachTo _rope;
private _hook = createVehicle [QGVAR(hook), [0, 0, 0], [], 0, "NONE"];
_hook attachTo [_child, _relativeAttachPos];
_hook setVariable [QGVAR(parent), _parent, true];
_hook setVariable [QGVAR(child), _child, true];
_child setVariable [QGVAR(rope), _rope, true];
_child setVariable [QGVAR(hook), _hook, true];
_parent setVariable [QGVAR(hook), _hook, true];
_hook setVariable [QGVAR(ropeClass), _ropeClass, true];
_child setVariable [QGVAR(towing), true, true];
_parent setVariable [QGVAR(towing), true, true];
_hook setVariable [QGVAR(parentDeleteEventHandler), _parent addEventHandler ["Deleted", {
params ["_entity"];
private _hook = _entity getVariable [QGVAR(hook), objNull];
private _child = _hook getVariable [QGVAR(child), objNull];
private _parent = _hook getVariable [QGVAR(parent), objNull];
[objNull, _parent, _child] call FUNC(detach);
}], true];
_hook setVariable [QGVAR(childDeleteEventHandler), _child addEventHandler ["Deleted", {
params ["_entity"];
private _hook = _entity getVariable [QGVAR(hook), objNull];
private _child = _hook getVariable [QGVAR(child), objNull];
private _parent = _hook getVariable [QGVAR(parent), objNull];
[objNull, _parent, _child] call FUNC(detach);
}], true];
_parent setVariable [QGVAR(ropeBreakEventHandler), _parent addEventHandler ["RopeBreak", {
params ["_parent", "_rope", "_child"];
[objNull, _parent, _child] call FUNC(detach);
_parent removeEventHandler ["RopeBreak", _parent getVariable QGVAR(ropeBreakEventHandler)];
_parent setVariable [QGVAR(ropeBreakEventHandler), -1];
}], true];
_args set [0, TOW_STATE_CLEANUP];
};
case TOW_STATE_CANCEL: {
TRACE_1("state cancel",_rope);
if !(isNull _rope) then {
ropeDestroy _rope;
};
[_unit, _ropeClass, true] call CBA_fnc_addItem;
_args set [0, TOW_STATE_CLEANUP];
GVAR(cancel) = false;
[QGVAR(ropeDeployCanceled), [_unit, _ropeClass]] call CBA_fnc_localEvent;
(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;
_unit setVariable [QGVAR(hint), []];
call EFUNC(interaction,hideMouseHint);
if (GVAR(blockFireEHID) != -1) then {
[_unit, "DefaultAction", GVAR(blockFireEHID)] call EFUNC(common,removeActionEventHandler);
GVAR(blockFireEHID) = -1;
};
};
};