Jump to content
madrussian

[problem] Simple Cargo Transfer (crate to crate)

Recommended Posts

I’m looking to transfer all contents from one crate to another.  Four types of things to transfer: weapons, magazines, items, and backpacks.  I started with magazines, and everything went smoothly using magazinesAmmoCargo and addMagazineAmmoCargo (transfer works perfectly including ammo counts).

 

Hit a snag with containers (backpacks, uniforms & vests).  It is very important to me to transfer not just the containers, but the contents of these containers as well.  For instance, transfer a backpack (full of magazines) from one crate to another.

 

I can get all containers within a crate via everyContainer command, which gives back a list of objects (which appears to be exactly what we need).  Now I need to move these objects into the destination crate.

 

There are several commands to add to cargo to vessels (crates, vehicles, etc):

However, all of these commands have one thing in common, which is that they take classname as a string, and thus create new instances of things.

 

I am looking for a command/commands to add container objects (like those provided by everyContainer or everyBackpack commands as mentioned above), to crates.  Looking really hard for this command, but not seeing it.  Please tell me I’m missing something here?

 

Any ideas?  Anyone know how to move a loaded container (backpack, uniform, vest) into a crate via script?  I hope there’s a simple way, but if not I’m willing to get creative.  Thanks!

Share this post


Link to post
Share on other sites

I'm afraid there is no simple mean for that. Not found any command or function.

For backpacks, i think you must add a civilian unit (I failed to do the same with logic), hidden, damaged false, anywhere in the map. Say MGIciv1.

Then, run this code for the transfer between from crate1 to crate2:

 

fn_CrateTransfer = {
  params [["_crate1",objNull,[objNull]],["_crate2",objNull,[objNull]]];
  if (isNull _crate1 or isNull _crate2) exitWith {};
  if (isNil "MGIciv1" or {!(MGIciv1 iskindOf "CAManBase")}) exitWith {hint "You must add a unit called MGIciv1"};
  _bpks = everyBackpack _crate1;
  _bpkClasses = _bpks apply {typeOf _x};
  _cnt = (count _bpks) - 1;
  for "_i" from 0 to _cnt do {
    _bpk = _bpks select _i;
    MGIciv1 action ["AddBag", _crate1, _bpkClasses select _i];
    waitUntil {!(_bpk in ((everyContainer _crate1) apply {_x deleteAt 1}))};
    MGIciv1 action ["DropBag", _crate2, backpack MGIciv1];
    waitUntil {(_bpk in ((everyContainer _crate2) apply {_x deleteAt 1}))};
  }
};

[crate1,crate2] spawn fn_crateTransfer;

 

Share this post


Link to post
Share on other sites

I am not sure but I think I did this in my sssc. I saved backpacks with its contents and moved it in a vehicle. But I be not the time within the next weeks to take a look at it. Maybe u want to. The link to sssc is in my signature and I think I did it in the Dev version only. You ll find it in the related thread.
Just look how I saved and restored vehicles contents in it...

sent from mobile using Tapatalk

Share this post


Link to post
Share on other sites

Thanks for the responses.

 

@pierremgi, that's awesome!  I went off for a few hours to experiment and we came up with something very similar.  I too couldn't get a logic working to transfer the supplies, so I had to settle for an invisible, invulnerable dummy guy.  My script uses the dummy guy to move the weapons and the backpacks, and moves the rest (mags and items) without him.  There is a big drawback currently however.  I haven't yet found a way to move Uniform and Vest objects over, so they just get recreated and end up empty (or at default state from the config).  Otherwise works pretty well, dummy does his work very quickly!

 

params ["_source", "_destination"];

_group = createGroup sideLogic;
//_dummy = _group createUnit ["Logic", position _source, [], 0, ""];
_dummy = _group createUnit [typeOf player, [0,0,0], [], 0, ""];

_dummy allowDamage false;
_dummy setCaptive true;
_dummy setCombatMode "BLUE";
_dummy setBehaviour "CARELESS";

_dummy hideObject true;
_dummy attachTo [_source, [0,0,-1]];

removeAllWeapons _dummy;
removeUniform _dummy;
removeVest _dummy;
removeBackpack _dummy;

detach _dummy;

// Weapons
_weaponCargo = getWeaponCargo _source;
_weapons = _weaponCargo select 0;
_counts = _weaponCargo select 1;
_i = 0;
{
	_weapon = _x;
	_count = _counts select _i;
	for "_j" from 1 to _count do {
		_dummy action ["TakeWeapon", _source, _weapon];
		waitUntil { (currentWeapon _dummy) != "" };
		_dummy action ["DropWeapon", _destination, _weapon];
		waitUntil { (currentWeapon _dummy) == "" };
	};
	_i = _i + 1;
} foreach _weapons;

// Backpacks
{
	_container = _x;
	_dummy action ["AddBag", _source, typeOf _container];
	waitUntil { (backpack _dummy) != "" };
	_dummy action ["DropBag", _destination, typeOf _container];
	waitUntil { (backpack _dummy) == "" };
} foreach (everyBackpack _source);

