Merged master

This commit is contained in:
johnb432 2024-01-14 22:36:10 +01:00
commit ceb940a124
17 changed files with 415 additions and 237 deletions

View File

@ -1,7 +1,7 @@
#include "..\script_component.hpp"
/*
* Author: commy2, PabstMirror
* Unit claims the ownership over an object. This is used to prevent multiple players from draging the same ammo box or using up the same wheel when repairing etc.
* Unit claims the ownership over an object. This is used to prevent multiple players from dragging the same ammo box or using up the same wheel when repairing etc.
* This function only runs on the server and handles the "ace_common_claimSafe" event. It provides a network safe way claiming objects as all claims are run on server.
* Return event is passed [_unit, _target, _success] for new claims, no event on claim release
*

View File

@ -28,6 +28,8 @@ PREP(resumeDrag);
PREP(setCarryable);
PREP(setDraggable);
PREP(startCarry);
PREP(startCarryLocal);
PREP(startCarryPFH);
PREP(startDrag);
PREP(startDragLocal);
PREP(startDragPFH);

View File

@ -80,6 +80,9 @@ if (isNil QGVAR(maxWeightCarryRun)) then {
};
}] call CBA_fnc_addEventHandler;
[QGVAR(startCarry), LINKFUNC(startCarryLocal)] call CBA_fnc_addEventHandler;
[QGVAR(startDrag), LINKFUNC(startDragLocal)] call CBA_fnc_addEventHandler;
[QGVAR(carryingContainerClosed), {
params ["_container", "_owner"];
TRACE_2("carryingContainerClosed EH",_container,_owner);

View File

@ -18,7 +18,10 @@
params ["_unit", "_target"];
if !((alive _target || {_target isKindOf "CAManBase"}) && {_target getVariable [QGVAR(canCarry), false]} && {isNull objectParent _target}) exitWith {false};
private _alive = alive _target;
private _isPerson = _target isKindOf "CAManBase";
if !((_alive || _isPerson) && {_target getVariable [QGVAR(canCarry), false]} && {isNull objectParent _target}) exitWith {false};
if !([_unit, _target, []] call EFUNC(common,canInteractWith)) exitWith {false};
@ -26,18 +29,19 @@ if !([_unit, _target, []] call EFUNC(common,canInteractWith)) exitWith {false};
// The fireman carry animation does not slow down for injured legs, so you could carry and run
if ((_unit getHitPointDamage "HitLegs") >= 0.5) exitWith {false};
// Units need to be unconscious or limping; Units also need to not be in ragdoll if alive, as that causes desync issues
if (_isPerson) exitWith {
!_alive ||
{(isAwake _target) && // not ragdolled if alive
{!(lifeState _target in ["HEALTHY", "INJURED"]) ||
{_target getHitPointDamage "HitLegs" >= 0.5}}}
};
// Static weapons need to be empty for carrying (ignore UAV AI)
if (_target isKindOf "StaticWeapon") exitWith {
(crew _target) findIf {!unitIsUAV _x} == -1
};
// Units need to be unconscious or limping; Units also need to not be in ragdoll, as that causes desync issues
if (_target isKindOf "CAManBase") exitWith {
(isAwake _target == alive _target) && // not ragdolled
{!(lifeState _target in ["HEALTHY", "INJURED"]) ||
{_target getHitPointDamage "HitLegs" >= 0.5}}
};
// Check max items for WeaponHolders
if (["WeaponHolder", "WeaponHolderSimulated"] findIf {_target isKindOf _x} != -1) exitWith {
(count (weaponCargo _target + magazineCargo _target + itemCargo _target)) <= MAX_DRAGGED_ITEMS

View File

@ -18,22 +18,26 @@
params ["_unit", "_target"];
if !((alive _target || {_target isKindOf "CAManBase"}) && {_target getVariable [QGVAR(canDrag), false]} && {isNull objectParent _target}) exitWith {false};
private _alive = alive _target;
private _isPerson = _target isKindOf "CAManBase";
if !((_alive || _isPerson) && {_target getVariable [QGVAR(canDrag), false]} && {isNull objectParent _target}) exitWith {false};
if !([_unit, _target, ["isNotSwimming"]] call EFUNC(common,canInteractWith)) exitWith {false};
// Units need to be unconscious or limping; Units also need to not be in ragdoll if alive, as that causes desync issues
if (_isPerson) exitWith {
!_alive ||
{(isAwake _target) && // not ragdolled if alive
{!(lifeState _target in ["HEALTHY", "INJURED"]) ||
{_target getHitPointDamage "HitLegs" >= 0.5}}}
};
// Static weapons need to be empty for dragging (ignore UAV AI)
if (_target isKindOf "StaticWeapon") exitWith {
(crew _target) findIf {!unitIsUAV _x} == -1
};
// Units need to be unconscious or limping; Units also need to not be in ragdoll, as that causes desync issues
if (_target isKindOf "CAManBase") exitWith {
(isAwake _target == alive _target) && // not ragdolled
{!(lifeState _target in ["HEALTHY", "INJURED"]) ||
{_target getHitPointDamage "HitLegs" >= 0.5}}
};
// Check max items for WeaponHolders
if (["WeaponHolder", "WeaponHolderSimulated"] findIf {_target isKindOf _x} != -1) exitWith {
(count (weaponCargo _target + magazineCargo _target + itemCargo _target)) <= MAX_DRAGGED_ITEMS

View File

@ -4,7 +4,8 @@
* Creates a draggable / carryable clone of a dead unit.
*
* Arguments:
* 0: Dead unit <OBJECT>
* 0: Unit dragging/carrying <OBJECT>
* 1: Dead unit <OBJECT>
*
* Return Value:
* Cloned unit <OBJECT>
@ -15,17 +16,19 @@
* Public: No
*/
params ["_target"];
params ["_unit", "_target"];
// Get current position of unit, -10 m below surface
private _posATL = getPosATL _target;
private _posATL = getPosASL _target;
// Create clone
private _clone = createVehicle [QGVAR(clone), ASLToAGL _posATL, [], 0, "CAN_COLLIDE"];
// Claim the clone
[_unit, _clone] call EFUNC(common,claim);
// Move unit -10 m below terrain in order to hide it and remove its inventory access
_posATL set [2, -10];
private _clone = createVehicle [QGVAR(clone), _posATL];
// Clone loadout
[_clone, _target call CBA_fnc_getLoadout] call CBA_fnc_setLoadout;
// Hide unit until it can be moved below terrain
private _isObjectHidden = isObjectHidden _target;
@ -48,13 +51,15 @@ if (_isInRemainsCollector) then {
// Make sure clone has the same wound textures as the corpse
private _targetDamage = damage _target;
if (_targetDamage != 0) then {
_clone setDamage (_targetDamage min 0.99); // Don't kill the clone
_clone setDamage (_targetDamage min 0.99); // don't kill the clone
};
private _relevantHitpoints = ["HitHead", "HitBody", "HitHands", "HitLegs"];
{
private _hitpointDamage = _target getHitPointDamage _x;
_clone setHitPointDamage [_x, _hitpointDamage min 0.99];
_clone setHitPointDamage [_x, (_target getHitPointDamage _x) min 0.99];
} forEach _relevantHitpoints;
// Disable all damage
@ -65,16 +70,38 @@ _clone setVariable [QGVAR(original), [_target, _isInRemainsCollector, _isObjectH
[QEGVAR(common,awake), [_target, true]] call CBA_fnc_globalEvent;
[{
params ["_target", "_posATL"];
params ["_clone", "_target", "_posATL"];
// Remove clone from all zeuses
if (["ace_zeus"] call EFUNC(common,isModLoaded)) then {
[QEGVAR(zeus,removeObjects), [[_clone]]] call CBA_fnc_serverEvent;
};
// Make sure PhysX is on
[QEGVAR(common,awake), [_target, true]] call CBA_fnc_globalEvent;
// Move unit below terrain in order to hide it and remove its inventory access
_target setPosATL _posATL;
}, [_target, _posATL], 0.25] call CBA_fnc_waitAndExecute;
// Clone loadout (sometimes default loadouts are randomised, so overwrite those)
[_clone, _target call CBA_fnc_getLoadout] call CBA_fnc_setLoadout;
// Sets the facial expression
[[QGVAR(cloneCreated), [_target, _clone]] call CBA_fnc_globalEventJIP, _clone] call CBA_fnc_removeGlobalEventJIP;
// Sets the facial expression
[[QGVAR(cloneCreated), [_target, _clone]] call CBA_fnc_globalEventJIP, _clone] call CBA_fnc_removeGlobalEventJIP;
// Corpse is desynced, but it doesn't matter here
_target setPosATL _posATL;
// Release claim on corpse
[objNull, _target] call EFUNC(common,claim);
}, [_clone, _target, _posATL], 0.25] call CBA_fnc_waitAndExecute;
// Save which curators had this object as editable
if (["ace_zeus"] call EFUNC(common,isModLoaded)) then {
private _objectCurators = objectCurators _target;
_target setVariable [QGVAR(objectCurators), _objectCurators, true];
if (_objectCurators isEqualTo []) exitWith {};
[QEGVAR(zeus,removeObjects), [[_target], _objectCurators]] call CBA_fnc_serverEvent;
};
_clone

View File

@ -37,40 +37,49 @@ if (!isNull _target) then {
_posASL = _posASL vectorAdd [0, 0, 0.05];
};
// Set the unit's direction
[QEGVAR(common,setDir), [_target, getDir _unit + 180], _target] call CBA_fnc_targetEvent;
[{
params ["_target", "", "", "", "_posASL", "_dir"];
params ["_target", "_clone", "_isObjectHidden", "_simulationEnabled", "_posASL"];
// Make sure PhysX is on
[QEGVAR(common,awake), [_target, true]] call CBA_fnc_globalEvent;
// Set the unit's direction
[QEGVAR(common,setDir), [_target, _dir], _target] call CBA_fnc_targetEvent;
// Bring unit back to clone's position
_target setPosASL _posASL;
[{
params ["_target", "_clone", "_isObjectHidden", "_simulationEnabled"];
// Unhide unit
if (!_isObjectHidden) then {
[QEGVAR(common,hideObjectGlobal), [_target, false]] call CBA_fnc_serverEvent;
};
if (!_isObjectHidden) then {
[QEGVAR(common,hideObjectGlobal), [_target, false]] call CBA_fnc_serverEvent;
};
// Enable simulation again
if (_simulationEnabled) then {
[QEGVAR(common,enableSimulationGlobal), [_target, true]] call CBA_fnc_serverEvent;
};
if (_simulationEnabled) then {
[QEGVAR(common,enableSimulationGlobal), [_target, true]] call CBA_fnc_serverEvent;
};
// Detach first to prevent objNull in attachedObjects
detach _clone;
deleteVehicle _clone;
}, [_target, _clone, _isObjectHidden, _simulationEnabled, _posASL], 0.25] call CBA_fnc_waitAndExecute;
deleteVehicle _clone;
}, _this, 0.25] call CBA_fnc_waitAndExecute;
}, [_target, _clone, _isObjectHidden, _simulationEnabled, _posASL, getDir _unit + 180], 0.25] call CBA_fnc_waitAndExecute;
// Get which curators had this object as editable
if (["ace_zeus"] call EFUNC(common,isModLoaded)) then {
private _objectCurators = _target getVariable [QGVAR(objectCurators), []];
if (_objectCurators isEqualTo []) exitWith {};
[QEGVAR(zeus,addObjects), [[_target], _objectCurators]] call CBA_fnc_serverEvent;
};
if (_isInRemainsCollector) then {
addToRemainsCollector [_target];
};
} else {
// Detach first to prevent objNull in attachedObjects
detach _clone;
deleteVehicle _clone;
};
// Detach first to prevent objNull in attachedObjects
detach _clone;
deleteVehicle _clone;
_target

