Thread Tools Display Modes
09/16/15, 11:31 PM   #1
Motokosworld
Join Date: Sep 2015
Posts: 6
move item from bag to bank

Hi!
I a new to this forum here, i hope i got the right tread to ask a question. I am from Germany so sorry for any wrong English sentences/words.
I wanna make some Addons for TESO.
On the first hand to get better in coding on the other hand to have some to fit my needs.
I learn java at university and I am new to lua.
I tried to move an item from the bagpack to the bank but it do not work.
I used the "my first addon" help out of the wiki from esoui. And looked into other persons code. But still not working.

I want to move all items of a special kind to the bank, for example all food. I also wanted to use the "y" key function to stack if you can use it. ATM i do not find that function.

Hope someone can give me an example or some tipps. Also some webseites with more tutorials or code explanation would be helpful.
AT my programming its always a little problem /wrong thinking that stops all. >.<""!


My code atm: move 1 item and then crash game >.<



function FooAddon.OnOpenBank(eventcode)
for num = 1, GetBagSize(1), 1 do
firstFreeSlot = FindFirstEmptySlotInBag(2)
icon, istack, sellPrice, meetsUsageRequirement, locked, equipType, itemStyle, quality = GetItemInfo(1, num)
if 0 ~= GetNumBagFreeSlots(2) then
if IsProtectedFunction("RequestMoveItem") then
CallSecureProtected("RequestMoveItem", 1, num, 2, firstFreeSlot, istack)
else
RequestMoveItem(1, num, 2, firstFreeSlot, istack)
end
end
end
end

Last edited by Motokosworld : 09/17/15 at 01:23 AM.
  Reply With Quote
09/17/15, 01:27 AM   #2
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 1,577
Hello and welcome to EsoUI, Motokosworld!

You found the right place for asking this kind of question.

What you want to do can be broken down into four parts:
1, Offer a way to trigger your function
2. Detect when you are at a bank
3. Find all instances of the item in your inventory and move them to the bank
4. Use the 'y' stack function to stack them

I will offer you a basic example that you can use as a starting point.
ad 1)
There are many ways how this can happen.
You can offer a chat command, automatically trigger it whenever the user visits a bank, add a keybind or show some GUI elements that can be clicked.
The first two are comparatively simple while the others require quite some code, so we will stick to a chat command for now.
Lua Code:
  1. SLASH_COMMANDS["/dumpall"] = function()
  2. MyAddon.DumpItemsToBank()
  3. end

ad 2)
This is necessary because you cannot access BAG_BANK unless you are at a banker and chose the bank dialog.
For now we will add a function to prevent DumpItemsToBank from doing anything while we are not at a bank.
Lua Code:
  1. local function IsAtBank()
  2.   return GetInteractionType() == INTERACTION_BANK
  3. end
  4.  
  5. function MyAddon.DumpItemsToBank()
  6.   if not IsAtBank() then return end
  7. end

ad 3)
Now we get to the interesting part. First we have to iterate over all our items and test if they are of the type we want to dump.
You mentioned that you want to move all food to bank, so we stick to that for now.
You already found the necessary methods so everything we need to do is combine it like this:
Lua Code:
  1. for slotIndex = 1, GetBagSize(BAG_BACKPACK) do
  2.   if GetItemType(BAG_BACKPACK, slotIndex) == ITEMTYPE_FOOD then
  3.     MoveItemToBank(slotIndex)
  4.   end
  5. end

GetFirstFreeValidSlotForItem seems to work on the same bag only as it requires a slotIndex to specify an item. FindFirstEmptySlotInBag(integer Bag bagId) is more likely to do what we want so we will try it.
We also need to get the stack size in order to move the correct amount. This can be done with GetSlotStackSize(integer bagId, integer slotIndex).
Once we have the slot we can move request to move it there with the function you already have found.
Lua Code:
  1. local function MoveItemToBank(slotIndex)
  2.   local stackCount = GetSlotStackSize(BAG_BACKPACK, slotIndex)
  3.   local destSlot = FindFirstEmptySlotInBag(BAG_BANK)
  4.   CallSecureProtected("RequestMoveItem", BAG_BACKPACK, slotIndex, BAG_BANK, destSlot, stackCount)
  5. end

