From e4db621d0139686a076051e50dd29eb02ecaf657 Mon Sep 17 00:00:00 2001 From: Dart Date: Sun, 18 Jan 2026 12:34:44 -0600 Subject: [PATCH 01/14] Port status effects to CBA --- addons/statuseffects/$PBOPREFIX$ | 1 + addons/statuseffects/CfgEventHandlers.hpp | 11 ++ addons/statuseffects/CfgFunctions.hpp | 9 ++ addons/statuseffects/XEH_PREP.hpp | 4 + addons/statuseffects/XEH_postInit.sqf | 131 ++++++++++++++++++ addons/statuseffects/XEH_preInit.sqf | 7 + addons/statuseffects/XEH_preStart.sqf | 3 + addons/statuseffects/config.cpp | 18 +++ .../statuseffects/fnc_addStatusEffectType.sqf | 47 +++++++ addons/statuseffects/fnc_getStatusEffect.sqf | 68 +++++++++ addons/statuseffects/fnc_localEH.sqf | 39 ++++++ addons/statuseffects/fnc_resetVariables.sqf | 51 +++++++ addons/statuseffects/fnc_respawnEH.sqf | 38 +++++ addons/statuseffects/fnc_sendEffects.sqf | 60 ++++++++ addons/statuseffects/fnc_setStatusEffect.sqf | 81 +++++++++++ addons/statuseffects/script_component.hpp | 16 +++ addons/statuseffects/stringtable.xml | 8 ++ 17 files changed, 592 insertions(+) create mode 100644 addons/statuseffects/$PBOPREFIX$ create mode 100644 addons/statuseffects/CfgEventHandlers.hpp create mode 100644 addons/statuseffects/CfgFunctions.hpp create mode 100644 addons/statuseffects/XEH_PREP.hpp create mode 100644 addons/statuseffects/XEH_postInit.sqf create mode 100644 addons/statuseffects/XEH_preInit.sqf create mode 100644 addons/statuseffects/XEH_preStart.sqf create mode 100644 addons/statuseffects/config.cpp create mode 100644 addons/statuseffects/fnc_addStatusEffectType.sqf create mode 100644 addons/statuseffects/fnc_getStatusEffect.sqf create mode 100644 addons/statuseffects/fnc_localEH.sqf create mode 100644 addons/statuseffects/fnc_resetVariables.sqf create mode 100644 addons/statuseffects/fnc_respawnEH.sqf create mode 100644 addons/statuseffects/fnc_sendEffects.sqf create mode 100644 addons/statuseffects/fnc_setStatusEffect.sqf create mode 100644 addons/statuseffects/script_component.hpp create mode 100644 addons/statuseffects/stringtable.xml diff --git a/addons/statuseffects/$PBOPREFIX$ b/addons/statuseffects/$PBOPREFIX$ new file mode 100644 index 0000000000..a7387fcb45 --- /dev/null +++ b/addons/statuseffects/$PBOPREFIX$ @@ -0,0 +1 @@ +x\cba\addons\statuseffects diff --git a/addons/statuseffects/CfgEventHandlers.hpp b/addons/statuseffects/CfgEventHandlers.hpp new file mode 100644 index 0000000000..4300a157b9 --- /dev/null +++ b/addons/statuseffects/CfgEventHandlers.hpp @@ -0,0 +1,11 @@ +class Extended_PreInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_SCRIPT(XEH_preInit)); + }; +}; + +class Extended_PostInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_SCRIPT(XEH_postInit)); + }; +}; diff --git a/addons/statuseffects/CfgFunctions.hpp b/addons/statuseffects/CfgFunctions.hpp new file mode 100644 index 0000000000..75dd80c83b --- /dev/null +++ b/addons/statuseffects/CfgFunctions.hpp @@ -0,0 +1,9 @@ +class CfgFunctions { + class CBA { + class StatusEffects { + PATHTO_FNC(addStatusEffectType); + PATHTO_FNC(getStatusEffect); + PATHTO_FNC(setStatusEffect); + }; + }; +}; diff --git a/addons/statuseffects/XEH_PREP.hpp b/addons/statuseffects/XEH_PREP.hpp new file mode 100644 index 0000000000..6664581b6d --- /dev/null +++ b/addons/statuseffects/XEH_PREP.hpp @@ -0,0 +1,4 @@ +PREP(localEH); +PREP(resetVariables); +PREP(respawnEH); +PREP(sendEffects); diff --git a/addons/statuseffects/XEH_postInit.sqf b/addons/statuseffects/XEH_postInit.sqf new file mode 100644 index 0000000000..6c6616e6e0 --- /dev/null +++ b/addons/statuseffects/XEH_postInit.sqf @@ -0,0 +1,131 @@ +#include "script_component.hpp" + +[QGVAR(setStatusEffect), LINKFUNC(statusEffect_set)] call CBA_fnc_addEventHandler; +["forceWalk", false, ["ace_advanced_fatigue", "ace_attach", "ace_dragging", "ace_explosives", "ace_medical_fracture", "ace_rearm", "ace_refuel", "ace_sandbag", "ace_switchunits", "ace_tacticalladder", "ace_trenches"]] call CBA_fnc_addStatusEffectType; +["blockSprint", false, ["ace_advanced_fatigue", "ace_dragging", "ace_medical_fracture"]] call CBA_fnc_addStatusEffectType; +["setCaptive", true, ["ace_captives_handcuffed", "ace_captives_surrendered"]] call CBA_fnc_addStatusEffectType; +["blockDamage", false, ["fixCollision", "ace_cargo"]] call CBA_fnc_addStatusEffectType; +["blockEngine", false, ["ace_refuel"]] call CBA_fnc_addStatusEffectType; +["blockThrow", false, ["ace_attach", "ace_concertina_wire", "ace_dragging", "ace_explosives", "ace_rearm", "ace_refuel", "ace_sandbag", "ace_tacticalladder", "ace_trenches", "ace_tripod"]] call CBA_fnc_addStatusEffectType; +["setHidden", true, ["ace_unconscious"]] call CBA_fnc_addStatusEffectType; +["blockRadio", false, ["ace_captives_handcuffed", "ace_captives_surrendered", "ace_unconscious"]] call CBA_fnc_addStatusEffectType; +["blockSpeaking", false, ["ace_unconscious"]] call CBA_fnc_addStatusEffectType; +["disableWeaponAssembly", false, ["ace_common", "ace_common_lockVehicle", "ace_csw"]] call CBA_fnc_addStatusEffectType; +["lockInventory", true, [], true] call CBA_fnc_addStatusEffectType; + +[QGVAR(forceWalk), { + params ["_object", "_set"]; + TRACE_2("forceWalk EH",_object,_set); + _object forceWalk (_set > 0); +}] call CBA_fnc_addEventHandler; + +[QGVAR(blockSprint), { //Name reversed from `allowSprint` because we want NOR logic + params ["_object", "_set"]; + TRACE_2("blockSprint EH",_object,_set); + _object allowSprint (_set == 0); +}] call CBA_fnc_addEventHandler; + +[QGVAR(setAnimSpeedCoef), { + params ["_object", "_set"]; + _object setAnimSpeedCoef _set; +}] call CBA_fnc_addEventHandler; + +[QGVAR(setCaptive), { + params ["_object", "_set"]; + TRACE_2("setCaptive EH",_object,_set); + _object setCaptive (_set > 0); +}] call CBA_fnc_addEventHandler; + +[QGVAR(setHidden), { + params ["_object", "_set"]; + TRACE_2("setHidden EH",_object,_set); + // May report nil. Default to factor 1. + private _vis = [_object getUnitTrait "camouflageCoef"] param [0, 1]; + if (_set > 0) then { + if (_vis != 0) then { + _object setVariable [QGVAR(oldVisibility), _vis]; + _object setUnitTrait ["camouflageCoef", 0]; + { + if (side _x != side group _object) then { + _x forgetTarget _object; + }; + } forEach allGroups; + }; + } else { + _vis = _object getVariable [QGVAR(oldVisibility), _vis]; + _object setUnitTrait ["camouflageCoef", _vis]; + }; +}] call CBA_fnc_addEventHandler; + +[QGVAR(blockRadio), { + params ["_object", "_set"]; + TRACE_2("blockRadio EH",_object,_set); + if (_object isEqualTo ACE_Player && {_set > 0}) then { + call FUNC(endRadioTransmission); + }; + if ("task_force_radio" call FUNC(isModLoaded)) then { + _object setVariable ["tf_unable_to_use_radio", _set > 0, true]; + }; + if ("acre_main" call FUNC(isModLoaded)) then { + _object setVariable ["acre_sys_core_isDisabledRadio", _set > 0, true]; + }; +}] call CBA_fnc_addEventHandler; + +[QGVAR(blockSpeaking), { + params ["_object", "_set"]; + TRACE_2("blockSpeaking EH",_object,_set); + if ("task_force_radio" call FUNC(isModLoaded)) then { + _object setVariable ["tf_voiceVolume", parseNumber (_set == 0), true]; + }; + if ("acre_main" call FUNC(isModLoaded)) then { + _object setVariable ["acre_sys_core_isDisabled", _set > 0, true]; + }; +}] call CBA_fnc_addEventHandler; + +[QGVAR(blockDamage), { //Name reversed from `allowDamage` because we want NOR logic + params ["_object", "_set"]; + if ((_object isKindOf "CAManBase") && {("ace_medical" call FUNC(isModLoaded))}) then { + TRACE_2("blockDamage EH (using medical)",_object,_set); + _object setVariable ["ace_medical_allowDamage", (_set == 0), true]; + } else { + TRACE_2("blockDamage EH (using allowDamage)",_object,_set); + _object allowDamage (_set == 0); + }; +}] call CBA_fnc_addEventHandler; + +[QGVAR(blockEngine), { + params ["_vehicle", "_set"]; + _vehicle setVariable ["ace_common_blockEngine", _set > 0, true]; + _vehicle engineOn false; +}] call CBA_fnc_addEventHandler; + +[QGVAR(setMass), { + params ["_object", "_mass"]; + _object setMass _mass; +}] call CBA_fnc_addEventHandler; + +[QGVAR(disableWeaponAssembly), { + params ["_object", "_set"]; + _object enableWeaponDisassembly (_set < 1); +}] call CBA_fnc_addEventHandler; + +[QGVAR(lockInventory), { + params ["_object", "_set"]; + TRACE_2("lockInventory EH",_object,_set); + _object lockInventory (_set > 0); +}] call CBA_fnc_addEventHandler; + +[QGVAR(lockVehicle), { + _this setVariable [QGVAR(lockStatus), locked _this]; + _this lock 2; + if ([] isNotEqualTo getArray (configOf _this >> "assembleInfo" >> "dissasembleTo")) then { + [_this, "disableWeaponAssembly", "ace_common_lockVehicle", true] call FUNC(setStatusEffect); + }; +}] call CBA_fnc_addEventHandler; + +[QGVAR(unlockVehicle), { + _this lock (_this getVariable ["ace_common_lockStatus", locked _this]); + if ([] isNotEqualTo getArray (configOf _this >> "assembleInfo" >> "dissasembleTo")) then { + [_this, "disableWeaponAssembly", "ace_common_lockVehicle", false] call FUNC(setStatusEffect); + }; +}] call CBA_fnc_addEventHandler; diff --git a/addons/statuseffects/XEH_preInit.sqf b/addons/statuseffects/XEH_preInit.sqf new file mode 100644 index 0000000000..a7feade1c3 --- /dev/null +++ b/addons/statuseffects/XEH_preInit.sqf @@ -0,0 +1,7 @@ +#include "script_component.hpp" + +ADDON = false; + +#include "XEH_PREP.hpp" + +ADDON = true; diff --git a/addons/statuseffects/XEH_preStart.sqf b/addons/statuseffects/XEH_preStart.sqf new file mode 100644 index 0000000000..022888575e --- /dev/null +++ b/addons/statuseffects/XEH_preStart.sqf @@ -0,0 +1,3 @@ +#include "script_component.hpp" + +#include "XEH_PREP.hpp" diff --git a/addons/statuseffects/config.cpp b/addons/statuseffects/config.cpp new file mode 100644 index 0000000000..b3fd81b404 --- /dev/null +++ b/addons/statuseffects/config.cpp @@ -0,0 +1,18 @@ +#include "script_component.hpp" + +class CfgPatches { + class ADDON { + name = CSTRING(component); + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = {"cba_common", "cba_settings"}; + author = "$STR_CBA_Author"; + authors[] = {"PabstMirror", "DartRuffian"}; + url = "$STR_CBA_URL"; + VERSION_CONFIG; + }; +}; + +#include "CfgEventHandlers.hpp" +#include "CfgFunctions.hpp" diff --git a/addons/statuseffects/fnc_addStatusEffectType.sqf b/addons/statuseffects/fnc_addStatusEffectType.sqf new file mode 100644 index 0000000000..0278a62f6a --- /dev/null +++ b/addons/statuseffects/fnc_addStatusEffectType.sqf @@ -0,0 +1,47 @@ +#include "..\script_component.hpp" +/* ---------------------------------------------------------------------------- +Function: CBA_fnc_addStatusEffectType +Description: + Adds a status effect that will be handled. + +Parameters: + _name - Status Effect Name, this should match a corresponding event name + _isGlobal - Send event globally (optional, default: false) + _commonReasonsArray - Common Effect Reasons to pre-seed during init (optional, default: []) + _sendJIP - Send event to JIP (requires sending event globally) (default: false) + _eventName - Event name (default: "CBA_statusEffects_") + +Returns: + None + +Examples + (begin example) + ["setCaptive", true, []] call CBA_fnc_addStatusEffectType + (end) + +Author: + PabstMirror +---------------------------------------------------------------------------- */ +SCRIPT(addStatusEffectType); +params [ + ["_name", "", [""]], + ["_isGlobal", false, [false]], + ["_commonReasonsArray", [], [[]]], + ["_sendJIP", false, [false]], + ["_eventName", "", [""]] +]; + +_name = toLowerANSI _name; +if (_name == "") exitWith {ERROR_1("addStatusEffectType - Bad Name %1",_this)}; +if (_name in GVAR(statusEffects)) exitWith {WARNING_1("addStatusEffectType - Effect Already Added (note, will not update global bit) %1",_this)}; +if (_sendJIP && !_isGlobal) exitWith {WARNING_1("addStatusEffectType - Trying to add non-global JIP effect %1",_this)}; +if (_eventName == "") then { _eventName = format [QGVAR(%1), _name]; }; + +GVAR(statusEffects) set [_name, [_isGlobal, _sendJIP, _eventName]]; + +// We add reasons at any time, but more efficenet to add all common ones at one time during init +if (isServer && {_commonReasonsArray isNotEqualTo []}) then { + // Switch case to lower: + _commonReasonsArray = _commonReasonsArray apply { toLowerANSI _x }; + missionNamespace setVariable [(format [QGVAR(statusEffects_%1), _name]), _commonReasonsArray, true]; +}; diff --git a/addons/statuseffects/fnc_getStatusEffect.sqf b/addons/statuseffects/fnc_getStatusEffect.sqf new file mode 100644 index 0000000000..bd02ecdeb6 --- /dev/null +++ b/addons/statuseffects/fnc_getStatusEffect.sqf @@ -0,0 +1,68 @@ +#include "..\script_component.hpp" +/* ---------------------------------------------------------------------------- +Function: CBA_fnc_getStatusEffect +Description: + Retrieves list of current status effects + +Parameters: + _object - Vehicle that it will be attached to (player or vehicle) + _effectName - Effect Name + +Returns: + Effect status + - 0: is actively set (if false, the effect is ignored and never modified) + - 1: reasons why it is set true (list of strings, count of 0 = false, 1+ = true) + +Examples + (begin example) + [player, "forceWalk"] call CBA_fnc_getStatusEffect + (end) + +Author: + PabstMirror +---------------------------------------------------------------------------- */ +SCRIPT(getStatusEffect); +params [ + ["_object", objNull, [objNull]], + ["_effectName", "", [""]] +]; + +if (isNull _object) exitWith { + TRACE_1("null",_object); + [false, []] +}; + +[_object, false] call FUNC(resetVariables); // Check for mismatch + +// List of reasons +private _statusReasons = missionNamespace getVariable [(format [QGVAR(statusEffects_%1), _effectName]), []]; +if (_statusReasons isEqualTo []) exitWith { + TRACE_1("no reasons - bad effect?",_statusReasons); + [false, []] +}; + +// Get Effect Number +private _effectVarName = format [QGVAR(effect_%1), _effectName]; +private _effectNumber = _object getVariable [_effectVarName, -1]; +TRACE_2("current",_effectVarName,_effectNumber); + +if (_effectNumber == -1) exitWith { // Nil array - no effect + [false, []] +}; +if (_effectNumber == 0) exitWith { // Empty array - false effect + [true, []] +}; + +// If no change: skip sending publicVar and events +private _effectBoolArray = [_effectNumber, count _statusReasons] call FUNC(binarizeNumber); +TRACE_1("bitArray",_effectBoolArray); + +private _activeEffects = []; +{ + if (_x) then { + _activeEffects pushBack (_statusReasons select _forEachIndex); + }; +} forEach _effectBoolArray; + +// Non-empty array - true effect +[true, _activeEffects] diff --git a/addons/statuseffects/fnc_localEH.sqf b/addons/statuseffects/fnc_localEH.sqf new file mode 100644 index 0000000000..04443ca072 --- /dev/null +++ b/addons/statuseffects/fnc_localEH.sqf @@ -0,0 +1,39 @@ +#include "..\script_component.hpp" +/* ---------------------------------------------------------------------------- +Function: CBA_statusEffects_fnc_localEH +Description: + Handles locality switch, runs a respawn check and then reapplies all effect events. + +Parameters: + _object - Vehicle that it will be attached to (player or vehicle) + _isLocal - Is local + +Returns: + None + +Examples + (begin example) + [player, true] call CBA_statusEffects_fnc_localEH + (end) + +Author: + PabstMirror +---------------------------------------------------------------------------- */ +SCRIPT(localEH); +params ["_object", "_isLocal"]; + +// Only run this after the settings are initialized +// Need to wait for all EH to be installed (local event will happen between pre and post init) +if !(GVAR(settingsInitFinished)) exitWith { // TODO: Switch to CBA equivalent, was ace_common_... + TRACE_1("pushing to runAtSettingsInitialized",_this); + GVAR(runAtSettingsInitialized) pushBack [FUNC(localEH), _this]; +}; + +if (!_isLocal) exitWith { TRACE_1("object no longer local",_this) }; +if (isNull _object) exitWith { TRACE_1("object null",_this) }; + +// Reset any variables because of respawn +[_object, false] call FUNC(resetVariables); + +// Send all Variables to client +[_object, ""] call FUNC(sendEffects); diff --git a/addons/statuseffects/fnc_resetVariables.sqf b/addons/statuseffects/fnc_resetVariables.sqf new file mode 100644 index 0000000000..0ac26acb2d --- /dev/null +++ b/addons/statuseffects/fnc_resetVariables.sqf @@ -0,0 +1,51 @@ +#include "..\script_component.hpp" +/* ---------------------------------------------------------------------------- +Function: CBA_statusEffects_fnc_resetVariables +Description: + Resets all effect numbers to 0 when an object respawns (but does not apply the effect event). + +Parameters: + _object - Vehicle that it will be attached to (player or vehicle) + _setObjectRef - Explicitly set object reference (optional, default: false) + +Returns: + None + +Examples + (begin example) + [player, true] call CBA_statusEffects_fnc_resetVariables + (end) + +Author: + PabstMirror +---------------------------------------------------------------------------- */ +SCRIPT(resetVariables); +params [ + ["_object", objNull, [objNull]], + ["_setObjectRef", false, [false]] +]; + +if (isNull _object) exitWith {}; + +private _objectRef = _object getVariable QGVAR(object); +TRACE_2("testing",_object,_objectRef); + +// If nothing was ever set, or objects match, exit (always true unless respawned) +if (isNil "_objectRef") exitWith { + if (_setObjectRef) then { + _object setVariable [QGVAR(object), _object, true]; // Explicitly set new object ref + }; +}; +if (_object == _objectRef) exitWith {}; + +// Mismatch, so if effect has ever been defined, reset to 0 +{ + private _effectVarName = format [QGVAR(effect_%1), _x]; + private _effectNumber = _object getVariable [_effectVarName, -1]; + if (_effectNumber != -1) then { + TRACE_2("forced reset defined array on object mismatch",_x,_effectNumber); + _object setVariable [_effectVarName, 0, true]; // This always resets to 0 (not -1/nil)! + }; +} forEach GVAR(statusEffects); + +_object setVariable [QGVAR(statusEffect_object), _object, true]; diff --git a/addons/statuseffects/fnc_respawnEH.sqf b/addons/statuseffects/fnc_respawnEH.sqf new file mode 100644 index 0000000000..07c3fcba8b --- /dev/null +++ b/addons/statuseffects/fnc_respawnEH.sqf @@ -0,0 +1,38 @@ +#include "..\script_component.hpp" +/* ---------------------------------------------------------------------------- +Function: CBA_statusEffects_fnc_respawnEH +Description: + Handles the Respawn Event Handler to reset effects. + +Parameters: + _object - Vehicle that it will be attached to (player or vehicle) + +Returns: + None + +Examples + (begin example) + [player, objNull] call CBA_statusEffects_fnc_respawnEH + (end) + +Author: + PabstMirror +---------------------------------------------------------------------------- */ +SCRIPT(respawnEH); +params ["_object"]; + +// Only run this after the settings are initialized +// Need to wait for all EH to be installed (local event will happen between pre and post init) +if !(GVAR(settingsInitFinished)) exitWith { // TODO: Switch to CBA equivalent, was ace_common_... + TRACE_1("pushing to runAtSettingsInitialized",_this); + GVAR(runAtSettingsInitialized) pushBack [FUNC(respawnEH), _this]; +}; + +if (!local _object) exitWith {TRACE_1("object no longer local",_this)}; +if (isNull _object) exitWith {TRACE_1("object null",_this)}; + + // Reset any variables on "real" respawn +[_object, false] call FUNC(resetVariables); + +// Send all Variables to client +[_object, ""] call FUNC(sendEffects); diff --git a/addons/statuseffects/fnc_sendEffects.sqf b/addons/statuseffects/fnc_sendEffects.sqf new file mode 100644 index 0000000000..84b2136c6c --- /dev/null +++ b/addons/statuseffects/fnc_sendEffects.sqf @@ -0,0 +1,60 @@ +#include "..\script_component.hpp" +/* ---------------------------------------------------------------------------- +Function: CBA_statusEffects_fnc_sendEffects +Description: + Sends all status effects for an object (can be run on non-local objects) + +Parameters: + _object - Object + _effectName - Effect name (or "" to send all) + +Returns: + None + +Examples + (begin example) + [player, ""] call CBA_statusEffects_fnc_sendEffects + (end) + +Author: + PabstMirror +---------------------------------------------------------------------------- */ +SCRIPT(sendEffects); +params [ + ["_object", objNull, [objNull]], + ["_effectName", "", [""]] +]; + +if (isNull _object) exitWith {}; + +if (_effectName == "") exitWith { // Recurse through all possible effects + { + [_object, _x] call FUNC(sendEffects) + } forEach (keys GVAR(statusEffects)); +}; + + +private _effectVarName = format [QGVAR(effect_%1), _effectName]; +private _effectNumber = _object getVariable [_effectVarName, -1]; + +// We only do anything if the effect has been defined at some point in the game for this unit +TRACE_2("checking if event is nil",_effectName,_effectNumber); +if (_effectNumber != -1) then { + (GVAR(statusEffects) get toLowerANSI _effectName) params ["_isGlobal", "_sendJIP", "_eventName"]; + switch (true) do { + case (_sendJIP): { + TRACE_2("Sending Global JIP Event",_object,_effectNumber); + private _jipID = format [QGVAR(effect_%1_%2), _eventName, hashValue _object]; + [_eventName, [_object, _effectNumber], _jipID] call CBA_fnc_globalEventJIP; + [_jipID, _object] call CBA_fnc_removeGlobalEventJIP; + }; + case (_isGlobal): { + TRACE_2("Sending Global Event",_object,_effectNumber); + [_eventName, [_object, _effectNumber]] call CBA_fnc_globalEvent; + }; + default { + TRACE_2("Sending Target Event",_object,_effectNumber); + [_eventName, [_object, _effectNumber], _object] call CBA_fnc_targetEvent; + }; + }; +}; diff --git a/addons/statuseffects/fnc_setStatusEffect.sqf b/addons/statuseffects/fnc_setStatusEffect.sqf new file mode 100644 index 0000000000..2eb209f60d --- /dev/null +++ b/addons/statuseffects/fnc_setStatusEffect.sqf @@ -0,0 +1,81 @@ +#include "..\script_component.hpp" +/* ---------------------------------------------------------------------------- +Function: CBA_fnc_setStatusEffect +Description: + Adds or removes an id to a status effect and will send an event to apply. + +Parameters: + _object - Vehicle that it will be attached to (player or vehicle) + _effectName - Effect Name + _id - Unique Reason ID + _set - Is Set (true adds/false removes) + +Returns: + None + +Examples + (begin example) + [player, "setCaptive", "reason1", true] call CBA_fnc_setStatusEffect + (end) + +Author: + PabstMirror +---------------------------------------------------------------------------- */ +SCRIPT(sendEffects); +params [ + ["_object", objNull, [objNull]], + ["_effectName", "", [""]], + ["_id", "", [""]], + ["_set", true, [false]] +]; + +// Only run this after the settings are initialized +if !(GVAR(settingsInitFinished)) exitWith { // TODO: Switch to CBA equivalent, was ace_common_... + TRACE_1("pushing to runAtSettingsInitialized",_this); + GVAR(runAtSettingsInitialized) pushBack [FUNC(setStatusEffect), _this]; +}; + +if (isNull _object) exitWith {TRACE_1("null",_object);}; + +[_object, true] call FUNC(resetVariables); // Check for mismatch, and set object ref + +// Check ID case and set globally if not already set: +_id = toLowerANSI _id; +private _statusReasons = missionNamespace getVariable [(format [QGVAR(statusEffects_%1), _effectName]), []]; +private _statusIndex = _statusReasons find _id; +if (_statusIndex == -1) then { + TRACE_2("ID not in global reasons, adding",_statusReasons,_id); + _statusIndex = _statusReasons pushBack _id; + missionNamespace setVariable [(format [QGVAR(statusEffects_%1), _effectName]), _statusReasons, true]; +}; + +private _effectVarName = format [QGVAR(effect_%1), _effectName]; +private _effectNumber = _object getVariable [_effectVarName, -1]; +TRACE_2("current",_effectVarName,_effectNumber); + +if ((_effectNumber == -1) && {!_set}) exitWith { + // Optimization for modules that always set an ID to false even if never set true + TRACE_2("Set False on nil array, exiting",_set,_effectNumber); +}; + +if (_effectNumber == -1) then {_effectNumber = 0}; // Reset (-1/nil) to 0 + +// If no change: skip sending publicVar and events +private _effectBoolArray = [_effectNumber, count _statusReasons] call FUNC(binarizeNumber); +TRACE_2("bitArray",_statusIndex,_effectBoolArray); +if (_set isEqualTo (_effectBoolArray select _statusIndex)) exitWith { + TRACE_2("No Change, exiting",_set,_effectBoolArray select _statusIndex); +}; + +TRACE_2("Setting to new value",_set,_effectBoolArray select _statusIndex); +_effectBoolArray set [_statusIndex, _set]; +private _newEffectNumber = _effectBoolArray call FUNC(toBitmask); // Convert array back to number + +TRACE_2("Saving globally",_effectVarName,_newEffectNumber); +_object setVariable [_effectVarName, _newEffectNumber, true]; + +if (_effectNumber == 0 || {_newEffectNumber == 0}) then { + [_object, _effectName] call FUNC(sendEffects); +} else { + LOG("not sending more than once"); +}; diff --git a/addons/statuseffects/script_component.hpp b/addons/statuseffects/script_component.hpp new file mode 100644 index 0000000000..a102aa882f --- /dev/null +++ b/addons/statuseffects/script_component.hpp @@ -0,0 +1,16 @@ +#define COMPONENT statuseffects +#include "\x\cba\addons\main\script_mod.hpp" + +// #define DEBUG_MODE_FULL +// #define DISABLE_COMPILE_CACHE +// #define DEBUG_ENABLED_ACCESSORY + +#ifdef DEBUG_ENABLED_STATUSEFFECTS + #define DEBUG_MODE_FULL +#endif + +#ifdef DEBUG_SETTINGS_STATUSEFFECTS + #define DEBUG_SETTINGS DEBUG_SETTINGS_STATUSEFFECTS +#endif + +#include "\x\cba\addons\main\script_macros.hpp" diff --git a/addons/statuseffects/stringtable.xml b/addons/statuseffects/stringtable.xml new file mode 100644 index 0000000000..427c5022e3 --- /dev/null +++ b/addons/statuseffects/stringtable.xml @@ -0,0 +1,8 @@ + + + + + Community Base Addons - Status Effects Component + + + From 4060c07dd4eb415e73272b2c23cc21da3a6668aa Mon Sep 17 00:00:00 2001 From: Dart Date: Sun, 18 Jan 2026 12:42:59 -0600 Subject: [PATCH 02/14] Add todos, fix includes and function names --- addons/statuseffects/XEH_postInit.sqf | 12 ++++++------ addons/statuseffects/fnc_addStatusEffectType.sqf | 2 +- addons/statuseffects/fnc_getStatusEffect.sqf | 4 ++-- addons/statuseffects/fnc_localEH.sqf | 2 +- addons/statuseffects/fnc_resetVariables.sqf | 2 +- addons/statuseffects/fnc_respawnEH.sqf | 2 +- addons/statuseffects/fnc_sendEffects.sqf | 2 +- addons/statuseffects/fnc_setStatusEffect.sqf | 8 ++++---- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/addons/statuseffects/XEH_postInit.sqf b/addons/statuseffects/XEH_postInit.sqf index 6c6616e6e0..864ab00ee8 100644 --- a/addons/statuseffects/XEH_postInit.sqf +++ b/addons/statuseffects/XEH_postInit.sqf @@ -1,6 +1,6 @@ #include "script_component.hpp" -[QGVAR(setStatusEffect), LINKFUNC(statusEffect_set)] call CBA_fnc_addEventHandler; +[QGVAR(setStatusEffect), CBA_fnc_setStatusEffect] call CBA_fnc_addEventHandler; ["forceWalk", false, ["ace_advanced_fatigue", "ace_attach", "ace_dragging", "ace_explosives", "ace_medical_fracture", "ace_rearm", "ace_refuel", "ace_sandbag", "ace_switchunits", "ace_tacticalladder", "ace_trenches"]] call CBA_fnc_addStatusEffectType; ["blockSprint", false, ["ace_advanced_fatigue", "ace_dragging", "ace_medical_fracture"]] call CBA_fnc_addStatusEffectType; ["setCaptive", true, ["ace_captives_handcuffed", "ace_captives_surrendered"]] call CBA_fnc_addStatusEffectType; @@ -19,7 +19,7 @@ _object forceWalk (_set > 0); }] call CBA_fnc_addEventHandler; -[QGVAR(blockSprint), { //Name reversed from `allowSprint` because we want NOR logic +[QGVAR(blockSprint), { // Name reversed from `allowSprint` because we want NOR logic params ["_object", "_set"]; TRACE_2("blockSprint EH",_object,_set); _object allowSprint (_set == 0); @@ -61,9 +61,9 @@ params ["_object", "_set"]; TRACE_2("blockRadio EH",_object,_set); if (_object isEqualTo ACE_Player && {_set > 0}) then { - call FUNC(endRadioTransmission); + call FUNC(endRadioTransmission); // TODO: ACE function }; - if ("task_force_radio" call FUNC(isModLoaded)) then { + if ("task_force_radio" call FUNC(isModLoaded)) then { // TODO: ACE function _object setVariable ["tf_unable_to_use_radio", _set > 0, true]; }; if ("acre_main" call FUNC(isModLoaded)) then { @@ -119,13 +119,13 @@ _this setVariable [QGVAR(lockStatus), locked _this]; _this lock 2; if ([] isNotEqualTo getArray (configOf _this >> "assembleInfo" >> "dissasembleTo")) then { - [_this, "disableWeaponAssembly", "ace_common_lockVehicle", true] call FUNC(setStatusEffect); + [_this, "disableWeaponAssembly", "ace_common_lockVehicle", true] call CBA_fnc_setStatusEffect; }; }] call CBA_fnc_addEventHandler; [QGVAR(unlockVehicle), { _this lock (_this getVariable ["ace_common_lockStatus", locked _this]); if ([] isNotEqualTo getArray (configOf _this >> "assembleInfo" >> "dissasembleTo")) then { - [_this, "disableWeaponAssembly", "ace_common_lockVehicle", false] call FUNC(setStatusEffect); + [_this, "disableWeaponAssembly", "ace_common_lockVehicle", false] call CBA_fnc_setStatusEffect; }; }] call CBA_fnc_addEventHandler; diff --git a/addons/statuseffects/fnc_addStatusEffectType.sqf b/addons/statuseffects/fnc_addStatusEffectType.sqf index 0278a62f6a..c4775ebcac 100644 --- a/addons/statuseffects/fnc_addStatusEffectType.sqf +++ b/addons/statuseffects/fnc_addStatusEffectType.sqf @@ -1,4 +1,4 @@ -#include "..\script_component.hpp" +#include "script_component.hpp" /* ---------------------------------------------------------------------------- Function: CBA_fnc_addStatusEffectType Description: diff --git a/addons/statuseffects/fnc_getStatusEffect.sqf b/addons/statuseffects/fnc_getStatusEffect.sqf index bd02ecdeb6..acc17f1dca 100644 --- a/addons/statuseffects/fnc_getStatusEffect.sqf +++ b/addons/statuseffects/fnc_getStatusEffect.sqf @@ -1,4 +1,4 @@ -#include "..\script_component.hpp" +#include "script_component.hpp" /* ---------------------------------------------------------------------------- Function: CBA_fnc_getStatusEffect Description: @@ -54,7 +54,7 @@ if (_effectNumber == 0) exitWith { // Empty array - false effect }; // If no change: skip sending publicVar and events -private _effectBoolArray = [_effectNumber, count _statusReasons] call FUNC(binarizeNumber); +private _effectBoolArray = [_effectNumber, count _statusReasons] call FUNC(binarizeNumber); // TODO: ACE Function TRACE_1("bitArray",_effectBoolArray); private _activeEffects = []; diff --git a/addons/statuseffects/fnc_localEH.sqf b/addons/statuseffects/fnc_localEH.sqf index 04443ca072..5d6da7ebad 100644 --- a/addons/statuseffects/fnc_localEH.sqf +++ b/addons/statuseffects/fnc_localEH.sqf @@ -1,4 +1,4 @@ -#include "..\script_component.hpp" +#include "script_component.hpp" /* ---------------------------------------------------------------------------- Function: CBA_statusEffects_fnc_localEH Description: diff --git a/addons/statuseffects/fnc_resetVariables.sqf b/addons/statuseffects/fnc_resetVariables.sqf index 0ac26acb2d..729cd156fe 100644 --- a/addons/statuseffects/fnc_resetVariables.sqf +++ b/addons/statuseffects/fnc_resetVariables.sqf @@ -1,4 +1,4 @@ -#include "..\script_component.hpp" +#include "script_component.hpp" /* ---------------------------------------------------------------------------- Function: CBA_statusEffects_fnc_resetVariables Description: diff --git a/addons/statuseffects/fnc_respawnEH.sqf b/addons/statuseffects/fnc_respawnEH.sqf index 07c3fcba8b..6d86524fc3 100644 --- a/addons/statuseffects/fnc_respawnEH.sqf +++ b/addons/statuseffects/fnc_respawnEH.sqf @@ -1,4 +1,4 @@ -#include "..\script_component.hpp" +#include "script_component.hpp" /* ---------------------------------------------------------------------------- Function: CBA_statusEffects_fnc_respawnEH Description: diff --git a/addons/statuseffects/fnc_sendEffects.sqf b/addons/statuseffects/fnc_sendEffects.sqf index 84b2136c6c..a7aafbf79e 100644 --- a/addons/statuseffects/fnc_sendEffects.sqf +++ b/addons/statuseffects/fnc_sendEffects.sqf @@ -1,4 +1,4 @@ -#include "..\script_component.hpp" +#include "script_component.hpp" /* ---------------------------------------------------------------------------- Function: CBA_statusEffects_fnc_sendEffects Description: diff --git a/addons/statuseffects/fnc_setStatusEffect.sqf b/addons/statuseffects/fnc_setStatusEffect.sqf index 2eb209f60d..c05e9be827 100644 --- a/addons/statuseffects/fnc_setStatusEffect.sqf +++ b/addons/statuseffects/fnc_setStatusEffect.sqf @@ -1,4 +1,4 @@ -#include "..\script_component.hpp" +#include "script_component.hpp" /* ---------------------------------------------------------------------------- Function: CBA_fnc_setStatusEffect Description: @@ -32,7 +32,7 @@ params [ // Only run this after the settings are initialized if !(GVAR(settingsInitFinished)) exitWith { // TODO: Switch to CBA equivalent, was ace_common_... TRACE_1("pushing to runAtSettingsInitialized",_this); - GVAR(runAtSettingsInitialized) pushBack [FUNC(setStatusEffect), _this]; + GVAR(runAtSettingsInitialized) pushBack [CBA_fnc_setStatusEffect, _this]; }; if (isNull _object) exitWith {TRACE_1("null",_object);}; @@ -61,7 +61,7 @@ if ((_effectNumber == -1) && {!_set}) exitWith { if (_effectNumber == -1) then {_effectNumber = 0}; // Reset (-1/nil) to 0 // If no change: skip sending publicVar and events -private _effectBoolArray = [_effectNumber, count _statusReasons] call FUNC(binarizeNumber); +private _effectBoolArray = [_effectNumber, count _statusReasons] call FUNC(binarizeNumber); // TODO: ACE function TRACE_2("bitArray",_statusIndex,_effectBoolArray); if (_set isEqualTo (_effectBoolArray select _statusIndex)) exitWith { TRACE_2("No Change, exiting",_set,_effectBoolArray select _statusIndex); @@ -69,7 +69,7 @@ if (_set isEqualTo (_effectBoolArray select _statusIndex)) exitWith { TRACE_2("Setting to new value",_set,_effectBoolArray select _statusIndex); _effectBoolArray set [_statusIndex, _set]; -private _newEffectNumber = _effectBoolArray call FUNC(toBitmask); // Convert array back to number +private _newEffectNumber = _effectBoolArray call FUNC(toBitmask); // Convert array back to number // TODO: ACE function TRACE_2("Saving globally",_effectVarName,_newEffectNumber); _object setVariable [_effectVarName, _newEffectNumber, true]; From 6b3e2c7575fede4ead29806bb56cb2fc9f694149 Mon Sep 17 00:00:00 2001 From: Dart Date: Sun, 18 Jan 2026 12:55:11 -0600 Subject: [PATCH 03/14] Port binNumber / toBitMask --- addons/common/CfgFunctions.hpp | 2 + addons/common/fnc_binarizeNumber.sqf | 49 ++++++++++++++++++++ addons/common/fnc_toBitMask.sqf | 30 ++++++++++++ addons/statuseffects/fnc_getStatusEffect.sqf | 2 +- addons/statuseffects/fnc_setStatusEffect.sqf | 4 +- 5 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 addons/common/fnc_binarizeNumber.sqf create mode 100644 addons/common/fnc_toBitMask.sqf diff --git a/addons/common/CfgFunctions.hpp b/addons/common/CfgFunctions.hpp index ee691f693c..41b14c02ea 100644 --- a/addons/common/CfgFunctions.hpp +++ b/addons/common/CfgFunctions.hpp @@ -153,6 +153,8 @@ class CfgFunctions { PATHTO_FNC(cssColorToHEX); PATHTO_FNC(cssColorToTexture); PATHTO_FNC(attachToBone); + PATHTO_FNC(binarizeNumber); + PATHTO_FNC(toBitMask); }; class Broken { diff --git a/addons/common/fnc_binarizeNumber.sqf b/addons/common/fnc_binarizeNumber.sqf new file mode 100644 index 0000000000..d60046b297 --- /dev/null +++ b/addons/common/fnc_binarizeNumber.sqf @@ -0,0 +1,49 @@ +#include "script_component.hpp" +/* ---------------------------------------------------------------------------- +Function: CBA_fnc_binarizeNumber +Description: + Get a binary equivalent of a decimal number. + +Parameters: + _number - Decimal Number + _minLength - Minimum length of the returned Array, note: returned array can be larger (optional, default: 8) + +Returns: + Booleans + +Examples + (begin example) + [5, 5] call CBA_fnc_binarizeNumber + (end) + +Author: + commy2 +---------------------------------------------------------------------------- */ +SCRIPT(binarizeNumber); +params [ + ["_number", nil, [0]], + ["_minLength", 8, [0]] +]; + +if (isNil "_number") exitWith {}; + +_number = round _number; + +private _array = []; +_array resize _minLength; + +for "_index" from 0 to (_minLength - 1) do { + _array set [_index, false]; +}; + +private _index = 0; + +while {_number > 0} do { + private _rest = _number mod 2; + _number = floor (_number / 2); + + _array set [_index, _rest == 1]; + _index = _index + 1; +}; + +_array; diff --git a/addons/common/fnc_toBitMask.sqf b/addons/common/fnc_toBitMask.sqf new file mode 100644 index 0000000000..180376be3a --- /dev/null +++ b/addons/common/fnc_toBitMask.sqf @@ -0,0 +1,30 @@ +#include "script_component.hpp" +/* ---------------------------------------------------------------------------- +Function: CBA_fnc_toBitMask +Description: + Convert an array of booleans into a number. + Takes Input (limited to float precision) + +Parameters: + _input - Boolean (least significant bit) + +Returns: + Bitmask + +Examples + (begin example) + [[true, false]] call CBA_fnc_toBitmask + (end) + +Author: + commy2 +---------------------------------------------------------------------------- */ +SCRIPT(toBitMask); +params [["_input", [], [[]]]]; + +private _result = 0; +{ + if (_x) then {_result = _result + 2 ^ _forEachIndex}; +} forEach _input; + +_result; diff --git a/addons/statuseffects/fnc_getStatusEffect.sqf b/addons/statuseffects/fnc_getStatusEffect.sqf index acc17f1dca..155a69166e 100644 --- a/addons/statuseffects/fnc_getStatusEffect.sqf +++ b/addons/statuseffects/fnc_getStatusEffect.sqf @@ -54,7 +54,7 @@ if (_effectNumber == 0) exitWith { // Empty array - false effect }; // If no change: skip sending publicVar and events -private _effectBoolArray = [_effectNumber, count _statusReasons] call FUNC(binarizeNumber); // TODO: ACE Function +private _effectBoolArray = [_effectNumber, count _statusReasons] call CBA_fnc_binarizeNumber; TRACE_1("bitArray",_effectBoolArray); private _activeEffects = []; diff --git a/addons/statuseffects/fnc_setStatusEffect.sqf b/addons/statuseffects/fnc_setStatusEffect.sqf index c05e9be827..7386dce35c 100644 --- a/addons/statuseffects/fnc_setStatusEffect.sqf +++ b/addons/statuseffects/fnc_setStatusEffect.sqf @@ -61,7 +61,7 @@ if ((_effectNumber == -1) && {!_set}) exitWith { if (_effectNumber == -1) then {_effectNumber = 0}; // Reset (-1/nil) to 0 // If no change: skip sending publicVar and events -private _effectBoolArray = [_effectNumber, count _statusReasons] call FUNC(binarizeNumber); // TODO: ACE function +private _effectBoolArray = [_effectNumber, count _statusReasons] call CBA_fnc_binarizeNumber; TRACE_2("bitArray",_statusIndex,_effectBoolArray); if (_set isEqualTo (_effectBoolArray select _statusIndex)) exitWith { TRACE_2("No Change, exiting",_set,_effectBoolArray select _statusIndex); @@ -69,7 +69,7 @@ if (_set isEqualTo (_effectBoolArray select _statusIndex)) exitWith { TRACE_2("Setting to new value",_set,_effectBoolArray select _statusIndex); _effectBoolArray set [_statusIndex, _set]; -private _newEffectNumber = _effectBoolArray call FUNC(toBitmask); // Convert array back to number // TODO: ACE function +private _newEffectNumber = _effectBoolArray call CBA_fnc_toBitmask; // Convert array back to number TRACE_2("Saving globally",_effectVarName,_newEffectNumber); _object setVariable [_effectVarName, _newEffectNumber, true]; From afa4aa9a3daef95fab53a83cc5fdebf5f1b135e5 Mon Sep 17 00:00:00 2001 From: Dart Date: Sun, 18 Jan 2026 13:03:29 -0600 Subject: [PATCH 04/14] Port isModLoaded, add disableCollision SE --- addons/common/CfgFunctions.hpp | 1 + addons/common/XEH_preInit.sqf | 4 +++- addons/common/fnc_isModLoaded.sqf | 24 ++++++++++++++++++++++++ addons/statuseffects/XEH_postInit.sqf | 19 +++++++++++++------ 4 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 addons/common/fnc_isModLoaded.sqf diff --git a/addons/common/CfgFunctions.hpp b/addons/common/CfgFunctions.hpp index 41b14c02ea..1a68b7816c 100644 --- a/addons/common/CfgFunctions.hpp +++ b/addons/common/CfgFunctions.hpp @@ -12,6 +12,7 @@ class CfgFunctions { PATHTO_FNC(inheritsFrom); PATHTO_FNC(getTurret); PATHTO_FNC(getNonPresetClass); + PATHTO_FNC(isModLoaded); }; class Entities { diff --git a/addons/common/XEH_preInit.sqf b/addons/common/XEH_preInit.sqf index 3a02d3adc5..eb1ac70e7a 100644 --- a/addons/common/XEH_preInit.sqf +++ b/addons/common/XEH_preInit.sqf @@ -17,6 +17,8 @@ CBA_logic = objNull; }; }] call CBA_fnc_compileFinal; +GVAR(isModLoadedCache) = createHashMap; + // FSM GVAR(delayless) = QUOTE(PATHTOF(delayless.fsm)); GVAR(delayless_loop) = QUOTE(PATHTOF(delayless_loop.fsm)); @@ -41,7 +43,7 @@ GVAR(featureCamerasNames) = [ "animViewer", // Animation viewer camera "classic" // Classic camera ]; -if (isClass (configFile >> "CfgPatches" >> "missions_f_vietnam")) then { // Add SOG Cinematic module camera if CDLC loaded +if ("missions_f_vietnam" call CBA_fnc_isModLoaded) then { // Add SOG Cinematic module camera if CDLC loaded ["vn_cinematic", {missionNamespace getVariable ["vn_cinematic_running", false]}] call CBA_fnc_registerFeatureCamera; }; diff --git a/addons/common/fnc_isModLoaded.sqf b/addons/common/fnc_isModLoaded.sqf new file mode 100644 index 0000000000..de7a2e3b5a --- /dev/null +++ b/addons/common/fnc_isModLoaded.sqf @@ -0,0 +1,24 @@ +#include "script_component.hpp" +/* ---------------------------------------------------------------------------- +Function: CBA_fnc_isModLoaded +Description: + Check in CfgPatches if an addon is loaded + +Parameters: + _modName - Classname of the mod in CfgPatches + +Returns: + True if addon is loaded, otherwise false + +Examples + (begin example) + "class" call CBA_fnc_isModLoaded + (end) + +Authors: + Glowbal, Grim +---------------------------------------------------------------------------- */ +SCRIPT(isModLoaded); +params [["_modName", "", [""]]]; + +GVAR(isModLoadedCache) getOrDefaultCall [toLowerANSI _modName, { isClass (configFile >> "CfgPatches" >> _modName) }, true] diff --git a/addons/statuseffects/XEH_postInit.sqf b/addons/statuseffects/XEH_postInit.sqf index 864ab00ee8..06370f6b45 100644 --- a/addons/statuseffects/XEH_postInit.sqf +++ b/addons/statuseffects/XEH_postInit.sqf @@ -12,6 +12,7 @@ ["blockSpeaking", false, ["ace_unconscious"]] call CBA_fnc_addStatusEffectType; ["disableWeaponAssembly", false, ["ace_common", "ace_common_lockVehicle", "ace_csw"]] call CBA_fnc_addStatusEffectType; ["lockInventory", true, [], true] call CBA_fnc_addStatusEffectType; +["disableCollision", true, [], true] call CBA_fnc_addStatusEffectType; [QGVAR(forceWalk), { params ["_object", "_set"]; @@ -63,10 +64,10 @@ if (_object isEqualTo ACE_Player && {_set > 0}) then { call FUNC(endRadioTransmission); // TODO: ACE function }; - if ("task_force_radio" call FUNC(isModLoaded)) then { // TODO: ACE function + if ("task_force_radio" call CBA_fnc_isModLoaded) then { _object setVariable ["tf_unable_to_use_radio", _set > 0, true]; }; - if ("acre_main" call FUNC(isModLoaded)) then { + if ("acre_main" call CBA_fnc_isModLoaded) then { _object setVariable ["acre_sys_core_isDisabledRadio", _set > 0, true]; }; }] call CBA_fnc_addEventHandler; @@ -74,17 +75,17 @@ [QGVAR(blockSpeaking), { params ["_object", "_set"]; TRACE_2("blockSpeaking EH",_object,_set); - if ("task_force_radio" call FUNC(isModLoaded)) then { + if ("task_force_radio" call CBA_fnc_isModLoaded) then { _object setVariable ["tf_voiceVolume", parseNumber (_set == 0), true]; }; - if ("acre_main" call FUNC(isModLoaded)) then { + if ("acre_main" call CBA_fnc_isModLoaded) then { _object setVariable ["acre_sys_core_isDisabled", _set > 0, true]; }; }] call CBA_fnc_addEventHandler; -[QGVAR(blockDamage), { //Name reversed from `allowDamage` because we want NOR logic +[QGVAR(blockDamage), { // Name reversed from `allowDamage` because we want NOR logic params ["_object", "_set"]; - if ((_object isKindOf "CAManBase") && {("ace_medical" call FUNC(isModLoaded))}) then { + if ((_object isKindOf "CAManBase") && {("ace_medical" call CBA_fnc_isModLoaded)}) then { TRACE_2("blockDamage EH (using medical)",_object,_set); _object setVariable ["ace_medical_allowDamage", (_set == 0), true]; } else { @@ -129,3 +130,9 @@ [_this, "disableWeaponAssembly", "ace_common_lockVehicle", false] call CBA_fnc_setStatusEffect; }; }] call CBA_fnc_addEventHandler; + +[QGVAR(disableCollision), { // Name "reversed" from `setPhysicsCollisionFlag` because we want NOR logic + params ["_object", "_set"]; + TRACE_2("disableCollision EH",_object,_set); + _object setPhysicsCollisionFlag (_set < 1); +}] call CBA_fnc_addEventHandler; From 4729d8139c61aea8e29a6b9d658858f54e808e3d Mon Sep 17 00:00:00 2001 From: Dart Date: Sun, 18 Jan 2026 13:15:03 -0600 Subject: [PATCH 05/14] Port endRadioTransmission --- addons/common/CfgFunctions.hpp | 1 + addons/common/fnc_endRadioTransmission.sqf | 45 ++++++++++++++++++++++ addons/statuseffects/XEH_postInit.sqf | 11 +++--- 3 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 addons/common/fnc_endRadioTransmission.sqf diff --git a/addons/common/CfgFunctions.hpp b/addons/common/CfgFunctions.hpp index 1a68b7816c..ce5ffa380c 100644 --- a/addons/common/CfgFunctions.hpp +++ b/addons/common/CfgFunctions.hpp @@ -156,6 +156,7 @@ class CfgFunctions { PATHTO_FNC(attachToBone); PATHTO_FNC(binarizeNumber); PATHTO_FNC(toBitMask); + PATHTO_FNC(endRadioTransmission); }; class Broken { diff --git a/addons/common/fnc_endRadioTransmission.sqf b/addons/common/fnc_endRadioTransmission.sqf new file mode 100644 index 0000000000..f2d230d2cc --- /dev/null +++ b/addons/common/fnc_endRadioTransmission.sqf @@ -0,0 +1,45 @@ +#include "script_component.hpp" +/* ---------------------------------------------------------------------------- +Function: CBA_fnc_endRadioTransmission + +Description: + End radio transmissions of addons TFAR and ACRE2. TFAR v0.9.x, ACRE Public Beta 2.0.3.571, TFAR v1.0.-1.x + +Parameters: + None + +Returns: + None + +Examples: + (begin example) + [] call CBA_fnc_endRadioTransmission + (end) + +Author: + commy2 +---------------------------------------------------------------------------- */ +SCRIPT(endRadioTransmission); + +["CBA_endRadioTransmissions"] call CBA_fnc_localEvent; +["ace_endRadioTransmissions"] call CBA_fnc_localEvent; // Ported from ACE + +// ACRE +if ("acre_main" call CBA_fnc_isModLoaded) then { + [-1] call acre_sys_core_fnc_handleMultiPttKeyPressUp; + [0] call acre_sys_core_fnc_handleMultiPttKeyPressUp; + [1] call acre_sys_core_fnc_handleMultiPttKeyPressUp; + [2] call acre_sys_core_fnc_handleMultiPttKeyPressUp; +}; + +// TFAR +if ("task_force_radio" call CBA_fnc_isModLoaded) then { + if ("tfar_core" call CBA_fnc_isModLoaded) exitWith { // Beta TFAR, exit to avoid script errors from legacy functions not existing + ([] call CBA_fnc_currentUnit) call TFAR_fnc_releaseAllTangents; + }; + [] call TFAR_fnc_onSwTangentReleased; + [] call TFAR_fnc_onAdditionalSwTangentReleased; + [] call TFAR_fnc_onLRTangentReleased; + [] call TFAR_fnc_onAdditionalLRTangentReleased; + [] call TFAR_fnc_onDDTangentReleased; +}; diff --git a/addons/statuseffects/XEH_postInit.sqf b/addons/statuseffects/XEH_postInit.sqf index 06370f6b45..d9b714d81a 100644 --- a/addons/statuseffects/XEH_postInit.sqf +++ b/addons/statuseffects/XEH_postInit.sqf @@ -61,14 +61,15 @@ [QGVAR(blockRadio), { params ["_object", "_set"]; TRACE_2("blockRadio EH",_object,_set); - if (_object isEqualTo ACE_Player && {_set > 0}) then { - call FUNC(endRadioTransmission); // TODO: ACE function + private _disable = _set > 0; + if (_disable && { _object isEqualTo ([] call CBA_fnc_currentUnit) }) then { + [] call CBA_fnc_endRadioTransmission; }; if ("task_force_radio" call CBA_fnc_isModLoaded) then { - _object setVariable ["tf_unable_to_use_radio", _set > 0, true]; + _object setVariable ["tf_unable_to_use_radio", _disable, true]; }; if ("acre_main" call CBA_fnc_isModLoaded) then { - _object setVariable ["acre_sys_core_isDisabledRadio", _set > 0, true]; + _object setVariable ["acre_sys_core_isDisabledRadio", _disable, true]; }; }] call CBA_fnc_addEventHandler; @@ -85,7 +86,7 @@ [QGVAR(blockDamage), { // Name reversed from `allowDamage` because we want NOR logic params ["_object", "_set"]; - if ((_object isKindOf "CAManBase") && {("ace_medical" call CBA_fnc_isModLoaded)}) then { + if ((_object isKindOf "CAManBase") && { "ace_medical" call CBA_fnc_isModLoaded }) then { TRACE_2("blockDamage EH (using medical)",_object,_set); _object setVariable ["ace_medical_allowDamage", (_set == 0), true]; } else { From fc64e5a1eb60f28995f42449d17c504c7fb6cb56 Mon Sep 17 00:00:00 2001 From: Dart Date: Sun, 18 Jan 2026 13:22:13 -0600 Subject: [PATCH 06/14] Add engine blocking --- addons/statuseffects/CfgEventHandlers.hpp | 6 +++++ addons/statuseffects/XEH_PREP.hpp | 1 + addons/statuseffects/XEH_postInit.sqf | 10 ++++----- addons/statuseffects/fnc_handleEngine.sqf | 27 +++++++++++++++++++++++ 4 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 addons/statuseffects/fnc_handleEngine.sqf diff --git a/addons/statuseffects/CfgEventHandlers.hpp b/addons/statuseffects/CfgEventHandlers.hpp index 4300a157b9..ab13d7467c 100644 --- a/addons/statuseffects/CfgEventHandlers.hpp +++ b/addons/statuseffects/CfgEventHandlers.hpp @@ -9,3 +9,9 @@ class Extended_PostInit_EventHandlers { init = QUOTE(call COMPILE_SCRIPT(XEH_postInit)); }; }; + +class Extended_Engine_EventHandlers { + class All { + ADDON = QUOTE(call FUNC(handleEngine)); + }; +}; diff --git a/addons/statuseffects/XEH_PREP.hpp b/addons/statuseffects/XEH_PREP.hpp index 6664581b6d..78d5e2db1a 100644 --- a/addons/statuseffects/XEH_PREP.hpp +++ b/addons/statuseffects/XEH_PREP.hpp @@ -1,3 +1,4 @@ +PREP(handleEngine); PREP(localEH); PREP(resetVariables); PREP(respawnEH); diff --git a/addons/statuseffects/XEH_postInit.sqf b/addons/statuseffects/XEH_postInit.sqf index d9b714d81a..3f501cf0f5 100644 --- a/addons/statuseffects/XEH_postInit.sqf +++ b/addons/statuseffects/XEH_postInit.sqf @@ -88,16 +88,16 @@ params ["_object", "_set"]; if ((_object isKindOf "CAManBase") && { "ace_medical" call CBA_fnc_isModLoaded }) then { TRACE_2("blockDamage EH (using medical)",_object,_set); - _object setVariable ["ace_medical_allowDamage", (_set == 0), true]; + _object setVariable ["ace_medical_allowDamage", (_set == 0), true]; } else { TRACE_2("blockDamage EH (using allowDamage)",_object,_set); - _object allowDamage (_set == 0); + _object allowDamage (_set == 0); }; }] call CBA_fnc_addEventHandler; [QGVAR(blockEngine), { params ["_vehicle", "_set"]; - _vehicle setVariable ["ace_common_blockEngine", _set > 0, true]; + _vehicle setVariable ["CBA_blockEngine", _set > 0, true]; _vehicle engineOn false; }] call CBA_fnc_addEventHandler; @@ -118,7 +118,7 @@ }] call CBA_fnc_addEventHandler; [QGVAR(lockVehicle), { - _this setVariable [QGVAR(lockStatus), locked _this]; + _this setVariable ["CBA_lockStatus", locked _this]; _this lock 2; if ([] isNotEqualTo getArray (configOf _this >> "assembleInfo" >> "dissasembleTo")) then { [_this, "disableWeaponAssembly", "ace_common_lockVehicle", true] call CBA_fnc_setStatusEffect; @@ -126,7 +126,7 @@ }] call CBA_fnc_addEventHandler; [QGVAR(unlockVehicle), { - _this lock (_this getVariable ["ace_common_lockStatus", locked _this]); + _this lock (_this getVariable ["CBA_lockStatus", locked _this]); if ([] isNotEqualTo getArray (configOf _this >> "assembleInfo" >> "dissasembleTo")) then { [_this, "disableWeaponAssembly", "ace_common_lockVehicle", false] call CBA_fnc_setStatusEffect; }; diff --git a/addons/statuseffects/fnc_handleEngine.sqf b/addons/statuseffects/fnc_handleEngine.sqf new file mode 100644 index 0000000000..ddf5a9ef87 --- /dev/null +++ b/addons/statuseffects/fnc_handleEngine.sqf @@ -0,0 +1,27 @@ +#include "script_component.hpp" +/* ---------------------------------------------------------------------------- +Function: CBA_statusEffects_fnc_handleEngine +Description: + Blocks turning on the vehicles engine if set by the status effect handler. + +Parameters: + _vehicle - Vehicle + _engineState - Engine state + +Returns: + None + +Examples + (begin example) + [player, true] call CBA_statusEffects_fnc_handleEngine + (end) + +Author: + BaerMitUmlaut +---------------------------------------------------------------------------- */ +SCRIPT(handleEngine); +params ["_vehicle", "_engineOn"]; + +if (local _vehicle && _engineOn && {_vehicle getVariable ["CBA_blockEngine", false]}) then { + _vehicle engineOn false; +}; From 6b481083ae6a93a3c1b82e3a874692191764ea71 Mon Sep 17 00:00:00 2001 From: Dart Date: Sun, 18 Jan 2026 13:33:44 -0600 Subject: [PATCH 07/14] Add runAtSettingsInitialized array --- addons/settings/XEH_preInit.sqf | 7 +++++++ addons/settings/config.cpp | 2 +- addons/statuseffects/fnc_localEH.sqf | 4 ++-- addons/statuseffects/fnc_respawnEH.sqf | 4 ++-- addons/statuseffects/fnc_setStatusEffect.sqf | 4 ++-- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/addons/settings/XEH_preInit.sqf b/addons/settings/XEH_preInit.sqf index 7bd7503139..b27d78d5e7 100644 --- a/addons/settings/XEH_preInit.sqf +++ b/addons/settings/XEH_preInit.sqf @@ -118,4 +118,11 @@ private _ctrlAddonOptions = (uiNamespace getVariable "RscDisplayMain") displayCt _ctrlAddonOptions ctrlEnable true; _ctrlAddonOptions ctrlSetTooltip LLSTRING(menu_button_tooltip); +GVAR(runAtSettingsInitialized) = []; +["CBA_settingsInitialized", { + { + (_this select 1) call (_this select 0); + } forEach GVAR(runAtSettingsInitialized); +}] call CBA_fnc_addEventHandler; + ADDON = true; diff --git a/addons/settings/config.cpp b/addons/settings/config.cpp index 99b5d0b582..8f9dcafe92 100644 --- a/addons/settings/config.cpp +++ b/addons/settings/config.cpp @@ -6,7 +6,7 @@ class CfgPatches { units[] = {}; weapons[] = {}; requiredVersion = REQUIRED_VERSION; - requiredAddons[] = {"cba_common", "cba_events"}; + requiredAddons[] = {"cba_common", "cba_settings", "cba_events"}; author = "$STR_CBA_Author"; authors[] = {"commy2"}; url = "$STR_CBA_URL"; diff --git a/addons/statuseffects/fnc_localEH.sqf b/addons/statuseffects/fnc_localEH.sqf index 5d6da7ebad..8fef64a433 100644 --- a/addons/statuseffects/fnc_localEH.sqf +++ b/addons/statuseffects/fnc_localEH.sqf @@ -24,9 +24,9 @@ params ["_object", "_isLocal"]; // Only run this after the settings are initialized // Need to wait for all EH to be installed (local event will happen between pre and post init) -if !(GVAR(settingsInitFinished)) exitWith { // TODO: Switch to CBA equivalent, was ace_common_... +if !(missionNamespace getVariable [QGVAR(ready), false]) exitWith { TRACE_1("pushing to runAtSettingsInitialized",_this); - GVAR(runAtSettingsInitialized) pushBack [FUNC(localEH), _this]; + EGVAR(settings,runAtSettingsInitialized) pushBack [FUNC(localEH), _this]; }; if (!_isLocal) exitWith { TRACE_1("object no longer local",_this) }; diff --git a/addons/statuseffects/fnc_respawnEH.sqf b/addons/statuseffects/fnc_respawnEH.sqf index 6d86524fc3..4e267410b5 100644 --- a/addons/statuseffects/fnc_respawnEH.sqf +++ b/addons/statuseffects/fnc_respawnEH.sqf @@ -23,9 +23,9 @@ params ["_object"]; // Only run this after the settings are initialized // Need to wait for all EH to be installed (local event will happen between pre and post init) -if !(GVAR(settingsInitFinished)) exitWith { // TODO: Switch to CBA equivalent, was ace_common_... +if !(missionNamespace getVariable [QGVAR(ready), false]) exitWith { TRACE_1("pushing to runAtSettingsInitialized",_this); - GVAR(runAtSettingsInitialized) pushBack [FUNC(respawnEH), _this]; + EGVAR(settings,runAtSettingsInitialized) pushBack [FUNC(respawnEH), _this]; }; if (!local _object) exitWith {TRACE_1("object no longer local",_this)}; diff --git a/addons/statuseffects/fnc_setStatusEffect.sqf b/addons/statuseffects/fnc_setStatusEffect.sqf index 7386dce35c..1594039a70 100644 --- a/addons/statuseffects/fnc_setStatusEffect.sqf +++ b/addons/statuseffects/fnc_setStatusEffect.sqf @@ -30,9 +30,9 @@ params [ ]; // Only run this after the settings are initialized -if !(GVAR(settingsInitFinished)) exitWith { // TODO: Switch to CBA equivalent, was ace_common_... +if !(missionNamespace getVariable [QGVAR(ready), false]) exitWith { TRACE_1("pushing to runAtSettingsInitialized",_this); - GVAR(runAtSettingsInitialized) pushBack [CBA_fnc_setStatusEffect, _this]; + EGVAR(settings,runAtSettingsInitialized) pushBack [CBA_fnc_setStatusEffect, _this]; }; if (isNull _object) exitWith {TRACE_1("null",_object);}; From eeb037b1d3df7e3412da60210e9a94eadf72049d Mon Sep 17 00:00:00 2001 From: Dart Date: Sun, 18 Jan 2026 13:41:50 -0600 Subject: [PATCH 08/14] Fix using ace vcar --- addons/statuseffects/XEH_postInit.sqf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/statuseffects/XEH_postInit.sqf b/addons/statuseffects/XEH_postInit.sqf index 3f501cf0f5..32d805896e 100644 --- a/addons/statuseffects/XEH_postInit.sqf +++ b/addons/statuseffects/XEH_postInit.sqf @@ -10,7 +10,7 @@ ["setHidden", true, ["ace_unconscious"]] call CBA_fnc_addStatusEffectType; ["blockRadio", false, ["ace_captives_handcuffed", "ace_captives_surrendered", "ace_unconscious"]] call CBA_fnc_addStatusEffectType; ["blockSpeaking", false, ["ace_unconscious"]] call CBA_fnc_addStatusEffectType; -["disableWeaponAssembly", false, ["ace_common", "ace_common_lockVehicle", "ace_csw"]] call CBA_fnc_addStatusEffectType; +["disableWeaponAssembly", false, ["CBA_lockVehicle", "ace_common", "ace_csw"]] call CBA_fnc_addStatusEffectType; ["lockInventory", true, [], true] call CBA_fnc_addStatusEffectType; ["disableCollision", true, [], true] call CBA_fnc_addStatusEffectType; @@ -121,14 +121,14 @@ _this setVariable ["CBA_lockStatus", locked _this]; _this lock 2; if ([] isNotEqualTo getArray (configOf _this >> "assembleInfo" >> "dissasembleTo")) then { - [_this, "disableWeaponAssembly", "ace_common_lockVehicle", true] call CBA_fnc_setStatusEffect; + [_this, "disableWeaponAssembly", "CBA_lockVehicle", true] call CBA_fnc_setStatusEffect; }; }] call CBA_fnc_addEventHandler; [QGVAR(unlockVehicle), { _this lock (_this getVariable ["CBA_lockStatus", locked _this]); if ([] isNotEqualTo getArray (configOf _this >> "assembleInfo" >> "dissasembleTo")) then { - [_this, "disableWeaponAssembly", "ace_common_lockVehicle", false] call CBA_fnc_setStatusEffect; + [_this, "disableWeaponAssembly", "CBA_lockVehicle", false] call CBA_fnc_setStatusEffect; }; }] call CBA_fnc_addEventHandler; From 9299d960a39843b8f6857282291d6ad2cbbd5996 Mon Sep 17 00:00:00 2001 From: Dart Date: Sun, 18 Jan 2026 13:46:57 -0600 Subject: [PATCH 09/14] Fix requiredAddons --- addons/settings/config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/settings/config.cpp b/addons/settings/config.cpp index 8f9dcafe92..99b5d0b582 100644 --- a/addons/settings/config.cpp +++ b/addons/settings/config.cpp @@ -6,7 +6,7 @@ class CfgPatches { units[] = {}; weapons[] = {}; requiredVersion = REQUIRED_VERSION; - requiredAddons[] = {"cba_common", "cba_settings", "cba_events"}; + requiredAddons[] = {"cba_common", "cba_events"}; author = "$STR_CBA_Author"; authors[] = {"commy2"}; url = "$STR_CBA_URL"; From 90c8fb64b1089bacc68857f99a41c09299218e43 Mon Sep 17 00:00:00 2001 From: Dart Date: Sun, 18 Jan 2026 13:49:10 -0600 Subject: [PATCH 10/14] Clear array after running --- addons/settings/XEH_preInit.sqf | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/settings/XEH_preInit.sqf b/addons/settings/XEH_preInit.sqf index b27d78d5e7..42a04dab4b 100644 --- a/addons/settings/XEH_preInit.sqf +++ b/addons/settings/XEH_preInit.sqf @@ -123,6 +123,7 @@ GVAR(runAtSettingsInitialized) = []; { (_this select 1) call (_this select 0); } forEach GVAR(runAtSettingsInitialized); + GVAR(runAtSettingsInitialized) = nil; }] call CBA_fnc_addEventHandler; ADDON = true; From bc8777a715d9f8076f84d9b2f5ddbed58c8c5b83 Mon Sep 17 00:00:00 2001 From: Dart Date: Sun, 25 Jan 2026 11:55:30 -0600 Subject: [PATCH 11/14] Fix status effects, fix setting check, fix debug macro --- addons/statuseffects/XEH_preInit.sqf | 2 ++ addons/statuseffects/fnc_localEH.sqf | 2 +- addons/statuseffects/fnc_respawnEH.sqf | 2 +- addons/statuseffects/fnc_sendEffects.sqf | 6 +++--- addons/statuseffects/fnc_setStatusEffect.sqf | 6 +++--- addons/statuseffects/script_component.hpp | 2 +- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/addons/statuseffects/XEH_preInit.sqf b/addons/statuseffects/XEH_preInit.sqf index a7feade1c3..da51b0844b 100644 --- a/addons/statuseffects/XEH_preInit.sqf +++ b/addons/statuseffects/XEH_preInit.sqf @@ -4,4 +4,6 @@ ADDON = false; #include "XEH_PREP.hpp" +GVAR(statusEffects) = createHashMap; + ADDON = true; diff --git a/addons/statuseffects/fnc_localEH.sqf b/addons/statuseffects/fnc_localEH.sqf index 8fef64a433..dae0126e4d 100644 --- a/addons/statuseffects/fnc_localEH.sqf +++ b/addons/statuseffects/fnc_localEH.sqf @@ -24,7 +24,7 @@ params ["_object", "_isLocal"]; // Only run this after the settings are initialized // Need to wait for all EH to be installed (local event will happen between pre and post init) -if !(missionNamespace getVariable [QGVAR(ready), false]) exitWith { +if !(missionNamespace getVariable [QEGVAR(settings,ready), false]) exitWith { TRACE_1("pushing to runAtSettingsInitialized",_this); EGVAR(settings,runAtSettingsInitialized) pushBack [FUNC(localEH), _this]; }; diff --git a/addons/statuseffects/fnc_respawnEH.sqf b/addons/statuseffects/fnc_respawnEH.sqf index 4e267410b5..0d05c56601 100644 --- a/addons/statuseffects/fnc_respawnEH.sqf +++ b/addons/statuseffects/fnc_respawnEH.sqf @@ -23,7 +23,7 @@ params ["_object"]; // Only run this after the settings are initialized // Need to wait for all EH to be installed (local event will happen between pre and post init) -if !(missionNamespace getVariable [QGVAR(ready), false]) exitWith { +if !(missionNamespace getVariable [QEGVAR(settings,ready), false]) exitWith { TRACE_1("pushing to runAtSettingsInitialized",_this); EGVAR(settings,runAtSettingsInitialized) pushBack [FUNC(respawnEH), _this]; }; diff --git a/addons/statuseffects/fnc_sendEffects.sqf b/addons/statuseffects/fnc_sendEffects.sqf index a7aafbf79e..4fc690ba19 100644 --- a/addons/statuseffects/fnc_sendEffects.sqf +++ b/addons/statuseffects/fnc_sendEffects.sqf @@ -43,17 +43,17 @@ if (_effectNumber != -1) then { (GVAR(statusEffects) get toLowerANSI _effectName) params ["_isGlobal", "_sendJIP", "_eventName"]; switch (true) do { case (_sendJIP): { - TRACE_2("Sending Global JIP Event",_object,_effectNumber); + TRACE_3("Sending Global JIP Event",_object,_effectNumber,_eventName); private _jipID = format [QGVAR(effect_%1_%2), _eventName, hashValue _object]; [_eventName, [_object, _effectNumber], _jipID] call CBA_fnc_globalEventJIP; [_jipID, _object] call CBA_fnc_removeGlobalEventJIP; }; case (_isGlobal): { - TRACE_2("Sending Global Event",_object,_effectNumber); + TRACE_3("Sending Global Event",_object,_effectNumber,_eventName); [_eventName, [_object, _effectNumber]] call CBA_fnc_globalEvent; }; default { - TRACE_2("Sending Target Event",_object,_effectNumber); + TRACE_3("Sending Target Event",_object,_effectNumber,_eventName); [_eventName, [_object, _effectNumber], _object] call CBA_fnc_targetEvent; }; }; diff --git a/addons/statuseffects/fnc_setStatusEffect.sqf b/addons/statuseffects/fnc_setStatusEffect.sqf index 1594039a70..d811c7bec7 100644 --- a/addons/statuseffects/fnc_setStatusEffect.sqf +++ b/addons/statuseffects/fnc_setStatusEffect.sqf @@ -30,7 +30,7 @@ params [ ]; // Only run this after the settings are initialized -if !(missionNamespace getVariable [QGVAR(ready), false]) exitWith { +if !(missionNamespace getVariable [QEGVAR(settings,ready), false]) exitWith { TRACE_1("pushing to runAtSettingsInitialized",_this); EGVAR(settings,runAtSettingsInitialized) pushBack [CBA_fnc_setStatusEffect, _this]; }; @@ -69,12 +69,12 @@ if (_set isEqualTo (_effectBoolArray select _statusIndex)) exitWith { TRACE_2("Setting to new value",_set,_effectBoolArray select _statusIndex); _effectBoolArray set [_statusIndex, _set]; -private _newEffectNumber = _effectBoolArray call CBA_fnc_toBitmask; // Convert array back to number +private _newEffectNumber = [_effectBoolArray] call CBA_fnc_toBitmask; // Convert array back to number TRACE_2("Saving globally",_effectVarName,_newEffectNumber); _object setVariable [_effectVarName, _newEffectNumber, true]; -if (_effectNumber == 0 || {_newEffectNumber == 0}) then { +if (_effectNumber == 0 || _newEffectNumber == 0) then { [_object, _effectName] call FUNC(sendEffects); } else { LOG("not sending more than once"); diff --git a/addons/statuseffects/script_component.hpp b/addons/statuseffects/script_component.hpp index a102aa882f..11d809d59a 100644 --- a/addons/statuseffects/script_component.hpp +++ b/addons/statuseffects/script_component.hpp @@ -3,7 +3,7 @@ // #define DEBUG_MODE_FULL // #define DISABLE_COMPILE_CACHE -// #define DEBUG_ENABLED_ACCESSORY +// #define DEBUG_ENABLED_STATUSEFFECTS #ifdef DEBUG_ENABLED_STATUSEFFECTS #define DEBUG_MODE_FULL From 3bc36476bb2c2225d9ca07e768e1fe8cf638f34b Mon Sep 17 00:00:00 2001 From: Dart Date: Sun, 1 Feb 2026 10:53:27 -0600 Subject: [PATCH 12/14] Add statuses for disableNVG/TIEquipment --- addons/statuseffects/XEH_postInit.sqf | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/addons/statuseffects/XEH_postInit.sqf b/addons/statuseffects/XEH_postInit.sqf index 32d805896e..d72323f554 100644 --- a/addons/statuseffects/XEH_postInit.sqf +++ b/addons/statuseffects/XEH_postInit.sqf @@ -13,6 +13,8 @@ ["disableWeaponAssembly", false, ["CBA_lockVehicle", "ace_common", "ace_csw"]] call CBA_fnc_addStatusEffectType; ["lockInventory", true, [], true] call CBA_fnc_addStatusEffectType; ["disableCollision", true, [], true] call CBA_fnc_addStatusEffectType; +["disableNVGEquipment", false, []] call CBA_fnc_addStatusEffectType; +["disableTIEquipment", false, []] call CBA_fnc_addStatusEffectType; [QGVAR(forceWalk), { params ["_object", "_set"]; @@ -26,11 +28,6 @@ _object allowSprint (_set == 0); }] call CBA_fnc_addEventHandler; -[QGVAR(setAnimSpeedCoef), { - params ["_object", "_set"]; - _object setAnimSpeedCoef _set; -}] call CBA_fnc_addEventHandler; - [QGVAR(setCaptive), { params ["_object", "_set"]; TRACE_2("setCaptive EH",_object,_set); @@ -101,11 +98,6 @@ _vehicle engineOn false; }] call CBA_fnc_addEventHandler; -[QGVAR(setMass), { - params ["_object", "_mass"]; - _object setMass _mass; -}] call CBA_fnc_addEventHandler; - [QGVAR(disableWeaponAssembly), { params ["_object", "_set"]; _object enableWeaponDisassembly (_set < 1); @@ -137,3 +129,17 @@ TRACE_2("disableCollision EH",_object,_set); _object setPhysicsCollisionFlag (_set < 1); }] call CBA_fnc_addEventHandler; + +// TODO: disableNVG/TIEquipment only work on vehicles, but we could make the status effects work for units as well +// One possible solution would be hooking into VisionModeChanged and using `player action ["NvGogglesOff", player]` +[QGVAR(disableNVGEquipment), { + params ["_object", "_set"]; + _object disableNVGEquipment (_set > 0); + TRACE_2("disableNVGEquipment EH",_object,_set); +}] call CBA_fnc_addEventHandler; + +[QGVAR(disableTIEquipment), { + params ["_object", "_set"]; + TRACE_2("disableTIEquipment EH",_object,_set); + _object disableTIEquipment (_set > 0); +}] call CBA_fnc_addEventHandler; From c58dea82bb4fac0e9889712578f6fced126d4771 Mon Sep 17 00:00:00 2001 From: Dart Date: Sun, 1 Feb 2026 10:57:06 -0600 Subject: [PATCH 13/14] Move toBitMask to bitwise --- addons/bitwise/CfgFunctions.hpp | 1 + addons/{common => bitwise}/fnc_toBitMask.sqf | 0 addons/common/CfgFunctions.hpp | 1 - 3 files changed, 1 insertion(+), 1 deletion(-) rename addons/{common => bitwise}/fnc_toBitMask.sqf (100%) diff --git a/addons/bitwise/CfgFunctions.hpp b/addons/bitwise/CfgFunctions.hpp index 761ea99ce9..af683d415f 100644 --- a/addons/bitwise/CfgFunctions.hpp +++ b/addons/bitwise/CfgFunctions.hpp @@ -15,6 +15,7 @@ class CfgFunctions { PATHTO_FNC(bitwiseRSHFT); PATHTO_FNC(bitwiseXOR); PATHTO_FNC(logBase2); + PATHTO_FNC(toBitMask); }; }; }; diff --git a/addons/common/fnc_toBitMask.sqf b/addons/bitwise/fnc_toBitMask.sqf similarity index 100% rename from addons/common/fnc_toBitMask.sqf rename to addons/bitwise/fnc_toBitMask.sqf diff --git a/addons/common/CfgFunctions.hpp b/addons/common/CfgFunctions.hpp index ce5ffa380c..fbc16954b7 100644 --- a/addons/common/CfgFunctions.hpp +++ b/addons/common/CfgFunctions.hpp @@ -155,7 +155,6 @@ class CfgFunctions { PATHTO_FNC(cssColorToTexture); PATHTO_FNC(attachToBone); PATHTO_FNC(binarizeNumber); - PATHTO_FNC(toBitMask); PATHTO_FNC(endRadioTransmission); }; From 1bf1c7b59dd81114cd47859a731575ad51f9e57c Mon Sep 17 00:00:00 2001 From: Dart Date: Sun, 1 Feb 2026 11:14:46 -0600 Subject: [PATCH 14/14] Add missing entries to main requiredAddons --- addons/main/config.cpp | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/addons/main/config.cpp b/addons/main/config.cpp index bc04591e6c..b4f7ff2a5a 100644 --- a/addons/main/config.cpp +++ b/addons/main/config.cpp @@ -8,31 +8,39 @@ class CfgPatches { weapons[] = {}; requiredVersion = REQUIRED_VERSION; requiredAddons[] = { + "cba_accessory", + "cba_ai", + "cba_arrays", + "cba_bitwise", + "cba_characters", "cba_common", + "cba_diagnostic", + "cba_disposable", "cba_events", "cba_hashes", + "cba_help", + "cba_jam", + "cba_jam_finish", + "cba_jr", "cba_jr_prep", "cba_keybinding", + "cba_loadout", + "cba_main", "cba_modules", "cba_music", "cba_network", + "cba_optics", + "cba_pid", + "cba_pylons", + "cba_quicktime", "cba_settings", "cba_statemachine", + "cba_statuseffects", "cba_strings", - "cba_vectors", - "cba_xeh", - "cba_accessory", - "cba_ai", - "cba_arrays", - "cba_diagnostic", - "cba_help", - "cba_jr", - "cba_jam", "cba_ui", + "cba_vectors", "cba_versioning", - "cba_optics", - "cba_disposable", - "cba_quicktime" + "cba_xeh", }; author = "$STR_CBA_Author"; authors[] = {};