Sync corpses when JIP to avoid weird hitbox collision, renamed function and added API

The idea behind the API is for 3rd party mods that include garbage collectors to exclude corpses that are being dragged/carried.
This commit is contained in:
johnb432 2024-07-01 18:36:37 +02:00
parent 9c65030b41
commit 28560b9ad9
7 changed files with 102 additions and 56 deletions

View File

@ -6,9 +6,9 @@ PREP(canRun_carry);
PREP(carryObject);
PREP(carryObjectPFH);
PREP(createClone);
PREP(deleteClone);
PREP(dragObject);
PREP(dragObjectPFH);
PREP(dropClone);
PREP(dropObject);
PREP(dropObject_carry);
PREP(getWeight);

View File

@ -1,9 +1,72 @@
// by PabstMirror, commy2
#include "script_component.hpp"
[QGVAR(moveCorpse), {
params ["_corpse", "_dir", "_posATL"];
_posATL params ["_xPos", "_yPos", "_zPos"];
if (isNull _corpse) exitWith {};
private _currentPos = getPosATL _corpse;
// Check if the corpse is already close to the target
// If so, don't teleport
if !(
(_currentPos select 0 <= _xPos + 0.25) &&
{_currentPos select 0 >= _xPos - 0.25} &&
{_currentPos select 1 <= _yPos + 0.25} &&
{_currentPos select 1 >= _yPos - 0.25} &&
{_currentPos select 2 <= _zPos + 0.25} &&
{_currentPos select 2 >= _zPos - 0.25}
) then {
// Set direction before position
_corpse setDir _dir;
// Bring corpse back to clone's position
_corpse setPosATL _posATL;
};
// Sync the corpse with its position
[{
_this awake true;
[{
_this awake false;
}, _this] call CBA_fnc_execNextFrame;
}, _corpse] call CBA_fnc_execNextFrame;
// Allow the corpse to be synced for JIP players
if (isServer) exitWith {
GVAR(movedCorpses) pushBackUnique _corpse;
};
}] call CBA_fnc_addEventHandler;
if (isServer) then {
// Release object on disconnection. Function is identical to killed
addMissionEventHandler ["HandleDisconnect", LINKFUNC(handleKilled)];
GVAR(movedCorpses) = [];
["CAManBase", "Deleted", {
GVAR(movedCorpses) deleteAt (GVAR(movedCorpses) find (_this select 0));
}, true, [], true] call CBA_fnc_addClassEventHandler;
[QGVAR(disableSyncMovedCorpseOnJIP), {
params ["_corpse"];
GVAR(movedCorpses) deleteAt (GVAR(movedCorpses) find _corpse);
}] call CBA_fnc_addEventHandler;
// Sync position of dead corpse for JIP unit (prevents weird invisible hitboxes on corpses)
[QGVAR(requestSyncMovedCorpsesJIP), {
params ["_clientOwner"];
{
[QGVAR(moveCorpse), [_x, getDir _x, getPosATL _x], _clientOwner] call CBA_fnc_ownerEvent;
} forEach GVAR(movedCorpses);
}] call CBA_fnc_addEventHandler;
} else {
[QGVAR(requestSyncMovedCorpsesJIP), clientOwner] call CBA_fnc_serverEvent;
};
if (!hasInterface) exitWith {};
@ -59,50 +122,17 @@ if (isNil QGVAR(maxWeightCarryRun)) then {
// Handle waking up dragged unit and falling unconscious while dragging
["ace_unconscious", LINKFUNC(handleUnconscious)] call CBA_fnc_addEventHandler;
// Handle local effect commands for clones
[QGVAR(cloneCreated), {
params ["_unit", "_clone"];
_clone setFace face _unit;
_clone setMimic "unconscious";
}] call CBA_fnc_addEventHandler;
[QGVAR(moveCorpse), {
params ["_corpse", "_dir", "_pos"];
_pos params ["_xPos", "_yPos", "_zPos"];
private _currentPos = getPosATL _corpse;
// Check if the corpse is already close to the target
// If so, don't teleport
if !(
(_currentPos select 0 <= _xPos + 0.25) &&
{_currentPos select 0 >= _xPos - 0.25} &&
{_currentPos select 1 <= _yPos + 0.25} &&
{_currentPos select 1 >= _yPos - 0.25} &&
{_currentPos select 2 <= _zPos + 0.25} &&
{_currentPos select 2 >= _zPos - 0.25}
) then {
// Set direction before position
_corpse setDir _dir;
// Bring corpse back to clone's position
_corpse setPosATL _pos;
};
// Sync the corpse with its position
[{
_this awake true;
[{
_this awake false;
}, _this] call CBA_fnc_execNextFrame;
}, _corpse] call CBA_fnc_execNextFrame;
}] call CBA_fnc_addEventHandler;
// Display event handler
["MouseZChanged", {(_this select 1) call FUNC(handleScrollWheel)}] call CBA_fnc_addDisplayHandler;
// Handle local effect commands for clones
[QGVAR(setCloneFace), {
params ["_clone", "_corpse"];
_clone setFace face _corpse;
_clone setMimic "unconscious";
}] call CBA_fnc_addEventHandler;
// Handle surrendering and handcuffing
["ace_captiveStatusChanged", {
params ["_unit", "_state"];

View File

@ -11,13 +11,16 @@
* Cloned unit <OBJECT>
*
* Example:
* [player] call ace_dragging_fnc_createClone;
* [player, cursorObject] call ace_dragging_fnc_createClone;
*
* Public: No
*/
params ["_unit", "_target"];
// Don't sync corpse when a player joins in progress until the corpse is in its proper position
[QGVAR(disableSyncMovedCorpseOnJIP), _target] call CBA_fnc_serverEvent;
private _posATL = getPosATL _target;
// Create clone
@ -54,11 +57,11 @@ if (_isInRemainsCollector) then {
};
// Make sure clone has the same wound textures as the corpse
_clone setDamage ((damage _target) min 0.99); // don't kill the clone
_clone setDamage ((damage _target) min 0.99); // Don't kill the clone
{
_clone setHitPointDamage [_x, (_target getHitPointDamage _x) min 0.99];
} forEach ["HitHead", "HitBody", "HitHands", "HitLegs"]; // relevant hitpoints
} forEach ["HitHead", "HitBody", "HitHands", "HitLegs"]; // Relevant hitpoints
// Disable all damage
_clone allowDamage false;
@ -67,7 +70,10 @@ _clone setVariable [QGVAR(original), [_target, _isInRemainsCollector, _isObjectH
[_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;
[[QGVAR(setCloneFace), [_clone, _target]] call CBA_fnc_globalEventJIP, _clone] call CBA_fnc_removeGlobalEventJIP;
// API
[QGVAR(cloneCreated), [_clone, _target]] call CBA_fnc_localEvent;
[{
params ["_clone", "_target"];

View File

@ -12,7 +12,7 @@
* Original unit <OBJECT>
*
* Example:
* [player, cursorObject, false] call ace_dragging_fnc_dropClone;
* [player, cursorObject, false] call ace_dragging_fnc_deleteClone;
*
* Public: No
*/
@ -26,21 +26,24 @@ params ["_unit", "_clone", "_inBuilding"];
["_simulationEnabled", true]
];
// API
[QGVAR(cloneDeleted), [_clone, _target]] call CBA_fnc_localEvent;
// Check if unit was deleted
if (!isNull _target) then {
private _pos = getPosATL _clone;
private _posATL = getPosATL _clone;
if (_inBuilding) then {
_pos = _pos vectorAdd [0, 0, 0.05];
_posATL = _posATL vectorAdd [0, 0, 0.05];
};
// Make sure position is not underground
if (_pos select 2 < 0.05) then {
_pos set [2, 0.05];
// Make sure position isn't underground
if (_posATL select 2 < 0.05) then {
_posATL set [2, 0.05];
};
// Move the unit globally (important, as it doesn't work otherwise)
[QGVAR(moveCorpse), [_target, getDir _unit + 180, _pos]] call CBA_fnc_globalEvent;
// Move the unit globally (important, as it desyncs the corpse position otherwise)
[QGVAR(moveCorpse), [_target, getDir _unit + 180, _posATL]] call CBA_fnc_globalEvent;
// Unhide unit
if (!_isObjectHidden) then {

View File

@ -35,7 +35,7 @@ private _isClone = _target isKindOf QGVAR(clone);
// Drop cloned dead units
if (_isClone) then {
_target = [_unit, _target, _inBuilding] call FUNC(dropClone);
_target = [_unit, _target, _inBuilding] call FUNC(deleteClone);
};
// Play release animation

View File

@ -29,7 +29,7 @@ private _isClone = _target isKindOf QGVAR(clone);
// Drop cloned dead units
if (_isClone) then {
_target = [_unit, _target, _inBuilding] call FUNC(dropClone);
_target = [_unit, _target, _inBuilding] call FUNC(deleteClone);
};
// Prevent collision damage

View File

@ -167,6 +167,13 @@ MenuType: 0 = Interaction, 1 = Self Interaction
| `ace_headless_groupTransferPre` | [_group, _HC (OBJECT), _previousOwner, _idHC] | Target | Listen | Called just before a group is transferred from any machine to a HC. Called where group currently is local and on the HC, where group is going to be local.
| `ace_headless_groupTransferPost` | [_group, _HC (OBJECT), _previousOwner, _idHC, _transferredSuccessfully] | Target | Listen | Called just after a group is transferred from a machine to a HC. Called where group was local and on the HC, where group is now local. `_transferredSuccessfully` is passed so mods can actually check if the locality was properly transferred, as ownership transfer is not guaranteed.
### 2.18 Interaction (`ace_dragging`)
| Event Key | Parameters | Locality | Type | Description |
|---------- |------------|----------|------|-------------|
| `ace_dragging_cloneCreated` | [_clone, _corpse] | Local | Listen | Called when a clone used for dragging/carrying corpses is created
| `ace_dragging_cloneDeleted` | [_clone, _corpse] | Local | Listen | Called when a clone used for dragging/carrying corpses is deleted
## 3. Usage
Also Reference [CBA Events System](https://github.com/CBATeam/CBA_A3/wiki/Custom-Events-System){:target="_blank"} documentation.