ad 4)
All that is left now is to find out how the key bind to stack items is working. For this we need to have a look at the UI source code which can be found here.
The bank is simply another inventory so we take a look at ingame/inventory/inventory.lua and by looking for the keyword "stack" we find StackBag(BAG_BANK).
So after we put everything together in DumpItemsToBank we arrive at:
Lua Code:
  1. function MyAddon.DumpItemsToBank()
  2.   if not IsAtBank() then return end
  3.  
  4.   for slotIndex = 0, GetBagSize(BAG_BACKPACK)-1 do
  5.     if GetItemType(BAG_BACKPACK, slotIndex) == ITEMTYPE_FOOD then
  6.       MoveItemToBank(slotIndex)
  7.     end
  8.   end
  9.  
  10.   StackBag(BAG_BANK)
  11. end

This is completely untested so it might not work right away, but it should give you a general idea how it can be done.

EDIT: Just saw that you updated your post. Instead of adding a chat command you can just call MyAddon.DumpItemsToBank() from your event handler too and of course it will be necessary to check if the bank has enough space left before trying to move the item.
EDIT2: corrected code in response to votan

Last edited by sirinsidiator : 09/17/15 at 02:59 AM.
  Reply With Quote
09/17/15, 01:49 AM   #3
Motokosworld
Join Date: Sep 2015
Posts: 6
Thank you very much for your answer!
I will work now with the things you wrote and will write later how far i came with it!
  Reply With Quote
09/17/15, 01:56 AM   #4
votan
 
votan's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2014
Posts: 577
slot-indexes are (the only) zero-based indexes.

Lua Code:
  1. for slotIndex = 0, GetBagSize(BAG_BACKPACK)-1 do ...

Und Willkommen, Motokosworld.
  Reply With Quote
09/17/15, 02:30 AM   #5
Motokosworld
Join Date: Sep 2015
Posts: 6
Thx votan for your advice. About that i was also thinking, because out of java i know that everything start at 0 and then max-1 so i correct that now.

The problem is, it work 1 time if i open the bank and then again if i open the bank again. SO i think the loop do not work, but why? If i try out some thinks like quote out the if that i only move food, it works once and then if i talk to the banker the second time my game crash.
Maybe there is a problem with that function(RequestMoveItem) or the inventory do not update correctly? i will try out...


My code now much more clean and nice written code with a lot of comments^^, some are still from the tutorial, but i leave them there to learn the functions of all the lua code parts:


Lua Code:
  1. -- First, we create a namespace for our addon by declaring a top-level table that will hold everything else.
  2. BankService = {}
  3.  
  4. -- This isn't strictly necessary, but we'll use this string later when registering events.
  5. -- Better to define it in a single place rather than retyping the same string.
  6. BankService.name = "BankService"
  7.  
  8. -- if the bank is open start this
  9. function BankService.OnOpenBank()
  10.  
  11.     --Run through all slots of the bag
  12.     for slotInBag = 0, GetBagSize(BAG_BACKPACK)-1, 1 do
  13.    
  14.         --check if there is still space in bank and the slot is not empty
  15.         if 0 ~= GetNumBagFreeSlots(BAG_BANK) and GetItemName(BAG_BACKPACK, slotInBag) ~= "" then
  16.    
  17.             -- check if the itemtype is food
  18.             if GetItemType(BAG_BACKPACK, slotInBag) == ITEMTYPE_FOOD then
  19.            
  20.                 -- find a free bankslot
  21.                 local freeBankSlot = FindFirstEmptySlotInBag(BAG_BANK)
  22.                
  23.                 -- read out the stackSize of that item
  24.                 local stackSize = GetSlotStackSize(BAG_BACKPACK, slotInBag)
  25.                
  26.                 --use the protected function to move the item to the bank
  27.                 if IsProtectedFunction("RequestMoveItem") then
  28.                     CallSecureProtected("RequestMoveItem", BAG_BACKPACK, slotInBag, BAG_BANK, freeBankSlot, stackSize)
  29.                 else
  30.                     RequestMoveItem(BAG_BACKPACK, slotInBag, BAG_BANK, freeBankSlot, stackSize)
  31.                 -- close if checkProtectedFunction
  32.                 end
  33.                
  34.                 --use the integrated stack function to stack all in bank
  35.                 StackBag(BAG_BANK)
  36.                
  37.             -- close if checkItemtype
  38.             end
  39.         -- close if checkSpace and notEmpty
  40.         end
  41.     --close loop       
  42.     end
  43. --close function   
  44. end
  45.  
  46.  
  47. -- initialze function
  48. function BankService:Initialize()
  49.     --Register our event
  50.     EVENT_MANAGER:RegisterForEvent(self.name,  EVENT_OPEN_BANK, self.OnOpenBank)       
  51. end
  52.  
  53.  
  54. -- Event handler function, check if the loaded addon is mine
  55. -- Initialize our addon after all of its resources are fully loaded.
  56. function BankService.OnAddOnLoaded(event, addonName)
  57.   -- The event fires each time *any* addon loads - but we only care about when our own addon loads.
  58.   if addonName == BankService.name then
  59.     BankService:Initialize()
  60.   end
  61. end
  62.  
  63. -- Finally, we'll register our event handler function to be called when the proper event occurs.
  64. EVENT_MANAGER:RegisterForEvent(BankService.name, EVENT_ADD_ON_LOADED, BankService.OnAddOnLoaded)

