class OpenStash extends ActionBool
{

	public function SetProperties()
	{
		actionName = 'OpenStash';
		prop = DeviceActionPropertyFunctions.SetUpProperty_Bool( actionName, true, 'LocKey#15799', 'LocKey#15799' );
	}

	public static function IsDefaultConditionMet( device : ScriptableDeviceComponentPS, const context : ref< GetActionsContext > ) : Bool
	{
		if( IsAvailable( device ) && IsClearanceValid( context.clearance ) )
		{
			return true;
		}
		return false;
	}

	public static function IsAvailable( device : ScriptableDeviceComponentPS ) : Bool
	{
		if( device.IsUnpowered() || device.IsDisabled() )
		{
			return false;
		}
		return true;
	}

	public static function IsClearanceValid( clearance : Clearance ) : Bool
	{
		if( Clearance.IsInRange( clearance, DefaultActionsParametersHolder.GetInteractiveClearance() ) )
		{
			return true;
		}
		return false;
	}

}

class Stash extends InteractiveDevice
{
	default m_controllerTypeName = 'StashController';

	protected event OnRequestComponents( ri : EntityRequestComponentsInterface )
	{
		EntityRequestComponentsInterface.RequestComponent( ri, 'inventory', 'Inventory', false );
		super.OnRequestComponents( ri );
	}

	protected event OnTakeControl( ri : EntityResolveComponentsInterface )
	{
		super.OnTakeControl( ri );
		m_controller = ( ( StashController )( EntityResolveComponentsInterface.GetComponent( ri, 'controller' ) ) );
	}

	protected event OnInteractionActivated( evt : InteractionActivationEvent )
	{
		var actorUpdateData : HUDActorUpdateData;
		super.OnInteractionActivated( evt );
		if( evt.eventType == gameinteractionsEInteractionEventType.EIET_activate )
		{
			if( evt.layerData.tag == 'LogicArea' )
			{
				actorUpdateData = new HUDActorUpdateData;
				actorUpdateData.updateIsInIconForcedVisibilityRange = true;
				actorUpdateData.isInIconForcedVisibilityRangeValue = true;
				RequestHUDRefresh( actorUpdateData );
			}
		}
		else
		{
			if( evt.layerData.tag == 'LogicArea' )
			{
				actorUpdateData = new HUDActorUpdateData;
				actorUpdateData.updateIsInIconForcedVisibilityRange = true;
				actorUpdateData.isInIconForcedVisibilityRangeValue = false;
				RequestHUDRefresh( actorUpdateData );
			}
		}
	}

	public const override function DeterminGameplayRoleMappinVisuaState( const data : ref< SDeviceMappinData > ) : EMappinVisualState
	{
		if( GetDevicePS().IsDisabled() )
		{
			return EMappinVisualState.Inactive;
		}
		else
		{
			return EMappinVisualState.Default;
		}
	}

	public const override function GetDevicePS() : StashControllerPS
	{
		return GetController().GetPS();
	}

	private const override function GetController() : StashController
	{
		return ( ( StashController )( m_controller ) );
	}

	public const override function DeterminGameplayRole() : EGameplayRole
	{
		return EGameplayRole.PlayerStash;
	}

	protected event OnOpenStash( evt : OpenStash )
	{
		var transactionSystem : TransactionSystem;
		var player : GameObject;
		var storageBB : IBlackboard;
		var storageData : StorageUserData;
		transactionSystem = GameInstance.GetTransactionSystem( GetGame() );
		player = GameInstance.GetPlayerSystem( GetGame() ).GetLocalPlayerMainGameObject();
		if( transactionSystem && player )
		{
			ProcessStashRetroFixes( this );
			storageData = new StorageUserData;
			storageData.storageObject = this;
			storageBB = GameInstance.GetBlackboardSystem( GetGame() ).Get( GetAllBlackboardDefs().StorageBlackboard );
			if( storageBB )
			{
				storageBB.SetVariant( GetAllBlackboardDefs().StorageBlackboard.StorageData, storageData, true );
			}
		}
	}

	public const override function IsPlayerStash() : Bool
	{
		return true;
	}

	public static function IsInStash( stashObj : GameObject, item : ItemID ) : Bool
	{
		var transactionSystem : TransactionSystem;
		var storageItems : array< weak< gameItemData > >;
		var i : Int32;
		if( !( stashObj ) )
		{
			return false;
		}
		transactionSystem = GameInstance.GetTransactionSystem( stashObj.GetGame() );
		transactionSystem.GetItemList( stashObj, storageItems );
		for( i = 0; i < storageItems.Size(); i += 1 )
		{
			if( storageItems[ i ].GetID() == item )
			{
				return true;
			}
		}
		return false;
	}

