• You've discovered RedGuides, an EverQuest multi-boxing and scripting community 🧙‍♀️⚙️. We want you to play several EQ characters at once, come join us and say hello! 👋

  • A TLP without truebox has thawed (Very Vanilla ready)
    Frostreaver

Lua - How to use /SelectItem for exact matches

Joined
Jun 29, 2020
RedCents
216¢
I would like to have a Lua script sell some specific items for me. Going through the documentation on https://www.redguides.com/docs/projects/macroquest/reference/data-types/datatype-merchant/ and more specifically https://www.redguides.com/docs/projects/macroquest/reference/commands/selectitem/, I am using the following method to select an item from the players inventory to sell:

[CODE lang="Lua" title="SelectItem Usage"]mq.cmd('/selectitem "=Vinegar"');[/CODE]

based on the documentation in the Command wiki:
Selects items in your inventory when you have a merchant open. Partial match accepted, /selectitem "bottle of" will select a "bottle of vinegar". Exact match also accepted, /selectitem "=bottle of vinegar".

But I get the Following message in the MQ console:

/selectitem Could NOT find =Vinegar in your inventory to select.
Use /invoke ${Merchant.SelectItem[=Vinegar]} if you want to select an item in the merchants inventory.

it does work without the '=' in the argument, but that does a partial match and is sometimes selecting the wrong item if it happens to contain the full name of another item. I.E 'Banded Mail' and 'Large Banded Mail'.

Is there another way to accomplish selecting an item from the player's inventory by an exact match to sell to a merchant? Or is there something I am not doing correctly in Lua? Here is a screenshot of my inventory with the Vinegar item while the script is running and giving me the error above:

inventory.png
 
Lua:
local function pack_open(i)
    if mq.TLO.Me.Inventory(i).Open() == 1 then
        return true
    end
    return false
end

local function get_pack_name(i)
    local pack = {
        [23] = 'pack1',
        [24] = 'pack2',
        [25] = 'pack3',
        [26] = 'pack4',
        [27] = 'pack5',
        [28] = 'pack6',
        [29] = 'pack7',
        [30] = 'pack8',
        [31] = 'pack9',
        [32] = 'pack10',
        [33] = 'pack11',
        [34] = 'pack12'
    }
    return pack[i]
end

local function select_first_item_in_pack(name)
        local found_inv_top  = mq.TLO.FindItem('=' .. name).ItemSlot()
        local found_inv_slot = mq.TLO.FindItem('=' .. name).ItemSlot2() + 1

        if not pack_open(found_inv_top) then
            mq.cmdf('/itemnotify %s rightmouseup', found_inv_top)
            while not pack_open(found_inv_top) do
                mq.delay(100)
            end
        end
        mq.cmdf('/itemnotify in %s %s leftmouseup', get_pack_name(found_inv_top), found_inv_slot)
end
Is how I did it. You also need to make sure the pack is open first before you try to item notify.

You'll need to modify it so you can use it to find multiple things I'd guess but that's the basic idea for selecting an item in your inventory.

Edited: Edited the code. Something like that maybe? Completely untested for syntax/errors, but call it like select_first_item_in_pack('vinegar')

PS) There's no error checking in that at all. You'll need to add that or you'll run into crashes/errors.
 
Last edited:
Thanks! Modified it so it worked with items in the top level inventory as well as bags, and it works perfectly.
Lol I'm modifying it to do just that and releasing my own utils script for people to include right now lol I've got a bunch of stuff like that I've copied pasted to a bunch of my scripts and modified over and over.
 
This is what it looks like with all the error checking added.

Lua:
local function report_error(s, ...)
    print('Utils: ' .. string.format(s, ...))
end
local function pack_open(i)
    if mq.TLO.Me.Inventory(i).Open() == 1 then
        return true
    end
    return false
end
local function get_pack_name(i)
    local pack = {
        [23] = 'pack1',
        [24] = 'pack2',
        [25] = 'pack3',
        [26] = 'pack4',
        [27] = 'pack5',
        [28] = 'pack6',
        [29] = 'pack7',
        [30] = 'pack8',
        [31] = 'pack9',
        [32] = 'pack10',
        [33] = 'pack11',
        [34] = 'pack12'
    }
    return pack[i]
end
local function top_slot_is_pack(i)
    if i > 22 and i < 35 then
        local container = mq.TLO.Me.Inventory(i).Container()
        if container ~= nil and container > 0 then
            return true
        end
    end
    return false
end
local function select_first_item_in_inventory(name)
    local found_inv_top  = mq.TLO.FindItem('=' .. name).ItemSlot()
    local found_inv_slot = mq.TLO.FindItem('=' .. name).ItemSlot2() + 1
    if found_inv_top ~= nil then
        if top_slot_is_pack(found_inv_top) then
            if not pack_open(found_inv_top) then
                mq.cmdf('/itemnotify %s rightmouseup', found_inv_top)
                while not pack_open(found_inv_top) do
                    mq.delay(100)
                end
            end
            mq.cmdf('/itemnotify in %s %s leftmouseup', get_pack_name(found_inv_top), found_inv_slot)
        else
            mq.cmdf('/itemnotify %s leftmouseup', found_inv_top)
        end
    else
        report_error('Item Not Found (%s)', name)
    end
end
Bout to test it in my fishing macro right now. Gonna drastically cut the size of some of my macros removing reused code.
 