Last edited by Motokosworld : 09/17/15 at 03:00 AM.
  Reply With Quote
09/17/15, 02:57 AM   #6
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 1,577
Originally Posted by Motokosworld View Post
The problem is, it work 1 time if i open the bank and then again if i open the bank again. SO i think the loop do not work, but why?
That's what you are doing with your code. You react to EVENT_OPEN_BANK which is fired once when the bank opens, so it only runs one time when you open the bank and again when you open the bank another time.
If you want it to run again while you are still at the bank you need to provide a different way to trigger the function.
  Reply With Quote
09/17/15, 08:23 AM   #7
Motokosworld
Join Date: Sep 2015
Posts: 6
But I wrote a loop around that all, why it do not go through the loop? Normaly a loop means go through it until you checked all values inside the loop...

Or do I only need to write the loop into another subfunction?

Last edited by Motokosworld : 09/17/15 at 08:36 AM.
  Reply With Quote
09/17/15, 08:57 AM   #8
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
Because items are not moved immediately, the actual transfer is done later, not from Lua code. GetNumBagFreeSlots, FindFirstEmptySlotInBag will keep returning the same value during the whole frame. We've had the exact same issue some time ago http://www.esoui.com/forums/showthre...EmptySlotInBag
  Reply With Quote
09/17/15, 09:58 AM   #9
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 1,577
Oh. I didn't know that. I have never used these functions myself to move items around but it sounds reasonable. I guess you could listen to EVENT_INVENTORY_SINGLE_SLOT_UPDATE and wait until the move happened before doing the next one.
Just make sure to only register to it when you start the movement process and unregister again afterwards, because there are already some performance problems with that event.
  Reply With Quote
09/17/15, 10:14 AM   #10
Motokosworld
Join Date: Sep 2015
Posts: 6
So if i understand it correctly you move the item in imaging and if all your addon on progresses are run through the moving task will be sent to server and then the server will do it?

A bit difficult to understand, but i think its some of the problems you have with addons, because its not real coding. But implementing in an already running progress.

Now i rewrote a lot of my code, but my game freeze. I looked through the link you gave me and made these changes because of that. But i guess ther is still something wrong. So i will post my code here and also will work later or tomorrow on it.

I know that i can still improve a lot on my code, but i want at first a really working programm after that i optimize it.

I use Notepad++ maybe you have another codeeditor where i an jump to functions? And test for code errors. ATM i only test at teso.

So i am happy for some hints where the problem is.