View File

@ -1,7 +1,7 @@
#include "..\script_component.hpp"
/*
* Author: johnb43
* Removes user input affecting dragging.
* Removes user input affecting carrying.
*
* Arguments:
* 0: Unit <OBJECT>

View File

@ -56,8 +56,25 @@ GVAR(initializedClasses_carry) = _initializedClasses;
private _icon = [QPATHTOF(UI\icons\box_carry.paa), QPATHTOF(UI\icons\person_carry.paa)] select (_object isKindOf "CAManBase");
private _carryAction = [QGVAR(carry), LLSTRING(Carry), _icon, {[_player, _target] call FUNC(startCarry)}, {[_player, _target] call FUNC(canCarry)}] call EFUNC(interact_menu,createAction);
private _dropAction = [QGVAR(drop_carry), LLSTRING(Drop), "", {[_player, _target] call FUNC(dropObject_carry)}, {[_player, _target] call FUNC(canDrop_carry)}] call EFUNC(interact_menu,createAction);
private _carryAction = [
QGVAR(carry),
LLSTRING(Carry),
_icon,
{
[_player, _target] call FUNC(startCarry)
}, {
[_player, _target] call FUNC(canCarry)
}] call EFUNC(interact_menu,createAction);
private _dropAction = [
QGVAR(drop_carry),
LLSTRING(Drop),
"",
{
[_player, _target] call FUNC(dropObject_carry)
}, {
[_player, _target] call FUNC(canDrop_carry)
}] call EFUNC(interact_menu,createAction);
[_type, 0, ["ACE_MainActions"], _carryAction] call EFUNC(interact_menu,addActionToClass);
[_type, 0, [], _dropAction] call EFUNC(interact_menu,addActionToClass);

View File

@ -56,8 +56,25 @@ GVAR(initializedClasses) = _initializedClasses;
private _icon = [QPATHTOF(UI\icons\box_drag.paa), QPATHTOF(UI\icons\person_drag.paa)] select (_object isKindOf "CAManBase");
private _dragAction = [QGVAR(drag), LLSTRING(Drag), _icon, {[_player, _target] call FUNC(startDrag)}, {[_player, _target] call FUNC(canDrag)}] call EFUNC(interact_menu,createAction);
private _dropAction = [QGVAR(drop), LLSTRING(Drop), "", {[_player, _target] call FUNC(dropObject)}, {[_player, _target] call FUNC(canDrop)}] call EFUNC(interact_menu,createAction);
private _dragAction = [
QGVAR(drag),
LLSTRING(Drag),
_icon,
{
[_player, _target] call FUNC(startDrag)
}, {
[_player, _target] call FUNC(canDrag)
}] call EFUNC(interact_menu,createAction);
private _dropAction = [
QGVAR(drop),
LLSTRING(Drop),
"",
{
[_player, _target] call FUNC(dropObject);
}, {
[_player, _target] call FUNC(canDrop)
}] call EFUNC(interact_menu,createAction);
[_type, 0, ["ACE_MainActions"], _dragAction] call EFUNC(interact_menu,addActionToClass);
[_type, 0, [], _dropAction] call EFUNC(interact_menu,addActionToClass);

View File

@ -1,7 +1,7 @@
#include "..\script_component.hpp"
/*
* Author: commy2, PiZZADOX
* Starts the carrying process.
* Author: johnb43
* Starts the carrying process safely.
*
* Arguments:
* 0: Unit that should do the carrying <OBJECT>
@ -17,81 +17,6 @@
*/
params ["_unit", "_target"];
TRACE_2("params",_unit,_target);
// Exempt from weight check if object has override variable set
private _weight = 0;
if !(_target getVariable [QGVAR(ignoreWeightCarry), false]) then {
_weight = _target call FUNC(getWeight);
};
// Exit if object weight is over global var value
if (_weight > GETMVAR(ACE_maxWeightCarry,1E11)) exitWith {
[LLSTRING(UnableToDrag)] call EFUNC(common,displayTextStructured);
};
private _timer = CBA_missionTime + 5;
// Handle objects vs. persons
if (_target isKindOf "CAManBase") then {
// Create clone for dead units
if (!alive _target) then {
_target = _target call FUNC(createClone);
};
private _primaryWeapon = primaryWeapon _unit;
// Add a primary weapon if the unit has none
if (_primaryWeapon == "") then {
_unit addWeapon "ACE_FakePrimaryWeapon";
_primaryWeapon = "ACE_FakePrimaryWeapon";
};
// Select primary, otherwise the drag animation actions don't work
_unit selectWeapon _primaryWeapon;
// Move a bit closer and adjust direction when trying to pick up a person
[QEGVAR(common,setDir), [_target, getDir _unit + 180], _target] call CBA_fnc_targetEvent;
_target setPosASL (getPosASL _unit vectorAdd (vectorDir _unit));
[_unit, "AcinPknlMstpSnonWnonDnon_AcinPercMrunSnonWnonDnon", 2] call EFUNC(common,doAnimation);
[_target, "AinjPfalMstpSnonWrflDnon_carried_Up", 2] call EFUNC(common,doAnimation);
_timer = CBA_missionTime + 10;
} else {
// Select no weapon and stop sprinting
private _previousWeaponIndex = [_unit] call EFUNC(common,getFiremodeIndex);
_unit setVariable [QGVAR(previousWeapon), _previousWeaponIndex, true];
_unit action ["SwitchWeapon", _unit, _unit, 299];
[_unit, "AmovPercMstpSnonWnonDnon", 0] call EFUNC(common,doAnimation);
private _canRun = _weight call FUNC(canRun_carry);
// Only force walking if we're overweight
[_unit, "forceWalk", QUOTE(ADDON), !_canRun] call EFUNC(common,statusEffect_set);
[_unit, "blockSprint", QUOTE(ADDON), _canRun] call EFUNC(common,statusEffect_set);
};
[_unit, "blockThrow", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
// Prevent multiple players from accessing the same object
[_unit, _target, true] call EFUNC(common,claim);
// Prevents dragging and carrying at the same time
_unit setVariable [QGVAR(isCarrying), true, true];
// Required for aborting animation
_unit setVariable [QGVAR(carriedObject), _target, true];
[FUNC(startCarryPFH), 0.2, [_unit, _target, _timer]] call CBA_fnc_addPerFrameHandler;
// Disable collisions by setting the PhysX mass to almost zero
private _mass = getMass _target;
if (_mass > 1) then {
_target setVariable [QGVAR(originalMass), _mass, true];
[QEGVAR(common,setMass), [_target, 1e-12]] call CBA_fnc_globalEvent; // Force global sync
};
// Try to claim the object
[QEGVAR(common,claimSafe), [_unit, _target, true, QGVAR(startCarry)]] call CBA_fnc_serverEvent;

View File

@ -0,0 +1,97 @@
#include "..\script_component.hpp"
/*
* Author: commy2, PiZZADOX
* Starts the carrying process.
*
* Arguments:
* 0: Unit that should do the carrying <OBJECT>
* 1: Object to carry <OBJECT>
* 2: If object was successfully claimed <BOOL>
*
* Return Value:
* None
*
* Example:
* [player, cursorTarget, true] call ace_dragging_fnc_startCarryLocal;
*
* Public: No
*/
params ["_unit", "_target", "_claimed"];
TRACE_3("params",_unit,_target,_claimed);
if (!_claimed) exitWith {};
// Exempt from weight check if object has override variable set
private _weight = 0;
if !(_target getVariable [QGVAR(ignoreWeightCarry), false]) then {
_weight = _target call FUNC(getWeight);
};
// Exit if object weight is over global var value
if (_weight > GETMVAR(ACE_maxWeightCarry,1E11)) exitWith {
[LLSTRING(UnableToDrag)] call EFUNC(common,displayTextStructured);
};
// Create clone for dead units
if (!alive _target) then {
_target = [_unit, _target] call FUNC(createClone);
};
private _timer = CBA_missionTime + 5;
// Handle objects vs. persons
if (_target isKindOf "CAManBase") then {
private _primaryWeapon = primaryWeapon _unit;
// Add a primary weapon if the unit has none
if (_primaryWeapon == "") then {
_unit addWeapon "ACE_FakePrimaryWeapon";
_primaryWeapon = "ACE_FakePrimaryWeapon";
};
// Select primary, otherwise the drag animation actions don't work
_unit selectWeapon _primaryWeapon;
// Move a bit closer and adjust direction when trying to pick up a person
[QEGVAR(common,setDir), [_target, getDir _unit + 180], _target] call CBA_fnc_targetEvent;
_target setPosASL (getPosASL _unit vectorAdd (vectorDir _unit));
[_unit, "AcinPknlMstpSnonWnonDnon_AcinPercMrunSnonWnonDnon", 2] call EFUNC(common,doAnimation);
[_target, "AinjPfalMstpSnonWrflDnon_carried_Up", 2] call EFUNC(common,doAnimation);
_timer = CBA_missionTime + 10;
} else {
// Select no weapon and stop sprinting
private _previousWeaponIndex = [_unit] call EFUNC(common,getFiremodeIndex);
_unit setVariable [QGVAR(previousWeapon), _previousWeaponIndex, true];
_unit action ["SwitchWeapon", _unit, _unit, 299];
[_unit, "AmovPercMstpSnonWnonDnon", 0] call EFUNC(common,doAnimation);
private _canRun = _weight call FUNC(canRun_carry);
// Only force walking if we're overweight
[_unit, "forceWalk", QUOTE(ADDON), !_canRun] call EFUNC(common,statusEffect_set);
[_unit, "blockSprint", QUOTE(ADDON), _canRun] call EFUNC(common,statusEffect_set);
};
[_unit, "blockThrow", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
// Prevents dragging and carrying at the same time
_unit setVariable [QGVAR(isCarrying), true, true];
// Required for aborting animation
_unit setVariable [QGVAR(carriedObject), _target, true];
[FUNC(startCarryPFH), 0.2, [_unit, _target, _timer]] call CBA_fnc_addPerFrameHandler;
// Disable collisions by setting the PhysX mass to almost zero
private _mass = getMass _target;
if (_mass > 1) then {
_target setVariable [QGVAR(originalMass), _mass, true];
[QEGVAR(common,setMass), [_target, 1e-12]] call CBA_fnc_globalEvent; // Force global sync
};

View File

@ -1,10 +1,10 @@
#include "..\script_component.hpp"
/*
* Author: commy2, PiZZADOX, Malbryn
* Starts the dragging process.
* Author: johnb43
* Starts the dragging process safely.
*
* Arguments:
* 0: Unit that should do the dragging <OBJECT>
* 0: Unit that should do the carrying <OBJECT>
* 1: Object to drag <OBJECT>
*
* Return Value:
@ -17,93 +17,6 @@
*/
params ["_unit", "_target"];
TRACE_2("params",_unit,_target);
// Exempt from weight check if object has override variable set
private _weight = 0;
if !(_target getVariable [QGVAR(ignoreWeightDrag), false]) then {
_weight = _target call FUNC(getWeight);
};
// Exit if object weight is over global var value
if (_weight > GETMVAR(ACE_maxWeightDrag,1E11)) exitWith {
[LLSTRING(UnableToDrag)] call EFUNC(common,displayTextStructured);
};
// Create clone for dead units
if (!alive _target) then {
_target = _target call FUNC(createClone);
};
private _primaryWeapon = primaryWeapon _unit;
// Add a primary weapon if the unit has none
if !(GVAR(dragAndFire)) then {
if (_primaryWeapon == "") then {
_unit addWeapon "ACE_FakePrimaryWeapon";
_primaryWeapon = "ACE_FakePrimaryWeapon";
};
_unit selectWeapon _primaryWeapon;
} else { // Making sure the unit is holding a primary weapon or handgun
private _handgunWeapon = handgunWeapon _unit;
if !(currentWeapon _unit in [_primaryWeapon, _handgunWeapon]) then {
if (_primaryWeapon != "") then {
// Use primary if possible
_unit selectWeapon _primaryWeapon;
} else {
if (_handgunWeapon != "") then {
// Use pistol if unit has no primary
_unit selectWeapon _handgunWeapon;
} else {
// Add fake weapon if no weapons besides launcher are available
_unit addWeapon "ACE_FakePrimaryWeapon";
_unit selectWeapon "ACE_FakePrimaryWeapon";
};
};
};
};
// Save the weapon so we can monitor if it changes
_unit setVariable [QGVAR(currentWeapon), currentWeapon _unit];
[_unit, "blockThrow", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
// Prevent multiple players from accessing the same object
[_unit, _target, true] call EFUNC(common,claim);
// Can't play action that depends on weapon if it was added the same frame
if !(_unit call EFUNC(common,isSwimming)) then {
[{
private _unitWeapon = _this getVariable [QGVAR(currentWeapon), ""];
if (_unitWeapon isKindOf ["Pistol", configFile >> "CfgWeapons"]) then {
[_this, "ACE_dragWithPistol"] call EFUNC(common,doGesture);
} else {
[_this, "ACE_dragWithRifle"] 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 {
[QEGVAR(common,setDir), [_target, getDir _unit + 180], _target] call CBA_fnc_targetEvent;
_target setPosASL (getPosASL _unit vectorAdd (vectorDir _unit vectorMultiply 1.5));
[_target, "AinjPpneMrunSnonWnonDb_grab", 2] call EFUNC(common,doAnimation);
};
// Prevents dragging and carrying at the same time
_unit setVariable [QGVAR(isDragging), true, true];
[FUNC(startDragPFH), 0.2, [_unit, _target, CBA_missionTime + 5]] call CBA_fnc_addPerFrameHandler;
// Disable collisions by setting the physx mass to almost zero
private _mass = getMass _target;
if (_mass > 1) then {
_target setVariable [QGVAR(originalMass), _mass, true];
[QEGVAR(common,setMass), [_target, 1e-12]] call CBA_fnc_globalEvent; // Force global sync
};
// Try to claim the object
[QEGVAR(common,claimSafe), [_unit, _target, true, QGVAR(startDrag)]] call CBA_fnc_serverEvent;

View File

@ -0,0 +1,109 @@
#include "..\script_component.hpp"
/*
* Author: commy2, PiZZADOX, Malbryn
* Starts the dragging process.
*
* Arguments:
* 0: Unit that should do the dragging <OBJECT>
* 1: Object to drag <OBJECT>
* 2: If object was successfully claimed <BOOL>
*
* Return Value:
* None
*
* Example:
* [player, cursorTarget, true] call ace_dragging_fnc_startDragLocal;
*
* Public: No
*/
params ["_unit", "_target", "_claimed"];
TRACE_3("params",_unit,_target,_claimed);
if (!_claimed) exitWith {};
// Exempt from weight check if object has override variable set
private _weight = 0;
if !(_target getVariable [QGVAR(ignoreWeightDrag), false]) then {
_weight = _target call FUNC(getWeight);
};
// Exit if object weight is over global var value
if (_weight > GETMVAR(ACE_maxWeightDrag,1E11)) exitWith {
[LLSTRING(UnableToDrag)] call EFUNC(common,displayTextStructured);
};
// Create clone for dead units
if (!alive _target) then {
_target = [_unit, _target] call FUNC(createClone);
};
private _primaryWeapon = primaryWeapon _unit;
// Add a primary weapon if the unit has none
if !(GVAR(dragAndFire)) then {
if (_primaryWeapon == "") then {
_unit addWeapon "ACE_FakePrimaryWeapon";
_primaryWeapon = "ACE_FakePrimaryWeapon";
};
_unit selectWeapon _primaryWeapon;
} else { // Making sure the unit is holding a primary weapon or handgun
private _handgunWeapon = handgunWeapon _unit;
if !(currentWeapon _unit in [_primaryWeapon, _handgunWeapon]) then {
if (_primaryWeapon != "") then {
// Use primary if possible
_unit selectWeapon _primaryWeapon;
} else {
if (_handgunWeapon != "") then {
// Use pistol if unit has no primary
_unit selectWeapon _handgunWeapon;
} else {
// Add fake weapon if no weapons besides launcher are available
_unit addWeapon "ACE_FakePrimaryWeapon";
_unit selectWeapon "ACE_FakePrimaryWeapon";
};
};
};
};
// Save the weapon so we can monitor if it changes
_unit setVariable [QGVAR(currentWeapon), currentWeapon _unit];
[_unit, "blockThrow", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
// Can't play action that depends on weapon if it was added the same frame
if !(_unit call EFUNC(common,isSwimming)) then {
[{
private _unitWeapon = _this getVariable [QGVAR(currentWeapon), ""];
if (_unitWeapon isKindOf ["Pistol", configFile >> "CfgWeapons"]) then {
[_this, "ACE_dragWithPistol"] call EFUNC(common,doGesture);
} else {
[_this, "ACE_dragWithRifle"] 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 {
[QEGVAR(common,setDir), [_target, getDir _unit + 180], _target] call CBA_fnc_targetEvent;
_target setPosASL (getPosASL _unit vectorAdd (vectorDir _unit vectorMultiply 1.5));
[_target, "AinjPpneMrunSnonWnonDb_grab", 2] call EFUNC(common,doAnimation);
};
// Prevents dragging and carrying at the same time
_unit setVariable [QGVAR(isDragging), true, true];
[FUNC(startDragPFH), 0.2, [_unit, _target, CBA_missionTime + 5]] call CBA_fnc_addPerFrameHandler;
// Disable collisions by setting the physx mass to almost zero
private _mass = getMass _target;
if (_mass > 1) then {
_target setVariable [QGVAR(originalMass), _mass, true];
[QEGVAR(common,setMass), [_target, 1e-12]] call CBA_fnc_globalEvent; // Force global sync
};

View File

@ -5,7 +5,7 @@
if (!alive _player) exitWith {false};
if !([_player, objNull, ["isNotDragging", "isNotCarrying", "isNotSwimming"]] call EFUNC(common,canInteractWith)) exitWith {false};
// If we are drag/carrying something right now then just drop it:
// If we are dragging/carrying something right now then just drop it
if (_player getVariable [QGVAR(isDragging), false]) exitWith {
[_player, _player getVariable [QGVAR(draggedObject), objNull]] call FUNC(dropObject);
@ -34,7 +34,7 @@
if (!alive _player) exitWith {false};
if !([_player, objNull, ["isNotDragging", "isNotCarrying"]] call EFUNC(common,canInteractWith)) exitWith {false};
// If we are drag/carrying something right now then just drop it:
// If we are dragging/carrying something right now then just drop it
if (_player getVariable [QGVAR(isDragging), false]) exitWith {
[_player, _player getVariable [QGVAR(draggedObject), objNull]] call FUNC(dropObject);

View File

@ -32,7 +32,7 @@ GVAR(actions) = [];
if ("ace_dragging" call EFUNC(common,isModLoaded)) then {
GVAR(actions) pushBack [
localize ELSTRING(dragging,Drag), "drag",
LELSTRING(dragging,Drag), "drag",
{ACE_player != GVAR(target) && {[ACE_player, GVAR(target)] call EFUNC(dragging,canDrag)}},
{
GVAR(pendingReopen) = false;
@ -41,7 +41,7 @@ if ("ace_dragging" call EFUNC(common,isModLoaded)) then {
];
GVAR(actions) pushBack [
localize ELSTRING(dragging,Carry), "drag",
LELSTRING(dragging,Carry), "drag",
{ACE_player != GVAR(target) && {[ACE_player, GVAR(target)] call EFUNC(dragging,canCarry)}},
{
GVAR(pendingReopen) = false;

View File

@ -57,9 +57,60 @@ class ACE_Medical_Treatment_Actions {
};
```
## 2. Mission Variables
## 2. Medical Vehicles and Facilities
### 2.1 Grave Digging Object Configuration
### 2.1 Medical Vehicles
To configure a vehicle as a Medical Vehicle by default, set the `attendant` property in the vehicle's config to `1`.
```cpp
class CfgVehicles {
class MyAmbulance {
attendant = 1;
};
};
```
To set a vehicle as a Medical Vehicle mid-mission, set the `ace_medical_isMedicalVehicle` variable globally.
```sqf
// Sets the object behind your cursor to be a medical vehicle
cursorObject setVariable ["ace_medical_isMedicalVehicle", true, true];
// Create an interaction to turn a vehicle into a medical vehicle
private _statement = {_target setVariable ["ace_medical_isMedicalVehicle", true, true]};
private _action = ["TAG_makeMedicalVehicle", "Set as Medical Vehicle", _statement, {!([_target] call ace_medical_treatment_fnc_isMedicalVehicle)}] call ace_interact_menu_fnc_createAction;
[cursorObject, 0, ["ACE_MainActions"], _action] call ace_interact_menu_fnc_createAction;
// Set all vehicles of type "B_Truck_01_transport_F" as medical vehicles
private _classname = "B_Truck_01_transport_F";
private _affectChildClasses = false; // Affect variants of this vehicle
["B_Truck_01_transport_F", "InitPost", {
params ["_vehicle"];
if (!local _vehicle) exitWith {};
_vehicle setVariable ["ace_medical_isMedicalVehicle", true, true];
}, _affectChildClasses, [], true] call CBA_fnc_addClassEventHandler;
```
### 2.2 Medical Facilities
To configure an object as a Medical Facility by default, add a new array containing its classname to the `ace_medical_facilities` class in config root.
```cpp
class CfgVehicles {
class ThingX;
class MyMedicalFacility: ThingX {};
class MyMedicalFacility2_ElectricBoogaloo: MyMedicalFacility {};
};
class ace_medical_facilities {
TAG_allOfMyFacilities[] = {"MyMedicalFacility", "MyMedicalFacility2_ElectricBoogaloo"};
};
```
To set an object as a Medical Facility mid-mission, set the `ace_medical_isMedicalFacility` variable globally. See above.
Both Medical Facilities and Medical Vehicles can also be created via the Eden Editor's attributes menu.
## 3. Mission Variables
### 3.1 Grave Digging Object Configuration
The object created when digging a grave can be modified by setting the `ace_medical_treatment_graveClassname` variable.
```sqf
@ -71,7 +122,7 @@ The object's rotation can also be modified, if necessary.
ace_medical_treatment_graveRotation = 0; // rotation angle (will depend on model classname)
```
### 2.2 Zeus Medical Menu Module
### 3.2 Zeus Medical Menu Module
If a mission maker wishes to disable Zeus access to the medical menu, they can set the variable below:
ace_medical_gui_enableZeusModule = false; // default is true