	public static function ProcessStashRetroFixes( stashObj : GameObject )
	{
		var game : GameInstance;
		var factVal : Int32;
		if( !( stashObj ) )
		{
			return;
		}
		game = stashObj.GetGame();
		ScaleStashIconicsToPlayerLevel( stashObj );
		factVal = GetFact( game, 'ClothingModsRemovedStash' );
		if( ( factVal <= 0 ) && ( ( ( Int32 )( gameGameVersion.Current ) ) >= 1500 ) )
		{
			SetFactValue( game, 'ClothingModsRemovedStash', 1 );
		}
		factVal = GetFact( game, 'DLCPlayerStashItemsRevamp' );
		if( ( factVal <= 0 ) && ( ( ( Int32 )( gameGameVersion.Current ) ) >= 1500 ) )
		{
			SetFactValue( game, 'DLCPlayerStashItemsRevamp', 1 );
		}
		factVal = GetFact( game, 'CYBMETA1695' );
		if( factVal <= 0 )
		{
			SetFactValue( game, 'CYBMETA1695', 1 );
		}
		factVal = GetFact( game, 'BuckGradScopeStashFix' );
		if( ( factVal <= 0 ) && ( ( ( Int32 )( gameGameVersion.Current ) ) >= 1600 ) )
		{
			SetFactValue( game, 'BuckGradScopeStashFix', 1 );
		}
		factVal = GetFact( game, 'IconicReworkCompletedInStash' );
		if( ( factVal <= 0 ) && ( ( ( Int32 )( gameGameVersion.Current ) ) >= 2000 ) )
		{
			IconicsReworkCompensateInStash( stashObj );
			SetFactValue( game, 'IconicReworkCompletedInStash', 1 );
		}
		factVal = GetFact( game, 'WeaponAndClothingModsInStashAdjusted' );
		if( ( factVal <= 0 ) && ( ( ( Int32 )( gameGameVersion.Current ) ) >= 2000 ) )
		{
			ProcessWeaponsAndClothingModsPurgeInStash( stashObj );
			SetFactValue( game, 'WeaponAndClothingModsInStashAdjusted', 1 );
		}
		factVal = GetFact( game, 'ConsumablesPlayerStashRetroFix' );
		if( ( factVal <= 0 ) && ( ( ( Int32 )( gameGameVersion.Current ) ) >= 2000 ) )
		{
			ConsumablesRetrofix( stashObj );
			SetFactValue( game, 'ConsumablesPlayerStashRetroFix', 1 );
		}
		factVal = GetFact( game, 'IconicsFactsForBlackMarketerAddedInStash' );
		if( ( factVal <= 0 ) && ( ( ( Int32 )( gameGameVersion.Current ) ) >= 2000 ) )
		{
			ProcessIconicsFactsForBlackMarketerInStash( stashObj );
			SetFactValue( game, 'IconicsFactsForBlackMarketerAddedInStash', 1 );
		}
		factVal = GetFact( game, 'LeftHandWeaponsCompensatedInStash' );
		if( ( factVal <= 0 ) && ( ( ( Int32 )( gameGameVersion.Current ) ) >= 2000 ) )
		{
			ReplaceLeftHandVariantWeaponsWithRegularInStash( stashObj );
			ScaleAndLockLeftHandWeaponsCompensateInStash( stashObj );
			SetFactValue( game, 'LeftHandWeaponsCompensatedInStash', 1 );
		}
		factVal = GetFact( game, 'WeaponAndClothingModsInStashAdjusted_201' );
		if( ( factVal <= 0 ) && ( ( ( Int32 )( gameGameVersion.Current ) ) >= 2010 ) )
		{
			ProcessWeaponsModsCompensateInStash( stashObj );
			InstallModsToRedesignedItems( stashObj );
			SetFactValue( game, 'WeaponAndClothingModsInStashAdjusted_201', 1 );
		}
		factVal = GetFact( game, 'NonIconicWeaponsRescaledInStash' );
		if( ( factVal <= 0 ) && ( ( ( Int32 )( gameGameVersion.Current ) ) >= 2010 ) )
		{
			ProcessNonIconicWeaponsRescaleInStash( stashObj );
			SetFactValue( game, 'NonIconicWeaponsRescaledInStash', 1 );
		}
		factVal = GetFact( game, 'ReginaRewardCompensatedInStash' );
		if( ( factVal <= 0 ) && ( ( ( Int32 )( gameGameVersion.Current ) ) >= 2099 ) )
		{
			if( ( GetFact( game, 'wat_sts_counter' ) >= 23 ) && ( GetFact( game, 'regina_iconic_subdermalcoprocessor_acquired' ) <= 0 ) )
			{
				CheckReginaRewardsPresenceInStash( stashObj );
			}
			RemoveDeprecatedReginaCWRewardInStash( stashObj );
			SetFactValue( game, 'ReginaRewardCompensatedInStash', 1 );
		}
		factVal = GetFact( game, 'GritModsInStashPurged' );
		if( ( factVal <= 0 ) && ( ( ( Int32 )( gameGameVersion.Current ) ) >= 2099 ) )
		{
			ProcessGritModsPurgeInStash( stashObj );
			SetFactValue( game, 'GritModsInStashPurged', 1 );
		}
		factVal = GetFact( game, 'RasetsuRescaledandLockedInStash' );
		if( ( factVal <= 0 ) && ( ( ( Int32 )( gameGameVersion.Current ) ) >= 2099 ) )
		{
			RasetsuItemPlayerScalingInStash( stashObj );
			SetFactValue( game, 'RasetsuRescaledandLockedInStash', 1 );
		}
		factVal = GetFact( game, 'IconicsUpgradeCountWithEffectiveTierUnifiedInStash' );
		if( ( factVal <= 0 ) && ( ( ( Int32 )( gameGameVersion.Current ) ) >= 2099 ) )
		{
			UnifyIconicsUpgradeCountWithEffectiveTierInStash( stashObj );
			SetFactValue( game, 'IconicsUpgradeCountWithEffectiveTierUnifiedInStash', 1 );
		}
		factVal = GetFact( game, 'KurtMetelFactRetrofixedInStash' );
		if( ( factVal <= 0 ) && ( ( ( Int32 )( gameGameVersion.Current ) ) >= 2099 ) )
		{
			ProcessIconicsFactsForBlackMarketerInStash( stashObj );
			SetFactValue( game, 'KurtMetelFactRetrofixedInStash', 1 );
		}
		factVal = GetFact( game, 'AmazonGritAttachmentsInStashPurged' );
		if( ( factVal <= 0 ) && ( ( ( Int32 )( gameGameVersion.Current ) ) >= 2110 ) )
		{
			ProcessAmazonGritAttachmentsPurgeInStash( stashObj );
			SetFactValue( game, 'AmazonGritAttachmentsInStashPurged', 1 );
		}
	}

