Fix Underwater interactions (magrepack, loading, refuel, medical legs, dragging) (#5521)

* Fix Magazine Repack underwater - fix #5513
Also prevent common goKneeling function underwater

* Fix loading patients underwater - fix #5515

* Fix load object underwater

* Fix take nozzle on jerry can underwater

* Fix refuel underwater conditions further

* Use isTouchingGround, Make refuel semi-compatible
 reports false if head is out of the water, we want true even if we are not diving

* Less interact exceptions duplication

* Use animationState to determine if unit is swimming, create common function and use it instead of isTouchingGround

* Fix condition

* Support dragging underwater
No carrying due to animation timing issues and other misc things

* Allow Medical Legs SelfActions underwater

* Fix fixPosition function underwater (use getPosATL instead of getPos)

* Fix fixPosition's slope adjustment for non-gravity objects, Do the same for objects without simulation as well
This commit is contained in:
jonpas 2017-10-01 20:38:11 +02:00 committed by PabstMirror
parent ef25aaff02
commit 711e1fc026
30 changed files with 75 additions and 46 deletions

View File

@ -53,7 +53,7 @@ private _condition = {
{(_target getVariable [QGVAR(canLoad), getNumber (configFile >> "CfgVehicles" >> (typeOf _target) >> QGVAR(canLoad))]) in [true, 1]} &&
{locked _target < 2} &&
{alive _target} &&
{[_player, _target, []] call EFUNC(common,canInteractWith)} &&
{[_player, _target, ["isNotSwimming"]] call EFUNC(common,canInteractWith)} &&
{0 < {
private _type = typeOf _x;
private _hasCargoPublic = _x getVariable [QGVAR(hasCargo), false];

View File

@ -42,7 +42,9 @@ if ([_object, _vehicle] call FUNC(canLoadItemIn)) then {
[_object,_vehicle],
{["ace_loadCargo", _this select 0] call CBA_fnc_localEvent},
{},
localize LSTRING(LoadingItem)
localize LSTRING(LoadingItem),
{true},
["isNotSwimming"]
] call EFUNC(common,progressBar);
_return = true;
} else {

View File

@ -104,6 +104,7 @@ PREP(isInBuilding);
PREP(isMedic);
PREP(isModLoaded);
PREP(isPlayer);
PREP(isSwimming);
PREP(isUnderwater);
PREP(lightIntensityFromObject);
PREP(loadPerson);

View File

@ -1,6 +1,5 @@
/*
* Author: commy2
*
* Author: commy2, Jonpas
* Fixes position of an object. E.g. moves object above ground and adjusts to terrain slope. Requires local object.
*
* Arguments:
@ -10,7 +9,7 @@
* None
*
* Example:
* [bob] call ace_common_fnc_fixPosition
* bob call ace_common_fnc_fixPosition
*
* Public: No
*/
@ -19,25 +18,28 @@
// setVectorUp requires local object
if (!local _this) exitWith {};
if ((getText (configFile >> "CfgVehicles" >> (typeOf _this) >> "simulation")) == "house") then {
//Houses don't have gravity/physics, so make sure they are not floating
private _posAbove = (getPos _this) select 2;
// Objects with disabled simulation and objects with simulation type "house" don't have gravity/physics, so make sure they are not floating
private _hasGravity = simulationEnabled _this && {!(getText (configFile >> "CfgVehicles" >> typeOf _this >> "simulation") == "house")};
if (!_hasGravity) then {
private _posAbove = (getPosATL _this) select 2;
TRACE_2("house",_this,_posAbove);
if (_posAbove > 0.1) then {
private _newPosASL = (getPosASL _this) vectorDiff [0,0,_posAbove];
_this setPosASL _newPosASL;
private _newPosATL = (getPosATL _this) vectorDiff [0, 0, _posAbove];
_this setPosATL _newPosATL;
};
};
private _position = getPos _this;
private _position = getPosATL _this;
// don't place the object below the ground
// Don't place the object below the ground
if (_position select 2 < -0.1) then {
_position set [2, -0.1];
_this setPos _position;
_this setPosATL _position;
};
// adjust position to sloped terrain, if placed on ground
if (getPosATL _this select 2 == _position select 2) then {
// Adjust position to sloped terrain, if placed on ground
// Object without gravity/physics may have negative height when placed on slope, but those objects are definitely on the ground
if (!_hasGravity || {getPosATL _this select 2 == _position select 2}) then {
_this setVectorUp surfaceNormal _position;
};

View File

@ -1,6 +1,6 @@
/*
* Author: commy2
* Move unit to kneeling position (only if not yet prone).
* Move unit to kneeling position (only if not yet prone and not underwater).
*
* Arguments:
* 0: Unit <OBJECT>
@ -18,7 +18,7 @@
params ["_unit"];
// Animation changes even inside vehicle post-1.60
if (stance _unit == "PRONE" || {vehicle ACE_player != ACE_player}) exitWith {};
if (stance _unit == "PRONE" || {vehicle _unit != _unit} || {_unit call EFUNC(common,isSwimming)}) exitWith {};
[
_unit,

View File

@ -0,0 +1,20 @@
/*
* Author: das attorney, Jonpas
* Check if unit is swimming (surface swimming or diving).
*
* Arguments:
* 0: Unit <OBJECT>
*
* Return Value:
* If unit is swimming <BOOL>
*
* Example:
* [bob] call ace_common_fnc_isSwimming
*
* Public: Yes
*/
#include "script_component.hpp"
params [["_unit", objNull, [objNull]]];
((animationState _unit) select [1, 3]) in ["bdv","bsw","dve","sdv","ssw","swm"]

View File

@ -21,7 +21,7 @@
params ["_caller", "_unit", ["_vehicle", objNull]];
if (!([_caller, _unit, ["isNotDragging", "isNotCarrying"]] call FUNC(canInteractWith)) || {_caller == _unit}) exitWith {_vehicle};
if (!([_caller, _unit, ["isNotDragging", "isNotCarrying", "isNotSwimming"]] call FUNC(canInteractWith)) || {_caller == _unit}) exitWith {_vehicle};
// Try to use nearest vehicle if a vehicle hasn't been supplied
if (isNull _vehicle) then {

View File

@ -18,7 +18,7 @@
params ["_unit", "_target"];
if !([_unit, _target, []] call EFUNC(common,canInteractWith)) exitWith {false};
if !([_unit, _target, ["isNotSwimming"]] call EFUNC(common,canInteractWith)) exitWith {false};
// a static weapon has to be empty for dragging (ignore UAV AI)
if ((typeOf _target) isKindOf "StaticWeapon" && {{(getText (configFile >> "CfgVehicles" >> (typeOf _x) >> "simulation")) != "UAVPilot"} count crew _target > 0}) exitWith {false};

View File

@ -18,6 +18,6 @@
params ["_unit", "_target"];
if !([_unit, _target, ["isNotDragging"]] call EFUNC(common,canInteractWith)) exitWith {false};
if !([_unit, _target, ["isNotDragging", "isNotSwimming"]] call EFUNC(common,canInteractWith)) exitWith {false};
_unit getVariable [QGVAR(draggedObject), objNull] == _target

View File

@ -58,7 +58,7 @@ if (_inBuilding) then {
_unit setVariable [QGVAR(isDragging), false, true];
_unit setVariable [QGVAR(draggedObject), objNull, true];
// make object accesable for other units
// make object accessible for other units
[objNull, _target, true] call EFUNC(common,claim);
if !(_target isKindOf "CAManBase") then {

View File

@ -31,6 +31,7 @@ private _totalWeight = 0;
} forEach _item;
true
} count [
//IGNORE_PRIVATE_WARNING ["_x"];
[getMagazineCargo _object, {configFile >> "CfgMagazines" >> _x}],
[getBackpackCargo _object, {configFile >> "CfgVehicles" >> _x}],
[getItemCargo _object, {configFile >> "CfgWeapons" >> _x >> "ItemInfo"}],

View File

@ -30,7 +30,7 @@ if (_unit != _realUnit) exitWith {
if (_unit getVariable [QGVAR(isDragging), false]) then {
// drop dragged object when not in valid animation
if !(_anim in DRAG_ANIMATIONS) then {
if (!(_anim in DRAG_ANIMATIONS) && {!(_unit call EFUNC(common,isSwimming))}) then {
private _draggedObject = _unit getVariable [QGVAR(draggedObject), objNull];
if (!isNull _draggedObject) then {

View File

@ -39,9 +39,11 @@ _unit selectWeapon primaryWeapon _unit;
[_unit, _target, true] call EFUNC(common,claim);
// can't play action that depends on weapon if it was added the same frame
[{
[_this, "grabDrag"] call EFUNC(common,doGesture);
}, _unit] call CBA_fnc_execNextFrame;
if !(_unit call EFUNC(common,isSwimming)) then {
[{
[_this, "grabDrag"] call EFUNC(common,doGesture);
}, _unit] call CBA_fnc_execNextFrame;
};
// move a bit closer and adjust direction when trying to pick up a person
if (_target isKindOf "CAManBase") then {

View File

@ -50,7 +50,7 @@ if (CBA_missionTime > _timeOut) exitWith {
};
// unit is ready to start dragging
if (animationState _unit in DRAG_ANIMATIONS) exitWith {
if (animationState _unit in DRAG_ANIMATIONS || {_unit call EFUNC(common,isSwimming)}) exitWith {
TRACE_4("Start Dragging",_unit,_target,_timeOut,CBA_missionTime);
[_unit, _target] call FUNC(dragObject);

View File

@ -2,7 +2,7 @@
#define COMPONENT_BEAUTIFIED Dragging
#include "\z\ace\addons\main\script_mod.hpp"
//#define DEBUG_ENABLED_DRAGGING
// #define DEBUG_ENABLED_DRAGGING
// #define DEBUG_MODE_FULL
// #define DISABLE_COMPILE_CACHE
// #define ENABLE_PERFORMANCE_COUNTERS

View File

@ -106,7 +106,7 @@ GVAR(isOpeningDoor) = false;
{false},
[20, [true, false, false]], false] call CBA_fnc_addKeybind;
["isNotSwimming", {!underwater (_this select 0)}] call EFUNC(common,addCanInteractWithCondition);
["isNotSwimming", {!(_this call EFUNC(common,isSwimming))}] call EFUNC(common,addCanInteractWithCondition);
["isNotOnLadder", {getNumber (configFile >> "CfgMovesMaleSdr" >> "States" >> animationState (_this select 0) >> "ACE_isLadder") != 1}] call EFUNC(common,addCanInteractWithCondition);
["ace_settingsInitialized", {

View File

@ -25,7 +25,7 @@ if (_unit != ACE_player) exitWith {};
_timeToCut = if ([_unit] call EFUNC(common,isEngineer)) then {7.5} else {11};
if (!underwater _unit) then {
if !(_unit call EFUNC(common,isSwimming)) then {
[_unit, "AinvPknlMstpSnonWnonDr_medic5", 0] call EFUNC(common,doAnimation);
};
@ -33,7 +33,7 @@ _onCompletion = {
TRACE_1("_onCompletion",_this);
(_this select 0) params ["_fenceObject", "", "_unit"];
_fenceObject setdamage 1;
if (!underwater _unit) then {
if !(_unit call EFUNC(common,isSwimming)) then {
[_unit, "AmovPknlMstpSrasWrflDnon", 1] call EFUNC(common,doAnimation);
};
};
@ -41,7 +41,7 @@ _onCompletion = {
_onFail = {
TRACE_1("_onFail", _this);
(_this select 0) params ["", "", "_unit"];
if (!underwater _unit) then {
if !(_unit call EFUNC(common,isSwimming)) then {
[_unit, "AmovPknlMstpSrasWrflDnon", 1] call EFUNC(common,doAnimation);
};
};

View File

@ -25,7 +25,7 @@ _args params ["_magazineClassname", "_lastAmmoCount"];
private _fullMagazineCount = getNumber (configFile >> "CfgMagazines" >> _magazineClassname >> "count");
// Don't show anything if player can't interact
if (!([ACE_player, objNull, ["isNotInside", "isNotSitting", "isNowSwimming"]] call EFUNC(common,canInteractWith))) exitWith {};
if (!([ACE_player, objNull, ["isNotInside", "isNotSitting", "isNotSwimming"]] call EFUNC(common,canInteractWith))) exitWith {};
// Count mags
private _fullMags = 0;

View File

@ -351,7 +351,7 @@ class Medical {
class ACE_LegLeft {
displayName = ECSTRING(interaction,LegLeft);
runOnHover = 1;
exceptions[] = {"isNotInside", "isNotSitting"};
exceptions[] = {"isNotInside", "isNotSwimming", "isNotSitting"};
statement = QUOTE([ARR_3(_target, true, 4)] call DFUNC(displayPatientInformation));
modifierFunction = QUOTE([ARR_4(_target,_player,4,_this select 3)] call FUNC(modifyMedicalAction));
condition = "true";
@ -443,7 +443,7 @@ class Medical {
class ACE_LegRight {
displayName = ECSTRING(interaction,LegRight);
runOnHover = 1;
exceptions[] = {"isNotInside", "isNotSitting"};
exceptions[] = {"isNotInside", "isNotSwimming", "isNotSitting"};
statement = QUOTE([ARR_3(_target, true, 5)] call DFUNC(displayPatientInformation));
modifierFunction = QUOTE([ARR_4(_target,_player,5,_this select 3)] call FUNC(modifyMedicalAction));
condition = "true";

View File

@ -176,7 +176,7 @@ if (vehicle _caller == _caller && {_callerAnim != ""}) then {
_caller selectWeapon (primaryWeapon _caller); // unit always has a primary weapon here
};
if (!underwater _caller) then {
if !(_caller call EFUNC(common,isSwimming)) then {
// Weapon on back also does not work underwater
if (isWeaponDeployed _caller) then {
TRACE_1("Weapon Deployed, breaking out first",(stance _caller));

View File

@ -26,7 +26,7 @@ _args params ["_caller", "_target", "_selectionName", "_className", "_items", "_
if (primaryWeapon _caller == "ACE_FakePrimaryWeapon") then {
_caller removeWeapon "ACE_FakePrimaryWeapon";
};
if (vehicle _caller == _caller && {!underwater _caller}) then {
if (vehicle _caller == _caller && {!(_caller call EFUNC(common,isSwimming))}) then {
private _lastAnim = _caller getVariable [QGVAR(treatmentPrevAnimCaller), ""];
//Don't play another medic animation (when player is rapidily treating)
TRACE_2("Reseting to old animation", animationState player, _lastAnim);

View File

@ -26,7 +26,7 @@ _args params ["_caller", "_target", "_selectionName", "_className", "_items", "_
if (primaryWeapon _caller == "ACE_FakePrimaryWeapon") then {
_caller removeWeapon "ACE_FakePrimaryWeapon";
};
if (vehicle _caller == _caller && {!underwater _caller}) then {
if (vehicle _caller == _caller && {!(_caller call EFUNC(common,isSwimming))}) then {
private _lastAnim = _caller getVariable [QGVAR(treatmentPrevAnimCaller), ""];
//Don't play another medic animation (when player is rapidily treating)
TRACE_2("Reseting to old animation", animationState player, _lastAnim);

View File

@ -14,7 +14,7 @@
displayName = CSTRING(TakeNozzle); \
condition = QUOTE([ARR_2(_player,_target)] call FUNC(canTakeNozzle)); \
statement = QUOTE([ARR_2(_player,_target)] call FUNC(takeNozzle)); \
exceptions[] = {"isNotInside", "isNotOnLadder"}; \
exceptions[] = {INTERACT_EXCEPTIONS_REFUELING}; \
icon = QPATHTOF(ui\icon_refuel_interact.paa); \
}; \
class GVAR(TurnOn) { \
@ -35,7 +35,7 @@
displayName = CSTRING(Disconnect); \
condition = QUOTE([ARR_2(_player,_target)] call FUNC(canDisconnect)); \
statement = QUOTE([ARR_2(_player,_target)] call DFUNC(disconnect)); \
exceptions[] = {"isNotInside", "isNotOnLadder"}; \
exceptions[] = {INTERACT_EXCEPTIONS_REFUELING}; \
icon = QPATHTOF(ui\icon_refuel_interact.paa); \
}; \
}; \

View File

@ -44,7 +44,7 @@ private _action = [QGVAR(Refuel),
_action = [QGVAR(PickUpNozzle),
localize LSTRING(TakeNozzle),
QPATHTOF(ui\icon_refuel_interact.paa),
{[_player, _target] call FUNC(TakeNozzle)},
{[_player, _target] call FUNC(takeNozzle)},
{[_player, _target] call FUNC(canTakeNozzle)},
{},
[],

View File

@ -35,7 +35,7 @@ TRACE_2("start",_unit,_nozzle);
if !(
alive _unit
&& {"" isEqualTo currentWeapon _unit}
&& {"" isEqualTo currentWeapon _unit || {_unit call EFUNC(common,isSwimming)}}
&& {[_unit, objNull, [INTERACT_EXCEPTIONS, "notOnMap"]] call EFUNC(common,canInteractWith)}
&& {!("unconscious" isEqualTo toLower animationState _unit)}
&& {!(_unit getVariable ["ACE_isUnconscious", false])}

View File

@ -94,5 +94,5 @@ params [
{},
localize LSTRING(TakeNozzleAction),
{true},
["isNotInside", "isNotOnLadder"]
[INTERACT_EXCEPTIONS_REFUELING]
] call EFUNC(common,progressBar);

View File

@ -30,4 +30,5 @@
#define TIME_PROGRESSBAR(X) (X)
#endif
#define INTERACT_EXCEPTIONS "isNotInside", "isNotOnLadder", "isNotRefueling"
#define INTERACT_EXCEPTIONS_REFUELING "isNotInside", "isNotOnLadder", "isNotSwimming"
#define INTERACT_EXCEPTIONS INTERACT_EXCEPTIONS_REFUELING, "isNotRefueling"

View File

@ -169,7 +169,7 @@ if (vehicle _caller == _caller && {_callerAnim != ""}) then {
_caller selectWeapon (primaryWeapon _caller); // unit always has a primary weapon here
};
if (!underwater _caller) then {
if !(_caller call EFUNC(common,isSwimming)) then {
if (stance _caller == "STAND") then {
_caller setVariable [QGVAR(repairPrevAnimCaller), "amovpknlmstpsraswrfldnon"];
} else {

View File

@ -31,7 +31,7 @@ private ["_config","_callback", "_usersOfItems", "_weaponSelect"];
if (primaryWeapon _caller == "ACE_FakePrimaryWeapon") then {
_caller removeWeapon "ACE_FakePrimaryWeapon";
};
if (vehicle _caller == _caller && {!underwater _caller}) then {
if (vehicle _caller == _caller && {!(_caller call EFUNC(common,isSwimming))}) then {
[_caller, _caller getVariable [QGVAR(repairPrevAnimCaller), ""], 2] call EFUNC(common,doAnimation);
};
_caller setVariable [QGVAR(repairPrevAnimCaller), nil];

View File

@ -31,7 +31,7 @@ private ["_config","_callback", "_weaponSelect"];
if (primaryWeapon _caller == "ACE_FakePrimaryWeapon") then {
_caller removeWeapon "ACE_FakePrimaryWeapon";
};
if (vehicle _caller == _caller && {!underwater _caller}) then {
if (vehicle _caller == _caller && {!(_caller call EFUNC(common,isSwimming))}) then {
[_caller, _caller getVariable [QGVAR(repairPrevAnimCaller), ""], 2] call EFUNC(common,doAnimation);
};
_caller setVariable [QGVAR(repairPrevAnimCaller), nil];