Lua Code:
  1. -- First, we create a namespace for our addon by declaring a top-level table that will hold everything else.
  2. BankService = {}
  3.  
  4. -- This isn't strictly necessary, but we'll use this string later when registering events.
  5. -- Better to define it in a single place rather than retyping the same string.
  6. BankService.name = "BankService"
  7.  
  8. -- if the bank is open start this
  9. function BankService.OnOpenBank()
  10.     BankService.moveMyItems()
  11. end
  12.  
  13. function BankService.moveMyItems()
  14.         -- find a free slot in bank
  15.     local emptyIndex = findEmptySlotInBag(BAG_BANK, nil, GetBagSize(BAG_BANK) - 1)
  16.         -- start at the first slot in my backpack
  17.     local slotInBag = 0
  18.  
  19.     ----check if emptyINdex is not nil and the slotInBag is still inside my Bag limit only then run the loop (again)
  20.     while emptyIndex ~= nil and slotinBag ~= GetBagSize(BAG_BACKPACK) do
  21.    
  22.         --check if the slot is not empty or the item is stolen
  23.         if GetItemType(bagId, slotIndex) ~= ITEMTYPE_NONE and IsItemStolen(BAG_BACKPACK, slotInBag) == false then  
  24.        
  25.             -- check if the itemtype is food
  26.             if GetItemType(BAG_BACKPACK, slotInBag) == ITEMTYPE_FOOD then
  27.                    
  28.                 -- read out the stackSize of that item
  29.                 local stackSize = GetSlotStackSize(BAG_BACKPACK, slotInBag)
  30.                    
  31.                 --use the protected function to move the item to the bank
  32.                 if IsProtectedFunction("RequestMoveItem") then
  33.                     CallSecureProtected("RequestMoveItem", BAG_BACKPACK, slotInBag, BAG_BANK, emptyIndex, stackSize)
  34.                 else
  35.                     RequestMoveItem(BAG_BACKPACK, slotInBag, BAG_BANK, emptyIndex, stackSize)
  36.                 -- close if checkProtectedFunction
  37.                 end
  38.                 -- we now used our empty space so start looking one slot after the used one for a new one
  39.                 emptyIndex = findEmptySlotInBag(BAG_BANK, emptyIndex+1, GetBagSize(BAG_BANK)-1)                    
  40.             -- close if checkItemtype
  41.             end
  42.         -- close if checkSpace and notEmpty
  43.         end
  44.         -- we checked the slot so move on to the next one
  45.         slotInBag = slotInBag+1    
  46.     --close loop           
  47.     end
  48.     -- Sort the bank
  49.     -- StackBag(BAG_BANK)
  50. --close function   
  51. end
  52.  
  53. function findEmptySlotInBag(bagId, prevIndex, lastIndex)
  54.     local slotIndex = prevIndex or -1
  55.     while slotIndex < lastIndex do
  56.         slotIndex = slotIndex + 1
  57.         if GetItemType(bagId, slotIndex) == ITEMTYPE_NONE then
  58.             return slotIndex
  59.         end
  60.     end
  61.     return nil
  62. end
  63.  
  64. ------------------------------------------------------------------------------------------------------------------------
  65. -- initialze function
  66. ------------------------------------------------------------------------------------------------------------------------
  67. function BankService:Initialize()
  68.     --Register our event
  69.     EVENT_MANAGER:RegisterForEvent(self.name,  EVENT_OPEN_BANK, self.OnOpenBank)       
  70. end
  71.  
  72.  
  73. -- Event handler function, check if the loaded addon is mine
  74. -- Initialize our addon after all of its resources are fully loaded.
  75. function BankService.OnAddOnLoaded(event, addonName)
  76.   -- The event fires each time *any* addon loads - but we only care about when our own addon loads.
  77.   if addonName == BankService.name then
  78.     BankService:Initialize()
  79.   end
  80. end
  81.  
  82. -- Finally, we'll register our event handler function to be called when the proper event occurs.
  83. EVENT_MANAGER:RegisterForEvent(BankService.name, EVENT_ADD_ON_LOADED, BankService.OnAddOnLoaded)

Last edited by Motokosworld : 09/17/15 at 10:33 AM.
  Reply With Quote
09/17/15, 10:58 AM   #11
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
Originally Posted by sirinsidiator View Post
Oh. I didn't know that. I have never used these functions myself to move items around but it sounds reasonable. I guess you could listen to EVENT_INVENTORY_SINGLE_SLOT_UPDATE and wait until the move happened before doing the next one.
Just make sure to only register to it when you start the movement process and unregister again afterwards, because there are already some performance problems with that event.
You can request multiple at once, but you need to find the next free slot yourself (i.e. remember where you already tried to put something).
  Reply With Quote
09/17/15, 11:21 AM   #12
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
You have a couple typos in that code.

slotinBag ~= GetBagSize(BAG_BACKPACK) -- always true => freeze

GetItemType(bagId, slotIndex) -- undefined vars

Also don't make the function findEmptySlotInBag global. Define it local before use, or place it in your namespace.
  Reply With Quote
09/17/15, 04:34 PM   #13
Motokosworld
Join Date: Sep 2015
Posts: 6
I do not now how to make the change you wrote.
if i write local in front of the function the other do not find it. I corrected the 2 wrong variables.


Now its working! THX!!!!!!!

