Plugin to provide a bar of "action icons"

Posted by Nick Gammon on Wed 25 Feb 2009 10:44 PM — 30 posts, 140,180 views.

Australia Forum Administrator #0
The plugin below uses miniwindows to implement "action icons" (see screenshot in the next post).

[EDIT] For a newer version that also shows cooldown times, see http://www.gammon.com.au/forum/?id=9359

What this lets you do is have a configurable (by editing the plugin) bar of icons, which can be dragged around to anywhere in your output window.

Each button has an image on it which is loaded from a BMP or PNG file. If you click on a button, then the associated action is performed. You can do either or both of:

  • Execute a command (this is sent to the command processor in MUSHclient). The default is, that the command would be sent to the MUD, unless it matches an alias. Variables in the form @name are expanded, so you can do things like: kick @target
  • Execute a script function. This lets you do fancier things like doing something if your health is low, and something else if it is high.


The icon size is configurable (see ICON_SIZE below). I chose 32 x 32 as that gives a reasonable icon. The image files you specify are shrunk or expanded to that 32 x 32 box, so the best results would occur if your images are the same size as ICON_SIZE.

The bar automatically resizes to fit as many buttons as you specify.

You configure the plugin by editing (and adding to) the buttons table below (the part in bold). Hopefully it is reasonably self-explanatory. The icon files default to being in the same directory as the MUSHclient executable.

If you want to change that, change the line below:


if WindowLoadImage (win, n, GetInfo (66) .. v.icon) ~= error_code.eOK then


to something that suits you. For example, make it just:


if WindowLoadImage (win, n, v.icon) ~= error_code.eOK then


If you do that, then you have to specify the full pathname for each image file.

Or, you could put the icons in a sub-directory, like this:


if WindowLoadImage (win, n, GetInfo (66) .. "icons\\" .. v.icon) ~= error_code.eOK then


You drag the button bar around by mousing down in the gaps between the icons (or at the edge of the window) in such a way that you aren't clicking on an icon itself. Then the window can be moved around.

Below is the plugin.

Save between the lines as Icon_Bar.xml and use File menu -> Plugins to load that file as a plugin.

[EDIT] Newer version released below (further down this thread) on 29th March 2009. See. http://www.gammon.com.au/forum/?id=9280&reply=8#reply8


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE muclient>

<muclient>
<plugin
   name="Icon_Bar"
   author="Nick Gammon"
   id="ede0920fc1173d5a03140f0e"
   language="Lua"
   purpose="Shows a bar of buttons you can click on to do things"
   date_written="2009-02-26 09:00"
   requires="4.40"
   save_state="y"
   version="1.0"
   >
   
<description trim="y">
<![CDATA[
Install this plugin to show an button bar.

Click on an icon to execute a script or send a command to the MUD.

]]>
</description>

</plugin>

<!--  Script  -->