	private static function InstallModsToRedesignedItems( stashObj : GameObject )
	{
		var i : Int32;
		var storageItems : array< weak< gameItemData > >;
		var itemData : gameItemData;
		var transactionSystem : TransactionSystem;
		var itemModificationSystem : weak< ItemModificationSystem >;
		var partItemID : ItemID;
		transactionSystem = GameInstance.GetTransactionSystem( stashObj.GetGame() );
		itemModificationSystem = ( ( ItemModificationSystem )( GameInstance.GetScriptableSystemsContainer( stashObj.GetGame() ).Get( 'ItemModificationSystem' ) ) );
		transactionSystem.GetItemList( stashObj, storageItems );
		for( i = 0; i < storageItems.Size(); i += 1 )
		{
			itemData = storageItems[ i ];
			if( itemData && itemData.HasTag( 'Gog_Katana' ) )
			{
				partItemID = ItemID.FromTDBID( T"Items.GogKatanaWeaponMod" );
				transactionSystem.GiveItem( stashObj, partItemID, 1 );
				itemModificationSystem.QueueRequest( CreateInstallPartRequest_Mod( stashObj, itemData, partItemID ) );
			}
			if( itemData && itemData.HasTag( 'Buck_Grad' ) )
			{
				partItemID = ItemID.FromTDBID( T"Items.Buck_scope" );
				transactionSystem.GiveItem( stashObj, partItemID, 1 );
				itemModificationSystem.QueueRequest( CreateInstallPartRequest_Attachment( stashObj, itemData, partItemID ) );
			}
			if( itemData && itemData.HasTag( 'Tactician_Headsman' ) )
			{
				partItemID = ItemID.FromTDBID( T"Items.Headsman_scope" );
				transactionSystem.GiveItem( stashObj, partItemID, 1 );
				itemModificationSystem.QueueRequest( CreateInstallPartRequest_Attachment( stashObj, itemData, partItemID ) );
			}
			if( itemData && itemData.HasTag( 'Sasquatch_Hammer' ) )
			{
				partItemID = ItemID.FromTDBID( T"Items.Hammer_Sasquatch_Mod" );
				transactionSystem.GiveItem( stashObj, partItemID, 1 );
				itemModificationSystem.QueueRequest( CreateInstallPartRequest_Mod( stashObj, itemData, partItemID ) );
			}
			if( itemData && itemData.HasTag( 'Nekomata_Breakthrough' ) )
			{
				partItemID = ItemID.FromTDBID( T"Items.Breakthrough_scope" );
				transactionSystem.GiveItem( stashObj, partItemID, 1 );
				itemModificationSystem.QueueRequest( CreateInstallPartRequest_Attachment( stashObj, itemData, partItemID ) );
			}
			if( itemData && itemData.HasTag( 'Competition_Lexington' ) )
			{
				partItemID = ItemID.FromTDBID( T"Items.Lexington_Shooting_Competition_scope" );
				transactionSystem.GiveItem( stashObj, partItemID, 1 );
				itemModificationSystem.QueueRequest( CreateInstallPartRequest_Attachment( stashObj, itemData, partItemID ) );
			}
			if( itemData && itemData.HasTag( 'Competition_Lexington' ) )
			{
				partItemID = ItemID.FromTDBID( T"Items.CollectibleIconicWeaponMod" );
				transactionSystem.GiveItem( stashObj, partItemID, 1 );
				itemModificationSystem.QueueRequest( CreateInstallPartRequest_Mod( stashObj, itemData, partItemID ) );
			}
			if( itemData && itemData.HasTag( 'Grad_Panam' ) )
			{
				partItemID = ItemID.FromTDBID( T"Items.Panam_scope" );
				transactionSystem.GiveItem( stashObj, partItemID, 1 );
				itemModificationSystem.QueueRequest( CreateInstallPartRequest_Attachment( stashObj, itemData, partItemID ) );
			}
			if( itemData && itemData.HasTag( 'ChemResMod' ) )
			{
				partItemID = ItemID.FromTDBID( T"Items.IntrinsicFabricEnhancer12" );
				transactionSystem.GiveItem( stashObj, partItemID, 1 );
				itemModificationSystem.QueueRequest( CreateInstallPartRequest_Mod( stashObj, itemData, partItemID ) );
			}
			if( itemData && itemData.HasTag( 'ZoomMod' ) )
			{
				partItemID = ItemID.FromTDBID( T"Items.IntrinsicFabricEnhancer07a" );
				transactionSystem.GiveItem( stashObj, partItemID, 1 );
				itemModificationSystem.QueueRequest( CreateInstallPartRequest_Mod( stashObj, itemData, partItemID ) );
			}
			if( itemData && itemData.HasTag( 'QuickhackUploadMod' ) )
			{
				partItemID = ItemID.FromTDBID( T"Items.IntrinsicFabricEnhancer10" );
				transactionSystem.GiveItem( stashObj, partItemID, 1 );
				itemModificationSystem.QueueRequest( CreateInstallPartRequest_Mod( stashObj, itemData, partItemID ) );
			}
			if( itemData && itemData.HasTag( 'VisibilityMod' ) )
			{
				partItemID = ItemID.FromTDBID( T"Items.IntrinsicFabricEnhancer05" );
				transactionSystem.GiveItem( stashObj, partItemID, 1 );
				itemModificationSystem.QueueRequest( CreateInstallPartRequest_Mod( stashObj, itemData, partItemID ) );
			}
			if( itemData && itemData.HasTag( 'MeleeDmgRedMod' ) )
			{
				partItemID = ItemID.FromTDBID( T"Items.IntrinsicFabricEnhancer09" );
				transactionSystem.GiveItem( stashObj, partItemID, 1 );
				itemModificationSystem.QueueRequest( CreateInstallPartRequest_Mod( stashObj, itemData, partItemID ) );
			}
			if( itemData && itemData.HasTag( 'QuickhackDmgRedMod' ) )
			{
				partItemID = ItemID.FromTDBID( T"Items.IntrinsicFabricEnhancer11" );
				transactionSystem.GiveItem( stashObj, partItemID, 1 );
				itemModificationSystem.QueueRequest( CreateInstallPartRequest_Mod( stashObj, itemData, partItemID ) );
			}
			if( itemData && itemData.HasTag( 'ArmorMod' ) )
			{
				partItemID = ItemID.FromTDBID( T"Items.IntrinsicFabricEnhancer01" );
				transactionSystem.GiveItem( stashObj, partItemID, 1 );
				itemModificationSystem.QueueRequest( CreateInstallPartRequest_Mod( stashObj, itemData, partItemID ) );
			}
			if( itemData && itemData.HasTag( 'ReloadMod' ) )
			{
				partItemID = ItemID.FromTDBID( T"Items.IntrinsicFabricEnhancer08" );
				transactionSystem.GiveItem( stashObj, partItemID, 1 );
				itemModificationSystem.QueueRequest( CreateInstallPartRequest_Mod( stashObj, itemData, partItemID ) );
			}
		}
	}

	private static function CreateInstallPartRequest_Mod( stashObj : GameObject, itemData : gameItemData, part : ItemID ) : InstallItemPart
	{
		var installPartRequest : InstallItemPart;
		var slotID : TweakDBID;
		switch( itemData.GetItemType() )
		{
			case gamedataItemType.Wea_Katana:
			case gamedataItemType.Wea_Hammer:
				slotID = T"AttachmentSlots.IconicMeleeWeaponMod1";
			break;
			case gamedataItemType.Wea_Handgun:
				slotID = T"AttachmentSlots.IconicWeaponModLegendary";
			break;
			case gamedataItemType.Clo_InnerChest:
				slotID = T"AttachmentSlots.InnerChestFabricEnhancer1";
			break;
			case gamedataItemType.Clo_OuterChest:
				slotID = T"AttachmentSlots.OuterChestFabricEnhancer1";
			break;
			case gamedataItemType.Clo_Head:
				slotID = T"AttachmentSlots.HeadFabricEnhancer1";
			break;
			case gamedataItemType.Clo_Face:
				slotID = T"AttachmentSlots.FaceFabricEnhancer1";
			break;
			default:
				break;
		}
		installPartRequest = new InstallItemPart;
		installPartRequest.Set( stashObj, itemData.GetID(), part, slotID );
		return installPartRequest;
	}

	private static function ConsumablesRetrofix( stashObj : GameObject )
	{
		var i : Int32;
		var chargedConsumables : array< weak< gameItemData > >;
		var transactionSystem : TransactionSystem;
		transactionSystem = GameInstance.GetTransactionSystem( stashObj.GetGame() );
		transactionSystem.GetItemListByTag( stashObj, 'ChargedConsumable', chargedConsumables );
		for( i = 0; i < chargedConsumables.Size(); i += 1 )
		{
			transactionSystem.RemoveItem( stashObj, chargedConsumables[ i ].GetID(), chargedConsumables[ i ].GetQuantity() );
		}
	}

	private static function CreateInstallPartRequest_Attachment( stashObj : GameObject, itemData : gameItemData, part : ItemID ) : InstallItemPart
	{
		var installPartRequest : InstallItemPart;
		var slotID : TweakDBID;
		switch( itemData.GetItemType() )
		{
			case gamedataItemType.Wea_Handgun:
			case gamedataItemType.Wea_SniperRifle:
			case gamedataItemType.Wea_Shotgun:
				slotID = T"AttachmentSlots.Scope";
			break;
			default:
				break;
		}
		installPartRequest = new InstallItemPart;
		installPartRequest.Set( stashObj, itemData.GetID(), part, slotID );
		return installPartRequest;
	}

	private static function RemoveAllModsFromClothing( stashObj : GameObject )
	{
		var i, j : Int32;
		var storageItems : array< weak< gameItemData > >;
		var itemData : gameItemData;
		var transactionSystem : TransactionSystem;
		var itemModificationSystem : weak< ItemModificationSystem >;
		var usedSlots : array< TweakDBID >;
		var currentItem : ItemID;
		transactionSystem = GameInstance.GetTransactionSystem( stashObj.GetGame() );
		itemModificationSystem = ( ( ItemModificationSystem )( GameInstance.GetScriptableSystemsContainer( stashObj.GetGame() ).Get( 'ItemModificationSystem' ) ) );
		transactionSystem.GetItemList( stashObj, storageItems );
		for( i = 0; i < storageItems.Size(); i += 1 )
		{
			itemData = storageItems[ i ];
			if( itemData )
			{
				currentItem = itemData.GetID();
				if( RPGManager.IsItemClothing( currentItem ) )
				{
					usedSlots.Clear();
					transactionSystem.GetUsedSlotsOnItem( stashObj, currentItem, usedSlots );
					for( j = 0; j < usedSlots.Size(); j += 1 )
					{
						itemModificationSystem.QueueRequest( CreateRemovePartRequest( stashObj, currentItem, usedSlots[ j ] ) );
					}
				}
			}
		}
	}

	private static function ProcessWeaponsAndClothingModsPurgeInStash( stashObj : GameObject )
	{
		var i, j : Int32;
		var storageItems : array< weak< gameItemData > >;
		var itemData : gameItemData;
		var transactionSystem : TransactionSystem;
		var usedSlots : array< TweakDBID >;
		var currentItem : ItemID;
		transactionSystem = GameInstance.GetTransactionSystem( stashObj.GetGame() );
		transactionSystem.GetItemList( stashObj, storageItems );
		for( i = 0; i < storageItems.Size(); i += 1 )
		{
			itemData = storageItems[ i ];
			if( itemData )
			{
				currentItem = itemData.GetID();
				if( RPGManager.IsItemClothing( currentItem ) || RPGManager.IsItemWeapon( currentItem ) )
				{
					usedSlots.Clear();
					usedSlots = RPGManager.GetModsSlotIDs( itemData.GetItemType() );
					for( j = 0; j < usedSlots.Size(); j += 1 )
					{
						transactionSystem.RemovePart( stashObj, currentItem, usedSlots[ j ] );
					}
				}
				if( RPGManager.IsItemWeapon( currentItem ) )
				{
					usedSlots.Clear();
					usedSlots = RPGManager.GetAttachmentSlotIDs();
					for( j = 0; j < usedSlots.Size(); j += 1 )
					{
						transactionSystem.RemovePart( stashObj, currentItem, usedSlots[ j ] );
					}
				}
			}
		}
	}

	private static function ProcessWeaponsModsCompensateInStash( stashObj : GameObject )
	{
		var i : Int32;
		var storageItems : array< weak< gameItemData > >;
		var transactionSystem : TransactionSystem;
		var playerLevel : Float;
		var statSys : StatsSystem;
		statSys = GameInstance.GetStatsSystem( stashObj.GetGame() );
		playerLevel = statSys.GetStatValue( GameInstance.GetPlayerSystem( stashObj.GetGame() ).GetLocalPlayerMainGameObject().GetEntityID(), gamedataStatType.PowerLevel );
		transactionSystem = GameInstance.GetTransactionSystem( stashObj.GetGame() );
		transactionSystem.GetItemList( stashObj, storageItems );
		for( i = 0; i < storageItems.Size(); i += 1 )
		{
			if( storageItems[ i ].HasTag( 'DeprecatedWeaponMod' ) && !( storageItems[ i ].HasTag( 'DummyWeaponMod' ) ) )
			{
				if( playerLevel < 17.0 )
				{
					transactionSystem.GiveItemByItemQuery( stashObj, T"Query.CommonWeaponModsQuery" );
				}
				else if( playerLevel < 33.0 )
				{
					transactionSystem.GiveItemByItemQuery( stashObj, T"Query.UncommonWeaponModsQuery" );
				}
				else
				{
					transactionSystem.GiveItemByItemQuery( stashObj, T"Query.RareWeaponModsQuery" );
				}
			}
		}
	}

	private static function RemoveRedundantScopesFromAchillesRifles( stashObj : GameObject )
	{
		var ts : TransactionSystem;
		var ims : ItemModificationSystem;
		var stashItems : array< weak< gameItemData > >;
		ts = GameInstance.GetTransactionSystem( stashObj.GetGame() );
		ims = ( ( ItemModificationSystem )( GameInstance.GetScriptableSystemsContainer( stashObj.GetGame() ).Get( 'ItemModificationSystem' ) ) );
		if( !( ts ) || !( ims ) )
		{
			return;
		}
		ts.GetItemList( stashObj, stashItems );
		ims.RemoveRedundantScopesFromAchillesRifles( stashItems );
	}

