Pattoh

Weapon Attachment Dupe Fix (FULL, Updated 5/12/2018)

4 posts in this topic

UPDATED AGAIN - BUG FIX 5/15/2018

This stops players from selling attachments when they are attached on to the weapon, if they aren't attached to the weapon you can sell them though or the weapons themselves as well. I covered gear, vests, uniforms, vehicles and backpacks, I haven't tested mission boxes or crates but I think they are covered, if they aren't let me know and I'll make a fix for them. 

 

3b41ce31ff1e70e65c642c7bc40d5136.jpg

Copy the contents below to a blank page.

Spoiler

/**
 * ExileClient_gui_traderDialog_updateInventoryListBox
 *
 * Exile Mod
 * www.exilemod.com
 * © 2015 Exile Mod Team
 *
 * This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License. 
 * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/.
 */
private ["_dialog", "_inventoryDropdown", "_dropdownIndex", "_tradeContainerType", "_tradeVehicleObject", "_inventoryListBox",
 "_currentLoad", "_maximumLoad", "_items", "_containerClass", "_tradeVehicleNetID", "_inventoryLoadProgress",
 "_inventoryLoadValue", "_itemClassName", "_configName", "_quality", "_sellPrice", "_qualityColor", "_indexEntryIndex",
 "_canSellItem", "_containerClassName", "_containerContainer", "_itemsInContainer", "_nesT", "_backNest", "_vestNest",
 "_gearNest", "_vehNest", "_uniformNest", "_attachList"];
 
