StoreItems() Additional Functionality Help

08/20/2018 19:18 Big Q#1
Hi guys. Long time lurker, first time poster.

I've recently started building bots from the bots and pieces here on these forums. I'm currently adding StoreItems functionality to a version of War Raptor 1.2 that I've spent the last week fixing, adding stuff to and tweaking.

My StoreItems function works just like it should, however, if I have several Black Dyes in my storage already and my bot goes to add another it won't add it to the stack. I understand why this is happening (my bot only searches for empty spaces), and I understand what must happen for the bot to add it to the stack (it must check every item in the bank to see if it matches one), I just can't get my head around how to code it without breaking what is already there.

My StoreItems code

I'm not looking for anyone to code it for me, but maybe a hint in the right direction. The name of a function that exists already. or a few that could be put together to make a new one. I've checked all of the #includes I have and searched these forums and the web but I just can't find what I'm looking for.

Any help is appreciated.

P.S. I've already thought about waiting for a full stack before adding to storage, but that doesn't seem practical.
08/20/2018 23:02 Underavelvetmoon#2
The best way would be similar to the CanPickUp functions you should typically see for PickUpLoot. I guess you could just check every slot that registers as $Full against a model ID then if it matches move the item to the same slot. So something similar to this:

Code:
If $SlotFull = True Then
   If CanMoveItem($aItem) = True Then
      $toMove = GetItemSlotByModelID(DllStructGetData($SlotFull, "ModelID")
      MoveItem($aItem, $toMove)
   EndIf
EndIf

Func CanMoveItem($aItem)
Local $ModelID = DllStructGetData($aItem, "ModelID")

Switch $ModelID
Case $BlackDye, $Whatever ;~ Although for Black dye you will need Extra ID also
I wrote some functions to equip a specific weapon when it appears in the inventory, maybe they could be of some use to you? I think they give off the right idea :P

Code:
Func ReturnItemExists($lItem)
   Local $aBag
   Local $aItem
   Sleep(200)
   For $i = 1 To 4
	  $aBag = GetBag($i)
	  For $j = 1 To DllStructGetData($aBag, "Slots")
		 $aItem = GetItemBySlot($aBag, $j)
		 If DllStructGetData($aItem, "ModelID") == $lItem Then
			Out("Found Item Model: " & $lItem & " in slot: " & $j)
			Return $aItem
		 Else
			Out("Couldnt find specified item")
			Return False
		 EndIf
	  Next
   Next
EndFunc
Func ReturnItemModelIDBySlot($lBag, $lSlot)
   Local $aBag
   Local $aItem
   Sleep(200)
   $aItem = GetItemBySlot($lBag, $lSlot)
   If DllStructGetData($aItem, "ModelID") <> 0 Then
	  Return DllStructGetData($aItem, "ModelID")
   Else
	  Out("Couldnt find an item in that slot")
	  Return 0
   EndIf
EndFunc
Also waiting for a full stack is totally fine. I do not see any benefit to waiting for a full stack or not, and I do not store anything on any bots I run :P Just keep only the best things which kind of takes care of itself without the need for much inventory management.

Either way, hope it helps!
08/20/2018 23:49 Big Q#3
First off thanks for your contributions here on the forums. I use your ModStructs for Perfect Items and your _PickUpLootEx religiously.

Yes, I was thinking about structuring the function similar to a CanLoot function. I had a thought about using quantity to determine if $eItem is stackable, in place of CanLoot. i.e.

Code:
If DllStructGetData($eItem, 'Quantity') > 1 And DllStructGetData($eItem, 'Quantity') < 250
Is there already a GetIsStackable function? Perhaps an ExtraID for stackable item Type?

If it is stackable I would then try to match it to an item in storage. If I assign a new variable to the storage item $fItem, storage bag $fBag and for the slot it's in $fSlot then I think I can adapt some code to see if they match. Your ReturnItemExists is basically what I need to find the storage item. After that it's as easy as changing a couple of variables in my MoveItem function. i.e.

Code:
MoveItem($eItem, $fbag, $fSlot)
I'd have to re-loop it if not all of it will fit in the existing stack, but that's a second problem for after I solve the first. :)

Again, thanks for the help man. I've gotten help from your hard work on more than this one occasion, you just didn't know it. Keep it up!

I need all the code examples I can get, so if you feel like throwing some of those custom bots my way I sure wouldn't mind. Always looking for inspiration.
08/21/2018 00:20 Underavelvetmoon#4
Happy to be of service!

Unfortunately like I said I do very little with storage, but this is what I came up with, no idea if it'll work but maybe you'll have a brain wave and adapt something :P