I am doing something similar where I am writing a lot of these functions in a way that they can be in their own file to be used in other scripts I write. Ill eventually move them out and then have a build process to merge and minify the script. Makes it a lot easier to unit test each piece before I use it. I am currently using Luamin to do the minification and obstification. This is my first time using Lua so I'm trying to learn as I go.

Out of curiosity, what IDE do you use? I have been just using notepad++, but I think I am going to switch to IntelliJ, so I can get resharper and copilot working. Is there any Lua IDE that you found was pretty good? I manly default to using Jetbrains products, because I already use Rider, CLion, PyCharm, and WebStorm for work.
 
I am doing something similar where I am writing a lot of these functions in a way that they can be in their own file to be used in other scripts I write. Ill eventually move them out and then have a build process to merge and minify the script. Makes it a lot easier to unit test each piece before I use it. I am currently using Luamin to do the minification and obstification. This is my first time using lua so I'm trying to learn as I go.

Out of curiosity, what IDE do you use? I have been just using notepad++, but I think I am going to switch to IntelliJ, so I can get resharper and copilot working. Is there any lua IDE that you found was pretty good? I manly default to using Jetbrains products, because I already use Rider, CLion, PyCharm, and WebStorm for work.
Minifying seems a bit overkill. Considering it's compiled at run time, most of that stuff is removed automatically. All it technically helps with is download size when being updated through pacman or something. Considering we aren't handling files that are gigs in size I don't really see a huge benefit to it. Owning a web hosting company myself I do understand the habit though.

I've been using VSCode.
 
Yeah that makes since My source file has a lot of doc comments in it to get intellisense in the IDE for example
Lua:
------------------------------------------------
-- Halts the script while waiting for the action to return true, or until the timeout period is reached
-- @param action A boolean expression to wait for.  If no action is passed then a default constant expression of false is used.
-- @param timeout The amount of milliseconds to wait for the action to return true.  If no value is passed, then a default value of 5000 is used.
-- @return True, if the action returned true.  Otherwise false if the action never returned true, and the timeout period was reached.
------------------------------------------------
local function waitForAction(action, timeout)
    action = action or function()
        return false;
    end
    
    timeout = timeout or 5000;
    
    local currentTime = 0;
    local pollTime = 100;
    repeat
        wait(pollTime);
        currentTime = currentTime+pollTime;
    until (action() or currentTime > timeout);
    return action();
end

So I'm able to reduce my current size of 28,239 bytes to 11,640 bytes. I would say probably tripping over dollars to save pennies, but it is all built-in so it doesn't take any effort to do
 
The "Could not find =Vinegar" in the output is just a display error in the output, it is actually searching for Vinegar and not =Vinegar.
 
This is what it looks like with all the error checking added.

Lua:
local function report_error(s, ...)
    print('Utils: ' .. string.format(s, ...))
end
local function pack_open(i)
    if mq.TLO.Me.Inventory(i).Open() == 1 then
        return true
    end
    return false
end
local function get_pack_name(i)
    local pack = {
        [23] = 'pack1',
        [24] = 'pack2',
        [25] = 'pack3',
        [26] = 'pack4',
        [27] = 'pack5',
        [28] = 'pack6',
        [29] = 'pack7',
        [30] = 'pack8',
        [31] = 'pack9',
        [32] = 'pack10',
        [33] = 'pack11',
        [34] = 'pack12'
    }
    return pack[i]
end
local function top_slot_is_pack(i)
    if i > 22 and i < 35 then
        local container = mq.TLO.Me.Inventory(i).Container()
        if container ~= nil and container > 0 then
            return true
        end
    end
    return false
end
local function select_first_item_in_inventory(name)
    local found_inv_top  = mq.TLO.FindItem('=' .. name).ItemSlot()
    local found_inv_slot = mq.TLO.FindItem('=' .. name).ItemSlot2() + 1
    if found_inv_top ~= nil then
        if top_slot_is_pack(found_inv_top) then
            if not pack_open(found_inv_top) then
                mq.cmdf('/itemnotify %s rightmouseup', found_inv_top)
                while not pack_open(found_inv_top) do
                    mq.delay(100)
                end
            end
            mq.cmdf('/itemnotify in %s %s leftmouseup', get_pack_name(found_inv_top), found_inv_slot)
        else
            mq.cmdf('/itemnotify %s leftmouseup', found_inv_top)
        end
    else
        report_error('Item Not Found (%s)', name)
    end
end
Bout to test it in my fishing macro right now. Gonna drastically cut the size of some of my macros removing reused code.
How does this work if you want to sell an item in inventory but you have the same item equipped? Without selling your equipped item? Provided the item is sellable. One is equipped and one is in my bags. Seems to be reading the location of the same one twice instead of the one in my bag.

this is a print of
print(gear_id)
print(gear_name)
print(inv_top)
print(inv_slot)
 

Attachments

  • Untitled.jpg
    Untitled.jpg
    23.1 KB · Views: 1
How does this work if you want to sell an item in inventory but you have the same item equipped? Without selling your equipped item? Provided the item is sellable. One is equipped and one is in my bags. Seems to be reading the location of the same one twice instead of the one in my bag.

this is a print of
print(gear_id)
print(gear_name)
print(inv_top)
print(inv_slot)
I mean mine only searches for items in top level inventory slots. It drops anything that doesn't fit into a certain range of ItemSlot numbers. I think its 23-34 or something if I remember right off the top of my head
 
Lua - How to use /SelectItem for exact matches

Users who are viewing this thread

Back
Top
Cart