disableSerialization;
_dialog = uiNameSpace getVariable ["RscExileTraderDialog", displayNull];
_inventoryDropdown = _dialog displayCtrl 4004;
_dropdownIndex = lbCurSel _inventoryDropdown;
_tradeContainerType = _inventoryDropdown lbValue _dropdownIndex;
_tradeVehicleObject = objNull;
_inventoryListBox = _dialog displayCtrl 4005;
lbClear _inventoryListBox;
switch (_tradeContainerType) do
{
	case 1: 
	{
		_currentLoad = (loadAbs player);
		_maximumLoad = getNumber(configfile >> "CfgInventoryGlobalVariable" >> "maxSoldierLoad");
		_items = [player, true] call ExileClient_util_playerEquipment_list;
	};
	case 2:
	{
		_containerClass = getText(configFile >> "CfgWeapons" >> (uniform player) >> "ItemInfo" >> "containerClass");
		_maximumLoad = getNumber(configFile >> "CfgVehicles" >> _containerClass >> "maximumLoad");
		_currentLoad = (loadUniform player) * _maximumLoad;
		_items = (uniformContainer player) call ExileClient_util_containerCargo_list;
	};
	case 3: 
	{
		_containerClass = getText(configFile >> "CfgWeapons" >> (vest player) >> "ItemInfo" >> "containerClass");
		_maximumLoad = getNumber(configFile >> "CfgVehicles" >> _containerClass >> "maximumLoad");
		_currentLoad = (loadVest player) * _maximumLoad;
		_items = (vestContainer player) call ExileClient_util_containerCargo_list;
	};
	case 4:
	{
		_maximumLoad = getNumber(configFile >> "CfgVehicles" >> (backpack player) >> "maximumLoad");
		_currentLoad = (loadBackpack player) * _maximumLoad;
		_items = (backpackContainer player) call ExileClient_util_containerCargo_list;
	};
	default 
	{
		_tradeVehicleNetID = _inventoryDropdown lbData _dropdownIndex;
		_tradeVehicleObject = objectFromNetId _tradeVehicleNetID;
		_maximumLoad = getNumber(configFile >> "CfgVehicles" >> (typeOf _tradeVehicleObject) >> "maximumLoad");
		_items = _tradeVehicleObject call ExileClient_util_containerCargo_list;
		_currentLoad = _items call ExileClient_util_gear_calculateLoad;
	};
};
_inventoryLoadProgress = _dialog displayCtrl 4012;
_inventoryLoadProgress progressSetPosition (_currentLoad / (_maximumLoad max 1));
_inventoryLoadValue = _dialog displayCtrl 4014;
_inventoryLoadValue ctrlSetStructuredText (parseText format["<t size='1' font='puristaMedium' align='right'>%1/%2</t>", round(_currentLoad), _maximumLoad]);
{
	_itemClassName = _x;
	_configName = _x call ExileClient_util_gear_getConfigNameByClassName;
	_quality = getNumber(missionConfigFile >> "CfgExileArsenal" >> _itemClassName >> "quality");
	_sellPrice = _itemClassName call ExileClient_util_gear_calculateSellPrice;
	_qualityColor = [1, 1, 1, 1];
	switch (_quality) do
	{
		case 2: 		 { _qualityColor = [0.62, 0.87 ,0.23, 1]; };
		case 3:		 { _qualityColor = [0, 0.78, 0.92, 1]; };
		case 4:		 { _qualityColor = [0.62, 0.27, 0.58, 1]; };
		case 5:		 { _qualityColor = [1, 0.7, 0.09, 1]; };
		case 6:		 { _qualityColor = [0.93, 0, 0.48, 1]; };						
	};
	_indexEntryIndex = _inventoryListBox lbAdd getText(configFile >> _configName >> _itemClassName >> "displayName");
	_inventoryListBox lbSetData [_indexEntryIndex, _itemClassName];
	_inventoryListBox lbSetColor [_indexEntryIndex, _qualityColor];
	_inventoryListBox lbSetPicture [_indexEntryIndex, getText(configFile >> _configName >> _itemClassName >> "picture")];
	_canSellItem = true;
	if (_tradeContainerType isEqualTo 1) then
	{
		scopeName "OUTER";
		{
			_containerClassName = _x select 0;
			_containerContainer = _x select 1;
			if (_itemClassName isEqualTo _containerClassName) then
			{
				_itemsInContainer = _containerContainer call ExileClient_util_containerCargo_list;
				if !((count _itemsInContainer) isEqualTo 0) then
				{
					_canSellItem = false;
					breakTo "OUTER";
				};
			};
		}
		forEach 
		[
			[uniform player, uniformContainer player], 
			[vest player, vestContainer player], 
			[backpack player, backpackContainer player]
		];
		if (_itemClassName isEqualTo (primaryWeapon player)) then
		{
			{
				{
					if !(_x isEqualTo "") then
					{
						_sellPrice = _sellPrice + (_x call ExileClient_util_gear_calculateSellPrice);
					};
				}
				forEach _x;
			}
			forEach 
			[
				primaryWeaponItems player,
				primaryWeaponMagazine player
			];
		};
		if (_itemClassName isEqualTo (handgunWeapon player)) then
		{
			{
				{
					if !(_x isEqualTo "") then
					{
						_sellPrice = _sellPrice + (_x call ExileClient_util_gear_calculateSellPrice);
					};
				}
				forEach _x;
			}
			forEach 
			[
				handgunItems player,
				handgunMagazine player
			];
		};
	};
		
	_nesT = [];
	
	if !IsNil {weaponsitemscargo unitBackpack player} then {
		_backNest = weaponsitemscargo unitBackpack player;
		_nesT append _backNest;
	};
	if !IsNil {weaponsitemscargo vestContainer player} then {
		_vestNest = weaponsitemscargo vestContainer player;
		_nesT append _vestNest;
	};
	if !IsNil {weaponsitemscargo uniformContainer player} then {
		_uniformNest = weaponsitemscargo uniformContainer player;
		_nesT append _uniformNest;
	};
	if !IsNil {weaponsItems player} then {
		_gearNest = weaponsItems player;
		_nesT append _gearNest;
	};
	if !IsNil {weaponsitemscargo _tradeVehicleObject} then {
		_vehNest = weaponsitemscargo _tradeVehicleObject;
		_nesT + _vehNest;
	};
	
	_attachList = []; 
	{ 
		
		_attachList pushBack [_x select 1,_x select 2, _x select 3,_x select 5]; 
	 
		if (_itemClassName in (_attachList select _forEachIndex)) then 
		{
			_canSellItem = false;
		};
		
	} forEach _nesT;

	if (_canSellItem) then
	{
    	if (_sellPrice > 0 || ((getText(missionConfigFile >> "Header" >> "gameType") isEqualTo "Escape") && {_sellPrice >= 0})) then
    	{
    		_inventoryListBox lbSetValue [_indexEntryIndex, _sellPrice];
	    	_inventoryListBox lbSetTextRight [_indexEntryIndex, format["%1", _sellPrice]];
	    	_inventoryListBox lbSetPictureRight [_indexEntryIndex, "exile_assets\texture\ui\poptab_trader_ca.paa"];
    	}
    	else 
    	{
    		_inventoryListBox lbSetValue [_indexEntryIndex, -1];
    		_inventoryListBox lbSetColorRight [_indexEntryIndex, [0.5, 0.5, 0.5, 1]];
    		_inventoryListBox lbSetTextRight [_indexEntryIndex, "(unsaleable)"];	
    	};
	}
	else 
	{
		_inventoryListBox lbSetValue [_indexEntryIndex, -1];
		_inventoryListBox lbSetColorRight [_indexEntryIndex, [0.5, 0.5, 0.5, 1]];
		_inventoryListBox lbSetTextRight [_indexEntryIndex, "(not empty/detached)"];		
	};
}
forEach _items;
true

 