<script>
<![CDATA[

-- table of buttons

--[[
  Each button can have up to four entries:
  
  icon - filename of the image to draw
  tooltip - what to show if you hover the mouse over the button
  send - what to send to the MUD
  script - a script function to call

--]]
  

buttons = {

  -- button 1
  {
  icon = "HealIcon.png",
  tooltip = "Heal self",
  send = "cast 'lesser heal' self",
  },
  
  -- button 2
  {
  icon = "SwordIcon.png",
  tooltip = "Attack",
  send = "kill @target",
  },
  
  -- button 3
 {
  icon = "SparkIcon2.png",
  tooltip = "Cast Fireball",
  send = "cast fireball",
  script = function () 
            ColourNote ('white', 'green', 'script test') 
            end,
  },
  
  
 --> add more buttons here
 
  
} -- end of buttons table


-- configuration

ICON_SIZE = 32

BACKGROUND_COLOUR = ColourNameToRGB "bisque"
BOX_COLOUR = ColourNameToRGB "royalblue"
BUTTON_EDGE = ColourNameToRGB "silver"

MOUSE_DOWN_COLOUR = ColourNameToRGB "darkorange"

FONT_NAME = "Fixedsys"
FONT_SIZE = 9

-- where to put the window
WINDOW_POSITION = 6  -- top right
OFFSET = 6  -- gap inside box
EDGE_WIDTH = 2 -- size of border stroke

--[[
Useful positions:

4 = top left
5 = center left-right at top
6 = top right
7 = on right, center top-bottom
8 = on right, at bottom
9 = center left-right at bottom
--]]

function mousedown (flags, hotspot_id)

  if hotspot_id == "box" then
  
    -- find where mouse is so we can adjust window relative to mouse
    startx, starty = WindowInfo (win, 14), WindowInfo (win, 15)
    
    -- find where window is in case we drag it offscreen
    origx, origy = WindowInfo (win, 10), WindowInfo (win, 11)
  
    return
  end -- if the box, not a button
    
   -- convert id to a number, for table lookup
  local n = tonumber (hotspot_id)
  
  -- draw the button border in another colour for visual feedback
  WindowRectOp (win, 1, 
                frames [n].x1, frames [n].y1, frames [n].x2, frames [n].y2, 
                MOUSE_DOWN_COLOUR) 
  
  Redraw ()                
end -- mousedown

function cancelmousedown (flags, hotspot_id)
  local n = tonumber (hotspot_id)
  
  -- draw the button border in original colour for visual feedback
  WindowRectOp (win, 1, 
                frames [n].x1, frames [n].y1, frames [n].x2, frames [n].y2, 
                BUTTON_EDGE) 
  Redraw ()                

end -- cancelmousedown

function mouseup (flags, hotspot_id)
    
  -- fix border colour
  cancelmousedown (flags, hotspot_id)
  
  local n = tonumber (hotspot_id)
  
  local button = buttons [n]
  
  -- send to world if something specified
  if type (button.send) == "string" and 
    button.send ~= "" then
     
    local errors =  {} -- no errors yet
  
    -- function to do the replacements for string.gsub
    
    local function replace_variables (s)
      s = string.sub (s, 2)  -- remove the @
      replacement = GetPluginVariable ("", s)    -- look up variable in global variables
      if not replacement then  -- not there, add to errors list
        table.insert (errors, s)
        return
      end -- not there
      return replacement  -- return variable
    end -- replace_variables 
    
    -- replace all variables starting with @
    
    local command = string.gsub (button.send, "@%a[%w_]*", replace_variables)
    
    -- report any errors
    
    if #errors > 0 then
      for k, v in ipairs (errors) do
        ColourNote ("white", "red", "Variable '" .. v .. "' does not exist")
      end -- for
      return
    end -- error in replacing
     
    Execute (command)
  end -- if
  
  -- execute script if wanted
  if type (button.script) == "function" then
    button.script (n) 
  end -- if
     
end -- mouseup

function dragmove(flags, hotspot_id)

  -- find where it is now
  local posx, posy = WindowInfo (win, 17),
                     WindowInfo (win, 18)

  -- move the window to the new location
  WindowPosition(win, posx - startx, posy - starty, 0, 2);
  
  -- change the mouse cursor shape appropriately
  if posx < 0 or posx > GetInfo (281) or
     posy < 0 or posy > GetInfo (280) then
    check (SetCursor ( 11))   -- X cursor
  else
    check (SetCursor ( 1))   -- hand cursor
  end -- if
  
end -- dragmove

function dragrelease(flags, hotspot_id)
  local newx, newy = WindowInfo (win, 17), WindowInfo (win, 18)
  
  -- don't let them drag it out of view
  if newx < 0 or newx > GetInfo (281) or
     newy < 0 or newy > GetInfo (280) then
     -- put it back
    WindowPosition(win, origx, origy, 0, 2);
  end -- if out of bounds
  
end -- dragrelease

frames = {}

function OnPluginInstall ()

  local x, y, mode, flags = 
      tonumber (GetVariable ("windowx")) or 0,
      tonumber (GetVariable ("windowy")) or 0,
      tonumber (GetVariable ("windowmode")) or WINDOW_POSITION, -- top right
      tonumber (GetVariable ("windowflags")) or 0
  
  win = GetPluginID ()  -- get a unique name
  
  -- make the miniwindow
  WindowCreate (win, 
             x, y,   -- left, top (auto-positions)
             (#buttons * (ICON_SIZE + OFFSET)) + OFFSET,     -- width
             ICON_SIZE + (OFFSET * 2),  -- height
             mode,   -- position mode
             flags,  -- flags
             BACKGROUND_COLOUR) 
                
  -- draw the buttons
  
  for n, v in ipairs (buttons) do

    if v.icon then
      if WindowLoadImage (win, n, GetInfo (66) .. v.icon) ~= error_code.eOK then
          ColourNote ("white", "red", "Could not load image '" .. GetInfo (66) .. v.icon .. "'")
      end -- if
    end -- if icon specified
         
    -- where to draw the icon
    local x1, y1 = (n - 1) * (ICON_SIZE + OFFSET) + OFFSET, OFFSET
    local x2, y2 = n * (ICON_SIZE + OFFSET) + OFFSET, ICON_SIZE + OFFSET
    
    -- draw the image
    WindowDrawImage(win, n, 
                    x1, y1,   -- left, top
                    x2 - OFFSET, y2,  -- right, bottom
                    2)  -- mode - stretch or shrink

    -- remember where to draw the frame, for mouse clicks
    frames [n] = { 
            x1 = x1 - 1,
            y1 = y1 - 1,
            x2 = x2 - OFFSET + 1,
            y2 = y2 + 1
            }
    
    -- draw the button border
    WindowRectOp (win, 1, 
                  frames [n].x1, frames [n].y1, frames [n].x2, frames [n].y2, 
                  BUTTON_EDGE) 
    
    -- make a hotspot we can click on
    WindowAddHotspot(win, n,  
                 x1 - 1, y1 - 1, x2 - OFFSET + 1, y2 + 1,   -- rectangle
                 "",   -- mouseover
                 "",   -- cancelmouseover
                 "mousedown",
                 "cancelmousedown", 
                 "mouseup", 
                 v.tooltip,  -- tooltip text
                 1, 0)  -- hand cursor
                      
  end --  for each button
  

  -- draw the border of the whole box
  WindowCircleOp (win, 2, 0, 0, 0, 0, BOX_COLOUR, 6, EDGE_WIDTH, 0x000000, 1) 
    
  -- make a hotspot
  WindowAddHotspot(win, "box",  
                   0, 0, 0, 0,   -- whole window
                   "",   -- MouseOver
                   "",   -- CancelMouseOver
                   "mousedown",
                   "",   -- CancelMouseDown
                   "",   -- MouseUp
                   "Drag to move",  -- tooltip text
                   1, 0)  -- hand cursor
                   
  WindowDragHandler(win, "box", "dragmove", "dragrelease", 0) 
  
  if GetVariable ("enabled") == "false" then
    ColourNote ("yellow", "", "Warning: Plugin " .. GetPluginName ().. " is currently disabled.")
    check (EnablePlugin(GetPluginID (), false))
    return
  end -- they didn't enable us last time
 
  -- ensure window visible
  WindowShow (win, true)
    
end -- OnPluginInstall

-- hide window on removal
function OnPluginClose ()
  WindowShow (win,  false)  -- hide it
end -- OnPluginClose

-- show window on enable
function OnPluginEnable ()
  WindowShow (win,  true)  -- show it
end -- OnPluginEnable

-- hide window on disable
function OnPluginDisable ()
  WindowShow (win,  false)  -- hide it
end -- OnPluginDisable

function OnPluginSaveState ()
  SetVariable ("enabled", tostring (GetPluginInfo (GetPluginID (), 17)))
  SetVariable ("windowx", tostring (WindowInfo (win, 10)))
  SetVariable ("windowy", tostring (WindowInfo (win, 11)))
  SetVariable ("windowmode", tostring (WindowInfo (win, 7)))
  SetVariable ("windowflags", tostring (WindowInfo (win, 8)))
end -- OnPluginSaveState

]]>
</script>

</muclient>
Amended on Tue 12 Dec 2017 03:28 AM by Nick Gammon
Australia Forum Administrator #1

Example of it in operation:

USA #2
HOLY COW! I never thought I'd see the day when this would be implemented in the client itself, this is probably the one thing that will bring me back to playing again. I, when I started mudding used zMud, and absolutely LOVED the buttons for doing things, including the tri-state buttons, and toggle buttons, but using that plugin I see those being easily done in just a few lines. I ultimately chose MUSHclient due to its customization abilities and scripting for several "standardized" languages, unlike zMud that has a language all its own.

Now to make toggleable buttons need to implement a dual-icon option, or even a triple one, and have it redraw whenever an icon is pushed to show its new status. As well as add an externally callable function to toggle the state of a button.

I cant wait to add things to it when I do get time to get back into mudding.

-Onoitsu2
#3
I noticed in the code the following line...

requires="4.40"


I also noticed that if I try to load this plugin into version 4.37 that it doesn't work and throws a warning/error stating that I need version 4.40 or higher of the client.

Does this plugin actually work under 4.37? If not, does that mean it only works in the current SVN version of the program?

Thanks,
Drake
Australia Forum Administrator #4
It requires 4.40 onwards because 4.40 introduced support for dragging windows around.

However version 4.40 can be downloaded (as an installer) from here:

http://www.gammon.com.au/forum/?id=9264
#5
Awesome! Thanks a lot Nick :)
Canada #6
Is there a limit on # of buttons you can have? And, if you have enough to go from the left side of the screen all the way to the right then add a new one, will it create a second row of buttons?
Australia Forum Administrator #7
No particular limit, but they'll eventually disappear off the edge of the screen.

