Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve removeXCargo functions to retain readded items properly #596

Merged
merged 14 commits into from
Mar 20, 2017
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions addons/common/CfgFunctions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class CfgFunctions {
PATHTO_FNC(getWeaponModes);
PATHTO_FNC(inheritsFrom);
PATHTO_FNC(getTurret);
PATHTO_FNC(getNonPresetClass);
};

class Entities {
Expand Down
55 changes: 55 additions & 0 deletions addons/common/fnc_getNonPresetClass.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* ----------------------------------------------------------------------------
Function: CBA_fnc_getNonPresetClass

Description:
Get ancestor class of a weapon or container which has no preset attachments/contents.

Parameters:
_item - Classname of weapon/container <STRING>
_configRoot - Root config ("CfgWeapons", "CfgVehicles", ...) <STRING> (Default: "CfgWeapons")

Returns:
Ancestor class without preset attachments/contents sub-class on success, "" otherwise <STRING>

Examples:
(begin example)
// Get parent class without preset attachments of a weapon (returns "arifle_MX_F")
_ancestorClass = ["arifle_MX_ACO_pointer_F"] call CBA_fnc_getNonPresetClass;
(end)

Author:
Jonpas
---------------------------------------------------------------------------- */
#include "script_component.hpp"
SCRIPT(getNonPresetClass);

params [["_class", "", [""]], ["_rootConfig", "CfgWeapons", [""]]];

private _config = configFile >> _rootConfig >> _class;

// Invalid class/root config
if (!isClass _config) exitWith {
_class
};

// Return current class - has no preset attachments/contents
if (
// CfgWeapons
(configProperties [_config >> "LinkedItems", "isClass _x", true] isEqualTo []) &&
// CfgVehicles
{configProperties [_config >> "TransportItems", "isClass _x", true] isEqualTo []} &&
{configProperties [_config >> "TransportMagazines", "isClass _x", true] isEqualTo []} &&
{configProperties [_config >> "TransportWeapons", "isClass _x", true] isEqualTo []}
) exitWith {
_class
};

// Check parent
private _parent = inheritsFrom _config;
if (_parent isEqualTo configNull) then {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isNull

// We reached configNull, stuff must be invalid, return empty string
""
} else {
// Recursively search the ancestor tree
[configName _parent, _rootConfig] call CBA_fnc_getNonPresetClass;
};
94 changes: 66 additions & 28 deletions addons/common/fnc_removeBackpackCargo.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Function: CBA_fnc_removeBackpackCargo
Description:
Removes specific backpack(s) from cargo space.

Warning: Backpack's inventory information is lost.
Warning: All weapon attachments/magazines in all backpacks in container will become detached.

Parameters:
_container - Object with cargo <OBJECT>
Expand All @@ -15,13 +15,13 @@ Returns:
true on success, false otherwise <BOOLEAN>

Examples:
(begin example)
// Remove 1 Kitbag Tan backpack locally from a box
_success = [myCoolBackpackBox, "B_Kitbag_cbr"] call CBA_fnc_removeBackpackCargo;
(begin example)
// Remove 1 Kitbag Tan backpack from a box
_success = [myCoolBackpackBox, "B_Kitbag_cbr"] call CBA_fnc_removeBackpackCargo;

// Remove 2 Carryall Desert Camo backpacks locally from a box
_success = [myCoolBackpackBox, "B_Carryall_ocamo", 2] call CBA_fnc_removeBackpackCargo;
(end)
// Remove 2 Carryall Desert Camo backpacks from a box
_success = [myCoolBackpackBox, "B_Carryall_ocamo", 2] call CBA_fnc_removeBackpackCargo;
(end)

Author:
Jonpas
Expand All @@ -31,55 +31,93 @@ SCRIPT(removeBackpackCargo);

params [["_container", objNull, [objNull]], ["_item", "", [""]], ["_count", 1, [0]]];

private _return = false;

if (isNull _container) exitWith {
TRACE_2("Container not Object or null",_container,_item);
_return
false
};

if (_item isEqualTo "") exitWith {
TRACE_2("Item not String or empty",_container,_item);
_return
false
};

private _config = _item call CBA_fnc_getObjectConfig;

if (isNull _config || {getNumber (_config >> "scope") < 1} || {getNumber (_config >> "isBackpack") != 1}) exitWith {
TRACE_2("Item not exist in Config",_container,_item);
_return
false
};

if (_count <= 0) exitWith {
TRACE_3("Count is not a positive number",_container,_item,_count);
_return
false
};

// Ensure proper count
_count = round _count;

// Returns array containing two arrays: [[type1, typeN, ...], [count1, countN, ...]]
(getBackpackCargo _container) params ["_allItemsType", "_allItemsCount"];
// Save backpacks and contents
private _backpackData = [];
{
_backpackData pushBack [typeOf _x, getItemCargo _x, magazinesAmmoCargo _x, weaponsItemsCargo _x];
} forEach (everyBackpack _container); // [object1, object2, ...]

// Clear cargo space and readd the items as long it's not the type in question
clearBackpackCargoGlobal _container;

{
private _itemCount = _allItemsCount select _forEachIndex;
_x params ["_backpackClass", "_itemCargo", "_magazinesAmmoCargo", "_weaponsItemsCargo"];

if (_x == _item) then {
if (_count != 0 && {_backpackClass == _item}) then {
// Process removal
_return = true;

_itemCount = _itemCount - _count;
if (_itemCount > 0) then {
// Add with new count
_container addBackpackCargoGlobal [_x, _itemCount];
};
_count = _count - 1;
} else {
// Readd only
_container addBackpackCargoGlobal [_x, _itemCount];
// Save all backpacks for finding the one we readd after this
private _addedBackpacks = everyBackpack _container;

// Readd
private _backpack = [_backpackClass, "CfgVehicles"] call CBA_fnc_getNonPresetClass;
_container addBackpackCargoGlobal [_backpack, 1];

// Find just added backpack and add contents (no command returns reference when adding)
private _backpack = (everyBackpack _container - _addedBackpacks) select 0;

// Items
{
private _itemCount = (_itemCargo select 1) select _forEachIndex;
_backpack addItemCargoGlobal [_x, _itemCount];
} forEach (_itemCargo select 0);

// Magazines (and their ammo count)
{
_backpack addMagazineAmmoCargo [_x select 0, 1, _x select 1];
} forEach _magazinesAmmoCargo;

// Weapons (and their attachments)
// Put attachments next to weapon, no command to put it directly onto a weapon when weapon is in a container
{
_x params ["_weapon", "_muzzle", "_pointer", "_optic", "_magazine", "_magazineGL", "_bipod"];
// weaponsItems magazineGL does not exist if not loaded (not even as empty array)
if (count _x < 7) then {
_bipod = _magazineGL;
_magazineGL = "";
};

private _weapon = [_weapon] call CBA_fnc_getNonPresetClass;
_backpack addWeaponCargoGlobal [_weapon, 1];

_backpack addItemCargoGlobal [_muzzle, 1];
_backpack addItemCargoGlobal [_pointer, 1];
_backpack addItemCargoGlobal [_optic, 1];
_backpack addItemCargoGlobal [_bipod, 1];

_magazine params ["_magazineClass", "_magazineAmmoCount"];
_backpack addMagazineAmmoCargo [_magazineClass, 1, _magazineAmmoCount];

_magazineGL params ["_magazineGLClass", "_magazineGLAmmoCount"];
_backpack addMagazineAmmoCargo [_magazineGLClass, 1, _magazineGLAmmoCount];
} forEach _weaponsItemsCargo;
};
} forEach _allItemsType;
} forEach _backpackData;

_return
(_count == 0)
26 changes: 12 additions & 14 deletions addons/common/fnc_removeItemCargo.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ Returns:
true on success, false otherwise <BOOLEAN>

Examples:
(begin example)
// Remove 1 GPS locally from a box
_success = [myCoolItemBox, "ItemGPS"] call CBA_fnc_removeItemCargo;
(begin example)
// Remove 1 GPS from a box
_success = [myCoolItemBox, "ItemGPS"] call CBA_fnc_removeItemCargo;

// Remove 2 Compasses locally from a box
_success = [myCoolItemBox, "ItemCompass", 2] call CBA_fnc_removeItemCargo;
(end)
// Remove 2 Compasses from a box
_success = [myCoolItemBox, "ItemCompass", 2] call CBA_fnc_removeItemCargo;
(end)

Author:
Jonpas
Expand All @@ -29,28 +29,26 @@ SCRIPT(removeItemCargo);

params [["_container", objNull, [objNull]], ["_item", "", [""]], ["_count", 1, [0]]];

private _return = false;

if (isNull _container) exitWith {
TRACE_2("Container not Object or null",_container,_item);
_return
false
};

if (_item isEqualTo "") exitWith {
TRACE_2("Item not String or empty",_container,_item);
_return
false
};

private _config = _item call CBA_fnc_getItemConfig;

if (isNull _config || {getNumber (_config >> "scope") < 1}) exitWith {
TRACE_2("Item does not exist in Config",_container,_item);
_return
false
};

if (_count <= 0) exitWith {
TRACE_3("Count is not a positive number",_container,_item,_count);
_return
false
};

// Ensure proper count
Expand All @@ -67,7 +65,7 @@ clearItemCargoGlobal _container;

if (_x == _item) then {
// Process removal
_return = true;
_count = 0;

_itemCount = _itemCount - _count;
if (_itemCount > 0) then {
Expand All @@ -80,4 +78,4 @@ clearItemCargoGlobal _container;
};
} forEach _allItemsType;

_return
(_count == 0)
54 changes: 24 additions & 30 deletions addons/common/fnc_removeMagazineCargo.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -4,82 +4,76 @@ Function: CBA_fnc_removeMagazineCargo
Description:
Removes specific magazine(s) from cargo space.

Warning: Magazine's ammo count is lost and becomes full.

Parameters:
_container - Object with cargo <OBJECT>
_item - Classname of magazine(s) to remove <STRING>
_count - Number of magazine(s) to remove <NUMBER> (Default: 1)
_ammo - Ammo of magazine(s) to remove (-1 for magazine(s) with any ammo) <NUMBER> (Default: -1)

Returns:
true on success, false otherwise <BOOLEAN>

Examples:
(begin example)
// Remove 1 Smokegrenade locally from a box
_success = [myCoolMagazineBox, "SmokeShell"] call CBA_fnc_removeMagazineCargo;
(begin example)
// Remove 1 Smokegrenade from a box
_success = [myCoolMagazineBox, "SmokeShell"] call CBA_fnc_removeMagazineCargo;

// Remove 2 Handgrenades from a box
_success = [myCoolMagazineBox, "HandGrenade_West", 2] call CBA_fnc_removeMagazineCargo;

// Remove 2 Handgrenades locally from a box
_success = [myCoolMagazineBox, "HandGrenade_West", 2] call CBA_fnc_removeMagazineCargo;
(end)
// Remove 2 magazines which each have 5 bullets in them from a box
_success = [myCoolMagazineBox, "30Rnd_65x39_caseless_mag", 2, 5] call CBA_fnc_removeMagazineCargo;
(end)

Author:
silencer.helling3r 2012-12-22, Jonpas
---------------------------------------------------------------------------- */
#include "script_component.hpp"
SCRIPT(removeMagazineCargo);

params [["_container", objNull, [objNull]], ["_item", "", [""]], ["_count", 1, [0]]];

private _return = false;
params [["_container", objNull, [objNull]], ["_item", "", [""]], ["_count", 1, [0]], ["_ammo", -1, [0]]];

if (isNull _container) exitWith {
TRACE_2("Container not Object or null",_container,_item);
_return
false
};

if (_item isEqualTo "") exitWith {
TRACE_2("Item not String or empty",_container,_item);
_return
false
};

private _config = configFile >> "CfgMagazines" >> _item;

if (isNull _config || {getNumber (_config >> "scope") < 2}) exitWith {
TRACE_2("Item does not exist in Config",_container,_item);
_return
false
};

if (_count <= 0) exitWith {
TRACE_3("Count is not a positive number",_container,_item,_count);
_return
false
};

// Ensure proper count
_count = round _count;

// Returns array containing two arrays: [[type1, typeN, ...], [count1, countN, ...]]
(getMagazineCargo _container) params ["_allItemsType", "_allItemsCount"];
// [[type1, ammo1], [type2, ammo2], ...]
private _magazinesAmmo = magazinesAmmoCargo _container;

// Clear cargo space and readd the items as long it's not the type in question
clearMagazineCargoGlobal _container;

{
private _itemCount = _allItemsCount select _forEachIndex;
_x params ["_magazineClass", "_magazineAmmo"];

if (_x == _item) then {
if (_count != 0 && {_magazineClass == _item} && {_ammo < 0 || {_magazineAmmo == _ammo}}) then {
// Process removal
_return = true;

_itemCount = _itemCount - _count;
if (_itemCount > 0) then {
// Add with new count
_container addMagazineCargoGlobal [_x, _itemCount];
};
_count = _count - 1;
} else {
// Readd only
_container addMagazineCargoGlobal [_x, _itemCount];
// Readd
_container addMagazineAmmoCargo [_magazineClass, 1, _magazineAmmo];
};
} forEach _allItemsType;
} forEach _magazinesAmmo;

_return
(_count == 0)
Loading