	private static function CreateRemovePartRequest( stashObj : GameObject, item : ItemID, slotID : TweakDBID ) : RemoveItemPart
	{
		var removePartRequest : RemoveItemPart;
		removePartRequest = new RemoveItemPart;
		removePartRequest.Set( stashObj, item, slotID );
		return removePartRequest;
	}

	private static function IconicsReworkCompensateInStash( stashObj : GameObject )
	{
		var i : Int32;
		var storageItems : array< weak< gameItemData > >;
		var transactionSystem : TransactionSystem;
		transactionSystem = GameInstance.GetTransactionSystem( stashObj.GetGame() );
		transactionSystem.GetItemList( stashObj, storageItems );
		for( i = 0; i < storageItems.Size(); i += 1 )
		{
			if( storageItems[ i ].HasTag( 'IconicWeapon' ) && !( storageItems[ i ].HasTag( 'StashScaling_Iconic' ) ) )
			{
				RescaleStashedIconicsToPlayerLevel( stashObj, storageItems[ i ] );
			}
		}
	}

	public static function RescaleStashedIconicsToPlayerLevel( stashObj : GameObject, itemData : gameItemData )
	{
		var lootLevelMod : gameStatModifierData;
		var itemLeveltier5LimiterMod : gameStatModifierData;
		var zeroUpgradeMod : gameStatModifierData;
		var qualityToUpgradeMod : gameStatModifierData;
		var plusToUpgradeMod : gameStatModifierData;
		var upgradeToQualityMod : gameStatModifierData;
		var upgradeToPlusMod : gameStatModifierData;
		var playerLevel : Float;
		var statSys : StatsSystem;
		statSys = GameInstance.GetStatsSystem( stashObj.GetGame() );
		playerLevel = statSys.GetStatValue( GameInstance.GetPlayerSystem( stashObj.GetGame() ).GetLocalPlayerMainGameObject().GetEntityID(), gamedataStatType.Level );
		lootLevelMod = RPGManager.CreateStatModifier( gamedataStatType.LootLevel, gameStatModifierType.Additive, playerLevel );
		zeroUpgradeMod = RPGManager.CreateStatModifier( gamedataStatType.WasItemUpgraded, gameStatModifierType.Additive, itemData.GetStatValueByType( gamedataStatType.WasItemUpgraded ) * -1.0 );
		GameInstance.GetStatsSystem( stashObj.GetGame() ).RemoveAllModifiers( itemData.GetStatsObjectID(), gamedataStatType.PowerLevel, true );
		GameInstance.GetStatsSystem( stashObj.GetGame() ).RemoveAllModifiers( itemData.GetStatsObjectID(), gamedataStatType.LootLevel, true );
		GameInstance.GetStatsSystem( stashObj.GetGame() ).RemoveAllModifiers( itemData.GetStatsObjectID(), gamedataStatType.ItemLevel, true );
		GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), zeroUpgradeMod );
		GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), lootLevelMod );
		itemLeveltier5LimiterMod = RPGManager.CreateStatModifierUsingCurve( gamedataStatType.ItemLevel, gameStatModifierType.Additive, gamedataStatType.LootLevel, 'quality_curves', 'iconic_weapon_level_tier5_limiter_retrofix' );
		GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), itemLeveltier5LimiterMod );
		lootLevelMod = RPGManager.CreateStatModifier( gamedataStatType.LootLevel, gameStatModifierType.Additive, itemData.GetStatValueByType( gamedataStatType.ItemLevel ) );
		GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), lootLevelMod );
		qualityToUpgradeMod = RPGManager.CreateStatModifier( gamedataStatType.WasItemUpgraded, gameStatModifierType.Additive, itemData.GetStatValueByType( gamedataStatType.Quality ) * 2.0 );
		GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), qualityToUpgradeMod );
		upgradeToQualityMod = RPGManager.CreateStatModifier( gamedataStatType.Quality, gameStatModifierType.Additive, itemData.GetStatValueByType( gamedataStatType.WasItemUpgraded ) * -0.5 );
		GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), upgradeToQualityMod );
		plusToUpgradeMod = RPGManager.CreateStatModifier( gamedataStatType.WasItemUpgraded, gameStatModifierType.Additive, itemData.GetStatValueByType( gamedataStatType.IsItemPlus ) );
		GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), plusToUpgradeMod );
		GameInstance.GetStatsSystem( stashObj.GetGame() ).RemoveAllModifiers( itemData.GetStatsObjectID(), gamedataStatType.IsItemPlus, true );
		upgradeToPlusMod = RPGManager.CreateStatModifierUsingCurve( gamedataStatType.IsItemPlus, gameStatModifierType.Additive, gamedataStatType.WasItemUpgraded, 'quality_curves', 'iconic_upgrades_amount_to_plus' );
		GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), upgradeToPlusMod );
	}

	private static function ProcessIconicsFactsForBlackMarketerInStash( stashObj : GameObject )
	{
		var i : Int32;
		var storageItems : array< weak< gameItemData > >;
		var transactionSystem : TransactionSystem;
		transactionSystem = GameInstance.GetTransactionSystem( stashObj.GetGame() );
		transactionSystem.GetItemList( stashObj, storageItems );
		for( i = 0; i < storageItems.Size(); i += 1 )
		{
			if( storageItems[ i ].HasTag( 'IconicWeapon' ) )
			{
				RPGManager.ProcessOnLootedPackages( stashObj, storageItems[ i ].GetID() );
			}
		}
	}

	public static function ScaleStashIconicsToPlayerLevel( stashObj : GameObject )
	{
		var i : Int32;
		var storageItems : array< weak< gameItemData > >;
		var transactionSystem : TransactionSystem;
		transactionSystem = GameInstance.GetTransactionSystem( stashObj.GetGame() );
		transactionSystem.GetItemList( stashObj, storageItems );
		for( i = 0; i < storageItems.Size(); i += 1 )
		{
			if( storageItems[ i ].HasTag( 'StashScaling_Iconic' ) && ( storageItems[ i ].GetStatValueByType( gamedataStatType.ScalingBlocked ) < 1.0 ) )
			{
				RescaleStashedIconicsToPlayerLevel( stashObj, storageItems[ i ] );
				BlockScalingInStash( stashObj, storageItems[ i ] );
			}
		}
	}

	public static function ScaleLeftHandCompensateWeaponsToPlayerLevelInStash( stashObj : GameObject, itemData : gameItemData )
	{
		var scalingMod : gameStatModifierData;
		var scalingBlocker : gameStatModifierData;
		var playerLevel : Float;
		var statSys : StatsSystem;
		statSys = GameInstance.GetStatsSystem( stashObj.GetGame() );
		playerLevel = statSys.GetStatValue( GameInstance.GetPlayerSystem( stashObj.GetGame() ).GetLocalPlayerMainGameObject().GetEntityID(), gamedataStatType.PowerLevel );
		if( TweakDBInterface.GetBool( ItemID.GetTDBID( itemData.GetID() ) + T".scaleToPlayerInStash", false ) && ( itemData.GetStatValueByType( gamedataStatType.ScalingBlocked ) < 1.0 ) )
		{
			GameInstance.GetStatsSystem( stashObj.GetGame() ).RemoveAllModifiers( itemData.GetStatsObjectID(), gamedataStatType.LootLevel, true );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).RemoveAllModifiers( itemData.GetStatsObjectID(), gamedataStatType.PowerLevel, true );
			scalingMod = RPGManager.CreateStatModifier( gamedataStatType.LootLevel, gameStatModifierType.Additive, playerLevel );
			scalingBlocker = RPGManager.CreateStatModifier( gamedataStatType.ScalingBlocked, gameStatModifierType.Additive, 1.0 );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), scalingMod );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), scalingBlocker );
		}
	}

	private static function BlockScalingInStash( stashObj : GameObject, itemData : gameItemData )
	{
		var scalingBlocker : gameStatModifierData;
		if( TweakDBInterface.GetBool( ItemID.GetTDBID( itemData.GetID() ) + T".scaleToPlayerInStash", false ) )
		{
			scalingBlocker = RPGManager.CreateStatModifier( gamedataStatType.ScalingBlocked, gameStatModifierType.Additive, 1.0 );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), scalingBlocker );
		}
	}

	private static function ReplaceLeftHandVariantWeaponsWithRegularInStash( stashObj : GameObject )
	{
		var i : Int32;
		var storageItems : array< weak< gameItemData > >;
		var transactionSystem : TransactionSystem;
		transactionSystem = GameInstance.GetTransactionSystem( stashObj.GetGame() );
		transactionSystem.GetItemList( stashObj, storageItems );
		for( i = 0; i < storageItems.Size(); i += 1 )
		{
			if( storageItems[ i ].HasTag( 'Left_Hand' ) )
			{
				RPGManager.ProcessOnLootedPackages( stashObj, storageItems[ i ].GetID() );
			}
		}
	}

	private static function ScaleAndLockLeftHandWeaponsCompensateInStash( stashObj : GameObject )
	{
		var player : weak< PlayerPuppet >;
		var evt : ScaleAndLockLeftHandWeaponsCompensateInStashEvent;
		player = GetMainPlayer( stashObj.GetGame() );
		if( player )
		{
			evt = new ScaleAndLockLeftHandWeaponsCompensateInStashEvent;
			GameInstance.GetDelaySystem( stashObj.GetGame() ).DelayEvent( stashObj, evt, 1.0 );
		}
	}

	public static function ProcessNonIconicWeaponsRescaleInStash( stashObj : GameObject )
	{
		var i : Int32;
		var storageItems : array< weak< gameItemData > >;
		var transactionSystem : TransactionSystem;
		transactionSystem = GameInstance.GetTransactionSystem( stashObj.GetGame() );
		transactionSystem.GetItemList( stashObj, storageItems );
		for( i = 0; i < storageItems.Size(); i += 1 )
		{
			if( !( RPGManager.IsItemIconic( storageItems[ i ] ) ) && RPGManager.IsItemWeapon( storageItems[ i ].GetID() ) )
			{
				RetroScaleNonIconicWeaponsInStash( stashObj, storageItems[ i ] );
			}
		}
	}

	public static function RetroScaleNonIconicWeaponsInStash( stashObj : GameObject, itemData : gameItemData )
	{
		var lootLevelMod : gameStatModifierData;
		var scalingBlocker : gameStatModifierData;
		var randomizerMod : gameStatModifierData;
		var qualityMod : gameStatModifierData;
		var randomCurveMod : gameStatModifierData;
		var statSys : StatsSystem;
		var playerLevel : Float;
		var playerMaxQualtity : Float;
		var weaponQuality : Float;
		statSys = GameInstance.GetStatsSystem( stashObj.GetGame() );
		playerLevel = statSys.GetStatValue( GameInstance.GetPlayerSystem( stashObj.GetGame() ).GetLocalPlayerMainGameObject().GetEntityID(), gamedataStatType.Level );
		playerMaxQualtity = statSys.GetStatValue( GameInstance.GetPlayerSystem( stashObj.GetGame() ).GetLocalPlayerMainGameObject().GetEntityID(), gamedataStatType.MaxQuality );
		weaponQuality = itemData.GetStatValueByType( gamedataStatType.Quality );
		if( ( ( ( ( itemData.GetStatValueByType( gamedataStatType.ScalingBlocked ) < 1.0 ) && ( ( itemData.GetStatValueByType( gamedataStatType.LootLevel ) < 1.0 ) || ( itemData.GetStatValueByType( gamedataStatType.LootLevel ) > playerLevel ) ) ) && ( itemData.GetStatValueByType( gamedataStatType.IsItemCrafted ) < 1.0 ) ) && ( itemData.GetStatValueByType( gamedataStatType.ItemPurchasedAtVendor ) < 1.0 ) ) && ( itemData.GetStatValueByType( gamedataStatType.IsItemIconic ) < 1.0 ) )
		{
			GameInstance.GetStatsSystem( stashObj.GetGame() ).RemoveAllModifiers( itemData.GetStatsObjectID(), gamedataStatType.PowerLevel, true );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).RemoveAllModifiers( itemData.GetStatsObjectID(), gamedataStatType.LootLevel, true );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).RemoveAllModifiers( itemData.GetStatsObjectID(), gamedataStatType.RandomCurveInput, true );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).RemoveAllModifiers( itemData.GetStatsObjectID(), gamedataStatType.Quality, true );
			lootLevelMod = RPGManager.CreateStatModifier( gamedataStatType.LootLevel, gameStatModifierType.Additive, playerLevel );
			scalingBlocker = RPGManager.CreateStatModifier( gamedataStatType.ScalingBlocked, gameStatModifierType.Additive, 1.0 );
			randomizerMod = RPGManager.CreateStatModifier( gamedataStatType.NPCWeaponDropRandomizer, gameStatModifierType.Additive, RandRangeF( -0.80000001, 0.2 ) );
			randomCurveMod = RPGManager.CreateStatModifier( gamedataStatType.RandomCurveInput, gameStatModifierType.Additive, RandRangeF( 0.01, 0.99000001 ) );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), lootLevelMod );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), scalingBlocker );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), randomizerMod );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), randomCurveMod );
			lootLevelMod = RPGManager.CreateCombinedStatModifier( gamedataStatType.LootLevel, gameStatModifierType.AdditiveMultiplier, gamedataStatType.NPCWeaponDropRandomizer, gameCombinedStatOperation.Multiplication, 1.0, gameStatObjectsRelation.Self );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), lootLevelMod );
			randomCurveMod = RPGManager.CreateStatModifierUsingCurve( gamedataStatType.RandomCurveInput, gameStatModifierType.Additive, gamedataStatType.LootLevel, 'quality_curves', 'level_to_random_range_mult_new' );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), randomCurveMod );
			qualityMod = RPGManager.CreateStatModifierUsingCurve( gamedataStatType.Quality, gameStatModifierType.Additive, gamedataStatType.RandomCurveInput, 'random_distributions', 'quality_distribution_new' );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), qualityMod );
		}
		else if( ( ( ( itemData.GetStatValueByType( gamedataStatType.ScalingBlocked ) < 1.0 ) && ( itemData.GetStatValueByType( gamedataStatType.IsItemCrafted ) >= 1.0 ) ) && ( itemData.GetStatValueByType( gamedataStatType.IsItemIconic ) < 1.0 ) ) && ( ( weaponQuality - playerMaxQualtity ) >= 2.0 ) )
		{
			GameInstance.GetStatsSystem( stashObj.GetGame() ).RemoveAllModifiers( itemData.GetStatsObjectID(), gamedataStatType.Quality, true );
			qualityMod = RPGManager.CreateStatModifier( gamedataStatType.Quality, gameStatModifierType.Additive, playerMaxQualtity );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), qualityMod );
			scalingBlocker = RPGManager.CreateStatModifier( gamedataStatType.ScalingBlocked, gameStatModifierType.Additive, 1.0 );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), scalingBlocker );
		}
	}

	public static function CheckReginaRewardsPresenceInStash( stashObj : GameObject )
	{
		var i : Int32;
		var storageItems : array< weak< gameItemData > >;
		var transactionSystem : TransactionSystem;
		var coprocessorCounter : Float;
		transactionSystem = GameInstance.GetTransactionSystem( stashObj.GetGame() );
		transactionSystem.GetItemList( stashObj, storageItems );
		coprocessorCounter = 0.0;
		for( i = 0; i < storageItems.Size(); i += 1 )
		{
			if( storageItems[ i ].HasTag( 'AdvancedSubdermalCoProcessor_Regina' ) )
			{
				coprocessorCounter += 1.0;
			}
		}
		if( coprocessorCounter <= 0.0 )
		{
			GiveReginaRefinedCWRewardInStash( stashObj );
		}
	}

	private static function GiveReginaRefinedCWRewardInStash( stashObj : GameObject )
	{
		var transactionSystem : TransactionSystem;
		var item : ItemID;
		var playerLevel : Float;
		var statSys : StatsSystem;
		statSys = GameInstance.GetStatsSystem( stashObj.GetGame() );
		playerLevel = statSys.GetStatValue( GameInstance.GetPlayerSystem( stashObj.GetGame() ).GetLocalPlayerMainGameObject().GetEntityID(), gamedataStatType.PowerLevel );
		transactionSystem = GameInstance.GetTransactionSystem( stashObj.GetGame() );
		if( playerLevel >= 33.0 )
		{
			item = ItemID.FromTDBID( T"Items.IconicAdvancedSubdermalCoProcessorLegendary_Regina" );
		}
		else
		{
			item = ItemID.FromTDBID( T"Items.IconicAdvancedSubdermalCoProcessorEpic_Regina" );
		}
		transactionSystem.GiveItem( stashObj, item, 1 );
	}

	private static function RemoveDeprecatedReginaCWRewardInStash( stashObj : GameObject )
	{
		var transactionSystem : TransactionSystem;
		transactionSystem = GameInstance.GetTransactionSystem( stashObj.GetGame() );
		transactionSystem.RemoveItemByTDBID( stashObj, T"Items.NeoFiberLegendary", 1 );
	}

	private static function ProcessGritModsPurgeInStash( stashObj : GameObject )
	{
		var i, j : Int32;
		var storageItems : array< weak< gameItemData > >;
		var itemData : gameItemData;
		var transactionSystem : TransactionSystem;
		var usedSlots : array< TweakDBID >;
		var currentItem : ItemID;
		var partData : InnerItemData;
		var staticData : weak< Item_Record >;
		transactionSystem = GameInstance.GetTransactionSystem( stashObj.GetGame() );
		transactionSystem.GetItemList( stashObj, storageItems );
		for( i = 0; i < storageItems.Size(); i += 1 )
		{
			itemData = storageItems[ i ];
			if( itemData && itemData.HasTag( 'Grit' ) )
			{
				currentItem = itemData.GetID();
				usedSlots.Clear();
				usedSlots = RPGManager.GetModsSlotIDs( itemData.GetItemType() );
				for( j = 0; j < usedSlots.Size(); j += 1 )
				{
					itemData.GetItemPart( partData, usedSlots[ j ] );
					staticData = InnerItemData.GetStaticData( partData );
					if( staticData && staticData.TagsContains( 'DummyPart' ) )
					{
						continue;
					}
					transactionSystem.RemovePart( stashObj, currentItem, usedSlots[ j ] );
				}
			}
		}
	}

	private static function ProcessAmazonGritAttachmentsPurgeInStash( stashObj : GameObject )
	{
		var i, j : Int32;
		var storageItems : array< weak< gameItemData > >;
		var itemData : gameItemData;
		var transactionSystem : TransactionSystem;
		var usedSlots : array< TweakDBID >;
		var currentItem : ItemID;
		var partData : InnerItemData;
		var staticData : weak< Item_Record >;
		transactionSystem = GameInstance.GetTransactionSystem( stashObj.GetGame() );
		transactionSystem.GetItemList( stashObj, storageItems );
		for( i = 0; i < storageItems.Size(); i += 1 )
		{
			itemData = storageItems[ i ];
			if( ( itemData && itemData.HasTag( 'Grit' ) ) && itemData.HasTag( 'IconicWeapon' ) )
			{
				currentItem = itemData.GetID();
				usedSlots.Clear();
				usedSlots = RPGManager.GetAttachmentSlotIDs();
				for( j = 0; j < usedSlots.Size(); j += 1 )
				{
					itemData.GetItemPart( partData, usedSlots[ j ] );
					staticData = InnerItemData.GetStaticData( partData );
					if( staticData && staticData.TagsContains( 'DummyPart' ) )
					{
						continue;
					}
					transactionSystem.RemovePart( stashObj, currentItem, usedSlots[ j ] );
				}
			}
		}
	}

	public static function RasetsuItemPlayerScalingInStash( stashObj : GameObject )
	{
		var i : Int32;
		var storageItems : array< weak< gameItemData > >;
		var transactionSystem : TransactionSystem;
		transactionSystem = GameInstance.GetTransactionSystem( stashObj.GetGame() );
		transactionSystem.GetItemList( stashObj, storageItems );
		for( i = 0; i < storageItems.Size(); i += 1 )
		{
			if( RPGManager.IsItemIconic( storageItems[ i ] ) && storageItems[ i ].HasTag( 'Rasetsu' ) )
			{
				ScaleRasetsuToProperTierInStash( stashObj, storageItems[ i ] );
			}
		}
	}

	public static function ScaleRasetsuToProperTierInStash( stashObj : GameObject, itemData : gameItemData )
	{
		var scalingMod : gameStatModifierData;
		var scalingBlocker : gameStatModifierData;
		if( ( TweakDBInterface.GetBool( ItemID.GetTDBID( itemData.GetID() ) + T".scaleToPlayer", false ) && ( itemData.GetStatValueByType( gamedataStatType.ScalingBlocked ) < 1.0 ) ) && ( ( ( ( ( itemData.GetStatValueByType( gamedataStatType.PowerLevel ) <= 1.0 ) || itemData.HasTag( 'DLCStashItem' ) ) || itemData.HasTag( 'AutoScalingItem' ) ) || itemData.HasTag( 'StashScaling_Iconic' ) ) || itemData.HasTag( 'Left_Hand_Retrofix' ) ) )
		{
			GameInstance.GetStatsSystem( stashObj.GetGame() ).RemoveAllModifiers( itemData.GetStatsObjectID(), gamedataStatType.LootLevel, true );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).RemoveAllModifiers( itemData.GetStatsObjectID(), gamedataStatType.PowerLevel, true );
			scalingMod = RPGManager.CreateStatModifierUsingCurve( gamedataStatType.LootLevel, gameStatModifierType.Additive, gamedataStatType.WasItemUpgraded, 'quality_curves', 'iconic_upgrades_amount_to_level' );
			scalingBlocker = RPGManager.CreateStatModifier( gamedataStatType.ScalingBlocked, gameStatModifierType.Additive, 1.0 );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), scalingMod );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), scalingBlocker );
			scalingMod = RPGManager.CreateStatModifier( gamedataStatType.LootLevel, gameStatModifierType.Additive, itemData.GetStatValueByType( gamedataStatType.LootLevel ) );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).RemoveAllModifiers( itemData.GetStatsObjectID(), gamedataStatType.LootLevel, true );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), scalingMod );
		}
	}

	private static function UnifyIconicsUpgradeCountWithEffectiveTierInStash( stashObj : GameObject )
	{
		var player : weak< PlayerPuppet >;
		var evt : UnifyIconicsUpgradeCountWithEffectiveTierInStashEvent;
		player = GetMainPlayer( stashObj.GetGame() );
		if( player )
		{
			evt = new UnifyIconicsUpgradeCountWithEffectiveTierInStashEvent;
			GameInstance.GetDelaySystem( stashObj.GetGame() ).DelayEvent( stashObj, evt, 0.1 );
		}
	}

	public static function UnifyIconicWeaponsUpgradesCountWithEffectiveTierInStash( stashObj : GameObject, itemData : gameItemData )
	{
		var upgradeMod : gameStatModifierData;
		var plusMod : gameStatModifierData;
		var effectiveTier : Float;
		var upgradeCount : Float;
		effectiveTier = itemData.GetStatValueByType( gamedataStatType.EffectiveTier );
		upgradeCount = itemData.GetStatValueByType( gamedataStatType.WasItemUpgraded );
		if( upgradeCount < effectiveTier )
		{
			upgradeMod = RPGManager.CreateStatModifier( gamedataStatType.WasItemUpgraded, gameStatModifierType.Additive, itemData.GetStatValueByType( gamedataStatType.EffectiveTier ) );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).RemoveAllModifiers( itemData.GetStatsObjectID(), gamedataStatType.WasItemUpgraded, true );
			GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), upgradeMod );
		}
		GameInstance.GetStatsSystem( stashObj.GetGame() ).RemoveAllModifiers( itemData.GetStatsObjectID(), gamedataStatType.IsItemPlus, true );
		plusMod = RPGManager.CreateStatModifierUsingCurve( gamedataStatType.IsItemPlus, gameStatModifierType.Additive, gamedataStatType.WasItemUpgraded, 'quality_curves', 'iconic_upgrades_amount_to_plus' );
		GameInstance.GetStatsSystem( stashObj.GetGame() ).AddSavedModifier( itemData.GetStatsObjectID(), plusMod );
	}

}