There is no provision for two rows, I'll leave that as an exercise. :)

These two lines in particular would need to be fiddled with to allow for automatically making multiple lines:


-- where to draw the icon
local x1, y1 = (n - 1) * (ICON_SIZE + OFFSET) + OFFSET, OFFSET
local x2, y2 = n * (ICON_SIZE + OFFSET) + OFFSET, ICON_SIZE + OFFSET


Also the initial window creation size would need to be adjusted to make the window deeper if the number of icons warranted it.
Australia Forum Administrator #8
Below is an improved version that has the following extra features:

  • You can now have a horizontal or vertical bar. Just change the ENTITY in line 3 of the code below from "y" for horizontal to "n" for vertical.
  • When you mouse-over the button bar, when the mouse is over the places where it can be dragged, the mouse cursor turns into a NS-EW arrow, to distinguish it from the hand cursor that shows you can click on a button.


If you need more than one bar of icons you could easily install the plugin twice - just make a copy and change the plugin ID line below to something different (or you will get an error loading the second one). Then just load both plugins.

eg. Change the line:


  id="ede0920fc1173d5a03140f0e"


to:


  id="4a07bf87849d7b8df1345b3f"


Below is the plugin.

Save between the lines as Icon_Bar.xml and use File menu -> Plugins to load that file as a plugin.


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE muclient [
  <!ENTITY horizontal "y" > 
]>

