Modding Help Take all - Transfer all items of chest to inventory

Discussion in 'Starbound Modding' started by Rexaton, Jul 14, 2019.

  1. Rexaton

    Rexaton Void-Bound Voyager

    Hi all,

    I'm new to this game (started a week ago) and already addicted. I'm one of the players who simply collects everything and so I faced something which is annoying: when looting a chest I'm mostly clicking on "Take all". But after that the empty chest stays open and I have to press ESC for closing it.
    In my opinion it makes sense to close the window, if it's empty after pressing the button. Therefore I decided to create a mod, because it's just a simple "pane.dismiss()" command. Next step would be to check if the chest is really empty (perhaps the inventory is full) but first things first.

    So far I have two files:
    1. interface\chests\chest64.config.patch (starting with one chest size first)
      Code:
      [
          {"op":"add","path":"/gui/clear/callback","value":"take_all_and_close"},
          {"op":"add","path":"/scriptWidgetCallbacks","value":["take_all_and_close"]},
          {"op":"add","path":"/scripts","value":["/scripts/take_all_and_close/take_all_and_close.lua"]}
      ]
      
    2. scripts\take_all_and_close\take_all_and_close.lua
      Code:
      function take_all_and_close()
          --takeAll()
          pane.dismiss()
      end
    The code works and closes the window, but of course the part with the "Take all" is missing. But I cannot find a hint in the original assets how this is done? I thought it would be a single function call, but I don't know which one?

    Can someone help me with that?

    Thank you and best regards!
     
    Last edited: Jul 15, 2019
  2. Rexaton

    Rexaton Void-Bound Voyager

    I made some progress but could still need some help. This is my LUA-script:

    Code:
    function take_all_and_close()
        local container = pane.containerEntityId()
        local containerItems = world.containerItems(container)
        for index,item in pairs(containerItems) do
            player.giveItem(item)
            -- check if giveItem was successful, if not: cancel at this point (without closing the window)
            -- ...
            world.containerConsume(container, item)
        end
        pane.dismiss()
    end
    Now I need a way to check if "player.giveItem(item)" was successful because the inventory could be full. Currently if the inventory is full, the items fall to the ground. I prefer the transfer gets stopped if the inventory is full and the window should stay open.

    The documentation says the function "player.giveItem" doesn't have a return value. Does anyone have an idea? Or another solution?

    Thanks!

    BTW: are "player.giveItem" and "world.containerConsume" the correct functions for my case? I haven't tested it with all types of items yet.
     
    Last edited: Jul 19, 2019
  3. chase000

    chase000 Intergalactic Tourist

    The brute force thing would be to count all the items in the player's inventory (with stacks counting as the number of items stacked), and see if it changes after each `giveItem` call. Can you do something like that?
     
  4. Rexaton

    Rexaton Void-Bound Voyager

    Thanks for your answer @chase000! I would be fine with doing it the complicated way but I can not find any lua function which returns me a number of all items of the players inventory at https://starbounder.org/Modding:Lua/Tables/Player. I don't know how to detect a full inventory before giving items to the player.

    There is only one lua function which could show me that the count of a specific item has changed:

    Code:
    unsigned player.hasCountOfItem(ItemDescriptor item, [bool exactMatch])
    So if its count increases after "player.giveItem(item)" this would tell me if the last operation was successful. But if not, there is already one item at the floor next to the player. So that's too late. I want to have the same "Take-All"-behavior if the inventory is full like without my mod.

    Any idea?

    PS: tried it and it looks like this now. But it drops one item to the floor if inventory is full. Or can I revert/remove the object from the ground and putting it back to the container?
    And I'm not sure if it works with money.

    Code:
    function take_all_and_close()
        local container = pane.containerEntityId()
        local containerItems = world.containerItems(container)
        local isInventoryFull = false
        for index,item in pairs(containerItems) do
            local countBefore = player.hasCountOfItem(item, true)
            player.giveItem(item)
            world.containerConsume(container, item)
            local countAfter = player.hasCountOfItem(item, true)
      
            if countBefore == countAfter then
                isInventoryFull = true
                break
            end
        end
        if not isInventoryFull then
            pane.dismiss()
        end
    end
     
    Last edited: Jul 20, 2019
  5. chase000

    chase000 Intergalactic Tourist

    By the way, doesn't `world.containerTakeAll()` do what you need? Alternatively, can you treat the player as a container and use `world.containerItemsCanFit()`?
     
  6. Rexaton

    Rexaton Void-Bound Voyager

    Thanks! Can you guide me how to "treat the player as container" for using "world.containerItemsCanFit"?
     
  7. chase000

    chase000 Intergalactic Tourist

    Sorry, no, I'm not that familiar with the scripting API.
     
  8. Rexaton

    Rexaton Void-Bound Voyager

    This unfortunately doesn't work as the function name suggests: it simply consumes/removes all items from the container, doesn't put anything in the players inventory and doesn't give me any result (always nil).
    Code:
    local container = pane.containerEntityId()
    local result = world.containerTakeAll(container)

    So can anyone show me how to work with "world.containerItemsCanFit" and the players inventory?
     
    Last edited: Jul 21, 2019

Share This Page