deleteVehicle _dummy;
deletegroup _group;

// Magazines
{
	_info = _x;
	_type = _info select 0;
	_ammoCount = _info select 1;
	
	_destination addMagazineAmmoCargo [_type, 1, _ammoCount];
} foreach (magazinesAmmoCargo _source);
clearMagazineCargoGlobal _source;

// Items
_itemCargo = getItemCargo _source;
_items = _itemCargo select 0;
_counts = _itemCargo select 1;
_i = 0;
{
	_item = _x;
	_count = _counts select _i;
	_destination addItemCargoGlobal [_item, _count];
	
	_i = _i + 1;
} foreach _items;
clearItemCargoGlobal _source;

Edit: Strangely, my dummy had to be within ~100m of the crate or he wouldn't transfer anything.  Thus the attachTo.  Also, leaving him attached allowed him to transfer contents, only very slowly.  So I detach him, and he basically ends up (invisible) inside the crate and works quickly.

 

@sarogahtyp, thanks for that heads up, I'll definitely check out your script!

 

@BIS, we could really use some new alternative syntax on these existing commands:

If these could accept container objects (for vests, uniforms, and backpacks) as the contents being added to the crate/vehicle, that would be pretty awesome!  Would sure beat having to use an invisible/invincible dummy, which let's admit is pretty clumsy at best.

 

Also, unless I'm missing something, the current dummy method really only works for weapons and backpacks, and not uniforms or vests.  If we're going to be stuck with dummy transfer, could we please have a set of new actions (for the action command), to complement existing TakeWeapon, DropWeapon, AddBag, and DropBag.  The new ones would be something like: TakeUniform, DropUniform, TakeVest, and DropVest

 

 

In any event, anyone happen to know if we are missing commands in the ArmA2 and ArmA3 command listings?  I came across a semi-related command weaponAccessoriesCargo.  It's not listed in either spot, and it accepts a container as argument.  Makes me wonder if there are other cargo commands out there directly related to containers (and who knows, perhaps which add said containers to crates?)

 

About that command in particular (weaponAccessoriesCargo), it has an interesting syntax:

container weaponAccessoriesCargo [weaponId, creatorId]

Anyone know what's up with the "weaponId" and "creatorId"?  I've yet to run across another command that uses these arguments, but they sound like maybe a way to modify a weapon (or similar) while it's inside a container, which of course would be extremely handy.

 

If anyone has ideas about getting loaded uniform and vest containers correctly transferred into a crate/vehic (or any of this really) please don't hesitate to chime in.  Thanks!

 

Share this post


Link to post
Share on other sites

I did some tests and changed my code above to make it work what the distance of the unit could be. In fact, it's so strange, the delay to addBag / dropbag depends on distance of the unit to the crates! The command effect doesn't travel at the speed of the light! Waouh, some  BI works invalid the Einstein's theory! :don14:

 

More seriously, totally agree with you. Some nice command/function could help.

 

  • Like 1

Share this post


Link to post
Share on other sites

Here's a way to do it without the dummy if you so desire.
What it does:

- Replicate contents of given type from one container to another including containers (backpacks and vests and uniforms), if I remember right it should transfer the correct ammo count for each magazine too.

What it doesn't:

- Check cargo sizes to see if contents fit in the new container. Everything is squeezed in.
Use as you wish.

 

I've done it in three functions, you may define these as you wish, I personally use CfgFunctions to define 'em. If you change the tag it you also need to update fnc_transferContents since it calls the other two.
mis_fnc_transferContents

Spoiler

//fn_transferContents.sqf
/*
	Params: 
	Required
	0 - From 		- Object			- Source object
	1 - To 			- Object			- Target object
	Optional
	2 - Types 		- String or Array of strings	- Allowed strings: "items", "magazines", "weapons", "containers". If empty all contents will be transfered.
	3 - Clear From 	- Bool 				- Should From be emptied after transfer? Default: True
	4 - Clear To 	- Bool				- Should To be emptied before transfer? Default: True
*/

params [
	["_from", objNull, [objNull]],
	["_to", objNull, [objNull]],
	["_types", [], [[], ""]],
	["_clearFrom", true, [true]],
	["_clearTo", true, [true]]
];

if(_types isEqualType "") then { _types = [_types]; };

private _transferItems 		= "items" 		in _types;
private _transferMags 		= "magazines" 	in _types;
private _transferWeapons 	= "weapons" 	in _types;
private _transferContainers	= "containers" 	in _types;

if(count _types == 0) then {
	_transferItems 		= true;
	_transferMags 		= true;
	_transferWeapons 	= true;
	_transferContainers	= true;
};