<muclient>
<plugin
   name="Icon_Bar"
   author="Nick Gammon"
   id="ede0920fc1173d5a03140f0e"
   language="Lua"
   purpose="Shows a bar of buttons you can click on to do things"
   date_written="2009-02-26 09:00"
   date_modified="2009-03-29 07:00"
   requires="4.40"
   save_state="y"
   version="2.0"
   >
   
<description trim="y">
<![CDATA[
Install this plugin to show an button bar.

Click on an icon to execute a script or send a command to the MUD.

]]>
</description>

</plugin>

<!--  Script  -->

<script>

horizontal = ("&horizontal;"):lower ():sub (1, 1) == "y";

<![CDATA[

-- table of buttons

--[[
  Each button can have up to four entries:
  
  icon - filename of the image to draw
  tooltip - what to show if you hover the mouse over the button
  send - what to send to the MUD
  script - a script function to call

--]]
  

buttons = {

  -- button 1
  {
  icon = "HealIcon.png",    -- icon image
  tooltip = "Heal self",    -- tooltip help text
  send = "cast 'lesser heal' self",   -- what to send
  },   -- end of button 1
  
  -- button 2
  {
  icon = "SwordIcon.png",
  tooltip = "Attack",
  send = "kill @target",
  },   -- end of button 2
  
  -- button 3
 {
  icon = "SparkIcon2.png",
  tooltip = "Cast Fireball",
  send = "cast fireball",
  script = function () 
            ColourNote ('white', 'green', 'script test') 
            end,  -- function

  },   -- end of button 3
  
  
 --> add more buttons here
 
  
} -- end of buttons table


-- configuration

ICON_SIZE = 32

BACKGROUND_COLOUR = ColourNameToRGB "bisque"
BOX_COLOUR = ColourNameToRGB "royalblue"
BUTTON_EDGE = ColourNameToRGB "silver"

MOUSE_DOWN_COLOUR = ColourNameToRGB "darkorange"

FONT_NAME = "Fixedsys"
FONT_SIZE = 9

-- where to put the window
WINDOW_POSITION = 6  -- top right
OFFSET = 6  -- gap inside box
EDGE_WIDTH = 2 -- size of border stroke

--[[
Useful positions:

4 = top left
5 = center left-right at top
6 = top right
7 = on right, center top-bottom
8 = on right, at bottom
9 = center left-right at bottom
--]]


function mousedown (flags, hotspot_id)

  if hotspot_id == "_" then
  
    -- find where mouse is so we can adjust window relative to mouse
    startx, starty = WindowInfo (win, 14), WindowInfo (win, 15)
    
    -- find where window is in case we drag it offscreen
    origx, origy = WindowInfo (win, 10), WindowInfo (win, 11)
  
    return
    end -- if
    
    
  local n = tonumber (hotspot_id)
  
  -- draw the button border in another colour for visual feedback
  WindowRectOp (win, 1, 
                frames [n].x1, frames [n].y1, frames [n].x2, frames [n].y2, 
                MOUSE_DOWN_COLOUR) 
  
  Redraw ()                
end -- mousedown

function cancelmousedown (flags, hotspot_id)
  local n = tonumber (hotspot_id)
  
  -- draw the button border in original colour for visual feedback
  WindowRectOp (win, 1, 
                frames [n].x1, frames [n].y1, frames [n].x2, frames [n].y2, 
                BUTTON_EDGE) 
  Redraw ()                

end -- cancelmousedown

function mouseup (flags, hotspot_id)
   
  -- fix border colour
  cancelmousedown (flags, hotspot_id)
  
  local n = tonumber (hotspot_id)
  
  local button = buttons [n]
  
  -- send to world if something specified
  if type (button.send) == "string" and 
    button.send ~= "" then
     
    local errors =  {} -- no errors yet
  
    -- function to do the replacements for string.gsub
    
    local function replace_variables (s)
      s = string.sub (s, 2)  -- remove the @
      replacement = GetPluginVariable ("", s)    -- look up variable in global variables
      if not replacement then  -- not there, add to errors list
        table.insert (errors, s)
        return
      end -- not there
      return replacement  -- return variable
    end -- replace_variables 
    
    -- replace all variables starting with @
    
    local command = string.gsub (button.send, "@%a[%w_]*", replace_variables)
    
    -- report any errors
    
    if #errors > 0 then
      for k, v in ipairs (errors) do
        ColourNote ("white", "red", "Variable '" .. v .. "' does not exist")
      end -- for
      return
    end -- error in replacing
     
    Execute (command)
  end -- if
  
  -- execute script if wanted
  if type (button.script) == "function" then
    button.script (n) 
  end -- if
     
end -- mouseup

function dragmove(flags, hotspot_id)

  -- find where it is now
  local posx, posy = WindowInfo (win, 17),
                     WindowInfo (win, 18)

  -- move the window to the new location
  WindowPosition(win, posx - startx, posy - starty, 0, 2);
  
  -- change the mouse cursor shape appropriately
  if posx < 0 or posx > GetInfo (281) or
     posy < 0 or posy > GetInfo (280) then
    SetCursor (11)   -- X cursor
  else
    SetCursor (10)   -- arrow (NS/EW) cursor
  end -- if
  
end -- dragmove

function dragrelease(flags, hotspot_id)
  local newx, newy = WindowInfo (win, 17), WindowInfo (win, 18)
  
  -- don't let them drag it out of view
  if newx < 0 or newx > GetInfo (281) or
     newy < 0 or newy > GetInfo (280) then
     -- put it back
    WindowPosition(win, origx, origy, 0, 2);
  end -- if out of bounds
  
end -- dragrelease

frames = {}

function OnPluginInstall ()

  local x, y, mode, flags = 
      tonumber (GetVariable ("windowx")) or 0,
      tonumber (GetVariable ("windowy")) or 0,
      tonumber (GetVariable ("windowmode")) or WINDOW_POSITION, -- top right
      tonumber (GetVariable ("windowflags")) or 0
  
  win = GetPluginID ()  -- get a unique name
  
  local gauge_height, gauge_width
  
  if horizontal then
    window_width = (#buttons * (ICON_SIZE + OFFSET)) + OFFSET
    window_height = ICON_SIZE + (OFFSET * 2)
  else
    window_width = ICON_SIZE + (OFFSET * 2)
    window_height = (#buttons * (ICON_SIZE + OFFSET)) + OFFSET
  end -- if
  
  -- make the miniwindow
  WindowCreate (win, 
             x, y,   -- left, top (auto-positions)
             window_width,     -- width
             window_height,  -- height
             mode,   -- position mode
             flags,  -- flags
             BACKGROUND_COLOUR) 
                
  -- draw the buttons
  
  for n, v in ipairs (buttons) do

    if v.icon then
      if WindowLoadImage (win, n, GetInfo (66) .. v.icon) ~= error_code.eOK then
          ColourNote ("white", "red", "Could not load image '" .. GetInfo (66) .. v.icon .. "'")
      end -- if
    end -- if icon specified
       
    local x1, y1, x2, y2

    -- where to draw the icon
    if horizontal then
      x1, y1 = (n - 1) * (ICON_SIZE + OFFSET) + OFFSET, OFFSET
      x2, y2 = n * (ICON_SIZE + OFFSET), ICON_SIZE + OFFSET
    else
      x1, y1 = OFFSET, (n - 1) * (ICON_SIZE + OFFSET) + OFFSET
      x2, y2 = ICON_SIZE + OFFSET, n * (ICON_SIZE + OFFSET)
    end -- if
        
    -- draw the image
    WindowDrawImage(win, n, 
                    x1, y1,   -- left, top
                    x2, y2,  -- right, bottom
                    2)  -- mode - stretch or shrink

    -- remember where to draw the frame, for mouse clicks
    frames [n] = { 
            x1 = x1 - 1,
            y1 = y1 - 1,
            x2 = x2 + 1,
            y2 = y2 + 1
            }
    
    -- draw the button border
    WindowRectOp (win, 1, 
                  frames [n].x1, frames [n].y1, frames [n].x2, frames [n].y2, 
                  BUTTON_EDGE) 
    
    -- make a hotspot we can click on
    WindowAddHotspot(win, n,  
                 frames [n].x1, frames [n].y1, frames [n].x2, frames [n].y2,   -- rectangle
                 "",   -- mouseover
                 "",   -- cancelmouseover
                 "mousedown",
                 "cancelmousedown", 
                 "mouseup", 
                 v.tooltip,  -- tooltip text
                 1, 0)  -- hand cursor
                      
  end --  for each world
  

  -- draw the border of the whole box
  WindowCircleOp (win, 2, 0, 0, 0, 0, BOX_COLOUR, 6, EDGE_WIDTH, 0x000000, 1) 
    
  -- make a hotspot
  WindowAddHotspot(win, "_",  
                   0, 0, 0, 0,   -- whole window
                   "",   -- MouseOver
                   "",   -- CancelMouseOver
                   "mousedown",
                   "",   -- CancelMouseDown
                   "",   -- MouseUp
                   "Drag to move",  -- tooltip text
                   10, 0)  -- arrow (NS/EW) cursor
                   
  WindowDragHandler(win, "_", "dragmove", "dragrelease", 0) 
  
  if GetVariable ("enabled") == "false" then
    ColourNote ("yellow", "", "Warning: Plugin " .. GetPluginName ().. " is currently disabled.")
    EnablePlugin (GetPluginID (), false)
    return
  end -- they didn't enable us last time
 
  -- ensure window visible
  WindowShow (win, true)
    
end -- OnPluginInstall

-- hide window on removal
function OnPluginClose ()
  WindowShow (win,  false)  -- hide it
end -- OnPluginClose

-- show window on enable
function OnPluginEnable ()
  WindowShow (win,  true)  -- show it
end -- OnPluginEnable

-- hide window on disable
function OnPluginDisable ()
  WindowShow (win,  false)  -- hide it
end -- OnPluginDisable

function OnPluginSaveState ()
  SetVariable ("enabled",     tostring (GetPluginInfo (GetPluginID (), 17)))
  SetVariable ("windowx",     WindowInfo (win, 10))
  SetVariable ("windowy",     WindowInfo (win, 11))
  SetVariable ("windowmode",  WindowInfo (win, 7))
  SetVariable ("windowflags", WindowInfo (win, 8))
end -- OnPluginSaveState

]]>
</script>

</muclient>
Amended on Sat 02 May 2009 10:34 PM by Nick Gammon
#9
Would it be possible to create a popup menu for individual buttons to reduce the number of necessary buttons? For instance, instead of having five buttons for five special attacks, have one button with a popup menu listing those five specials.
Australia Forum Administrator #10
It is easy if you mean an "ordinary" menu, not a menu of icons.

For example, instead of the code for button 3 above, replace with this:


 -- button 3
 {
  icon = "SparkIcon2.png",
  tooltip = "Special Attacks",
  script = function () 
                  
        local result = WindowMenu (win, 
          WindowInfo (win, 14),  -- x
          WindowInfo (win, 15),  -- y

          "Backstab|Stun|Kick|Taunt")  -- menu items
        
        if result ~= "" then
          Send (result:lower () .. " " .. GetPluginVariable ("", "target"))
        end -- if

  
            end,  -- function

  },  -- end of button 3


This uses WindowMenu to display a pop-up menu with four items in it. If you select one of the four (and thus get a non-empty string as a result) you send the resulting command to the MUD, followed by the name of the current target.
Amended on Sun 29 Mar 2009 01:51 AM by Nick Gammon
Australia Forum Administrator #11

Example of how it looks:

#12
That looks terrific, but I'm having difficulty trying to wrap my head around configuring the code. In essence, what I want to achieve is this:

-- button 8
{
icon = "spear2.png",
tooltip = "Special Attacks",
script = function ()

local result = WindowMenu (win,
WindowInfo (win, 14), -- x
WindowInfo (win, 15), -- y

"Backstab|Stun|Kick|Taunt") -- menu items

if result ~= "Backstab" then
Send "say backstab"
if result ~= "Stun" then
Send "say backstab"
if result ~= "Kick" then
Send "say backstab"
if result ~= "Taunt" then
Send "say backstab"
end -- if

end, -- function

}, -- end of button 8
Australia Forum Administrator #13
I just don't get what your code is trying to do. For example this:


if result ~= "Backstab" then


means if they did not select Backstab.

Then you say if they did NOT select backstab:


Send "say backstab"


Why do that?

And then further down, you also "say backstab" no matter what the test is for.
USA #14
I think the issue was copying and pasting over exuberance, and not examining things that were pasted.

-Onoitsu2
#15
I'm just trying to set it up so that the command "say such and such" is sent when the menu option is chosen. I'm completely lost.
Australia Forum Administrator #16
You just need a slight change to what I posted before.

After calling the WindowMenu function, the variable "result" is either an empty string, or the word in the menu. So you test for an empty string (which happens if you press <esc> to cancel the menu), you simply send "say " concatenated with the result, like this:


-- button 3
 {
  icon = "spear2.png",
  tooltip = "Special Attacks",
  script = function () 
                  
        local result = WindowMenu (win, 
          WindowInfo (win, 14),  -- x
          WindowInfo (win, 15),  -- y

          "Backstab|Stun|Kick|Taunt")  -- menu items
        
        if result ~= "" then
          Send ("say " .. result)
        end -- if

            end,  -- function

  },  -- end of button 3

Australia Forum Administrator #17
Also see this thread for an improved version that handles cooldown times:

http://www.gammon.com.au/forum/?id=9359
#18
Brilliant. I am much obliged.
#19
How would one set up the drop down menu so that the options listed simply point to a string of commands, rather than act as part of the command itself?

This is what I'm trying to accomplish:

-- button 1
{
icon = "spear2.png",
tooltip = "Special Attacks",
script = function ()

local result = WindowMenu (win,
WindowInfo (win, 14), -- x
WindowInfo (win, 15), -- y

"special attack 1") -- menu items

if result = "special attack 1" then
Send ("say backstab/nbackstab opponent/nbury corpse")
end -- if

end, -- function

}, -- end of button 1
Australia Forum Administrator #20
You are on the right track. However comparing equal is == in Lua, not =.

Also, remember that a newline is \n not /n.

So, something like this should work:


if result == "special attack 1" then
  Send ("say backstab\nbackstab opponent\nbury corpse")
end -- if


#21
Ah, I think I understand now :)
Canada #22
After installing this plug-in (the improved Mar 29th version on page 1 changing only the button info) I get this error output to the mud..

Run-time error
Plugin: Icon_Bar (called from world: Fury Newest2)
Function/Sub: OnPluginInstall called by Plugin Icon_Bar
Reason: Executing plugin Icon_Bar sub OnPluginInstall
[string "Plugin"]:293: attempt to call global 'WindowDragHandler' (a nil value)
stack traceback:
        [string "Plugin"]:293: in function <[string "Plugin"]:196>
Error context in script:
 289 :                    "",   -- MouseUp
 290 :                    "Drag to move",  -- tooltip text
 291 :                    10, 0)  -- arrow (NS/EW) cursor
 292 :                    
 293*:   WindowDragHandler(win, "_", "dragmove", "dragrelease", 0) 
 294 :   
 295 :   if GetVariable ("enabled") == "false" then
 296 :     ColourNote ("yellow", "", "Warning: Plugin " .. GetPluginName ().. " is currently disabled.")
 297 :     EnablePlugin (GetPluginID (), false)


