diff --git a/addons/backpack_on_chest/$PBOPREFIX$ b/addons/backpack_on_chest/$PBOPREFIX$ new file mode 100644 index 00000000..21b1b587 --- /dev/null +++ b/addons/backpack_on_chest/$PBOPREFIX$ @@ -0,0 +1 @@ +x\tac\addons\backpack_on_chest diff --git a/addons/backpack_on_chest/ACE_Arsenal_Actions.hpp b/addons/backpack_on_chest/ACE_Arsenal_Actions.hpp new file mode 100644 index 00000000..10804324 --- /dev/null +++ b/addons/backpack_on_chest/ACE_Arsenal_Actions.hpp @@ -0,0 +1,27 @@ +class ace_arsenal_actions { + class ADDON { + displayName = CSTRING(DisplayName); + condition = QUOTE((_this select 0) call FUNC(canMovePack) && {backpack (_this select 0) != '' || {(_this select 0) call FUNC(chestpack) != ''}}); + scopeEditor = 0; + tabs[] = {5}; + class GVAR(chestpack) { + condition = QUOTE((_this select 0) call FUNC(chestpack) != ''); + textStatement = QUOTE(getText (configFile >> 'CfgVehicles' >> (_this select 0) call FUNC(chestpack) >> 'displayName')); + }; + class GVAR(onChest) { + label = CSTRING(OnChest); + condition = QUOTE((_this select 0) call FUNC(canMovePack) && {backpack (_this select 0) != ''} && {(_this select 0) call FUNC(chestpack) == ''}); + statement = QUOTE((_this select 0) call FUNC(actionOnChest)); + }; + class GVAR(onBack) { + label = CSTRING(OnBack); + condition = QUOTE((_this select 0) call FUNC(canMovePack) && {backpack (_this select 0) == ''} && {(_this select 0) call FUNC(chestpack) != ''}); + statement = QUOTE((_this select 0) call FUNC(actionOnBack)); + }; + class GVAR(swap) { + label = CSTRING(Swap); + condition = QUOTE((_this select 0) call FUNC(canMovePack) && {backpack (_this select 0) != ''} && {(_this select 0) call FUNC(chestpack) != ''}); + statement = QUOTE((_this select 0) call FUNC(actionSwap)); + }; + }; +}; diff --git a/addons/backpack_on_chest/CfgEventHandlers.hpp b/addons/backpack_on_chest/CfgEventHandlers.hpp new file mode 100644 index 00000000..f6503c24 --- /dev/null +++ b/addons/backpack_on_chest/CfgEventHandlers.hpp @@ -0,0 +1,17 @@ +class Extended_PreStart_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_SCRIPT(XEH_preStart)); + }; +}; + +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/backpack_on_chest/CfgVehicles.hpp b/addons/backpack_on_chest/CfgVehicles.hpp new file mode 100644 index 00000000..5bb22e2e --- /dev/null +++ b/addons/backpack_on_chest/CfgVehicles.hpp @@ -0,0 +1,40 @@ +class CfgVehicles { + class Man; + class CAManBase: Man { + class ACE_SelfActions { + class ACE_Equipment { + class GVAR(onChest) { + displayName = CSTRING(OnChest); + condition = QUOTE([_player] call FUNC(canMovePack) && {!(backpack _player isEqualTo '') && (([_player] call FUNC(chestpack)) isEqualTo '')}); + exceptions[] = {"isNotInside"}; + statement = QUOTE([_player] call FUNC(actionOnChest)); + showDisabled = 0; + priority = 2.5; + icon = QPATHTOF(ui\onchest_ca.paa); + }; + class GVAR(onBack) : GVAR(onChest) { + displayName = CSTRING(OnBack); + condition = QUOTE([_player] call FUNC(canMovePack) && {(backpack _player isEqualTo '') && !(([_player] call FUNC(chestpack)) isEqualTo '')}); + statement = QUOTE([_player] call FUNC(actionOnBack)); + icon = QPATHTOF(ui\onback_ca.paa); + }; + class GVAR(swap) : GVAR(onChest) { + displayName = CSTRING(Swap); + condition = QUOTE([_player] call FUNC(canMovePack) && {!(backpack _player isEqualTo '') && !(([_player] call FUNC(chestpack)) isEqualTo '')}); + statement = QUOTE([_player] call FUNC(actionSwap)); + icon = QPATHTOF(ui\swap_ca.paa); + }; + class GVAR(lower) : GVAR(onChest) { + displayName = CSTRING(lower); + condition = QUOTE([_player] call FUNC(canLower)); + statement = QUOTE([_player] call FUNC(actionLower)); + }; + class GVAR(cutLoweringLine) : GVAR(onChest) { + displayName = CSTRING(cutLoweringLine); + condition = QUOTE([_player] call FUNC(canCutLoweringLine)); + statement = QUOTE([_player] call FUNC(actionCutLoweringLine)); + }; + }; + }; + }; +}; diff --git a/addons/backpack_on_chest/README.md b/addons/backpack_on_chest/README.md new file mode 100644 index 00000000..79e72d92 --- /dev/null +++ b/addons/backpack_on_chest/README.md @@ -0,0 +1,8 @@ +# About + +Adds Backpack on Chest REDUX, with some minor reworks and optimisations + +### Authors +- [mjc4wilton](https://github.com/mjc4wilton) +- [DerZade](https://github.com/DerZade) +- [MikeMF](https://github.com/Mike-MF) diff --git a/addons/backpack_on_chest/XEH_PREP.hpp b/addons/backpack_on_chest/XEH_PREP.hpp new file mode 100644 index 00000000..c28d0194 --- /dev/null +++ b/addons/backpack_on_chest/XEH_PREP.hpp @@ -0,0 +1,33 @@ +PREP(actionCutLoweringLine); +PREP(actionLower); +PREP(actionOnBack); +PREP(actionSwap); +PREP(addChestpack); +PREP(addItemToChestpack); +PREP(addMagToChestpack); +PREP(arsenal_onButtonClick); +PREP(arsenal_opened); +PREP(arsenal_postInit); +PREP(arsenal_updateUI); +PREP(canAddItemToChestpack); +PREP(canCutLoweringLine); +PREP(canLower); +PREP(canMovePack); +PREP(chestpack); +PREP(chestpackContainer); +PREP(chestpackLoadout); +PREP(chestpackToHolder); +PREP(chestpackVariables); +PREP(clearAllCargo); +PREP(clearAllItemsFromChestpack); +PREP(clearCargoBackpacks); +PREP(EHAnimDone); +PREP(EHGetIn); +PREP(EHGetOut); +PREP(EHHandleDisconnect); +PREP(EHKilled); +PREP(itemMass); +PREP(removeChestpack); +PREP(removeItemFromChestpack); +PREP(removeMagFromChestpack); +PREP(setBackpackLoadout); diff --git a/addons/backpack_on_chest/XEH_postInit.sqf b/addons/backpack_on_chest/XEH_postInit.sqf new file mode 100644 index 00000000..7a46a3ea --- /dev/null +++ b/addons/backpack_on_chest/XEH_postInit.sqf @@ -0,0 +1,46 @@ +#include "script_component.hpp" + +[] call FUNC(arsenal_postInit); + +// Clear inventory of a container +[QGVAR(clearAllCargo), {call FUNC(clearAllCargo)}] call CBA_fnc_addEventHandler; +// Clear inventory of every backpack in a container +[QGVAR(clearCargoBackpacks), {call FUNC(clearCargoBackpacks)}] call CBA_fnc_addEventHandler; + +// Backpack classnames which will be made invisible instead of being made a chestpack. Useful for items like the vanilla legstrap. +GVAR(exceptions) = [ + "B_LegStrapBag_black_F", + "B_LegStrapBag_coyote_F", + "B_LegStrapBag_olive_F" +]; + +if (isServer) exitWith {}; + +[QGVAR(handleDisconnect), { + addMissionEventHandler ["HandleDisconnect", FUNC(EHHandleDisconnect)]; +}] call CBA_fnc_addEventHandler; + +// holding the backpack have landed +[QGVAR(checkLandedPFH), { + params ["_ropeTop", "_holder"]; + + // PFH to check when the helper object _ropeTop and the WeaponHolderSimulated + [{ + params ["_ropeTop", "_handle"]; + + if (speed _ropeTop < 1 && {((getPos _ropeTop) select 2) < 1}) exitWith { + deleteVehicle _ropeTop; + [_handle] call CBA_fnc_removePerFrameHandler; + }; + }, 0, _ropeTop] call CBA_fnc_addPerFrameHandler; + + [{ + params ["_holder", "_handle"]; + if (speed _holder < 1 && {getPos _holder # 2 < 1}) exitWith { + private _pos = getPos _holder; + _pos set [2, 0]; + _holder setPos _pos; + [_handle] call CBA_fnc_removePerFrameHandler; + }; + }, 0, _holder] call CBA_fnc_addPerFrameHandler; +}] call CBA_fnc_addEventHandler; diff --git a/addons/backpack_on_chest/XEH_preInit.sqf b/addons/backpack_on_chest/XEH_preInit.sqf new file mode 100644 index 00000000..0c98ca4d --- /dev/null +++ b/addons/backpack_on_chest/XEH_preInit.sqf @@ -0,0 +1,8 @@ +#include "script_component.hpp" + +ADDON = false; + +#include "XEH_PREP.hpp" +#include "initSettings.inc.sqf" + +ADDON = true; diff --git a/addons/backpack_on_chest/XEH_preStart.sqf b/addons/backpack_on_chest/XEH_preStart.sqf new file mode 100644 index 00000000..02288857 --- /dev/null +++ b/addons/backpack_on_chest/XEH_preStart.sqf @@ -0,0 +1,3 @@ +#include "script_component.hpp" + +#include "XEH_PREP.hpp" diff --git a/addons/backpack_on_chest/config.cpp b/addons/backpack_on_chest/config.cpp new file mode 100644 index 00000000..ea065d1b --- /dev/null +++ b/addons/backpack_on_chest/config.cpp @@ -0,0 +1,19 @@ +#include "script_component.hpp" + +class CfgPatches { + class ADDON { + name = COMPONENT_NAME; + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = {"tac_main"}; + author = ECSTRING(main,Author); + authors[] = {"DerZade", "mjc4wilton", "MikeMF"}; + url = ECSTRING(main,URL); + VERSION_CONFIG; + }; +}; + +#include "ACE_Arsenal_Actions.hpp" +#include "CfgEventHandlers.hpp" +#include "CfgVehicles.hpp" diff --git a/addons/backpack_on_chest/functions/fnc_EHAnimDone.sqf b/addons/backpack_on_chest/functions/fnc_EHAnimDone.sqf new file mode 100644 index 00000000..e29442b8 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_EHAnimDone.sqf @@ -0,0 +1,33 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Triggered by AnimDone-Eventhandler + * + * Arguments: + * 0: unit + * 1: animtaion + * + * Return Value: + * Nothing + * + * Example: + * _this call tac_backpack_on_chest_fnc_EHAnimDone; + * + * Public: No + */ +params ["_unit","_anim"]; + +if (isNil "_unit") exitWith { + ERROR("No proper argument(s) given."); +}; + +private _chestpack = [_unit] call FUNC(chestpackContainer); +private _chestpackClass = [_unit] call FUNC(chestpack); + +// freefall +if ((animationState _unit) find "halofreefall_" isEqualTo 0) then { + if !(_chestpackClass in GVAR(exceptions)) then { + _chestpack attachTo [_unit,[0,-0.4,0.05],"pelvis"]; + _chestpack setVectorDirAndUp [[0,0,1],[0,1,0]]; + }; +}; diff --git a/addons/backpack_on_chest/functions/fnc_EHGetIn.sqf b/addons/backpack_on_chest/functions/fnc_EHGetIn.sqf new file mode 100644 index 00000000..060be7d5 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_EHGetIn.sqf @@ -0,0 +1,36 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Triggered by GetInMan-Eventhandler + * + * Arguments: + * 0: unit + * 1: position + * 2: vehicle + * 3: turret path + * + * Return Value: + * Nothing + * + * Example: + * _this call tac_backpack_on_chest_fnc_EHGetIn; + * + * Public: No + */ +params ["_unit","_position","_veh"]; + +if (isNil "_unit" || isNil "_veh") exitWith { + ERROR("No proper argument(s) given."); +}; + +private _chestpack = [_unit] call FUNC(chestpackContainer); + +if (_veh isKindOf "ParachuteBase") then { + _chestpack attachTo [_veh, [0, -0.03, -0.5]]; + _chestpack setVectorDirAndUp [[-0.25, -1, 0], [0, 0, 1]]; + _chestpack hideObjectGlobal false; +} else { + detach _chestpack; + hideObjectGlobal _chestpack; + _chestpack setPos [-10000, -10000, -100]; +}; diff --git a/addons/backpack_on_chest/functions/fnc_EHGetOut.sqf b/addons/backpack_on_chest/functions/fnc_EHGetOut.sqf new file mode 100644 index 00000000..4d9da8bc --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_EHGetOut.sqf @@ -0,0 +1,37 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Triggered by GetOutMan-Eventhandler + * + * Arguments: + * 0: unit + * 1: position + * 2: vehicle + * 3: turret path + * + * Return Value: + * Nothing + * + * Example: + * _this call tac_backpack_on_chest_fnc_EHGetOut; + * + * Public: No + */ +params ["_unit","_position","_veh"]; + +if (isNil "_unit" || isNil "_veh") exitWith { + ERROR("No proper argument(s) given."); +}; + +private _chestpack = [_unit] call FUNC(chestpackContainer); +private _chestpackClass = [_unit] call FUNC(chestpack); + +if !(_chestpackClass in GVAR(exceptions)) then { + _chestpack attachTo [_unit, [0,-0.03,-0.5], "pelvis"]; + _chestpack setVectorDirAndUp [[-0.25,-1,0], [0,0,1]]; + _chestpack hideObjectGlobal false; +}; + +if (GVAR(walk)) then { + [_unit, "forceWalk", "BackpackOnChest", true] call ACEFUNC(common,statusEffect_set); +}; diff --git a/addons/backpack_on_chest/functions/fnc_EHHandleDisconnect.sqf b/addons/backpack_on_chest/functions/fnc_EHHandleDisconnect.sqf new file mode 100644 index 00000000..fec274d5 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_EHHandleDisconnect.sqf @@ -0,0 +1,28 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton, MikeMF + * Triggered by HandleDisconnect-Eventhandler on Server. + * Handles deleting the chestpack of old units form disconnected players. + * + * Arguments: + * 0: unit + * + * Return Value: + * Nothing + * + * Example: + * _this call tac_backpack_on_chest_fnc_EHHandleDisconnect; + * + * Public: Yes + */ +params ["_unit", "_id", "_uid", "_name"]; + +if ([_unit] call FUNC(chestpack) isEqualTo "") exitWith {}; + +[{ + params ["_unit"]; + private _container = _unit call FUNC(chestpackContainer); + if (!alive _unit) then { + deleteVehicle _container; + }; +}, _unit, 1.5] call CBA_fnc_waitAndExecute; diff --git a/addons/backpack_on_chest/functions/fnc_EHKilled.sqf b/addons/backpack_on_chest/functions/fnc_EHKilled.sqf new file mode 100644 index 00000000..fb968089 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_EHKilled.sqf @@ -0,0 +1,38 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton, Ampersand + * Triggered by Killed-Eventhandler + * + * Arguments: + * 0: unit + * + * Return Value: + * Nothing + * + * Example: + * [player] call tac_backpack_on_chest_fnc_EHKilled; + * + * Public: No + */ + +params ["_unit"]; + +private _chestpack = [_unit] call FUNC(chestpack); +private _chestpackLoadout = [_unit] call FUNC(chestpackLoadout); +private _chestpackVariables = [_unit] call FUNC(chestpackVariables); + +private _holder = createVehicle ["WeaponHolderSimulated", (getPos _unit), [], 0, "CAN_COLLIDE"]; + +// add pack +_holder addBackpackCargoGlobal [_chestpack, 1]; +private _backpack = firstBackpack _holder; + +[_backpack, _chestpackLoadout] call FUNC(setBackpackLoadout); + +// add variables +{ + _backpack setVariable [(_x select 0), (_x select 1), true]; +} forEach _chestpackVariables; + +// remove the backpack from the dead unit +[_unit] call FUNC(removeChestpack); diff --git a/addons/backpack_on_chest/functions/fnc_actionCutLoweringLine.sqf b/addons/backpack_on_chest/functions/fnc_actionCutLoweringLine.sqf new file mode 100644 index 00000000..78a7f609 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_actionCutLoweringLine.sqf @@ -0,0 +1,29 @@ +#include "..\script_component.hpp" +/* + * Author: Ampersand + * Triggered by the CutLoweringLine-action. Detaches the lowering line top + * + * Arguments: + * 0: Unit + * + * Return Value: + * Nothing + * + * Example: + * [player] call tac_backpack_on_chest_fnc_actionCutLoweringLine; + * + * Public: No + */ + +params ["_unit"]; +private _chute = vehicle _unit; +private _ropeTop = _chute getVariable [QGVAR(loweringLine), objNull]; +if (!isNull _ropeTop) then { + private _rope = (ropes _ropeTop) select 0; + private _holder = (ropeAttachedObjects _ropeTop) select 0; + if !(isNull _holder) then { + _holder ropeDetach _rope; + ropeDestroy _rope; + }; + _chute setVariable [QGVAR(loweringLine), nil, true]; +}; diff --git a/addons/backpack_on_chest/functions/fnc_actionLower.sqf b/addons/backpack_on_chest/functions/fnc_actionLower.sqf new file mode 100644 index 00000000..b5174548 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_actionLower.sqf @@ -0,0 +1,45 @@ +#include "..\script_component.hpp" +/* + * Author: Ampersand + * Triggered by the lower-action. Attaches chestpack to a dummy and connects dummy to parachute by rope. + * + * Arguments: + * 0: Unit + * + * Return Value: + * Nothing + * + * Example: + * [player] call tac_backpack_on_chest_fnc_actionLower; + * + * Public: No + */ + +params ["_unit"]; + +private _chute = vehicle _unit; + +// Rope top helper, workaround parachute rope visual bug, allow cut +private _ropeTop = createVehicle ["ace_fastroping_helper", getPos _chute, [], 0, "CAN_COLLIDE"]; +_chute setVariable [QGVAR(loweringLine), _ropeTop, true]; +_ropeTop allowDamage false; +_ropeTop disableCollisionWith _chute; + +// Weapon holder with backpack +private _holder = [_unit] call FUNC(chestpackToHolder); // Chestpack to holder +_holder disableCollisionWith _chute; +_holder setPos (_chute modelToWorld [0, 1, -1]); +_holder setVelocity velocity _chute; + +private _rope = ropeCreate [ + _ropeTop, [0,0,0], + _holder, [0.1,-0.2,-0.55], + 5 +]; + +[{ + params ["_chute", "_ropeTop"]; + _ropeTop attachTo [_chute, [0,0,0]]; +}, [_chute, _ropeTop]] call CBA_fnc_execNextFrame; + +[QGVAR(checkLandedPFH), [_ropeTop, _holder]] call CBA_fnc_serverEvent; diff --git a/addons/backpack_on_chest/functions/fnc_actionOnBack.sqf b/addons/backpack_on_chest/functions/fnc_actionOnBack.sqf new file mode 100644 index 00000000..e39212f5 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_actionOnBack.sqf @@ -0,0 +1,44 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Triggered by the onBack-action. Handles all the stuff. + * + * Arguments: + * 0: Unit + * + * Return Value: + * Nothing + * + * Example: + * [player] call tac_backpack_on_chest_fnc_actionOnBack; + * + * Public: No + */ +params ["_unit"]; + +private _chestpack = [_unit] call FUNC(chestpack); +private _chestpackLoadout = [_unit] call FUNC(chestpackLoadout); +private _chestpackVariables = [_unit] call FUNC(chestpackVariables); + +// make sure the player has a chestpack and no backpack +if ((_chestpack isEqualTo "") || (backpack _unit isNotEqualTo "")) exitWith {}; + +// add items +private _loadout = getUnitLoadout _unit; +_loadout set [5, [_chestpack, _chestpackLoadout]]; +_unit setUnitLoadout _loadout; + +/* + * prefilled versions of backpacks (ammo bearer, engineer, explosives, medic, repair, etc), can be emptied and placed in unit's backpack. + * they must each be emptied when added safe since game inventory won't let players add non-empty backpacks into their backpack + */ + +[QGVAR(clearCargoBackpacks), [backpackContainer _unit]] call CBA_fnc_globalEvent; + +// add variables +private _backpack = backpackContainer _unit; +{ + _backpack setVariable [(_x select 0), (_x select 1), true]; +} forEach _chestpackVariables; + +[_unit] call FUNC(removeChestpack); diff --git a/addons/backpack_on_chest/functions/fnc_actionOnChest.sqf b/addons/backpack_on_chest/functions/fnc_actionOnChest.sqf new file mode 100644 index 00000000..0de7b53b --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_actionOnChest.sqf @@ -0,0 +1,32 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Triggered by the onChest-action. Handles all the stuff. + * + * Arguments: + * 0: Unit + * + * Return Value: + * Nothing + * + * Example: + * [player] call tac_backpack_on_chest_fnc_actionOnChest; + * + * Public: No + */ + +params["_unit"]; + +private _backpack = backpack _unit; +private _backpackLoad = loadBackpack _unit; +private _backpackLoadout = ((getUnitLoadout _unit) select 5) select 1; +private _backpackVariables = []; + +{ + private _val = (backpackContainer _unit) getVariable _x; + _backpackVariables pushBack [_x, _val]; +} forEach ((allVariables (backpackContainer _unit) - GVAR(VarBlacklist))); + +[_unit, _backpack, _backpackLoadout, _backpackVariables, _backpackLoad] call FUNC(addChestpack); + +removeBackpackGlobal _unit; diff --git a/addons/backpack_on_chest/functions/fnc_actionSwap.sqf b/addons/backpack_on_chest/functions/fnc_actionSwap.sqf new file mode 100644 index 00000000..8e18eba3 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_actionSwap.sqf @@ -0,0 +1,53 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Triggered by the swap-action. Handles all the stuff. + * + * Arguments: + * 0: Unit + * + * Return Value: + * Nothing + * + * Example: + * [player] call tac_backpack_on_chest_fnc_actionSwap; + * + * Public: No + */ +params ["_unit"]; + +private _backpack = backpack _unit; +private _backpackLoad = loadBackpack _unit; +private _backpackLoadout = ((getUnitLoadout _unit) select 5) select 1; +private _backpackVariables = []; + +private _chestpack = [_unit] call FUNC(chestpack); +private _chestpackLoadout = [_unit] call FUNC(chestpackLoadout); +private _chestpackVariables = [_unit] call FUNC(chestpackVariables); + +// make sure the player has chest-pack and backpack +if ((_backpack isEqualTo "") || ([_unit] call FUNC(chestpack)) isEqualTo "") exitWith {}; + +// Backpack Variable Handling +{ + private _val = (backpackContainer _unit) getVariable _x; + _backpackVariables pushBack [_x, _val]; +} forEach ((allVariables (backpackContainer _unit) - GVAR(VarBlacklist))); + +// remove packs +[_unit] call FUNC(removeChestpack); +removeBackpackGlobal _unit; + +// add backpack loadout +private _loadout = getUnitLoadout _unit; +_loadout set [5, [_chestpack, _chestpackLoadout]]; +_unit setUnitLoadout _loadout; + +// add backpack variables +private _backpackNew = backpackContainer _unit; +{ + _backpackNew setVariable [(_x select 0), (_x select 1), true]; +} forEach _chestpackVariables; + +// add chestpack +[_unit, _backpack, _backpackLoadout, _backpackVariables, _backpackLoad] call FUNC(addChestpack); diff --git a/addons/backpack_on_chest/functions/fnc_addChestpack.sqf b/addons/backpack_on_chest/functions/fnc_addChestpack.sqf new file mode 100644 index 00000000..bed20654 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_addChestpack.sqf @@ -0,0 +1,59 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Adds a chestpack to a unit. If a unit already has one, the old chestpack will be ignored and will be deleted completely. + * + * Arguments: + * 0: Unit + * 1: Backpack Classname + * 2: Backpack Loadout + * 3: Backpack Variables + * + * Return Value: + * Nothing + * + * Example: + * [player, "B_Kitbag_rgr", ["FirstAidKit", 5], ["ace_gunbag_gunbagWeapon", "srifle_GM6_F"], []] call tac_backpack_on_chest_fnc_addChestpack; + * + * Public: No + */ +params ["_unit", "_chestpackClass", ["_backpackLoadout", []], ["_backpackVariables", []], ["_backpackLoad", -2]]; + +if (_backpackLoad isEqualTo -2) then { + _backpackLoad = loadBackpack _unit; +}; + +// add HandleDisconnect-EH on server if not done yet +if !(GETMVAR(GVAR(HDCEHadded),false)) then { + [QGVAR(handleDisconnect), []] call CBA_fnc_serverEvent; + GVAR(HDCEHadded) = true; + publicVariable QGVAR(HDCEHadded); +}; + +// delete existing chestpack, if there is one +if ([_unit] call FUNC(chestpack) != "") then { + [_unit] call FUNC(removeChestpack); +}; + +// add EHs +private _getInID = _unit addEventHandler ["GetInMan",FUNC(EHGetIn)]; +private _getOutID = _unit addEventHandler ["GetOutMan",FUNC(EHGetOut)]; +private _animID = _unit addEventHandler ["AnimDone",FUNC(EHAnimDone)]; +private _killedID = _unit addEventHandler ["Killed",FUNC(EHKilled)]; + +// create chestpack itself +private _chestpack = createSimpleObject [_chestpackClass, getPos _unit]; + +if (GVAR(walk)) then { + [_unit, "forceWalk", "BackpackOnChest", true] call ACEFUNC(common,statusEffect_set); +}; + +// set variable +_unit setVariable [QGVAR(chestpack), [[_chestpackClass, _chestpack], [_getInID, _getOutID, _animID, _killedID], _backpackLoadout, _backpackVariables, _backpackLoad], true]; + +// handle vehicles +if (vehicle _unit isNotEqualTo _unit) then { + [_unit, "", vehicle _unit] call FUNC(EHGetIn); +} else { + [_unit, "", objNull] call FUNC(EHGetOut); +}; diff --git a/addons/backpack_on_chest/functions/fnc_addItemToChestpack.sqf b/addons/backpack_on_chest/functions/fnc_addItemToChestpack.sqf new file mode 100644 index 00000000..bac4ce9c --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_addItemToChestpack.sqf @@ -0,0 +1,34 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Creates a new item and stores it in the soldier's chestpack. + * The item(s) won't be added, if adding them would cause an overflow of the backpack. + * + * Arguments: + * 0: Unit + * 1: Item + * + * Return Value: + * Nothing + * + * Example: + * [player,"FirstAidKit"] call tac_backpack_on_chest_fnc_addItemToChestpack; + * + * Public: No + */ +params ["_unit","_item"]; + +private _var = _unit getVariable [QGVAR(chestpack), nil]; + +// exit if there is not enough space left +if !([_unit, _item] call FUNC(canAddItemToChestpack)) exitWith {}; + +// add item +private _itemMass = [_item] call FUNC(itemMass); +private _maximumLoad = getNumber(configFile >> "CfgVehicles" >> ([_unit] call FUNC(chestpack)) >> "maximumLoad"); +private _preLoadPercent = _var select 4; +(_var select 2) pushBack [_item, 1]; +_var set [4, (_preLoadPercent + (_itemMass / _maximumLoad))]; + +// update public variable +_unit setVariable [QGVAR(chestpack), _var, true]; diff --git a/addons/backpack_on_chest/functions/fnc_addMagToChestpack.sqf b/addons/backpack_on_chest/functions/fnc_addMagToChestpack.sqf new file mode 100644 index 00000000..0bbbbf4a --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_addMagToChestpack.sqf @@ -0,0 +1,32 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Creates new magazine and stores it in the soldier's chestpack. Only magazines are supported. + * The purpose of this function is to ensure that magazines with a specified ammo count can be added. + * If you want to add a/multiple full magazine(s) you may want to use 'zade_boc_addItemToChestpack' instead. + * + * Arguments: + * 0: Unit + * 1: Classname + * 2: Ammo count + * 3: Quanitity (Optional) + * + * Return Value: + * Nothing + * + * Example: + * [player,"30Rnd_556x45_Stanag",25] call zade_boc_fnc_addMagToChestpack; + * + * Public: No + */ +params ["_unit","_item","_ammo", ["_quantity", 1]]; + +// exit if there is not enough space left +if !([_unit, _item, _quantity] call FUNC(canAddItemToChestpack)) exitWith {}; + +private _var = _unit getVariable [QGVAR(chestpack), nil]; + +(_var select 2) pushBack [_item, _quantity, _ammo]; + +// update variable +_unit setVariable [QGVAR(chestpack), _var, true]; diff --git a/addons/backpack_on_chest/functions/fnc_arsenal_onButtonClick.sqf b/addons/backpack_on_chest/functions/fnc_arsenal_onButtonClick.sqf new file mode 100644 index 00000000..e2e1252c --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_arsenal_onButtonClick.sqf @@ -0,0 +1,42 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Triggered by the onButtonClick-EventHandler. + * + * Arguments: + * None + * + * Return Value: + * Nothing + * + * Example: + * [] call tac_backpack_on_chest_fnc_arsenal_onButtonClick; + * + * Public: No + */ +private _center = missionNamespace getVariable ["BIS_fnc_arsenal_center", player]; + +private _chestpack = [_center] call FUNC(chestpack); +private _backpack = backpack _center; + +private _action = ["onback", "onchest"] select (_chestpack isEqualTo ""); + +if ((_backpack isNotEqualTo "") && (_chestpack isNotEqualTo "")) then { + _action = "swap"; +}; + +// execute action +switch (_action) do { + case ("onback"): { + [_center] call FUNC(actionOnBack); + }; + case ("onchest"): { + [_center] call FUNC(actionOnChest); + }; + case ("swap"): { + [_center] call FUNC(actionSwap); + }; +}; + +// update arsenal +["ListSelectCurrent"] call BIS_fnc_arsenal; diff --git a/addons/backpack_on_chest/functions/fnc_arsenal_opened.sqf b/addons/backpack_on_chest/functions/fnc_arsenal_opened.sqf new file mode 100644 index 00000000..fd02586e --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_arsenal_opened.sqf @@ -0,0 +1,56 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Called by XEH_postInit. Creates button. + * + * Arguments: + * 0: Arsenal Display + * + * Return Value: + * Nothing + * + * Example: + * [_disp] call tac_backpack_on_chest_fnc_arsenal_opened; + * + * Public: No + */ +params ["_display"]; + +// exit if BOC is disabled +if (GVAR(disabled)) exitWith {}; + +// get lowest button that is hidden +private _notshown = 948; +for "_i" from 948 to 945 step -1 do { + if !(ctrlShown (_display displayCtrl _i)) then { + _notshown = _i; + }; +}; + +// default offset of two buttons +private _offset = ((ctrlPosition (_display displayCtrl 932)) select 1) - ((ctrlPosition (_display displayCtrl 930)) select 1); + +private _btn = _display ctrlCreate ["RscButtonArsenal", 9233]; + +// set pos +private _pos = ctrlPosition (_display displayCtrl (_notshown - 1)); +_pos set [1, (_pos select 1) + _offset]; +_btn ctrlSetPosition _pos; +_btn ctrlCommit 0; + +// set color +_btn ctrlSetBackgroundColor [0,0,0,0.5]; + +// add EH to backpack list and to newly created button +(_display displayCtrl 965) ctrlAddEventHandler ["LBSelChanged",FUNC(arsenal_updateUI)]; +_btn ctrlAddEventHandler ["ButtonClick",FUNC(arsenal_onButtonClick)]; + +// this is for hiding the button when the rest of the ui is hidden (e.g. by pressing BACKSPACE) +_display displayAddEventHandler ["KeyDown", + "0 = _this spawn {sleep 0.02; ((_this select 0) displayCtrl 9233) ctrlShow (ctrlShown ((_this select 0) displayCtrl 932));};" +]; +_display displayAddEventHandler ["MouseButtonUp", + "0 = _this spawn {sleep 0.02; ((_this select 0) displayCtrl 9233) ctrlShow (ctrlShown ((_this select 0) displayCtrl 932));};" +]; + +[_display] call FUNC(arsenal_updateUI); diff --git a/addons/backpack_on_chest/functions/fnc_arsenal_postInit.sqf b/addons/backpack_on_chest/functions/fnc_arsenal_postInit.sqf new file mode 100644 index 00000000..99baeba9 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_arsenal_postInit.sqf @@ -0,0 +1,20 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Called by postInit. Adds local "arsenalOpened" scriptedEventhandler. + * + * Arguments: + * None + * + * Return Value: + * Nothing + * + * Example: + * [] call tac_backpack_on_chest_fnc_arsenalPostInit; + * + * Public: No + */ + +if !(hasInterface) exitWith {}; + +[missionNamespace, "arsenalOpened", FUNC(arsenal_opened)] call BIS_fnc_addScriptedEventHandler; diff --git a/addons/backpack_on_chest/functions/fnc_arsenal_updateUI.sqf b/addons/backpack_on_chest/functions/fnc_arsenal_updateUI.sqf new file mode 100644 index 00000000..66faac37 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_arsenal_updateUI.sqf @@ -0,0 +1,57 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Called when backpack of arsenal unit changes. Updates Button icon / tooltip. + * + * Arguments: + * 0: Arsenal Display + * + * Return Value: + * Nothing + * + * Example: + * [_display] call tac_backpack_on_chest_fnc_arsenal_updateUI; + * + * Public: No + */ + +disableSerialization; +params ["_display"]; + +// the onSelChanged EH calls before the actual backpack changed so we have to wait a little bit +if (_display isEqualType controlNull) exitWith { + [ctrlParent _display] spawn { + sleep 0.05; _this call FUNC(arsenal_updateUI) + }; +}; + +// the arsenal unit +private _center = missionNamespace getVariable ["BIS_fnc_arsenal_center", player]; + +private _chestpack = [_center] call FUNC(chestpack); +private _backpack = backpack _center; + +private _action = ["onBack", "onChest"] select (_chestpack isEqualTo ""); +if ((_backpack isNotEqualTo "") && (_chestpack isNotEqualTo "")) then {_action = "swap";}; + +switch (_action) do { + case ("onBack"): { + (_display displayCtrl 9233) ctrlSetText QPATHTOF(ui\onback_ca.paa); + (_display displayCtrl 9233) ctrlSetTooltip LLSTRING(onBack); + }; + case ("onChest"): { + (_display displayCtrl 9233) ctrlSetText QPATHTOF(ui\onchest_ca.paa); + (_display displayCtrl 9233) ctrlSetTooltip LLSTRING(onChest); + }; + case ("swap"): { + (_display displayCtrl 9233) ctrlSetText QPATHTOF(ui\swap_ca.paa); + (_display displayCtrl 9233) ctrlSetTooltip LLSTRING(swap); + }; +}; + +if ((_backpack isEqualTo "") && (_chestpack isEqualTo "")) then { + (_display displayCtrl 9233) ctrlEnable false; + (_display displayCtrl 9233) ctrlSetTooltip ""; +} else { + (_display displayCtrl 9233) ctrlEnable true; +}; diff --git a/addons/backpack_on_chest/functions/fnc_canAddItemToChestpack.sqf b/addons/backpack_on_chest/functions/fnc_canAddItemToChestpack.sqf new file mode 100644 index 00000000..72b9048b --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_canAddItemToChestpack.sqf @@ -0,0 +1,29 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Checks if given item can be stored into soldier's chestpack. + * + * Arguments: + * 0: Unit + * 1: Item/magazine/weapon classname + * 2: Amount (optional) + * + * Return Value: + * Can add item? + * + * Example: + * [player,"FirstAidKit",2] call tac_backpack_on_chest_fnc_canAddItemToChestpack; + * + * Public: No + */ +params ["_unit","_item",["_amount",1]]; + +private _var = _unit getVariable [QGVAR(chestpack), nil]; +private _preLoadPercent = _var select 4; + +//calculate space left in chestpack +private _maximumLoad = getNumber(configFile >> "CfgVehicles" >> ([_unit] call FUNC(chestpack)) >> "maximumLoad"); +private _remainingLoad = (1 - _preLoadPercent) * _maximumLoad; +private _itemMass = [_item] call FUNC(itemMass); + +[true, false] select ((_itemMass * _amount) > _remainingLoad); diff --git a/addons/backpack_on_chest/functions/fnc_canCutLoweringLine.sqf b/addons/backpack_on_chest/functions/fnc_canCutLoweringLine.sqf new file mode 100644 index 00000000..88c16b22 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_canCutLoweringLine.sqf @@ -0,0 +1,25 @@ +#include "..\script_component.hpp" +/* + * Author: Ampersand + * Checks if given unit can cut its lowering line + * + * Arguments: + * 0: Unit + * + * Return Value: + * Success + * + * Example: + * [_unit] call tac_backpack_on_chest_fnc_canCutLoweringLine; + * + * Public: No + */ + +params ["_unit"]; + +if (GVAR(disabled)) exitWith {false}; + +private _chute = vehicle _unit; + +_chute isKindOf "ParachuteBase" +&& {!isNull (_chute getVariable [QGVAR(loweringLine), objNull])} diff --git a/addons/backpack_on_chest/functions/fnc_canLower.sqf b/addons/backpack_on_chest/functions/fnc_canLower.sqf new file mode 100644 index 00000000..4c6eaa67 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_canLower.sqf @@ -0,0 +1,22 @@ +#include "..\script_component.hpp" +/* + * Author: Ampersand + * Checks if given unit can lower its chestpack + * + * Arguments: + * 0: Unit + * + * Return Value: + * Success + * + * Example: + * [_unit] call tac_backpack_on_chest_fnc_canLower; + * + * Public: No + */ + +params ["_unit"]; + +if (GVAR(disabled)) exitWith {false}; + +vehicle _unit isKindOf "ParachuteBase" && {[_player] call FUNC(chestpack) != ''} diff --git a/addons/backpack_on_chest/functions/fnc_canMovePack.sqf b/addons/backpack_on_chest/functions/fnc_canMovePack.sqf new file mode 100644 index 00000000..b8b28557 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_canMovePack.sqf @@ -0,0 +1,22 @@ +#include "..\script_component.hpp" +/* + * Author: Ampersand + * Checks if given unit can move its pack(s) + * + * Arguments: + * 0: Unit + * + * Return Value: + * Success + * + * Example: + * [_unit] call tac_backpack_on_chest_fnc_canMovePack; + * + * Public: No + */ + +params ["_unit"]; + +if (GVAR(disabled)) exitWith {false}; + +!(vehicle _unit isKindOf "ParachuteBase") // Can't move pack while in a parachute diff --git a/addons/backpack_on_chest/functions/fnc_chestpack.sqf b/addons/backpack_on_chest/functions/fnc_chestpack.sqf new file mode 100644 index 00000000..24970e91 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_chestpack.sqf @@ -0,0 +1,25 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Returns the classname of a unit's chestpack. + * + * Arguments: + * 0: Unit + * + * Return Value: + * Classname + * + * Example: + * [player] call tac_backpack_on_chest_fnc_chestpack; + * + * Public: No + */ +params ["_unit"]; + +private _var = _unit getVariable [QGVAR(chestpack), nil]; + +if (isNil "_var") exitWith {""}; +private _chestpackClass = (_var select 0) select 0; + +// return classname +_chestpackClass diff --git a/addons/backpack_on_chest/functions/fnc_chestpackContainer.sqf b/addons/backpack_on_chest/functions/fnc_chestpackContainer.sqf new file mode 100644 index 00000000..993882d5 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_chestpackContainer.sqf @@ -0,0 +1,29 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Returns the cargo container of a unit's chestpack. Note that this is only a prop and does not contain any items. Items which + * were added with vanilla commands like 'addWeaponCargo' etc. will be ignored. You have to use the provided functions instead. + * + * Arguments: + * 0: Unit + * + * Return Value: + * Cargo container or objNull + * + * Example: + * [player] call tac_backpack_on_chest_fnc_chestpackContainer; + * + * Public: No + */ +params ["_unit"]; + +if (isNil "_unit") exitWith { + ERROR("No proper argument(s) given."); +}; + +private _var = _unit getVariable [QGVAR(chestpack), nil]; +private _chestpack = (_var select 0) select 1; + +if (isNil "_var" || isNil "_chestpack") exitWith {objNull}; + +_chestpack diff --git a/addons/backpack_on_chest/functions/fnc_chestpackLoadout.sqf b/addons/backpack_on_chest/functions/fnc_chestpackLoadout.sqf new file mode 100644 index 00000000..21ddf05d --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_chestpackLoadout.sqf @@ -0,0 +1,26 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Returns Unit Loadout Array of chestpack of the given unit. + * + * Arguments: + * 0: Unit + * + * Return Value: + * Items + * + * Example: + * [player] call tac_backpack_on_chest_fnc_chestpackLoadout; + * + * Public: No + */ +params ["_unit"]; + +private _var = _unit getVariable [QGVAR(chestpack), nil]; +private _loadout = + (_var select 2); + +// return objNull +if (isNil "_var" || isNil "_loadout") exitWith {[]}; + +// return items +_loadout diff --git a/addons/backpack_on_chest/functions/fnc_chestpackToHolder.sqf b/addons/backpack_on_chest/functions/fnc_chestpackToHolder.sqf new file mode 100644 index 00000000..908297fb --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_chestpackToHolder.sqf @@ -0,0 +1,41 @@ +#include "..\script_component.hpp" +/* + * Author: Ampersand + * Returns WeaponHolderSimulated with copy of chestpack + * + * Arguments: + * 0: Unit + * + * Return Value: + * 0: WeaponHolderSimulated + * + * Example: + * [player] call tac_backpack_on_chest_fnc_chestpackToHolder; + * + * Public: No + */ + +params ["_unit"]; + +private _chestpack = [_unit] call FUNC(chestpack); +if (_chestpack isEqualTo "") exitWith {objNull}; +private _chestpackLoadout = [_unit] call FUNC(chestpackLoadout); +private _chestpackVariables = [_unit] call FUNC(chestpackVariables); + +private _holder = createVehicle ["WeaponHolderSimulated", (getPos _unit), [], 0, "CAN_COLLIDE"]; + +// add pack +_holder addBackpackCargoGlobal [_chestpack, 1]; +private _backpack = firstBackpack _holder; + +[_backpack, _chestpackLoadout] call FUNC(setBackpackLoadout); + +// add variables +{ + _backpack setVariable [(_x select 0), (_x select 1), true]; +} forEach _chestpackVariables; + +// remove the backpack from the dead unit +[_unit] call FUNC(removeChestpack); + +_holder diff --git a/addons/backpack_on_chest/functions/fnc_chestpackVariables.sqf b/addons/backpack_on_chest/functions/fnc_chestpackVariables.sqf new file mode 100644 index 00000000..958cebbf --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_chestpackVariables.sqf @@ -0,0 +1,26 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Returns array with all variables in chestpack of the given unit. + * + * Arguments: + * 0: Unit + * + * Return Value: + * variables + * + * Example: + * [player] call tac_backpack_on_chest_fnc_chestpackVariables; + * + * Public: No + */ +params ["_unit"]; + +private _var = _unit getVariable [QGVAR(chestpack), nil]; +private _variables = + (_var select 3); + + +if (isNil "_var" || isNil "_variables") exitWith {[]}; + +// return items +_variables diff --git a/addons/backpack_on_chest/functions/fnc_clearAllCargo.sqf b/addons/backpack_on_chest/functions/fnc_clearAllCargo.sqf new file mode 100644 index 00000000..e24035b2 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_clearAllCargo.sqf @@ -0,0 +1,23 @@ +#include "..\script_component.hpp" +/* + * Author: Ampersand + * Called locally by event. Clears all the cargo of given container. + * + * Arguments: + * 0: Container + * + * Return Value: + * NONE + * + * Example: + * [_container] call tac_backpack_on_chest_fnc_clearAllCargo; + * + * Public: No + */ + +params ["_container"]; + +clearItemCargo _container; +clearWeaponCargo _container; +clearMagazineCargo _container; +clearBackpackCargo _container; diff --git a/addons/backpack_on_chest/functions/fnc_clearAllItemsFromChestpack.sqf b/addons/backpack_on_chest/functions/fnc_clearAllItemsFromChestpack.sqf new file mode 100644 index 00000000..1ee4d5f0 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_clearAllItemsFromChestpack.sqf @@ -0,0 +1,29 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade + * Removes all items (includes weapons and magazines) from a unit's chestpack. + * + * Arguments: + * 0: Unit + * 1: Clear Variables (Optional) + * + * Return Value: + * Nothing + * + * Example: + * [player] call zade_boc_fnc_clearAllItemsFromChestpack; + * + * Public: No + */ +params ["_unit", ["_variables", true]]; + +private _var = _unit getVariable [QGVAR(chestpack),nil]; +_var set [2,[]]; + +if (_variables) then { + _var set [3, []]; +}; + +_var set [4, 0]; + +_unit setVariable [QGVAR(chestpack),_var, true]; diff --git a/addons/backpack_on_chest/functions/fnc_clearCargoBackpacks.sqf b/addons/backpack_on_chest/functions/fnc_clearCargoBackpacks.sqf new file mode 100644 index 00000000..e02911f0 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_clearCargoBackpacks.sqf @@ -0,0 +1,22 @@ +#include "..\script_component.hpp" +/* + * Author: Ampersand + * Called locally by event. Clear inventory of every backpack in given container. + * + * Arguments: + * 0: Container + * + * Return Value: + * NONE + * + * Example: + * [_container] call tac_backpack_on_chest_fnc_clearCargoBackpacks; + * + * Public: No + */ + +params ["_container"]; + +{ + [_x] call FUNC(clearAllCargo); +} forEach everyBackpack _container; diff --git a/addons/backpack_on_chest/functions/fnc_itemMass.sqf b/addons/backpack_on_chest/functions/fnc_itemMass.sqf new file mode 100644 index 00000000..01b6ef45 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_itemMass.sqf @@ -0,0 +1,49 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton, MikeMF + * Finds mass of given item. + * + * Arguments: + * 0: Item + * + * Return Value: + * Item mass + * + * Example: + * ["FirstAidKit"] call tac_backpack_on_chest_fnc_itemMass; + * + * Public: No + */ + +params ["_item"]; + +private _weaponConfig = configFile >> "CfgWeapons" >> _item; +private _weaponConfigItemInfo = _weaponConfig >> "ItemInfo"; + +if (isClass (_weaponConfigItemInfo)) exitWith { + getNumber (_weaponConfig >> "ItemInfo" >> "Mass"); +}; + +private _weaponConfigSlots = _weaponConfig >> "WeaponSlotsInfo"; + +if (isClass (_weaponConfigSlots)) exitWith { + getNumber (_weaponConfigSlots >> "Mass"); +}; + +private _magazineConfigMass = configFile >> "CfgMagazines" >> _item; + +if (isClass _magazineConfigMass) exitWith { + getNumber (_magazineConfigMass >> "Mass"); +}; + +private _vehiclesConfigMass = configFile >>"CfgVehicles">> _item; + +if (isClass _vehiclesConfigMass) exitWith { + getNumber (_vehiclesConfigMass >> "Mass"); +}; + +private _glassesConfigMass = configFile >> "CfgGlasses" >> _item; + +if (isClass _glassesConfigMass) exitWith { + getNumber (_glassesConfigMass >> "Mass"); +}; diff --git a/addons/backpack_on_chest/functions/fnc_removeChestpack.sqf b/addons/backpack_on_chest/functions/fnc_removeChestpack.sqf new file mode 100644 index 00000000..4cd4edfe --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_removeChestpack.sqf @@ -0,0 +1,35 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Removes unit's chestpack. + * + * Arguments: + * 0: Unit + * + * Return Value: + * Nothing + * + * Example: + * [player] call tac_backpack_on_chest_fnc_removeChestpack; + * + * Public: No + */ +params ["_unit"]; + +private _var = _unit getVariable [QGVAR(chestpack), nil]; + +// delete chestpackContainer +deleteVehicle ([_unit] call FUNC(chestpackContainer)); + +// remove all EHs +_unit removeEventHandler ["GetInMan",(_var select 1) select 0]; +_unit removeEventHandler ["GetOutMan",(_var select 1) select 1]; +_unit removeEventHandler ["AnimDone",(_var select 1) select 2]; +_unit removeEventHandler ["Killed",(_var select 1) select 3]; + +if (GVAR(walk)) then { + [_unit, "forceWalk", "BackpackOnChest", false] call ACEFUNC(common,statusEffect_set); +}; + +// reset variable +_unit setVariable [QGVAR(chestpack), nil, true]; diff --git a/addons/backpack_on_chest/functions/fnc_removeItemFromChestpack.sqf b/addons/backpack_on_chest/functions/fnc_removeItemFromChestpack.sqf new file mode 100644 index 00000000..67f96bf0 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_removeItemFromChestpack.sqf @@ -0,0 +1,46 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Removes item from unit's chestpack. + * + * Arguments: + * 0: Unit + * 1: Item/magazine/weapon classname + * 2: Quantity (Optional) + * + * Return Value: + * Nothing + * + * Example: + * [player,"FirstAidKit"] call tac_backpack_on_chest_fnc_removeItemFromChestpack; + * + * Public: No + */ +params ["_unit","_item", ["_quantity", 1]]; + +private _loadout = _unit call FUNC(chestpackLoadout); +private _itemFound = { + if (_x find _item isNotEqualTo -1) exitWith { + [_x, _forEachIndex, true] + }; +} forEach _loadout; + +// exit if no item found +if (_itemFound select 2 isNotEqualTo true) exitWith {}; + +private _var = _unit getVariable [QGVAR(chestpack), nil]; +private _currentItem = (_var select 2) select (_itemFound select 1); +private _newQuantity = (_currentItem select 1) - _quantity; + +if (_newQuantity <= 0) then { + (_var select 2) deleteAt (_itemFound select 1); +} else { + private _newItem = +(_currentItem); + _newItem set [1, _newQuantity]; + (_var select 2) set [(_itemFound select 1), _newItem]; +}; + +_unit setVariable [QGVAR(chestpack), _var, true]; + +// return deleted item +(_itemFound select 0) diff --git a/addons/backpack_on_chest/functions/fnc_removeMagFromChestpack.sqf b/addons/backpack_on_chest/functions/fnc_removeMagFromChestpack.sqf new file mode 100644 index 00000000..cbf6da08 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_removeMagFromChestpack.sqf @@ -0,0 +1,49 @@ +#include "..\script_component.hpp" +/* + * Author: DerZade, mjc4wilton + * Removes magazine from unit's chestpack. The purpose of this function is to ensure that magazines with a specified ammo count can be removed. + * If you want to remove a magazine with just any amount of ammo you may want to use 'zade_boc_fnc_removeItemFromChestpack' instead. + * + * Arguments: + * 0: Unit + * 1: Classname + * 2: Ammo count + * 3: Quantity (Optional) + * + * Return Value: + * [MagazineClassname, Qty, Rounds] + * + * Example: + * [player,"30Rnd_556x45_Stanag",25] call tac_backpack_on_chest_fnc_removeMagFromChestpack; + * + * Public: No + */ +params ["_unit","_item","_ammo", ["_quantity", 1]]; + +private _loadout = [_unit] call FUNC(chestpackLoadout); + +private _mag = { + if ((_x select 0 isEqualTo _item) && (_x select 2 isEqualTo _ammo)) exitWith { + [_x, _forEachIndex, true]; + }; +} forEach _loadout; + +// exit if there is no such item in chestpack +if (_mag select 2 isNotEqualTo true) exitWith {}; + +private _var = _unit getVariable [QGVAR(chestpack),nil]; +private _currentMag = (_var select 2) select (_mag select 1); +private _newQuantity = (_currentMag select 1) - (_quantity); + +if (_newQuantity <= 0) then { + (_var select 2) deleteAt (_mag select 1); +} else { + private _newMag = [(_currentMag select 0), _newQuantity, (_currentMag select 2)]; + (_var select 2) set [(_mag select 1), _newMag]; +}; + +// update variable +_unit setVariable [QGVAR(chestpack),_var,true]; + +// return item. +(_mag select 0); diff --git a/addons/backpack_on_chest/functions/fnc_setBackpackLoadout.sqf b/addons/backpack_on_chest/functions/fnc_setBackpackLoadout.sqf new file mode 100644 index 00000000..bb882ff9 --- /dev/null +++ b/addons/backpack_on_chest/functions/fnc_setBackpackLoadout.sqf @@ -0,0 +1,64 @@ +#include "..\script_component.hpp" +/* + * Author: Ampersand + * Returns WeaponHolderSimulated with copy of chestpack + * + * Arguments: + * 0: Backpack + * 1: Loadout + * + * Return Value: + * 0: Success + * + * Example: + * [_backpack, (getUnitLoadout _unit) select 5 select 1] call tac_backpack_on_chest_fnc_setBackpackLoadout; + * + * Public: No + */ + +params ["_backpack", "_loadout"]; +if (isNull _backpack) exitWith {false}; + +[QGVAR(clearAllCargo), [_backpack]] call CBA_fnc_globalEvent; + +// add items +private _cfgMagazines = configFile >> "CfgMagazines"; +private _cfgVehicles = configFile >> "CfgVehicles"; +{ + if (typeName (_x select 0) == "Array") then { + // weapon with attachments + for "_i" from 1 to (_x select 1) do { + _backpack addWeaponWithAttachmentsCargoGlobal _x; + }; + } else { + private _cargoClass = (_x select 0); + if (isClass (_cfgMagazines >> _cargoClass)) then { + + _backpack addMagazineAmmoCargo _x; + // Above command sometimes fails on its own, like with PCML Missile in NATO Ammo Bearer's backpack + [{ + params ["_backpack", "_mag", "_count", "_rounds"]; + private _countInBackpack = {_x isEqualTo [_mag, _rounds]} count magazinesAmmoCargo _backpack; + if (_countInBackpack < _count) then { + _backpack addMagazineAmmoCargo [_mag, 1, _rounds]; + }; + _countInBackpack == _count + }, {}, [_backpack] + _x, 1, { + WARNING("chestpackToHolder timed out adding magazines"); + TRACE_1("Container: ",_this); + }] call CBA_fnc_waitUntilAndExecute; + + } else { + // backpacks + private _cfgCargoBackpack = _cfgVehicles >> _cargoClass; + if (isClass _cfgCargoBackpack) then { + _backpack addBackpackCargoGlobal [_cargoClass, 1]; + [QGVAR(clearCargoBackpacks), [_backpack]] call CBA_fnc_globalEvent; + } else { + _backpack addItemCargoGlobal _x; + }; + }; + }; +} forEach _loadout; + +true diff --git a/addons/backpack_on_chest/initSettings.inc.sqf b/addons/backpack_on_chest/initSettings.inc.sqf new file mode 100644 index 00000000..d4c605d1 --- /dev/null +++ b/addons/backpack_on_chest/initSettings.inc.sqf @@ -0,0 +1,20 @@ +private _category = format ["TAC %1", QUOTE(COMPONENT_BEAUTIFIED)]; +[ + QGVAR(disabled), + "CHECKBOX", + [LSTRING(Disable), LSTRING(Disable_Description)], + _category, + true, + true +] call CBA_fnc_addSetting; + +[ + QGVAR(walk), "CHECKBOX", + [LSTRING(forceWalk), LSTRING(forceWalk_Description)], + category, + true, + true +] call CBA_fnc_addSetting; + +// Blacklisted variables for mods that don't want variables to be transferred. Useful for very particular cases. +GVAR(VarBlacklist) = []; diff --git a/addons/backpack_on_chest/script_component.hpp b/addons/backpack_on_chest/script_component.hpp new file mode 100644 index 00000000..1d8f95b2 --- /dev/null +++ b/addons/backpack_on_chest/script_component.hpp @@ -0,0 +1,17 @@ +#define COMPONENT backpack_on_chest +#define COMPONENT_BEAUTIFIED Backpack On Chest +#include "\x\tac\addons\main\script_mod.hpp" + +// #define DEBUG_MODE_FULL +// #define DISABLE_COMPILE_CACHE +// #define ENABLE_PERFORMANCE_COUNTERS + +#ifdef DEBUG_ENABLED_BACKPACK_ON_CHEST + #define DEBUG_MODE_FULL +#endif + +#ifdef DEBUG_SETTINGS_BACKPACK_ON_CHEST + #define DEBUG_SETTINGS BACKPACK_ON_CHEST +#endif + +#include "\x\tac\addons\main\script_macros.hpp" diff --git a/addons/backpack_on_chest/stringtable.xml b/addons/backpack_on_chest/stringtable.xml new file mode 100644 index 00000000..26113ae1 --- /dev/null +++ b/addons/backpack_on_chest/stringtable.xml @@ -0,0 +1,35 @@ + + + + + Disable Backpack On Chest + + + Prevent usage of Backpack on Chest features + + + Backpack on Chest + + + Lower chestpack + + + Put backpack on back + + + Put backpack on chest + + + Swap rucksacks + + + Cut lowering line + + + Force Walking + + + Force the unit to walk with backpack on chest + + + diff --git a/addons/backpack_on_chest/ui/onback_ca.paa b/addons/backpack_on_chest/ui/onback_ca.paa new file mode 100644 index 00000000..62ffd457 Binary files /dev/null and b/addons/backpack_on_chest/ui/onback_ca.paa differ diff --git a/addons/backpack_on_chest/ui/onchest_ca.paa b/addons/backpack_on_chest/ui/onchest_ca.paa new file mode 100644 index 00000000..4196023c Binary files /dev/null and b/addons/backpack_on_chest/ui/onchest_ca.paa differ diff --git a/addons/backpack_on_chest/ui/swap_ca.paa b/addons/backpack_on_chest/ui/swap_ca.paa new file mode 100644 index 00000000..caa8d76c Binary files /dev/null and b/addons/backpack_on_chest/ui/swap_ca.paa differ