11#include " ..\script_component.hpp"
22/*
33 * Author: PabstMirror
4- *
5- * Makes a unit drop items
4+ * Makes a unit drop items.
65 *
76 * Arguments:
8- * 0: Caller (player) <OBJECT>
7+ * 0: Caller <OBJECT>
98 * 1: Target <OBJECT>
109 * 2: Classnames <ARRAY>
1110 * 3: Do Not Drop Ammo <BOOL> (default: false)
2120
2221#define TIME_MAX_WAIT 5
2322
24- params [" _caller" , " _target" , " _listOfItemsToRemove" , [" _doNotDropAmmo" , false , [false ]]]; // By default units drop all weapon mags when dropping a weapon
25-
26- private _fncSumArray = {
27- private _return = 0 ;
28- {_return = _return + _x ;} count (_this select 0 );
29- _return
30- };
23+ params [" _caller" , " _target" , " _listOfItemsToRemove" , [" _doNotDropAmmo" , false ]]; // By default units drop all weapon mags when dropping a weapon
3124
32- // Sanity Checks
33- if ! ([ _target ] call FUNC(canBeDisarmed)) exitWith {
25+ // Sanity Checks
26+ if ! (_target call FUNC(canBeDisarmed)) exitWith {
3427 [_caller , _target , " Debug: Cannot disarm target" ] call FUNC(eventTargetFinish);
3528};
36- if (_doNotDropAmmo && {({ _x in _listOfItemsToRemove } count (magazines _target )) > 0 }) exitWith {
29+ if (_doNotDropAmmo && {_listOfItemsToRemove findAny (magazines _target ) ! = - 1 }) exitWith {
3730 [_caller , _target , " Debug: Trying to drop magazine with _doNotDropAmmo flag" ] call FUNC(eventTargetFinish);
3831};
3932
4033private _holder = objNull ;
4134
42- // if _target is in a vehicle, use vehicle inventory as container
35+ // If _target is in a vehicle, use vehicle inventory as container
4336if (! isNull objectParent _target ) then {
4437 _holder = objectParent _target ;
4538};
4639
47- // If not dropping ammo, don't use an existing container
40+ // If not dropping ammo, don't use an existing container
4841if (! _doNotDropAmmo ) then {
4942 {
5043 if ((_x getVariable [QGVAR(disarmUnit), objNull ]) == _target ) exitWith {
@@ -53,34 +46,33 @@ if (!_doNotDropAmmo) then {
5346 } forEach ((getPos _target ) nearObjects [DISARM_CONTAINER, 3 ]);
5447};
5548
56- // Create a new weapon holder
49+ // Create a new weapon holder
5750if (isNull _holder ) then {
58- private _dropPos = _target modelToWorld [0.4 , 0.75 , 0 ]; // offset someone unconscious isn't lying over it
59- _dropPos set [2 , (( getPosASL _target ) select 2 ) ];
51+ private _dropPos = _target modelToWorld [0.4 , 0.75 , 0 ]; // Offset someone unconscious isn't lying over it
52+ _dropPos set [2 , (getPosASL _target ) select 2 ];
6053 _holder = createVehicle [DISARM_CONTAINER, _dropPos , [], 0 , " CAN_COLLIDE" ];
6154 _holder setPosASL _dropPos ;
6255 _holder setVariable [QGVAR(disarmUnit), _target , true ];
6356};
6457
65- // Verify holder created
58+ // Verify holder created
6659if (isNull _holder ) exitWith {
6760 [_caller , _target , " Debug: Null Holder" ] call FUNC(eventTargetFinish);
6861};
69- // Make sure only one drop operation at a time (using PFEH system as a queue)
62+ // Make sure only one drop operation at a time (using PFH system as a queue)
7063if (_holder getVariable [QGVAR(holderInUse), false ]) exitWith {
71- [{
72- call FUNC(disarmDropItems);
73- }, _this ] call CBA_fnc_execNextFrame ;
64+ [FUNC(disarmDropItems), _this ] call CBA_fnc_execNextFrame ;
7465};
7566_holder setVariable [QGVAR(holderInUse), true ];
7667
77- // Remove Magazines
68+ // Remove Magazines
69+ private _cfgMagazines = configFile >> " CfgMagazines" ;
7870private _targetMagazinesStart = magazinesAmmo _target ;
7971private _holderMagazinesStart = magazinesAmmoCargo _holder ;
8072
8173{
8274 _x params [" _xClassname" , " _xAmmo" ];
83- if ((_xClassname in _listOfItemsToRemove ) && {(getNumber (configFile >> " CfgMagazines " >> _xClassname >> " ACE_isUnique" )) == 0 }) then {
75+ if ((_xClassname in _listOfItemsToRemove ) && {(getNumber (_cfgMagazines >> _xClassname >> " ACE_isUnique" )) == 0 }) then {
8476 _holder addMagazineAmmoCargo [_xClassname , 1 , _xAmmo ];
8577 _target removeMagazine _xClassname ;
8678 };
@@ -89,112 +81,121 @@ private _holderMagazinesStart = magazinesAmmoCargo _holder;
8981private _targetMagazinesEnd = magazinesAmmo _target ;
9082private _holderMagazinesEnd = magazinesAmmoCargo _holder ;
9183
92- // Verify Mags dropped from unit:
93- if (( {((_x select 0 ) in _listOfItemsToRemove ) && {(getNumber (configFile >> " CfgMagazines " >> ( _x select 0 ) >> " ACE_isUnique" )) == 0 }} count _targetMagazinesEnd ) ! = 0 ) exitWith {
84+ // Verify Mags dropped from unit
85+ if (_targetMagazinesEnd findIf {((_x select 0 ) in _listOfItemsToRemove ) && {(getNumber (_cfgMagazines >> _x select 0 >> " ACE_isUnique" )) == 0 }} ! = - 1 ) exitWith {
9486 _holder setVariable [QGVAR(holderInUse), false ];
9587 [_caller , _target , " Debug: Didn't Remove Magazines" ] call FUNC(eventTargetFinish);
9688};
97- // Verify holder has mags unit had
89+ // Verify holder has mags unit had
9890if ! ([_targetMagazinesStart , _targetMagazinesEnd , _holderMagazinesStart , _holderMagazinesEnd ] call FUNC(verifyMagazinesMoved)) then {
9991 _holder setVariable [QGVAR(holderInUse), false ];
10092 [_caller , _target , " Debug: Crate Magazines not in holder" ] call FUNC(eventTargetFinish);
10193};
10294
103- // Remove Items, Assigned Items and NVG
95+ // Remove Items, Assigned Items and NVG
10496private _holderItemsStart = getItemCargo _holder ;
10597private _targetItemsStart = (assignedItems _target ) + (items _target ) - (weapons _target );
10698if ((headgear _target ) ! = " " ) then {_targetItemsStart pushBack (headgear _target );};
10799if ((goggles _target ) ! = " " ) then {_targetItemsStart pushBack (goggles _target );};
108100
101+ private _addToCrate = createHashMap;
109102
110- private _addToCrateClassnames = [];
111- private _addToCrateCount = [];
112103{
113104 if (_x in _listOfItemsToRemove ) then {
114105 if (_x in (items _target )) then {
115106 _target removeItem _x ;
116107 } else {
117108 _target unlinkItem _x ;
118109 };
119- private _index = _addToCrateClassnames find _x ;
120- if (_index ! = - 1 ) then {
121- _addToCrateCount set [_index , ((_addToCrateCount select _index ) + 1 )];
122- } else {
123- _addToCrateClassnames pushBack _x ;
124- _addToCrateCount pushBack 1 ;
125- };
110+
111+ _addToCrate set [_x , (_addToCrate getOrDefault [_x , 0 ]) + 1 ];
126112 };
127113} forEach _targetItemsStart ;
128114
129- // Add the items to the holder (combined to reduce addItemCargoGlobal calls)
115+ private _addToCrateTotal = 0 ;
116+
117+ // Add the items to the holder (combined to reduce addItemCargoGlobal calls)
130118{
131- _holder addItemCargoGlobal [(_addToCrateClassnames select _forEachIndex ), (_addToCrateCount select _forEachIndex )];
132- } forEach _addToCrateClassnames ;
119+ _holder addItemCargoGlobal [_x , _y ];
120+ _addToCrateTotal = _addToCrateTotal + _y ;
121+ } forEach _addToCrate ;
133122
134123private _holderItemsEnd = getItemCargo _holder ;
135124private _targetItemsEnd = (assignedItems _target ) + (items _target ) - (weapons _target );
136125if ((headgear _target ) ! = " " ) then {_targetItemsEnd pushBack (headgear _target );};
137126if ((goggles _target ) ! = " " ) then {_targetItemsEnd pushBack (goggles _target );};
138127
139- // Verify Items Added
140- if (((count _targetItemsStart ) - (count _targetItemsEnd )) ! = ([ _addToCrateCount ] call _fncSumArray ) ) exitWith {
128+ // Verify Items Added
129+ if (((count _targetItemsStart ) - (count _targetItemsEnd )) ! = _addToCrateTotal ) exitWith {
141130 _holder setVariable [QGVAR(holderInUse), false ];
142131 [_caller , _target , " Debug: Items Not Removed From Player" ] call FUNC(eventTargetFinish);
143132};
144- if ((([_holderItemsEnd select 1 ] call _fncSumArray ) - ([_holderItemsStart select 1 ] call _fncSumArray )) ! = ([_addToCrateCount ] call _fncSumArray )) exitWith {
133+
134+ private _fncSumArray = {
135+ private _return = 0 ;
136+
137+ {
138+ _return = _return + _x ;
139+ } forEach _this ;
140+
141+ _return
142+ };
143+
144+ if ((((_holderItemsEnd select 1 ) call _fncSumArray ) - ((_holderItemsStart select 1 ) call _fncSumArray )) ! = _addToCrateTotal ) exitWith {
145145 _holder setVariable [QGVAR(holderInUse), false ];
146146 [_caller , _target , " Debug: Items Not Added to Holder" ] call FUNC(eventTargetFinish);
147147};
148148
149- // Script drop uniforms/vest if empty
149+ // Script drop uniforms/vest if empty
150150if (((uniform _target ) ! = " " ) && {(uniform _target ) in _listOfItemsToRemove } && {(uniformItems _target ) isEqualTo []}) then {
151- _holder addItemCargoGlobal [( uniform _target ) , 1 ];
151+ _holder addItemCargoGlobal [uniform _target , 1 ];
152152 removeUniform _target ;
153153};
154154if (((vest _target ) ! = " " ) && {(vest _target ) in _listOfItemsToRemove } && {(vestItems _target ) isEqualTo []}) then {
155- _holder addItemCargoGlobal [( vest _target ) , 1 ];
155+ _holder addItemCargoGlobal [vest _target , 1 ];
156156 removeVest _target ;
157157};
158158
159-
160- // If holder is still empty, it will be 'garbage collected' while we wait for the drop 'action' to take place
161- // So add a dummy item and just remove at the end
162- private _holderIsEmpty = ([_holder ] call FUNC(getAllGearContainer)) isEqualTo [[],[]];
159+ // If holder is still empty, it will be 'garbage collected' while we wait for the drop 'action' to take place
160+ // So add a dummy item and just remove at the end
161+ private _holderIsEmpty = (_holder call FUNC(getAllGearContainer)) isEqualTo [[], []];
163162if (_holderIsEmpty ) then {
164163 TRACE_1(" Debug: adding dummy item to holder" ,_holder );
165164 _holder addItemCargoGlobal [DUMMY_ITEM, 1 ];
166165};
167166
168- // Start the PFEH to do the actions (which could take >1 frame)
167+ // Start the PFH to do the actions (which could take >1 frame)
169168[{
170- params [" _args" , " _pfID " ];
169+ params [" _args" , " _pfhID " ];
171170 _args params [" _caller" , " _target" , " _listOfItemsToRemove" , " _holder" , " _holderIsEmpty" , " _maxWaitTime" , " _doNotDropAmmo" , " _startingMagazines" ];
172171
173- private _needToRemoveWeapon = ({ _x in _listOfItemsToRemove } count (weapons _target )) > 0 ;
174- private _needToRemoveMagazines = ({ _x in _listOfItemsToRemove } count (magazines _target )) > 0 ;
172+ private _needToRemoveWeapon = _listOfItemsToRemove findAny (weapons _target ) ! = - 1 ;
173+ private _needToRemoveMagazines = _listOfItemsToRemove findAny (magazines _target ) ! = - 1 ;
175174 private _needToRemoveBackpack = ((backpack _target ) ! = " " ) && {(backpack _target ) in _listOfItemsToRemove };
176175 private _needToRemoveVest = ((vest _target ) ! = " " ) && {(vest _target ) in _listOfItemsToRemove };
177176 private _needToRemoveUniform = ((uniform _target ) ! = " " ) && {(uniform _target ) in _listOfItemsToRemove };
178177
179- if ((CBA_missionTime < _maxWaitTime ) && {[ _target ] call FUNC(canBeDisarmed)} && {_needToRemoveWeapon || _needToRemoveMagazines || _needToRemoveBackpack }) then {
180- // action drop weapons (keeps loaded magazine and attachements)
178+ if ((CBA_missionTime < _maxWaitTime ) && {_target call FUNC(canBeDisarmed)} && {_needToRemoveWeapon || _needToRemoveMagazines || _needToRemoveBackpack }) then {
179+ // Action drop weapons (keeps loaded magazine and attachements)
181180 {
182181 if (_x in _listOfItemsToRemove ) then {
183182 _target action [" DropWeapon" , _holder , _x ];
184183 };
185184 } forEach (weapons _target );
186185
187- // Drop magazine (keeps unique ID)
186+ // Drop magazine (keeps unique ID)
188187 {
189188 if (_x in _listOfItemsToRemove ) then {
190189 _target action [" DropMagazine" , _holder , _x ];
191190 };
192191 } forEach (magazines _target );
193192
194- // Drop backpack (Keeps variables for ACRE/TFR)
195- if (_needToRemoveBackpack ) then {_target action [" DropBag" , _holder , (backpack _target )];};
193+ // Drop backpack (Keeps variables for ACRE/TFR)
194+ if (_needToRemoveBackpack ) then {
195+ _target action [" DropBag" , _holder , backpack _target ];
196+ };
196197 } else {
197- [ _pfID ] call CBA_fnc_removePerFrameHandler ;
198+ _pfhID call CBA_fnc_removePerFrameHandler ;
198199
199200 if (_doNotDropAmmo ) then {
200201 private _error = false ;
@@ -213,31 +214,31 @@ if (_holderIsEmpty) then {
213214 _magazinesInHolder deleteAt _index ;
214215 } forEach _magsToPickup ;
215216
216- // No Error (all the ammo in the container is ammo we should have);
217- if (( ! _error ) && {_magazinesInHolder isEqualTo []}) then {
217+ // No Error (all the ammo in the container is ammo we should have);
218+ if (! _error && {_magazinesInHolder isEqualTo []}) then {
218219 {
219220 _target addMagazine _x ;
220221 } forEach (magazinesAmmoCargo _holder );
221222 clearMagazineCargoGlobal _holder ;
222223 };
223224 };
224225
225- // If we added a dummy item, remove it now
226- if (_holderIsEmpty && {(getItemCargo _holder ) isNotEqualTo [[DUMMY_ITEM],[1 ]]}) exitWith {
226+ // If we added a dummy item, remove it now
227+ if (_holderIsEmpty && {(getItemCargo _holder ) isNotEqualTo [[DUMMY_ITEM], [1 ]]}) exitWith {
227228 _holder setVariable [QGVAR(holderInUse), false ];
228229 [_caller , _target , " Debug: Holder should only have dummy item" ] call FUNC(eventTargetFinish);
229230 };
230231 if (_holderIsEmpty ) then {
231232 TRACE_1(" Debug: removing dummy item from holder" ,_holder );
232233 clearItemCargoGlobal _holder ;
233234 };
234- // Verify we didn't timeout waiting on drop action
235+ // Verify we didn't timeout waiting on drop action
235236 if (CBA_missionTime >= _maxWaitTime ) exitWith {
236237 _holder setVariable [QGVAR(holderInUse), false ];
237238 [_caller , _target , " Debug: Drop Actions Timeout" ] call FUNC(eventTargetFinish);
238239 };
239- // If target lost disarm status:
240- if ! ([ _target ] call FUNC(canBeDisarmed)) exitWith {
240+ // If target lost disarm status:
241+ if ! (_target call FUNC(canBeDisarmed)) exitWith {
241242 _holder setVariable [QGVAR(holderInUse), false ];
242243 [_caller , _target , " Debug: Target cannot be disarmed" ] call FUNC(eventTargetFinish);
243244 };
@@ -246,20 +247,19 @@ if (_holderIsEmpty) then {
246247 [_caller , _target , " Debug: Vest Not Empty" ] call FUNC(eventTargetFinish);
247248 };
248249 if (_needToRemoveVest ) then {
249- _holder addItemCargoGlobal [( vest _target ) , 1 ];
250+ _holder addItemCargoGlobal [vest _target , 1 ];
250251 removeVest _target ;
251252 };
252253 if (_needToRemoveUniform && {(uniformItems _target ) isNotEqualTo []}) exitWith {
253254 _holder setVariable [QGVAR(holderInUse), false ];
254255 [_caller , _target , " Debug: Uniform Not Empty" ] call FUNC(eventTargetFinish);
255256 };
256257 if (_needToRemoveUniform ) then {
257- _holder addItemCargoGlobal [( uniform _target ) , 1 ];
258+ _holder addItemCargoGlobal [uniform _target , 1 ];
258259 removeUniform _target ;
259260 };
260261
261262 _holder setVariable [QGVAR(holderInUse), false ];
262263 [_caller , _target , " " ] call FUNC(eventTargetFinish);
263264 };
264-
265- }, 0.0 , [_caller ,_target , _listOfItemsToRemove , _holder , _holderIsEmpty , (CBA_missionTime + TIME_MAX_WAIT), _doNotDropAmmo , _targetMagazinesEnd ]] call CBA_fnc_addPerFrameHandler ;
265+ }, 0 , [_caller ,_target , _listOfItemsToRemove , _holder , _holderIsEmpty , CBA_missionTime + TIME_MAX_WAIT, _doNotDropAmmo , _targetMagazinesEnd ]] call CBA_fnc_addPerFrameHandler ;
0 commit comments