Any help is appreciated, I'm looking forward to trying it :)
Amended on Fri 01 May 2009 10:15 PM by Hanaisse
Netherlands #23
My guess is that you are using an old version of MUSHclient. Take a look at the Announcements forum for the latest released version.
Canada #24
As soon as I read that I thought 'doh!' but I'm using 4.37, which is the requirement of version 2.0 of this plug-in.
Netherlands #25
You need version 4.40. See: http://www.gammon.com.au/scripts/showrelnote.php?version=4.40&productid=0 for the changelog which details the function WindowDragHandler being added.


I guess Nick forgot to adjust the version attribute of the plugin. :)
Canada #26
Well grrrr @ Nick for that error :p

That was exactly it, this plug-in requires 4.40 not 4.37, and it works beautifully. Very cool and very handy trick.

The upgrade however brought about another issue but I'll make a new post about it.
Australia Forum Administrator #27
Ooops. That is what comes from adding functionality to an existing plugin. ;)

I have amended both posts.
#28
Nick Gammon said:


Each button can have up to four entries:

icon - filename of the image to draw
tooltip - what to show if you hover the mouse over the button
send - what to send to the MUD
script - a script function to call

--]]


buttons = {

-- button 1
{
icon = "HealIcon.png", -- icon image
tooltip = "Heal self", -- tooltip help text
send = "cast 'lesser heal' self", -- what to send
}, -- end of button 1

-- button 2
{
icon = "SwordIcon.png",
tooltip = "Attack",
send = "kill @target",
}, -- end of button 2

-- button 3
{
icon = "SparkIcon2.png",
tooltip = "Cast Fireball",
send = "cast fireball",
script = function ()
ColourNote ('white', 'green', 'script test')
end, -- function

}, -- end of button 3


--> add more buttons here





-----------------------------------------
Hi
I was wondering if there is some restrictions of certain kind of functions called by the buttons. i would like to disable some groups of triggers, so i wrote:

-- button 3
{
icon = "peace.png",
tooltip = "Pacific Mode",
send = "say hello",
script = function ()
EnableTriggerGroup ("attack", false)
end,
}, -- end of button 3

} -- end of buttons table


...but it didn't work, and the button 3 of your example seems to work perfecty. Mine says hello, that's ok, but can't disable the "attack" group of triggers. Thanks for your comments.
Amended on Tue 31 Jul 2012 02:29 AM by Edwin_r
Australia Forum Administrator #29
That should work. Where is the trigger group? In a plugin? Or the main world?

Actually, enabling a trigger group would not cross plugin boundaries, that is probably the problem.

What you could do is make an alias in the main world (eg. EnableAttackGroup) that you execute from the button, eg.


Execute ("EnableAttackGroup")


So the button "sends" EnableAttackGroup, the alias in the main world picks it up, and then this alias can enable the group.

The ColourNote works because that affects the output window, not a specific plugin's triggers.