Code:
Func GetIsStackableAndMoveToStorage($aItem)
   Local $M = DllStructGetData($aItem, 'ModelID')
   Local $Q = DllStructGetData($aItem, 'ModelID')
   Local $StackableItems = CanStack($aItem)
   
   Switch $M 
   Case $StackableItems
	  If $Q > 0 And $Q < 250 Then 
		 $Temp = ReturnItemExists($aItem) ;~ Will only search in bag
		 If $Temp <> 0 Then 
			$Temp2 = ReturnItemExistsStorage($Temp) ;~ Search bags other then inventory
			If $Temp2 <> 0 And (DllStructGetData($Temp2, 'Quantity') - $Q) < 251 Then ;~ If inventory item + Storage item = less then 251 we can merge stacks
			   MoveItem($Temp, DllStructGetData($Temp2, 'Bag'), DllStructGetData($Temp2, 'Slot'))
			   ;~ Do some error handling/report
			   Return True 
			EndIf
		 EndIf
	  EndIf
   EndSwitch
   Return False
EndFunc

Func CanStack($aItem)
   Local $M = DllStructGetData($aItem, 'ModelID')
   Local $E = DllStructGetData($aItem, 'ExtraID') ;~ Dyes
   
   Switch $M 
   Case $StackableMats
	  Return True
   Case 146
	  If $E = 10 Or $E = 12 Then ;~ Black and White dye
		 Return True
	  Else
		 Return False
	  EndIf
   Case $OtherStackable
	  Return True
   EndSwitch
   
   Return False
EndFunc
From what I can tell from looking at the structs there is no way to find if an item is stackable other then defining by model id or quantity. So you would have to make a list of all the mats/dyes/trophies you want to save and define them in an array or something similar like this:

Code:
Global $MaterialArray[7] = [937, 938, 935, 931, 932, 936, 930]
This just has the rare materials so you would have to find the other ID's yourself since I dont have them.

I also found these in the GWBible file, maybe they will help you!

Code:
Func CountItemInBagsByModelID($ItemModelID)
	$count = 0
	For $i = $BAG_Backpack To $BAG_Bag2
		For $j = 1 To DllStructGetData(GetBag($i), 'Slots')
			$lItemInfo = GetItemBySlot($i, $j)
			If DllStructGetData($lItemInfo, 'ModelID') = $ItemModelID Then $count += DllStructGetData($lItemInfo, 'quantity')
		Next
	Next
	Return $count
EndFunc   ;==>CountItemInBagsByModelID

Func CountItemInStorageByModelID($ItemModelID) ; Bag 6 is Material Storage, which is not included
	$count = 0
	For $i = $BAG_Storage1 To $BAG_Storage5
		If $i == 7 Then ContinueLoop
		For $j = 1 To DllStructGetData(GetBag($i), 'Slots')
			$lItemInfo = GetItemBySlot($i, $j)
			If DllStructGetData($lItemInfo, 'ModelID') = $ItemModelID Then $count += DllStructGetData($lItemInfo, 'quantity')
		Next
	Next
	Return $count
EndFunc   ;==>CountItemInStorageByModelID

Func CountItemTotalByModelID($ItemModelID) ; Bag 6 is Material Storage, which is not included
	$count = 0
	For $i = $BAG_Backpack To $BAG_Storage5
		If $i == 7 Then ContinueLoop
		For $j = 1 To DllStructGetData(GetBag($i), 'Slots')
			$lItemInfo = GetItemBySlot($i, $j)
			If DllStructGetData($lItemInfo, 'ModelID') = $ItemModelID Then $count += DllStructGetData($lItemInfo, 'quantity')
		Next
	Next
	Return $count
EndFunc  

Func FindBackpackStack($aModelID)
	Local $lBag
	Local $lReturnArray[2]
	Local $lItem

	For $i = 1 To 4
		$lBag = GetBag($i)
		For $j = 1 To DllStructGetData($lBag, 'Slots')
			$lItem = GetItemBySlot($lBag, $j)
			If DllStructGetData($lItem, 'ModelID') == $aModelID And DllStructGetData($lItem, 'Quantity') < 250 Then
				$lReturnArray[0] = $i
				$lReturnArray[1] = $j
				Return $lReturnArray
			EndIf
		Next
	Next
EndFunc   ;==>FindStorageStack

Func FindStorageStack($aModelID, $aExtraID)
	Local $lBag
	Local $lReturnArray[2]
	Local $lItem

	For $i = 8 To 16
		$lBag = GetBag($i)
		For $j = 1 To DllStructGetData($lBag, 'Slots')
			$lItem = GetItemBySlot($lBag, $j)
			If DllStructGetData($lItem, 'ModelID') == $aModelID And DllStructGetData($lItem, 'ExtraID') == $aExtraID And DllStructGetData($lItem, 'Quantity') < 250 Then
				$lReturnArray[0] = $i
				$lReturnArray[1] = $j
				Return $lReturnArray
			EndIf
		Next
	Next
EndFunc   ;==>FindStorageStack
Sorry to bombard you with code. Hopefully you can get something from it!