diff --git a/addons/common/XEH_PREP.hpp b/addons/common/XEH_PREP.hpp index a331837fb2..3fbe081fae 100644 --- a/addons/common/XEH_PREP.hpp +++ b/addons/common/XEH_PREP.hpp @@ -138,6 +138,7 @@ PREP(positionToASL); PREP(progressBar); PREP(readSettingFromModule); PREP(receiveRequest); +PREP(registerItemReplacement); PREP(removeCanInteractWithCondition); PREP(removeSpecificMagazine); PREP(requestCallback); diff --git a/addons/common/functions/fnc_registerItemReplacement.sqf b/addons/common/functions/fnc_registerItemReplacement.sqf new file mode 100644 index 0000000000..d70a718193 --- /dev/null +++ b/addons/common/functions/fnc_registerItemReplacement.sqf @@ -0,0 +1,112 @@ +#include "script_component.hpp" +/* + * Author: BaerMitUmlaut + * Registers an event handler that replaces an item or item type with one or + * more other items. + * + * Arguments: + * 0: Item or item type ID to replace + * 1: Item or list of items + * 2: Replace items that inherit from original item (only if 0 is STRING) (Optional) + * + * Return Value: + * None + * + * Example: + * ["FirstAidKit", "ACE_fieldDressing"] call ace_common_fnc_registerItemReplacement + * + * Public: Yes + */ +params [["_oldItem", "", [0,""]], ["_newItems", "", ["", []]], ["_replaceInherited", false, [false]]]; +TRACE_3("registerItemReplacement",_oldItem,_newItems,_replaceInherited); + +// CBA player event handler function +private _fnc_replaceItems = { + params ["_unit"]; + + private _items = items _unit; + if (_items isEqualTo GVAR(oldItems)) exitWith {}; + + private _newItems = _items - GVAR(oldItems); + if (_newItems isEqualTo []) exitWith { + GVAR(oldItems) = _items; + }; + + _newItems sort true; // Sort so all items of current class can be replaced at once + private _cfgWeapons = configFile >> "CfgWeapons"; // Microoptimization + + for "_i" from 0 to count _newItems - 1 do { + private _item = _newItems#_i; + + // Determine replacement items: direct replacements, ... + private _replacements = GVAR(itemReplacements) getVariable [_item, []]; + + // ... item type replacements ... + private _type = getNumber (_cfgWeapons >> _item >> "ItemInfo" >> "type"); + private _typeReplacements = GVAR(itemReplacements) getVariable ["$" + str _type, []]; + _replacements append _typeReplacements; + + // ... and inherited replacements + { + if (_item isKindOf [_x, _cfgWeapons]) then { + private _inheritedReplacements = GVAR(itemReplacements) getVariable [_x, []]; + _replacements append _inheritedReplacements; + }; + } forEach GVAR(inheritedReplacements); + + // Skip lookup for all following items of this class + private _count = 1; + while {_newItems#(_i + 1) == _item} do { // (i+1) can be out of bounds, but should fail safely + _count = _count + 1; + _i = _i + 1; + }; + + // Replace all items of current class in list + if !(_replacements isEqualTo []) then { + TRACE_3("replace",_item,_count,_replacements); + _unit removeItems _item; + + for "_j" from 1 to _count do { + { [_unit, _x] call FUNC(addToInventory) } forEach _replacements; + }; + }; + }; + + GVAR(oldItems) = items _unit; +}; + +// Setup on first run +if (isNil QGVAR(itemReplacements)) then { + GVAR(itemReplacements) = [] call CBA_fnc_createNamespace; + GVAR(inheritedReplacements) = []; + GVAR(oldItems) = []; + ["loadout", _fnc_replaceItems] call CBA_fnc_addPlayerEventHandler; +}; + +// Save item replacement +// $ prefix is used for types (numbers) and replacements with inheritance +if (_replaceInherited) then { + _oldItem = "$" + _oldItem; + GVAR(inheritedReplacements) pushBack _oldItem; +}; +if (_oldItem isEqualType 0) then { + _oldItem = "$" + str _oldItem; +}; +if (_newItems isEqualType "") then { + _newItems = [_newItems]; +}; + +private _oldReplacements = GVAR(itemReplacements) getVariable [_oldItem, []]; +_oldReplacements append _newItems; +GVAR(itemReplacements) setVariable [_oldItem, _newItems]; + +// Force item scan when new replacement was registered in PostInit +if (!isNull ACE_player) then { + GVAR(oldItems) = []; + + // Exec next frame to ensure full scan only runs once per frame + // For example, if item replacements are registred in PostInit (due to CBA + // settings) by different addons, the inventory is only scanned once in the + // next frame, not once per addon. + [_fnc_replaceItems, [ACE_player]] call CBA_fnc_execNextFrame; +}; diff --git a/addons/medical_treatment/CfgReplacementItems.hpp b/addons/medical_treatment/CfgReplacementItems.hpp index 295935e055..16a45d01cc 100644 --- a/addons/medical_treatment/CfgReplacementItems.hpp +++ b/addons/medical_treatment/CfgReplacementItems.hpp @@ -1,11 +1,14 @@ +// This config accepts both item type numbers and item class names +// Item type numbers need the prefix ItemType_, so for example ItemType_401 +// Class names need no special prefix class EGVAR(medical,replacementItems) { - FirstAidKit[] = { + DOUBLES(ItemType,TYPE_FIRST_AID_KIT)[] = { {"ACE_fieldDressing", 1}, {"ACE_packingBandage", 1}, {"ACE_morphine", 1}, {"ACE_tourniquet", 1} }; - Medikit[] = { + DOUBLES(ItemType,TYPE_MEDIKIT)[] = { {"ACE_fieldDressing", 1}, {"ACE_packingBandage", 2}, {"ACE_epinephrine", 1}, @@ -14,5 +17,7 @@ class EGVAR(medical,replacementItems) { {"ACE_tourniquet", 1}, {"ACE_splint", 2} }; - // todo: add GM medical items + ACE_atropine[] = { + {"ACE_adenosine", 1} + }; }; diff --git a/addons/medical_treatment/XEH_PREP.hpp b/addons/medical_treatment/XEH_PREP.hpp index 7d82ef7c9a..480a65f2cb 100644 --- a/addons/medical_treatment/XEH_PREP.hpp +++ b/addons/medical_treatment/XEH_PREP.hpp @@ -13,7 +13,6 @@ PREP(canTreatCached); PREP(canTreat_holsterCheck); PREP(checkBloodPressure); PREP(checkBloodPressureLocal); -PREP(checkItems); PREP(checkPulse); PREP(checkPulseLocal); PREP(checkResponse); diff --git a/addons/medical_treatment/XEH_postInit.sqf b/addons/medical_treatment/XEH_postInit.sqf index 1896d8d9f1..413f96cd43 100644 --- a/addons/medical_treatment/XEH_postInit.sqf +++ b/addons/medical_treatment/XEH_postInit.sqf @@ -9,12 +9,8 @@ } forEach (_unit getVariable [QEGVAR(medical,allLogs), []]); _unit setVariable [QEGVAR(medical,allLogs), [], true]; - - [_unit] call FUNC(checkItems); }] call CBA_fnc_addEventHandler; -["loadout", LINKFUNC(checkItems)] call CBA_fnc_addPlayerEventHandler; - // Handle body removal and litter on server if (isServer) then { [QGVAR(createLitterServer), LINKFUNC(createLitterServer)] call CBA_fnc_addEventHandler; @@ -36,3 +32,32 @@ if (isServer) then { // Logging events [QGVAR(addToLog), LINKFUNC(addToLog)] call CBA_fnc_addEventHandler; [QGVAR(addToTriageCard), LINKFUNC(addToTriageCard)] call CBA_fnc_addEventHandler; + +// replace medical items with their ACE equivalents +["ace_settingsInitialized", { + TRACE_1("ace_settingsInitialized EH",GVAR(convertItems)); // 0: Enabled 1: RemoveOnly 2:Disabled + if (GVAR(convertItems) == 2) exitWith {}; + { + // turn [["stuff", 2], ...] into ["stuff", "stuff", ...] + private _replacements = []; + if (GVAR(convertItems) == 0) then { + { + _x params ["_item", "_count"]; + for "_i" from 1 to _count do { + _replacements pushBack _item; + }; + } forEach getArray _x; + }; + + // check if replacement is for item type or class name + private _configName = configName _x; + private _toReplace = if ((_configName select [0,9]) == "ItemType_") then { + parseNumber (_configName select [9]) + } else { + _configName + }; + + // register replacement + [_toReplace, _replacements] call EFUNC(common,registerItemReplacement); + } forEach (configProperties [configFile >> QEGVAR(medical,replacementItems), "isArray _x"]); +}] call CBA_fnc_addEventHandler; diff --git a/addons/medical_treatment/XEH_preInit.sqf b/addons/medical_treatment/XEH_preInit.sqf index 79949c2479..dfb6bf6518 100644 --- a/addons/medical_treatment/XEH_preInit.sqf +++ b/addons/medical_treatment/XEH_preInit.sqf @@ -44,9 +44,4 @@ GVAR(facilityClasses) = []; } forEach getArray _x; } forEach configProperties [configFile >> QEGVAR(medical,facilities), "isArray _x"]; -// array of medical items to replace and their ACE equivalents -GVAR(replacementItems) = configProperties [configFile >> QEGVAR(medical,replacementItems), "isArray _x"] apply { - [configName _x, getArray _x] -}; - ADDON = true; diff --git a/addons/medical_treatment/functions/fnc_checkItems.sqf b/addons/medical_treatment/functions/fnc_checkItems.sqf deleted file mode 100644 index 2f4c20175e..0000000000 --- a/addons/medical_treatment/functions/fnc_checkItems.sqf +++ /dev/null @@ -1,47 +0,0 @@ -#include "script_component.hpp" -/* - * Author: KoffeinFlummi, commy2, mharis001 - * Handles converting vanilla medical items with ACE equivalents. - * - * Arguments: - * 0: Unit - * - * Return Value: - * None - * - * Example: - * [player] call ace_medical_treatment_fnc_checkItems - * - * Public: No - */ - -if (GVAR(convertItems) == 2) exitWith {}; - -params ["_unit"]; - -private _fnc_loop = if (GVAR(convertItems) == 0) then { - { - _x params ["_itemToRemove", "_replacementItems"]; - - private _count = [_unit, _itemToRemove] call EFUNC(common,getCountOfItem); - - if (_count > 0) then { - _unit removeItems _itemToRemove; - - { - _x params ["_item", "_amount"]; - - for "_i" from 1 to (_amount * _count) do { - _unit addItem _item; - }; - } forEach _replacementItems; - }; - } -} else { - { - _x params ["_itemToRemove"]; - _unit removeItems _itemToRemove; - } -}; - -_fnc_loop forEach GVAR(replacementItems);