my code look now like this:
Lua Code:
  1. -- First, we create a namespace for our addon by declaring a top-level table that will hold everything else.
  2. BankService = {}
  3.  
  4. -- This isn't strictly necessary, but we'll use this string later when registering events.
  5. -- Better to define it in a single place rather than retyping the same string.
  6. BankService.name = "BankService"
  7.  
  8. -- if the bank is open start this
  9. function BankService.OnOpenBank()
  10.     BankService.moveMyItems()
  11. end
  12.  
  13. function BankService.moveMyItems()
  14.     -- find a free slot in bank
  15.     local emptyIndex = findEmptySlotInBag(BAG_BANK, nil, GetBagSize(BAG_BANK) - 1)
  16.     -- start at the first slot in my backpack
  17.     local slotInBag = 1
  18.     --check if emptyINdex is not nil and the slotInBag is still inside my Bag limit only then run the loop (again)
  19.     while (emptyIndex ~= nil) and (slotInBag <= GetBagSize(BAG_BACKPACK)) do
  20.    
  21.         --check if the slot is not empty or the item is stolen
  22.         if GetItemType(bagId, slotInBag) ~= ITEMTYPE_NONE and IsItemStolen(BAG_BACKPACK, slotInBag) == false then  
  23.        
  24.             -- check if the itemtype is food
  25.             if GetItemType(BAG_BACKPACK, slotInBag) == ITEMTYPE_FOOD then
  26.                    
  27.                 -- read out the stackSize of that item
  28.                 local stackSize = GetSlotStackSize(BAG_BACKPACK, slotInBag)
  29.                    
  30.                 --use the protected function to move the item to the bank
  31.                 if IsProtectedFunction("RequestMoveItem") then
  32.                     CallSecureProtected("RequestMoveItem", BAG_BACKPACK, slotInBag, BAG_BANK, emptyIndex, stackSize)
  33.                 else
  34.                     RequestMoveItem(BAG_BACKPACK, slotInBag, BAG_BANK, emptyIndex, stackSize)
  35.                 -- close if checkProtectedFunction
  36.                 end
  37.                 -- we now used our empty space so start looking one slot after the used one for a new one
  38.                 emptyIndex = findEmptySlotInBag(BAG_BANK, emptyIndex+1, GetBagSize(BAG_BANK) - 1)                      
  39.             -- close if checkItemtype
  40.             end
  41.         -- close if checkSpace and notEmpty
  42.         end
  43.         -- we checked the slot so move on to the next one
  44.         slotInBag = slotInBag+1    
  45.     --close loop           
  46.     end
  47.     -- Sort the bank
  48.     -- StackBag(BAG_BANK)
  49. --close function   
  50. end
  51.  
  52. function findEmptySlotInBag(bagId, prevIndex, lastIndex)
  53.     local slotIndex = prevIndex or -1
  54.     while slotIndex < lastIndex do
  55.         slotIndex = slotIndex + 1
  56.         if GetItemType(bagId, slotIndex) == ITEMTYPE_NONE then
  57.             return slotIndex
  58.         end
  59.     end
  60.     return nil
  61. end
  62.  
  63. ------------------------------------------------------------------------------------------------------------------------
  64. -- initialze function
  65. ------------------------------------------------------------------------------------------------------------------------
  66. function BankService:Initialize()
  67.     --Register our event
  68.     EVENT_MANAGER:RegisterForEvent(self.name,  EVENT_OPEN_BANK, self.OnOpenBank)       
  69. end
  70.  
  71.  
  72. -- Event handler function, check if the loaded addon is mine
  73. -- Initialize our addon after all of its resources are fully loaded.
  74. function BankService.OnAddOnLoaded(event, addonName)
  75.   -- The event fires each time *any* addon loads - but we only care about when our own addon loads.
  76.   if addonName == BankService.name then
  77.     BankService:Initialize()
  78.   end
  79. end
  80.  
  81. -- Finally, we'll register our event handler function to be called when the proper event occurs.
  82. EVENT_MANAGER:RegisterForEvent(BankService.name, EVENT_ADD_ON_LOADED, BankService.OnAddOnLoaded)

Last edited by Motokosworld : 09/17/15 at 04:41 PM.
  Reply With Quote
09/17/15, 04:40 PM   #14
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
If it's local, it must be defined (lexically) before use, i.e. move the definition above BankService.moveMyItems. Or make it BankService.findEmptySlotInBag. Global namespace is shared among all ZOS and add-on code, it's best to put as few things in there as possible.

Btw you're skipping slots with findEmptySlotInBag(BAG_BANK, emptyIndex+1, ...); drop the +1, it's added in the function.

Last edited by merlight : 09/17/15 at 04:44 PM.
  Reply With Quote
09/18/15, 05:45 AM   #15
CrazyDutchGuy
 
CrazyDutchGuy's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 89
Or just take a peek in http://www.esoui.com/downloads/info4...nkStacker.html which does most of the stuff you want allready
  Reply With Quote

ESOUI » Developer Discussions » Lua/XML Help » move item from bag to bank

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off