Undeceived 392 Posted July 15, 2018 Hi guys, I would like to "collect" the items, weapons, magazines and backpacks that the player has put on the ground inside a certain trigger and put then into a crate. Is there a way to detect this stuff and create an array out of it. The relatively new command inAreaArray looked promising at first but unfortunately it doesn't recognize items, weapons and magazines (I couldn't do it at least). Does anyone know more? Thanks a lot! See the solution here: Share this post Link to post Share on other sites
haleks 8212 Posted July 15, 2018 27 minutes ago, Undeceived said: The relatively new command inAreaArray looked promising at first but unfortunately it doesn't recognize items, weapons and magazines (I couldn't do it at least). That's probably because those items are in virtual containers called "weaponHolders". Look for the "groundWeaponHolder" or "WeaponHolderSimulated" types of objects, and then check their content. Warning : it's boring. ^^ But I probably wrote something like that for Ravage already - I'll take a look and see if I can find some usefull bits of code. 1 Share this post Link to post Share on other sites
bad benson 1733 Posted July 15, 2018 in the meantime you can try this _stuff = [[],[],[],[]]; _objs = vehicles; _objs inAreaArray _trigger apply { (_stuff select 0) append (weaponCargo _x); (_stuff select 1) append (magazineCargo _x); (_stuff select 2) append (itemCargo _x); (_stuff select 2) append (backpackCargo _x); }; _stuff will contain the output. i used "vehicles". if you are using a trigger that will be activated to get the items you could also use the "thisList" variable inside the onActivation line of the trigger to get every object insdie the trigger area instead of checking all present vehicles in the mission. you could also filter that by class. some examples //to only check certain classes based on parent class do: _objs = vehicles select {_x isKindOf "Car"}; //or explicit classes: _objs = vehicles select {typeOf _x in ["GroundWeaponholder", "GroundWeaponholder_Scripted", "WeaponHolder_Simulated"]}; //or by string search _objs = vehicles select {toLower (typeOf _x) find "weaponholder" > -1}; that's just some quick and dirty examples though. not tested ingame. Share this post Link to post Share on other sites
Undeceived 392 Posted July 15, 2018 3 hours ago, bad benson said: in the meantime you can try this _stuff = [[],[],[],[]]; _objs = vehicles; _objs inAreaArray _trigger apply { (_stuff select 0) append (weaponCargo _x); (_stuff select 1) append (magazineCargo _x); (_stuff select 2) append (itemCargo _x); (_stuff select 2) append (backpackCargo _x); }; Thanks badbenson, I tried out this code but unfortunately the vehicles thing didn't work, so _stuff didn't have anything. As it seems to me, there are no vehicles in the trigger (I dropped an item, a mag and a rifle). Your explanations after this code were too much for my brain - couldn't understand it - sorry. EDIT: _objs = vehicles select {_x isKindOf "Car"}; worked when I placed a quad. But searching for the weaponholders didn't work. Share this post Link to post Share on other sites
Schatten 287 Posted July 15, 2018 @Undeceived, use this function: Spoiler private _allStuff = [ [], // Weapons [], // Magazines [], // Items [] // Backpacks ]; params [ ["_trigger", objNull, [objNull]] ]; if ((isNull _trigger) or {(typeOf _trigger) != "EmptyDetector"}) exitWith {_allStuff}; private ["_className", "_classNames", "_index", "_quantities", "_quantity", "_stuff", "_stuffOfType", "_weaponHolder", "_weaponHolders"]; _weaponHolders = (nearestObjects [_trigger, ["WeaponHolder", "WeaponHolderSimulated"], selectMax ((triggerArea _trigger) select [0, 2])]) select {_x inArea _trigger}; { _weaponHolder = _x; { _classNames = _x select 0; _quantities = _x select 1; _stuffOfType = _allStuff select _forEachIndex; { _className = _x; _quantity = _quantities select _forEachIndex; _index = _stuffOfType findIf {(_x select 0) == _className}; if (_index >= 0) then { _stuff = _stuffOfType select _index; _stuff set [1, (_stuff select 1) + _quantity]; } else { _stuffOfType pushBack [_className, _quantity]; }; } forEach _classNames; } forEach [ getWeaponCargo _weaponHolder, getMagazineCargo _weaponHolder, getItemCargo _weaponHolder, getBackpackCargo _weaponHolder ]; } forEach _weaponHolders; _allStuff Usage: _stuff = [_trigger] call fnc_getStuffInsideTrigger; Example of result: [[["hgun_Pistol_heavy_01_F",5]],[["11Rnd_45ACP_Mag",2]],[["H_MilCap_gry",3],["V_BandollierB_blk",1]],[["B_Kitbag_rgr",2]]] 1 1 Share this post Link to post Share on other sites
bad benson 1733 Posted July 15, 2018 @Undeceived you need to use the right input array. i didn't read the whole function by Schatten but he uses nearestObjects using the trigger properties to get the right input. so it'll probably work better for what you are searching for, if my stuff confuses you. of course you could just modify my version like this (just for completeness' sake) _objs = (nearestObjects [_trigger, ["All"], selectMax ((triggerArea _trigger) select [0, 2])]) select {_x inArea _trigger}; //taken from Schatten's code but his function also gives you an amount for each item while mine just uses doubles (class string for each individual item) which you probably want. so depends on what you need really. just to add something i have noticed debugging, in case someone else finds the useful. these are the classes i found in the config that have the word weaponholder in them. so if you are still not catching any of the ones you want with any of this code you might wanna try these classes for the filter. "GroundWeaponHolder", "GroundWeaponHolder_Scripted", "Library_WeaponHolder", "WeaponHolder", "WeaponHolder_Single_F", "WeaponHolder_Single_limited_item_F", "WeaponHolder_Single_limited_magazine_F", "WeaponHolder_Single_limited_weapon_F", "WeaponHolderSimulated", "WeaponHolderSimulated_Scripted" didn't have time to find out what those are used for. and several of those are probably parent classes. maybe someone knows more. might be used by Eden when you place a single item maybe. 1 Share this post Link to post Share on other sites
Undeceived 392 Posted July 16, 2018 @bad benson Cool, thanks for the addition / change. When using this, the code worked: _trigger = myCollectorTrigger; _stuff = [[],[],[],[]]; _objs = (nearestObjects [_trigger, ["All"], selectMax ((triggerArea _trigger) select [0, 2])]) select {_x inArea _trigger}; //taken from Schatten's code _objs inAreaArray _trigger apply { (_stuff select 0) append (weaponCargo _x); (_stuff select 1) append (magazineCargo _x); (_stuff select 2) append (itemCargo _x); (_stuff select 3) append (backpackCargo _x); }; The only problem left now is that all stuff that the units in the trigger have (and also the stuff that is in vehicles) is also added to the arrays. Is there a way to exclude everything so that only the stuff on the ground is collected? EDIT: 14 hours ago, bad benson said: but his function also gives you an amount for each item while mine just uses doubles (class string for each individual item) which you probably want. so depends on what you need really. Btw. this is what I need: One individual string for every item. Share this post Link to post Share on other sites
bad benson 1733 Posted July 16, 2018 @Undeceived yes. that's what the filtering is all about. _objs = (nearestObjects [_trigger, ["All"], selectMax ((triggerArea _trigger) select [0, 2])]) select {_x inArea _trigger}; i thought you wanted everything so i used "All". you should first try using the array that Schatten used in his function. like this _objs = (nearestObjects [_trigger, ["WeaponHolder", "WeaponHolderSimulated"], selectMax ((triggerArea _trigger) select [0, 2])]) select {_x inArea _trigger}; pretty sure that will give you all fo it. if not try some of the above mentioned classes. i think though that these two are the main parent classes, so it should work. 1 1 Share this post Link to post Share on other sites
Undeceived 392 Posted July 16, 2018 bad benson, yeah, that did the trick. Many thanks, man! To summarize the thread for mission designers that might have the same question: With this code you can create an array with items, magazines, weapons and backpacks that are laying on the ground in a trigger area: //Code by bad benson with elements of Schatten's function: _trigger = trigger_0; _stuff = [[],[],[],[]]; _objs = (nearestObjects [_trigger, ["WeaponHolder", "WeaponHolderSimulated"], selectMax ((triggerArea _trigger) select [0, 2])]) select {_x inArea _trigger}; _objs inAreaArray _trigger apply { (_stuff select 0) append (weaponCargo _x); (_stuff select 1) append (magazineCargo _x); (_stuff select 2) append (itemCargo _x); (_stuff select 3) append (backpackCargo _x); }; To show the array: hint str (_stuff); @bad benson's code creates an array with classname strings for each individual item. E.g.: [["hgun_P07_F"],["30Rnd_65x39_caseless_mag","30Rnd_65x39_caseless_mag","30Rnd_65x39_caseless_mag"],["FirstAidKit"],["B_AssaultPack_rgr_LAT"]] If you need an array that looks like this: [[["hgun_P07_F",1]],[["30Rnd_65x39_caseless_mag",3]],[["FirstAidKit",1]],[["B_AssaultPack_rgr_LAT",1]]] then you can use @Schatten's function: SCH_fnc_getStuffInsideTrigger = { private _allStuff = [ [], [], [], [] ]; params [ ["_trigger", objNull, [objNull]] ]; if ((isNull _trigger) or {(typeOf _trigger) != "EmptyDetector"}) exitWith {_allStuff}; private ["_className", "_classNames", "_index", "_quantities", "_quantity", "_stuff", "_stuffOfType", "_weaponHolder", "_weaponHolders"]; _weaponHolders = (nearestObjects [_trigger, ["WeaponHolder", "WeaponHolderSimulated"], selectMax ((triggerArea _trigger) select [0, 2])]) select {_x inArea _trigger}; { _weaponHolder = _x; { _classNames = _x select 0; _quantities = _x select 1; _stuffOfType = _allStuff select _forEachIndex; { _className = _x; _quantity = _quantities select _forEachIndex; _index = _stuffOfType findIf {(_x select 0) == _className}; if (_index >= 0) then { _stuff = _stuffOfType select _index; _stuff set [1, (_stuff select 1) + _quantity]; } else { _stuffOfType pushBack [_className, _quantity]; }; } forEach _classNames; } forEach [ getWeaponCargo _weaponHolder, getMagazineCargo _weaponHolder, getItemCargo _weaponHolder, getBackpackCargo _weaponHolder ]; } forEach _weaponHolders; _allStuff }; Show the result / call the function with: hint (str ([trigger_0] call SCH_fnc_getStuffInsideTrigger)); Many thanks to you both, guys. 1 1 Share this post Link to post Share on other sites
Undeceived 392 Posted July 16, 2018 Sorry for the double post: bad benson's result array brought up a last question: There's a way to remove the brackets so that the array looks like this, isn't it? ["hgun_P07_F","30Rnd_65x39_caseless_mag","30Rnd_65x39_caseless_mag","30Rnd_65x39_caseless_mag","FirstAidKit","B_AssaultPack_rgr_LAT"] Nevermind, I messed something up while writing the post above. bad benson's array result looks like this: [["hgun_P07_F"],["30Rnd_65x39_caseless_mag","30Rnd_65x39_caseless_mag","30Rnd_65x39_caseless_mag"],["FirstAidKit"],["B_AssaultPack_rgr_LAT"]] I checked it and for the achievement of my ultimate goal (fill the stuff into a crate) it's not needed to have all weapons+mags+items+backpacks in one array altogether. This will put the output of bad benson's code into a container: {crate addWeaponCargoGlobal [_x,1]; } forEach (_stuff select 0); {crate addMagazineCargoGlobal [_x,1]; } forEach (_stuff select 1); {crate addItemCargoGlobal [_x,1]; } forEach (_stuff select 2); {crate addBackpackCargoGlobal [_x,1]; } forEach (_stuff select 3); Share this post Link to post Share on other sites
bad benson 1733 Posted July 17, 2018 note that, you could've done that with Schatten's script too. this could potentially also be faster. although formating it the way he did takes some resources too, running addXCargoGlobal only once for each type of item is less stuff to do in the second part of it all. i don't want this to get too confusing but for this purpose there is no real reason to have individual strings. maybe i'm missing something. so with his output just do {_crate addWeaponCargoGlobal _x} forEach (_stuff select 0); {_crate addMagazineCargoGlobal _x} forEach (_stuff select 1); {_crate addItemCargoGlobal _x} forEach (_stuff select 2); {_crate addBackpackCargoGlobal _x} forEach (_stuff select 3); 2 Share this post Link to post Share on other sites
Schatten 287 Posted July 17, 2018 Well, I slightly improved my function: Spoiler private _allStuff = [ [], // Weapons [], // Magazines [], // Items [] // Backpacks ]; params [ ["_area", objNull, [objNull, ""]] ]; if ((_area isEqualType objNull) and {(isNull _area) or {(typeOf _area) != "EmptyDetector"}}) exitWith {_allStuff}; if ((_area isEqualType "") and {(_area == "") or {!(_area in allMapMarkers)} or {!((markerShape _area) in ["ELLIPSE", "RECTANGLE"])}}) exitWith {_allStuff}; private ["_className", "_classNames", "_index", "_predicate", "_quantities", "_quantity", "_stuff", "_stuffOfType", "_stuffType", "_values", "_weaponHolder", "_weaponHolders"]; _values = if (_area isEqualType "") then { [getMarkerPos _area, getMarkerSize _area] } else { [ASLToAGL (getPosASL _area), (triggerArea _area) select [0, 2]] }; _values params ["_areaPosition", "_areaSize"]; _weaponHolders = (nearestObjects [_areaPosition, ["WeaponHolder", "WeaponHolderSimulated"], selectMax _areaSize]) inAreaArray _area; { _weaponHolder = _x; { _classNames = _x select 0; _quantities = _x select 1; _stuffType = _forEachIndex; _stuffOfType = _allStuff select _stuffType; _predicate = if (_stuffType == 1) then { {((_x select 0) == _className) and {(_x select 2) == _quantity}} } else { {(_x select 0) == _className} }; { _values = if (_stuffType == 1) then {_x} else {[_x, _quantities select _forEachIndex]}; _className = _values select 0; _quantity = _values select 1; _index = _stuffOfType findIf _predicate; if (_index >= 0) then { if (_stuffType == 1) then {_quantity = 1;}; _stuff = _stuffOfType select _index; _stuff set [1, (_stuff select 1) + _quantity]; } else { _values = if (_stuffType == 1) then {[_className, 1, _quantity]} else {[_className, _quantity]}; _stuffOfType pushBack _values; }; } forEach _classNames; } forEach [ getWeaponCargo _weaponHolder, [magazinesAmmoCargo _weaponHolder, []], getItemCargo _weaponHolder, getBackpackCargo _weaponHolder ]; } forEach _weaponHolders; _allStuff Now it can accept either trigger object or marker name. Also it counts ammo inside magazines. Example of output: [ [["hgun_P07_F", 1], ["arifle_MX_ACO_pointer_F", 1], ["launch_NLAW_F", 1]], [["16Rnd_9x21_Mag", 1, 13], ["30Rnd_65x39_caseless_mag", 1, 27], ["Chemlight_green", 1, 1], ["30Rnd_65x39_caseless_mag", 2, 30]], [["FirstAidKit", 1], ["NVGoggles", 1], ["V_PlateCarrier2_rgr", 1], ["U_B_CombatUniform_mcam", 1], ["H_HelmetB_sand", 1]], [["B_AssaultPack_rgr_LAT", 1]] ] You can handle this array using this code: {_crate addWeaponCargoGlobal _x;} forEach (_stuff select 0); {_crate addMagazineAmmoCargo _x;} forEach (_stuff select 1); {_crate addItemCargoGlobal _x;} forEach (_stuff select 2); {_crate addBackpackCargoGlobal _x;} forEach (_stuff select 3); 1 Share this post Link to post Share on other sites
Undeceived 392 Posted January 6 Hi @Schatten @bad benson (or others who can help), how are you guys doing? After 5 years, I have another question on this topic: Is there a way to include items, magazines and weapons (in weaponsItems format) that are inside a container (e.g. vest or uniform) which is lying in the "collector" trigger area? EDIT: Brief summary of what I'm looking for: This code creates an array of all items, magazines and weapons that are on the ground in a trigger area (if I'm not mistaken, more precise, they're in a WeaponHolder in that trigger area). Later in the code, I also put all the stuff in a crate. Spoiler _trigger = triggerName; _stuff = [[],[],[],[]]; _objs = (nearestObjects [_trigger, ["WeaponHolder", "WeaponHolderSimulated"], selectMax ((triggerArea _trigger) select [0, 2])]) select {_x inArea _trigger}; _objs inAreaArray _trigger apply { (_stuff select 0) append (weaponsItemsCargo _x); (_stuff select 1) append (magazineCargo _x); (_stuff select 2) append (itemCargo _x); (_stuff select 3) append (backpackCargo _x); }; //Now put stuff in crate: stuffInTriggerArea = _stuff; {crate addWeaponWithAttachmentsCargoGlobal [_x,1]; } forEach (stuffInTriggerArea select 0); {crate addMagazineCargoGlobal [_x,1]; } forEach (stuffInTriggerArea select 1); {crate addItemCargoGlobal [_x,1]; } forEach (stuffInTriggerArea select 2); {crate addBackpackCargoGlobal [_x,1]; } forEach (stuffInTriggerArea select 3); Now I'd like to expand this code so it also gets items, mags and weapons that are in containers (e.g. vests, uniforms) which are in this trigger area. Any help would be much appreciated, thanks! Share this post Link to post Share on other sites
Undeceived 392 Posted January 6 (sorry, double post) Share this post Link to post Share on other sites
Clayman 20 Posted January 6 Hey Undeceived! How's it going? I haven't done any scripting in years, so bear with me... but if my memory doesn't fool me, everyContainer should do the trick. Maybe something like this: { (_stuff select 0) append (weaponsItemsCargo _x); (_stuff select 1) append (magazineCargo _x); (_stuff select 2) append (itemCargo _x); } forEach everyContainer (_stuff select 3); Not sure about syntax and stuff, like I said, it's been a long time. But hopefully it can point you in the right direction. 1 Share this post Link to post Share on other sites
Undeceived 392 Posted January 13 Thanks, @Clayman, and sorry for the late reply, I was busy with other things in the project. Now I got back to this. I couldn't make it work with your code, but I managed to use Larrow's code here as basis to make it work somehow. Collect items, magazines and weapons (in weaponsItems format) from a trigger area, INCLUDING everything that is inside a container (e.g. vest or uniform) and copy everything to a container: Spoiler _trigger = TRIGGER1; _targetContainer = CRATE1; //1: //Create array of all WeaponHolders in _trigger area (which means that you can place stuff in different places in the trigger area): _weaponHoldersInTriggerArea = (nearestObjects [_trigger, ["WeaponHolder", "WeaponHolderSimulated"], selectMax ((triggerArea _trigger) select [0, 2])]) select {_x inArea _trigger}; //2: //Let the magic begin: //Larrow's GET and SET code, slightly adapted: { _nul = [_x] call { //GET: _container = _this; TAG_fnc_getContents = { params[ "_container" ]; private _cargo = [ weaponsItemsCargo _container call BIS_fnc_consolidateArray, ( itemCargo _container select{ !( toLowerANSI( _x call BIS_fnc_itemType select 1 ) in [ "backpack", "uniform", "vest" ] ) } ) call BIS_fnc_consolidateArray, magazinesAmmoCargo _container call BIS_fnc_consolidateArray ]; private _containerCargo = everyContainer _container; { _x params[ "_type", "_object" ]; _containerCargo set[ _forEachIndex, [ _type, _object call TAG_fnc_getContents] ]; }forEach _containerCargo; [ _cargo, _containerCargo ] }; _contentWeaponHolder = _container call TAG_fnc_getContents; //SET: TAG_fnc_setContents = { params[ "_container", "_contents" ]; _contents params[ "_cargo", "_containers" ]; { _x params[ "_cont", "_contents" ]; _every = everyContainer _container; if ( _cont call BIS_fnc_itemType select 1 == "backpack" ) then { _container addBackpackCargoGlobal[ _cont, 1 ]; }else{ _container addItemCargoGlobal[ _cont, 1 ]; }; _addedContainer = ( everyContainer _container - _every ) select 0 select 1; clearItemCargoGlobal _addedContainer; clearWeaponCargoGlobal _addedContainer; clearBackpackCargoGlobal _addedContainer; clearMagazineCargoGlobal _addedContainer; [ _addedContainer, _contents ] call TAG_fnc_setContents; }forEach _containers; _fnc_addContents = { params[ "_index", "_details", "_count" ]; switch ( _index ) do { case ( 0 ) : { _container addWeaponWithAttachmentsCargoGlobal[ _details, _count ]; }; case ( 1 ) : { _container addItemCargoGlobal[ _details, _count ]; }; case ( 2 ) : { _details params[ "_mag", "_ammo" ]; _container addMagazineAmmoCargo[ _mag, _count, _ammo ]; }; }; }; { private _index = _forEachIndex; { _x params[ "_item", "_count" ]; [ _index, _item, _count ] call _fnc_addContents; }forEach _x; }forEach _cargo; }; [ _targetContainer, _contentWeaponHolder ] call TAG_fnc_setContents; } } forEach _weaponHoldersInTriggerArea; Small note: Uniforms, vests and backpacks will stay filled in the container with their content, like they were laying on the ground. If you want to "empty" the subcontainers in the target container (so that their content is outside of them in the target container), check Larrow's answer here. Super simple. 1 Share this post Link to post Share on other sites