Signup Now
Page 1 of 2 12 LastLast
Results 1 to 10 of 20

Thread: Context Menu

  1. #1
    Moderator Raphael's Avatar
    Join Date
    Dec 2013
    Location
    raphseller.com
    Posts
    2,441
    Reputation
    309
    Rep Power
    28

    Context Menu

    Context Menu


    Description

    Adds an extra context menu with extra options, along with Tibia's default context menu. By default, adds option to add waypoints through the world window, open Tibia character's page and set relations, such as enemy/ally/leader. Also allows for moving/resizing waypoints and special areas when used in conjunction with Show Waypoints and Show Special Areas.


    Configuration

    Edit the showProfile, showRelation, showWaypoints variables on the init block to specify which options should be displayed. Also edit mainWaypoints and secondaryWaypoints to specify which types of waypoints should be displayed.

    Video




    Code

    This is included in WindBot. Check ContextMenu.lua, under HUDs tab.

    init start
    -- local SCRIPT_VERSION = '2.2.0'

    local showProfile = true
    local showRelation = true
    local showWaypoints = true
    local mainWaypoints = {'Node', 'Stand', 'Action', 'Lure'}
    local secondaryWaypoints = {'Walk', 'Shovel', 'Rope', 'Machete', 'Ladder', 'Use'}
    local showSpecialAreas = true
    local specialAreas = {'none', 'cavebot', 'targeting', 'cavebot & targeting'}

    -- DO NOT EDIT BELOW THIS LINE --

    local defFontColor = color(223, 223, 223)
    local defBackColor = color(70, 70, 70)
    local defHighColor = color(128, 128, 128)
    local boxColor = color(70, 70, 70)
    local boxLightShadowColor = color(117, 117, 117)
    local boxDarkShadowColor = color(41, 41, 41)

    local borderSize = 4
    local paddingSize = 3

    local PROFILE_URL = "http://www.tibia.com/community/?subtopic=characters&Submit.x=1&name="

    ALIGN_LEFT = 0
    ALIGN_CENTER = 1
    ALIGN_RIGHT = 2

    MENU_SEPARATOR = '-- SEPARATOR --'

    local items, highlight, contextMenu, maxWidth, maxHeight, clicked

    do -- Register default handlers
    if showProfile then
    local function showProfileName(m)
    return 'Show page for ' .. m.creature.name
    end

    local function showProfileCall(m)
    openbrowser(PROFILE_URL .. m.creature.name:gsub(' ', '+'))
    end

    registermessagehandler('contextMenu_player', showProfileName, showProfileCall)
    registermessagehandler('contextMenu_player', MENU_SEPARATOR, nil)
    end

    if showRelation then
    local function currentRelationName(m)
    if m.creature.id ~= $self.id then
    return m.creature.name .. ': ' .. m.creature.teamname, m.creature.teamcolor, nil, color(70, 70, 70)
    end
    end

    registermessagehandler('contextMenu_player', currentRelationName, nil)
    registermessagehandler('contextMenu_player', MENU_SEPARATOR, nil)

    -- enemy
    local function setEnemyName(m)
    if m.creature.id ~= $self.id and not m.creature.isenemy then
    return 'Set ' .. m.creature.name .. ' as enemy'
    end
    end

    local function setEnemyCall(m)
    setrelation(m.creature, 'enemy')
    end

    registermessagehandler('contextMenu_player', setEnemyName, setEnemyCall)

    -- ally
    local function setAllyName(m)
    if m.creature.id ~= $self.id and (not m.creature.isally or m.creature.isleader) then
    return 'Set ' .. m.creature.name .. ' as ally'
    end
    end

    local function setAllyCall(m)
    setrelation(m.creature, 'ally')
    end

    registermessagehandler('contextMenu_player', setAllyName, setAllyCall)

    -- leader
    local function setLeaderName(m)
    if m.creature.id ~= $self.id and not m.creature.isleader then
    return 'Set ' .. m.creature.name .. ' as leader'
    end
    end

    local function setLeaderCall(m)
    setrelation(m.creature, 'leader')
    end

    registermessagehandler('contextMenu_player', setLeaderName, setLeaderCall)
    registermessagehandler('contextMenu_player', MENU_SEPARATOR, nil)
    end

    if showWaypoints then
    for _, v in ipairs({mainWaypoints, secondaryWaypoints}) do
    for _, vv in ipairs(v) do
    -- I learned this trick with JavaScript; basically, we call a anonymous
    -- function that returns the function we'll actually use. The trick is
    -- that we pass to this first anonymous function the type of the node
    -- we want the returned function to add. This works because the inner
    -- function is created in a scope where `type` has the desired value,
    -- so it's value is retained for future calls.
    registermessagehandler('contextMenu_world', 'Add ' .. vv, (function(type)
    return function(m)
    addwaypoint(type, m.posx, m.posy, m.posz)
    end
    end)(vv))
    end

    registermessagehandler('contextMenu_world', MENU_SEPARATOR, nil)
    end
    end

    if showSpecialAreas then
    for _, v in ipairs(specialAreas) do
    registermessagehandler('contextMenu_world', 'Add Special Area (' .. v:capitalizeall() .. ')', (function(type)
    return function(m)
    addspecialarea(type, m.posx, m.posy, m.posz)
    end
    end)(v))
    end

    registermessagehandler('contextMenu_world', MENU_SEPARATOR, nil)
    end
    end

    local function loadCategories(...)
    local categories = {...}

    for _, v in ipairs(categories) do
    local cat = 'contextMenu_' .. v
    foreach messagehandler m cat do
    local text, fontColor, backColor, highColor, align

    if type(m.name) == 'function' then
    text, fontColor, highColor, backColor, align = m.name(contextMenu)
    else
    text = m.name
    end

    if text and text ~= '' then
    local width
    if text == MENU_SEPARATOR then
    maxHeight = maxHeight + 8
    else
    width = (measurestring(text))

    maxHeight = maxHeight + 19
    maxWidth = math.max(maxWidth, width)
    end

    table.insert(items, {
    text = text,
    width = width,
    callback = m.callback,
    fontColor = fontColor or defFontColor,
    highColor = highColor or defHighColor,
    backColor = backColor or defBackColor
    });
    end
    end
    end
    end

    filterinput(false, true, true, false)
    function inputevents(e)
    local eventItem, itemIndex
    for i, v in ipairs(items) do
    if v.id == e.elementid then
    eventItem = v
    itemIndex = i
    break
    end
    end


    highlight = itemIndex
    if e.type == IEVENT_LMOUSEUP then
    if eventItem and eventItem.callback then
    eventItem.callback(contextMenu)
    end

    clicked = true
    highlight = nil
    waitforevents(false)
    press('[ESC]')
    waitforevents(true)
    end
    end

    setfontstyle('Tahoma', 7, 75, defFontColor, 1, 0x000000)
    setantialiasing(true)
    init end

    auto(10)

    contextMenu = contextmenuinfo()

    -- This prevents the HUD from redrawing after clicking
    if clicked then
    clicked = contextMenu ~= nil
    contextMenu = nil
    end

    if contextMenu == nil then
    highlight = nil
    return
    end

    items = {}
    maxWidth, maxHeight = 0, -4
    local fullWidth, fullHeight
    do -- Bootstrap

    -- Load categories
    if contextMenu.type == 'battle' or contextMenu.itemid == 99 then
    contextMenu.creature = getcreaturebyid(contextMenu.creatureid)

    if contextMenu.creature.isplayer then
    loadCategories(contextMenu.type .. 'Player', 'player')
    elseif contextMenu.creature.isnpc then
    loadCategories(contextMenu.type .. 'NPC', 'NPC')
    elseif contextMenu.creature.ismonster then
    loadCategories(contextMenu.type .. 'Monster', 'monster')
    end

    loadCategories(contextMenu.type .. 'Creature', 'creature')
    end

    if contextMenu.type == 'world' then
    if not contextMenu.creature then
    loadCategories('worldItem', 'item')
    end

    if contextMenu.posz == $posz then

    do
    local i = 0
    foreach settingsentry e 'Cavebot/Waypoints' do
    local x, y, z = get(e, 'Coordinates'):match(REGEX_COORDS)
    x, y, z = tonumber(x), tonumber(y), tonumber(z)

    if z == $posz then
    local diffX, diffY = contextMenu.posx - x, contextMenu.posy - y

    if diffX >= 0 and diffY >= 0 then
    local w, h = get(e, 'Range'):match(REGEX_RANGE)
    w, h = tonumber(w), tonumber(h)

    if diffX < w and diffY < h then
    contextMenu.waypoint = e
    contextMenu.waypointID = i
    end
    end
    end

    i = i + 1
    end

    if contextMenu.waypoint then
    loadCategories('worldWaypoint', 'waypoint')
    end
    end

    do
    foreach settingsentry e 'Cavebot/SpecialAreas' do
    local x, y, z = get(e, 'Coordinates'):match(REGEX_COORDS)
    x, y, z = tonumber(x), tonumber(y), tonumber(z)

    if z == $posz then
    local diffX, diffY = contextMenu.posx - x, contextMenu.posy - y

    if diffX >= 0 and diffY >= 0 then
    local w, h = get(e, 'Size'):match(REGEX_RANGE)
    w, h = tonumber(w), tonumber(h)

    if diffX < w and diffY < h then
    contextMenu.specialArea = e
    contextMenu.specialAreaName = get(e, 'Name')
    end
    end
    end
    end

    if contextMenu.specialArea then
    loadCategories('worldSpecialArea', 'specialArea')
    end
    end
    end
    elseif contextMenu.type == 'container' then
    loadCategories('containerItem', 'item')
    elseif contextMenu.type == 'equip' then
    loadCategories('equipItem', 'item')
    end
    loadCategories(contextMenu.type)

    -- We set it as true from the beginning so that it also removes the first
    -- item if it's a separator; we obviously don't want the first item to be a
    -- separator. NOTE: relies on the fact that ipairs() will traverse the
    -- table in ascending order, which isn't guaranteed by the reference manual
    -- but is the common implementation
    local lastSep = true

    -- Instead of removing the items at the for loop, we simply set it to nil
    -- and normalize it after; this is because if we did remove it, it would
    -- shift the indexes and end up fucking up posterior checks
    for i, v in ipairs(items) do
    local curSep = v.text == MENU_SEPARATOR
    if curSep and (lastSep or i == #items) then
    items[i] = nil
    maxHeight = maxHeight - 8
    end

    lastSep = curSep
    end
    table.normalize(items)

    -- No item to display, abort mission!
    if #items == 0 then
    return
    end

    -- The Tibia context menu has an extra width of 44 pixels for the longest
    -- item; here we account for that
    maxWidth = maxWidth + 44

    fullWidth, fullHeight = maxWidth + 2*borderSize, maxHeight + 2*borderSize
    setposition($clientwin.x + contextMenu.x - fullWidth - 2,$clientwin.y + contextMenu.y)
    end

    do -- Draw Container
    -- Draw main box
    setfillstyle('color', boxColor)
    setbordercolor(-1)
    drawrect(0, 0, fullWidth, fullHeight)

    -- Draw shadows
    setbordercolor(boxLightShadowColor)
    drawline(0, 0, fullWidth, 0)
    drawline(0, 0, 0, fullHeight)
    drawline(2, fullHeight - 2, fullWidth - borderSize, 0)
    drawline(fullWidth - 2, 2, 0, fullHeight - borderSize)

    setbordercolor(boxDarkShadowColor)
    drawline(2, 2, fullWidth - borderSize, 0)
    drawline(2, 2, 0, fullHeight - borderSize)
    drawline(0, fullHeight, fullWidth, 0)
    drawline(fullWidth, 0, 0, fullHeight)
    end

    do -- Draw items
    local curHeight = borderSize
    for i, v in ipairs(items) do
    -- Separators get special treatment here
    if v.text == MENU_SEPARATOR then
    setbordercolor(boxDarkShadowColor)
    drawline(borderSize, curHeight, maxWidth, 0)

    setbordercolor(boxLightShadowColor)
    drawline(borderSize, curHeight + 1, maxWidth, 0)

    curHeight = curHeight + 8
    else

    -- This is a dirty, dirrty attempt of making the code shorter; and
    -- that's what I love the most about programming
    local alignOffset = ((maxWidth - paddingSize - v.width) / 2) * (v.align or ALIGN_LEFT)

    -- Set style
    setbordercolor(-1)
    setfontcolor(v.fontColor)
    setfillstyle('color', tern(i == highlight, v.highColor, v.backColor))

    -- Draw stuff
    v.id = drawrect(borderSize, curHeight, maxWidth, 15)
    drawtext(v.text, borderSize + paddingSize + alignOffset, curHeight + paddingSize)

    curHeight = curHeight + 19
    end
    end
    end

    Git
    Last edited by Raphael; 06-25-2014 at 08:40 PM.

  2. #2
    Moderator mistgun's Avatar
    Join Date
    Dec 2013
    Location
    Lodz, Poland
    Posts
    1,821
    Reputation
    220
    Rep Power
    26
    Acha, acha I like it ! Amazing Joooob !

  3. #3
    Moderator SuNe's Avatar
    Join Date
    Dec 2013
    Location
    Sweden
    Posts
    2,880
    Reputation
    186
    Rep Power
    27
    That is just pure awesome

  4. #4
    Moderator Leonardo's Avatar
    Join Date
    Dec 2013
    Location
    Brazil
    Posts
    758
    Reputation
    77
    Rep Power
    22
    This and Spy Level are prolly the best HUD's around, meeh good job.

  5. #5
    Banned
    Join Date
    Dec 2013
    Location
    Poland
    Posts
    242
    Reputation
    14
    Rep Power
    0
    Nice

  6. #6
    Free User pradenho's Avatar
    Join Date
    Dec 2013
    Location
    Brazil
    Posts
    210
    Reputation
    23
    Rep Power
    21
    Amazing!

  7. #7
    Wind Tester
    Join Date
    Dec 2013
    Location
    Warsaw, Poland
    Posts
    2,579
    Reputation
    149
    Rep Power
    27
    Everytime i see new huds/actions from you, i think its best what could be done... but then you are making something better! Great work i love it

  8. #8
    Wind Powered
    Join Date
    Dec 2013
    Location
    dvscripts.com
    Posts
    7,105
    Reputation
    433
    Rep Power
    39
    Awesome !!!!! But in future will be option to add South West etc?
    Regards
    Thanks a lot !
    Last edited by Dworak; 02-06-2014 at 06:58 AM.

  9. #9
    Moderator Raphael's Avatar
    Join Date
    Dec 2013
    Location
    raphseller.com
    Posts
    2,441
    Reputation
    309
    Rep Power
    28
    Quote Originally Posted by Dworak View Post
    Awesome !!!!! But in future will be option to add South West etc?
    Regards
    Thanks a lot !
    Why don't you just click where you want it to be added?

  10. #10
    Moderator Raphael's Avatar
    Join Date
    Dec 2013
    Location
    raphseller.com
    Posts
    2,441
    Reputation
    309
    Rep Power
    28
    Script Updated!

    Removed some testing stuff.

 

 

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •