Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow damage handler (also block only collision damage) #2758

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions addons/common/XEH_postInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ if (isServer) then {
[FUNC(syncedEventPFH), 0.5, []] call CBA_fnc_addPerFrameHandler;
};

//Add allowDamage (and collision) synced event handler
[QGVAR(allowDamage), FUNC(handleAllowDamage), 0] call FUNC(addSyncedEventHandler);


// @todo deprecated
QGVAR(remoteFnc) addPublicVariableEventHandler {
(_this select 1) call FUNC(execRemoteFnc);
Expand Down
2 changes: 2 additions & 0 deletions addons/common/XEH_preInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ PREP(getWindDirection);
PREP(getZoom);
PREP(goKneeling);
PREP(hadamardProduct);
PREP(handleAllowDamage);
PREP(handleModifierKey);
PREP(handleModifierKeyUp);
PREP(handleModifierKeyInit);
Expand Down Expand Up @@ -150,6 +151,7 @@ PREP(selectWeaponMode);
PREP(sendRequest);
PREP(serverLog);
PREP(setAllGear);
PREP(setAllowDamage);
PREP(setCaptivityStatus);
PREP(setDefinedVariable);
PREP(setDisableUserInputStatus);
Expand Down
22 changes: 11 additions & 11 deletions addons/common/functions/fnc__handleSyncedEvent.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* Arguments [Client] :
* 0: eventName <STRING>
* 1: arguments <ARRAY>
* 2: ttl <SCALAR>
* 2: ttl <SCALAR><CODE>
*
* Return Value:
* Boolean of success <BOOL>
Expand All @@ -21,20 +21,20 @@ if (!HASH_HASKEY(GVAR(syncedEvents),_name)) exitWith {
false
};

private ["_internalData", "_eventCode"];

_internalData = HASH_GET(GVAR(syncedEvents),_name);
local _internalData = HASH_GET(GVAR(syncedEvents),_name);
_internalData params ["_eventCode", "_eventLog"];

if (isServer) then {
// Server needs to internally log it for synchronization
if (_ttl > -1) then {
_internalData = HASH_GET(GVAR(syncedEvents),_name);

private "_eventLog";
_eventLog = _internalData select 1;
_eventLog pushback [ACE_diagTime, _args, _ttl];
local _entry = [ACE_diagTime, _args, _ttl];
local _addToSync = if (typeName _ttl == "CODE") then {
[_eventCode, _entry] call _ttl;
} else {
_ttl > -1
};
if (_addToSync) then {
_eventLog pushback _entry;
};
};

_eventCode = _internalData select 0;
_args call _eventCode;
6 changes: 4 additions & 2 deletions addons/common/functions/fnc_fixCollision.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
if (!local _this) exitWith {};

// prevent collision damage, @todo allowDamage API
_this allowDamage false;
[_this, "fixCollision", 1] call FUNC(setAllowDamage);

// re-allow damage after 2 seconds
[{_this allowDamage true}, _this, 2, 0] call EFUNC(common,waitAndExecute);
[{
[_this, "fixCollision", 0] call FUNC(setAllowDamage);
}, _this, 2] call EFUNC(common,waitAndExecute);
8 changes: 7 additions & 1 deletion addons/common/functions/fnc_fixFloating.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,18 @@ _hitPointDamages = getAllHitPointsDamage _object;

// get correct format for objects without hitpoints
if (_hitPointDamages isEqualTo []) then {
_hitPointDamages = [[],[],[]];
_hitPointDamages = [[],[],[]];
};

//manualy set allowDamage true or setHitIndex does not work
_object allowDamage true;

// this prevents physx objects from floating when near other physx objects with allowDamage false
_object setDamage damage _object;

{
_object setHitIndex [_forEachIndex, _x];
} forEach (_hitPointDamages select 2);

//reset allowDamage to what it should be
[_object] call FUNC(handleAllowDamage);
55 changes: 55 additions & 0 deletions addons/common/functions/fnc_handleAllowDamage.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Author: PabstMirror
* Handles the "ace_common_allowDamage" synced event
*
* Arguments:
* 0: object<OBJECT>
*
* Return Value:
* None
*
* Example:
* [box1] call ace_common_fnc_handleAllowDamage;
*
* Public: No
*/
#define DEBUG_MODE_FULL
#include "script_component.hpp"

params ["_object"];
(_object getVariable [QGVAR(allowDamage), [-1, -1]]) params ["_blockCollisionNum", "_blockDamageNum"];

TRACE_3("",_object,_blockCollisionNum,_blockDamageNum);

if (_blockDamageNum > 0) then {
TRACE_1("allowDamage false",_blockDamageNum);
_object allowDamage false;
} else {
TRACE_1("allowDamage true",_blockDamageNum);
_object allowDamage true;
};

local _collisionHandler = _object getVariable [QGVAR(allowCollisionHandler), -1];
if (_blockCollisionNum > 0) then {
if (_collisionHandler == -1) then {
TRACE_1("Adding HandleDamage EH", _collisionHandler);
_collisionHandler = _object addEventHandler ["HandleDamage", {
params ["_object", "", "", "", "_projectile", "_index"];
TRACE_1("HD",_this);
if (!local _unit) exitWith {nil};
if (_projectile != "") exitWith {nil};
local _return = if (_index < 0) then {damage _object} else {_object getHitIndex _index};
TRACE_1("blocking",_return);
_return
}];
_object setVariable [QGVAR(allowCollisionHandler), _collisionHandler];
};
} else {
if (_collisionHandler != -1) then {
TRACE_1("Removing HandleDamage EH", _collisionHandler);
_object removeEventHandler ["HandleDamage", _collisionHandler];
_object setVariable [QGVAR(allowCollisionHandler), nil];
};
};

nil
88 changes: 88 additions & 0 deletions addons/common/functions/fnc_setAllowDamage.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Author: PabstMirror
* Allows multiple sources to block all or just collision damage on objects
*
* Arguments:
* 0: Object <OBJECT>
* 1: Source Reason <STRING>
* 2: State (0 = allow all, 1 = block colision, 2 = block all) <NUMBER>
*
* Return Value:
* None
*
* Example:
* [box1, "preventColision", 1] call ace_common_fnc_setAllowDamage;
*
* Public: Yes
*/
#define DEBUG_MODE_FULL
#include "script_component.hpp"

params ["_object", "_reason", "_state"];

TRACE_3("params",_object,_reason,_state);

_allowDamageReasons = missionNamespace getVariable [QGVAR(allowDamageReasons), []];

_objectAllowDamage = _object getVariable [QGVAR(allowDamage), [0,0]];
_objectAllowDamage params ["_blockCollisionNum", "_blockDamageNum"];

_blockCollisionArray = [_blockCollisionNum, count _allowDamageReasons] call FUNC(binarizeNumber);
_blockDamageArray = [_blockDamageNum, count _allowDamageReasons] call FUNC(binarizeNumber);

//If there is a reason, set it in the arrays:
if (_reason != "") then {
_reason = toLower _reason;
// register new reason (these reasons are shared publicly, since units can change ownership, but keep their forceWalk status)
if !(_reason in _allowDamageReasons) then {
_allowDamageReasons pushBack _reason;
GVAR(allowDamageReasons) = _allowDamageReasons;
publicVariable QGVAR(allowDamageReasons);
};
_index = _allowDamageReasons find _reason;
switch (_state) do {
case (0): {
_blockCollisionArray set [_index, false];
_blockDamageArray set [_index, false];
};
case (1): {
_blockCollisionArray set [_index, true];
_blockDamageArray set [_index, false];
};
case (2): {
_blockCollisionArray set [_index, false];
_blockDamageArray set [_index, true];
};
};
};

_newBlockCollisionNum = _blockCollisionArray call FUNC(toBitmask);
_newBlockDamageNum = _blockDamageArray call FUNC(toBitmask);

if ((_newBlockDamageNum == _blockDamageNum) && {_newBlockCollisionNum == _blockCollisionNum}) exitWith {
TRACE_2("No Change",_newBlockCollisionNum, _newBlockDamageNum);
};

TRACE_2("Updating",_newBlockCollisionNum, _newBlockDamageNum);
_object setVariable [QGVAR(allowDamage), [_newBlockCollisionNum, _newBlockDamageNum], true];

if ((_object isKindOf "CAManBase") && {["ace_medical"] call FUNC(isModLoaded)}) exitWith {
//ACE_medical already has a handleDamage installed on the Unit and we can just setVariables for it
TRACE_1("handled by ace medical", _object);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_object setvariable [QEGVAR(medical,allowdamage), false];

};

if ((_newBlockCollisionNum + _newBlockDamageNum) > 0) then {
local _ttlCondition = {
((_this select 1) select 1) params ["_object", "_statusArray"];
TRACE_1("TTL Check", _object);
//Only keep event if getVariable is same as event variable (also handles objNull)
(_statusArray isEqualTo (_object getVariable [QGVAR(allowDamage), [-1, -1]]))
};
TRACE_1("allowDamage event IS synced", _object);
[QGVAR(allowDamage), [_object, [_newBlockCollisionNum, _newBlockDamageNum]], _ttlCondition] call EFUNC(common,syncedEvent);
} else {
TRACE_1("allowDamage event IS NOT synced", _object);
[QGVAR(allowDamage), [_object, [_newBlockCollisionNum, _newBlockDamageNum]], -1] call EFUNC(common,syncedEvent);
};

nil
6 changes: 3 additions & 3 deletions addons/common/functions/fnc_syncedEventPFH.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ if (!isServer) exitWith {false};
_name = _x;

_data = HASH_GET(GVAR(syncedEvents),_name);
_data params ["_eventTime", "_eventLog", "_globalEventTTL"];
_data params ["_eventCode", "_eventLog", "_globalEventTTL"];

_newEventLog = [];

Expand All @@ -36,7 +36,7 @@ if (!isServer) exitWith {false};
_ttlReturn = true;

if (typeName _globalEventTTL == "CODE") then {
_ttlReturn = [_eventTime, _eventEntry] call _globalEventTTL;
_ttlReturn = [_eventCode, _eventEntry] call _globalEventTTL;
} else {
_ttlReturn = call {_globalEventTTL < 1 || {ACE_diagTime < (_eventEntry select 0) + _globalEventTTL}};
};
Expand All @@ -46,7 +46,7 @@ if (!isServer) exitWith {false};
_eventEntry params ["_time", "", "_eventTTL"];

if (typeName _eventTTL == "CODE") then {
_ttlReturn = [_eventTime, _eventEntry] call _eventTTL;
_ttlReturn = [_eventCode, _eventEntry] call _eventTTL;
} else {
_ttlReturn = call {_eventTTL < 1 || {ACE_diagTime < _time + _eventTTL}};
};
Expand Down
5 changes: 3 additions & 2 deletions addons/medical/XEH_postInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,9 @@ GVAR(lastHeartBeatSound) = ACE_time;
};

["SettingsInitialized", {
// Networked litter (need to wait for GVAR(litterCleanUpDelay) to be set)
[QGVAR(createLitter), FUNC(handleCreateLitter), GVAR(litterCleanUpDelay)] call EFUNC(common,addSyncedEventHandler);

if (GVAR(level) == 2) exitwith {
[
{(((_this select 0) getvariable [QGVAR(bloodVolume), 100]) < 65)},
Expand Down Expand Up @@ -276,8 +279,6 @@ GVAR(lastHeartBeatSound) = ACE_time;
[ACE_player] call FUNC(itemCheck);
}] call EFUNC(common,addEventHandler);

// Networked litter
[QGVAR(createLitter), FUNC(handleCreateLitter), GVAR(litterCleanUpDelay)] call EFUNC(common,addSyncedEventHandler);

if (hasInterface) then {
["PlayerJip", {
Expand Down
4 changes: 3 additions & 1 deletion addons/medical/functions/fnc_handleDamage.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ if (_selection == "legs") exitWith {_unit getHit "legs"};
if (_selection != "" && {!(_selection in GVAR(SELECTIONS))}) exitWith {0}; //@todo "neck", "pelvis", "spine1", "spine2", "spine3"

// Exit if we disable damage temporarily
if !(_unit getVariable [QGVAR(allowDamage), true]) exitWith {
(_unit getVariable [QEGVAR(common,allowDamage), [0,0]]) params ["_blockCollisionNum", "_blockDamageNum"];
TRACE_2("commonDamageBlock",_blockCollisionNum,_blockDamageNum);
if ((!(_unit getVariable [QGVAR(allowDamage), true])) || {(_blockCollisionNum > 0) && {_projectile == ""}} || {_blockDamageNum > 0}) exitWith {
TRACE_3("ACE_DEBUG: HandleDamage damage disabled.",_selection,damage _unit,_unit);
if (_selection == "") then {
damage _unit
Expand Down