class StashController extends ScriptableDeviceComponent
{

	public const override function GetPS() : StashControllerPS
	{
		return ( ( StashControllerPS )( GetBasePS() ) );
	}

}

class StashControllerPS extends ScriptableDeviceComponentPS
{
	default m_shouldScannerShowNetwork = false;
	default m_shouldScannerShowStatus = false;
	default m_shouldScannerShowAttitude = false;
	default m_shouldScannerShowHealth = false;

	private const function ActionOpenStash() : OpenStash
	{
		var action : OpenStash;
		action = new OpenStash;
		action.clearanceLevel = DefaultActionsParametersHolder.GetInteractiveClearance();
		action.SetUp( this );
		action.SetProperties();
		action.AddDeviceName( m_deviceName );
		action.CreateInteraction();
		return action;
	}

	private function OnOpenStash( evt : OpenStash ) : EntityNotificationType
	{
		UseNotifier( evt );
		return EntityNotificationType.SendThisEventToEntity;
	}

	public override function GetActions( out outActions : array< DeviceAction >, context : GetActionsContext ) : Bool
	{
		if( !( super.GetActions( outActions, context ) ) )
		{
			return false;
		}
		if( OpenStash.IsDefaultConditionMet( this, context ) )
		{
			outActions.PushBack( ActionOpenStash() );
		}
		SetActionIllegality( outActions, m_illegalActions.regularActions );
		return true;
	}

}