if(isNull _from || isNull _to) then {
	["A null parameter was provided. _this = %1", _this] call BIS_fnc_error;
} else {
	private _items = [];
	private _mags = [];
	private _weapons = [];
	private _containers = [];
	/* FROM */
	
	if(_transferItems) then {
		{
			private _isVest = (_x isKindOf ["Vest_Camo_Base", configFile >> "CfgWeapons"]) || (_x isKindOf ["Vest_NoCamo_Base", configFile >> "CfgWeapons"]);
			private _isUniform = _x isKindOf ["Uniform_base", configFile >> "CfgWeapons"];
			if !(_isVest || _isUniform) then {
				_items pushBack _x;
			};
		} forEach itemCargo _from;
	};
	if(_transferMags) then {
		_mags = magazinesAmmoCargo _from;
	};
	
	if(_transferWeapons) then {
		_weapons = weaponsItemsCargo _from;
	};
	
	if(_transferContainers) then {
		_containers = _from call mis_fnc_getContainerContents;
	};
	
	if(_clearFrom) then {
		clearItemCargoGlobal _from;
		clearMagazineCargoGlobal _from;
		clearWeaponCargoGlobal _from;
		clearBackpackCargoGlobal _from;
	};
	
	/* TO */
	if(_clearTo) then {
		clearItemCargoGlobal _to;
		clearMagazineCargoGlobal _to;
		clearWeaponCargoGlobal _to;
		clearBackpackCargoGlobal _to;
	};
	
	[_to, [_items, _mags, _weapons, _containers]] call mis_fnc_setContainerContents;	
};

 


mis_fnc_getContainerContents

Spoiler

 


//fn_getContainerContents.sqf
private _obj = _this;
private _r = [];
private _self = call compile _fnc_scriptName;

{
	_x params [
		"_xType",
		"_xObj"
	];
	
	private _items = [];
	{
		private _isVest = (_x isKindOf ["Vest_Camo_Base", configFile >> "CfgWeapons"]) || (_x isKindOf ["Vest_NoCamo_Base", configFile >> "CfgWeapons"]);
		private _isUniform = _x isKindOf ["Uniform_base", configFile >> "CfgWeapons"];
		if !(_isVest || _isUniform) then {
			_items pushBack _x;
		};
	} forEach itemCargo _xObj;
	
	private _mags = magazinesAmmoCargo _xObj;
	
	private _weapons = weaponsItemsCargo _xObj;
	
	private _containers = _xObj call _self;
	
	_r pushback [_xType, [_items, _mags, _weapons, _containers]];
} forEach everyContainer _obj;

_r

 

 

 

 

mis_fnc_setContainerContents

Spoiler

//fn_setContainerContents.sqf
private _fnc_addContainer = {
	params [
		["_obj", objNull, [objNull]],
		["_type", "", [""]]
	];

	private _r = objNull;
	if(!isNull _obj) then {
		private _old = everyContainer _obj;
		
		if(_type isKindOf ["Bag_base", configFile >> "CfgVehicles"]) then {
			_obj addBackpackCargoGlobal [_type, 1];
		} else {
			_obj addItemCargoGlobal [_type, 1];
		};
		
		private _new = (everyContainer _obj) - _old;
		if(count _new == 1) then {
			_r = _new select 0;
		} else {
			["_fnc_addContainer: Failed to add container to object. _this = %1", _this] call BIS_fnc_error;
		};
	} else {
		["_fnc_addContainer: Invalid parameter. _args = %1", _args] call BIS_fnc_error;
	};
	_r
};

params [
	"_obj", 
	"_data"
];

_data params [
	"_items",
	"_magazines",
	"_weapons",
	"_containers"
];

//Parse item cargo
{ _obj addItemCargoGlobal [_x, 1]; } forEach _items;
//Parse magazine cargo
{ _obj addMagazineAmmoCargo [_x select 0, 1, _x select 1]; } forEach _magazines;
//Parse weapons cargo
{
	private _elem = _x;
	{
		switch(typeName _x) do {
			case "STRING": {
				if(_x != "") then {
					if(_x isKindOf ["ItemCore", configFile >> "CfgWeapons"]) then {
						_obj addItemCargoGlobal [_x, 1];								_x;
					} else {
						private _baseWeapon = (_x call BIS_fnc_weaponComponents) select 0; 
						_obj addWeaponCargoGlobal [_baseWeapon, 1];
					};
				};
			};
			case "ARRAY": {
				if(count _x > 0) then {
					_obj addMagazineAmmoCargo [_x select 0, 1, _x select 1];
				};
			};
		};
	} forEach _elem;
} forEach _weapons;

//Parse container cargo
{
	_x params [
		"_type",
		"_contents"
	];
	
	private _xOBj = [_obj, _type] call _fnc_addContainer;
	["setcontainerdata", [_xObj select 1, _contents]] call SELF;
} forEach _containers;

 

 

Example usage:

//Short
[box1, box2] call mis_fnc_transferContents

//Long 
[box1, box2, ["weapons", "magazines"], true, true] call mis_fnc_transferContents

 

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×