save it as 

Quote

ExileClient_gui_traderDialog_updateInventoryListBox.sqf

Put it inside your custom code folder or where ever, update it accordingly were ever you put the override.

Add the file to the "class CfgExileCustomCode" section in config.cpp mission root or your external.

Quote

ExileClient_gui_traderDialog_updateInventoryListBox = "custom\ExileClient_gui_traderDialog_updateInventoryListBox.sqf";

 we are done here.

If you have anything to add let me know.

 

Edited by Pattoh
  • Like 8

Share this post


Link to post
Share on other sites
Advertisement

This seems to work great. Thanks for sharing your snippet @Pattoh.

I was wondering if anybody's found a workaround for attachments to stop magically appearing in vehicles whenever the inventory is updated? Say I have an RHS AKM in the trunk of a car without a muzzle attachment, and I sell a can of dog food out of the car, suddenly a DTK appears. And then another if I sell another can, and on, and on, and on... Most of these muzzles can't be sold but after a big haul I've had players with 30-40 DTKs in there. It's a real pain when you have to drag them all onto the ground one by one when you don't have access to the waste dump. 

An example: I had two empty AKMs in the car and started selling smoke grenades. 

capture.jpg

 

I know these weapons spawn with DTKs, and every time the vehicle updates its inventory it basically just wipes it and spawns a new one. And I know the easy way to get rid of this is to just remove the AKM and others like it, but there has to be a better way.

 

Solution Edit:

For anybody having this problem, what I did to fix it was make an array of the items that I know get duplicated (it's surprisingly small) and hooked into the ExileClient_util_containerCargo_deserialize function much the same way this thread hooks into the updateInventoryListBox function. At line 21 you should see the start of a loop that iterates over all the items passed to the function. Simply wrap everything in that loop in an if statement like so: 

Spoiler

forEach (_data select 0);
{
    {
        if !( _x IN [*your array here*] ) then 
        {
            if (_forEachIndex isEqualTo 0) then
            {
                if !(_x isEqualTo "") then
                {
                    _container addWeaponCargoGlobal [_x, 1];
                };
            }
            else 
            {
                if ((typeName _x) isEqualTo "ARRAY") then
                {
                    if !(_x isEqualTo []) then 
                    {
                        _container addMagazineAmmoCargo [_x select 0, 1, _x select 1];
                    };
                }
                else 
                {
                    if !(_x isEqualTo "") then
                    {
                        _container addItemCargoGlobal [_x, 1];
                    };
                };
            };
        };
    }
    forEach _x;
}

Package that file up into your custom code folder and call it just like you did with the original. That's all there is to it. It's certainly not elegant, but it's functional. 

Edited by The Velvet Gentleman
  • Like 1

Share this post


Link to post
Share on other sites
Advertisement

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.