Lets start the conversion.

Posted by David Berthiaume on Sat 11 Dec 2004 02:55 PM — 70 posts, 219,757 views.

#0
All right, I KNOW I'm going to have to switch to Lua eventually. The syntax is more or less the issue I'm going to have, being so used to VBscript.

The first thing I should switch over is my infobar script.

Quote:
<triggers>
<trigger
custom_colour="17"
enabled="y"
group="InfoBarScript"
keep_evaluating="y"
match="^\&lt;(.*)\%XTL\&gt;$"
omit_from_output="y"
regexp="y"
repeat="y"
send_to="12"
other_text_colour="darkcyan"
>
<send>world.setvariable "EXPTOLEVEL", "%1"
world.setvariable "XPNEW", "%1"
dim EXPTICK, TICK, TICKERNEW, TICKERBLANK, EXPTOLEVEL, EXPFROMLEVEL, count
dim XPOLD, XPNEW, XPDIFF
XPOLD = CInt(world.getvariable ("XPOLD"))
XPNEW = CInt(world.getvariable ("XPNEW"))
XPDIFF = (XPOLD - XPNEW)
if XPDIFF &lt; 0 then
XPDIFF = (XPDIFF + 100)
world.setvariable "XPOLD", XPNEW
world.setvariable "XPDIFF", XPDIFF
elseif XPDIFF &gt; 0 then
world.setvariable "XPOLD", XPNEW
world.setvariable "XPDIFF", XPDIFF
end if
EXPTOLEVEL = CInt(world.getvariable ("EXPTOLEVEL"))
EXPFROMLEVEL = (100 - EXPTOLEVEL)
world.setvariable "EXPFROMLEVEL", EXPFROMLEVEL
TICKERNEW = "|"
TICKERBLANK = ""
TICK = "|"
EXPTICK = ""
for count = 1 to CInt(world.getvariable ("EXPFROMLEVEL"))
TICKERBLANK = (TICKERBLANK + TICKERNEW)
next
for count = 1 to CInt(world.getvariable ("EXPTOLEVEL"))
EXPTICK = (EXPTICK + TICK)
next
dim space
space = " "
world.infoclear
world.InfoBackground "black"
world.InfoFont "Arial", 12, 1
world.infocolour "white"
world.info "("
if CInt(world.getvariable ("aaHP")) &lt; 100 then
world.info space
world.infocolour "white"
world.info world.getvariable ("aaHP") &amp; "%"
else
world.infocolour "white"
world.info world.getvariable ("aaHP") &amp; "%"
end if
world.infocolour "red"
world.info "HP"
world.infocolour "white"
world.info "|"
if CInt(world.getvariable("aaMana")) &lt; 100 then
world.info space
world.info world.getvariable ("aaMana")
else
world.info world.getvariable ("aaMana")
end if
world.info "%"
world.infocolour "olive"
world.info "Mana"
world.infocolour "white"
world.info "|"
if CInt(world.getvariable ("aaMove")) &lt; 100 then
world.info space
world.info world.getvariable ("aaMove")
else
world.info world.getvariable ("aaMove")
end if
world.info "%"
world.infocolour "darkcyan"
world.info "Move"
world.infocolour "white"
world.info ") ("
world.infocolour "lightgreen"
world.info world.getvariable ("aaHunger")
world.infocolour "white"
world.info ") "
world.info "XTL: ["
if CInt(world.getvariable ("EXPTOLEVEL")) &lt; 5 then
world.InfoColour "red"
world.InfoFont "Arial", 12, 0
world.info EXPTICK
elseif CInt(world.getvariable ("EXPTOLEVEL")) &lt; 10 then
world.InfoColour "lawngreen"
world.InfoFont "Arial", 12, 0
world.info EXPTICK
elseif CInt(world.getvariable ("EXPTOLEVEL")) &lt; 20 then
world.InfoColour "green"
world.InfoFont "Arial", 12, 0
world.info EXPTICK
elseif CInt(world.getvariable ("EXPTOLEVEL")) &lt; 30 then
world.InfoColour "darkorange"
world.InfoFont "Arial", 12, 0
world.info EXPTICK
elseif CInt(world.getvariable ("EXPTOLEVEL")) &lt; 40 then
world.InfoColour "orange"
world.InfoFont "Arial", 12, 0
world.info EXPTICK
elseif CInt(world.getvariable ("EXPTOLEVEL")) &lt; 50 then
world.InfoColour "goldenrod"
world.InfoFont "Arial", 12, 0
world.info EXPTICK
elseif CInt(world.getvariable ("EXPTOLEVEL")) &lt; 60 then
world.InfoColour "gold"
world.InfoFont "Arial", 12, 0
world.info EXPTICK
elseif CInt(world.getvariable ("EXPTOLEVEL")) &lt; 70 then
world.InfoColour "yellow"
world.InfoFont "Arial", 12, 0
world.info EXPTICK
elseif CInt(world.getvariable ("EXPTOLEVEL")) &lt; 80 then
world.InfoColour "blue"
world.InfoFont "Arial", 12, 0
world.info EXPTICK
elseif CInt(world.getvariable ("EXPTOLEVEL")) &lt; 90 then
world.InfoColour "mediumblue"
world.InfoFont "Arial", 12, 0
world.info EXPTICK
else
world.infocolour "darkblue"
world.InfoFont "Arial", 12, 0
world.info EXPTICK
end if
world.infocolour "dimgray"
world.info TICKERBLANK
world.InfoColour "white"

world.InfoFont "Arial", 12, 1
world.info "] ("
world.infocolour "yellow"
if CInt(world.getvariable ("EXPTOLEVEL")) &lt; 100 then
world.info space
world.info world.getvariable ("EXPTOLEVEL")
else
world.info world.getvariable ("EXPTOLEVEL")
end if
world.infocolour "white"
world.info "%) Last ("
world.infocolour "yellow"
world.info world.getvariable ("XPDIFF")
world.infocolour "white"
world.info "%) Level: "
world.infocolour "yellow"
if world.getvariable ("level2") = "subhero" then
world.info world.getvariable ("Level")
else
world.infocolour "red"
world.info world.getvariable ("level2") &amp; world.getvariable ("level")
end if

world.EnableGroup "SHighlight", 0</send>
</trigger>
<trigger
group="InfoBarScript"
ignore_case="y"
keep_evaluating="y"
match="^\&lt;(.*)\%HP\|(.*)\%Mana\|(.*)\%Move\&gt; \&lt;(.*)\&gt;$"
omit_from_output="y"
regexp="y"
repeat="y"
send_to="12"
sequence="1"
>
<send>world.setvariable "aaHP", "%1"
world.setvariable "aaMana", "%2"
world.setvariable "aaMove", "%3"
world.setvariable "aaHunger", "%4"
dim count, hunger
hunger= world.getvariable ("aaHunger")
if (hunger = "H") or (hunger = "T") or (hunger = "HT") then
for count = 1 to 2
world.sendimmediate "drink soup"
next
else
end if</send>
</trigger>
</triggers>
#1
As a side note, once I see the code for those Triggers, EVERYTHING else that I use I will be able to convert myself. Most of the code I use is involved in those 2 triggers. If I can lick those, I'll be able to do whatever it is I need to do.
Australia Forum Administrator #2
Good idea. Let's do a "before" and "after". First thing I'll do is format with a bit of indenting, and take them out of the XML format, so we can see "<" as itself rather than &lt; (just to make it easier to read) ...

First trigger, reformatted in VBscript



world.setvariable "EXPTOLEVEL", "%1"
world.setvariable "XPNEW", "%1"
dim EXPTICK, TICK, TICKERNEW, TICKERBLANK, EXPTOLEVEL, EXPFROMLEVEL, count
dim XPOLD, XPNEW, XPDIFF
XPOLD = CInt(world.getvariable ("XPOLD"))
XPNEW = CInt(world.getvariable ("XPNEW"))
XPDIFF = (XPOLD - XPNEW)

if XPDIFF < 0 then
  XPDIFF = (XPDIFF + 100)
  world.setvariable "XPOLD", XPNEW
  world.setvariable "XPDIFF", XPDIFF
elseif XPDIFF > 0 then
  world.setvariable "XPOLD", XPNEW
  world.setvariable "XPDIFF", XPDIFF
end if

EXPTOLEVEL = CInt(world.getvariable ("EXPTOLEVEL"))
EXPFROMLEVEL = (100 - EXPTOLEVEL)
world.setvariable "EXPFROMLEVEL", EXPFROMLEVEL
TICKERNEW = "|"
TICKERBLANK = ""
TICK = "|"
EXPTICK = ""

for count = 1 to CInt(world.getvariable ("EXPFROMLEVEL"))
  TICKERBLANK = (TICKERBLANK + TICKERNEW)
next

for count = 1 to CInt(world.getvariable ("EXPTOLEVEL"))
  EXPTICK = (EXPTICK + TICK)
next

dim space
space = "  "
world.infoclear
world.InfoBackground "black"
world.InfoFont "Arial", 12, 1
world.infocolour "white"
world.info "("

if CInt(world.getvariable ("aaHP")) < 100 then
  world.info space
  world.infocolour "white"
  world.info world.getvariable ("aaHP") & "%"
else
  world.infocolour "white"
  world.info world.getvariable ("aaHP") & "%"
end if

world.infocolour "red"
world.info "HP"
world.infocolour "white"
world.info "|"

if CInt(world.getvariable("aaMana")) < 100 then
  world.info space
  world.info world.getvariable ("aaMana")
else
  world.info world.getvariable ("aaMana")
end if

world.info "%"
world.infocolour "olive"
world.info "Mana"
world.infocolour "white"
world.info "|" 

if CInt(world.getvariable ("aaMove")) < 100 then
  world.info space
  world.info world.getvariable ("aaMove")
else
  world.info world.getvariable ("aaMove")
end if

world.info "%"
world.infocolour "darkcyan"
world.info "Move"
world.infocolour "white"
world.info ") ("
world.infocolour "lightgreen"
world.info world.getvariable ("aaHunger")
world.infocolour "white"
world.info ") "
world.info "XTL: ["

if CInt(world.getvariable ("EXPTOLEVEL")) < 5 then
  world.InfoColour "red"
  world.InfoFont "Arial", 12, 0
  world.info  EXPTICK
elseif CInt(world.getvariable ("EXPTOLEVEL")) < 10 then
  world.InfoColour "lawngreen"
  world.InfoFont "Arial", 12, 0
  world.info  EXPTICK
elseif CInt(world.getvariable ("EXPTOLEVEL")) < 20 then
  world.InfoColour "green"
  world.InfoFont "Arial", 12, 0
  world.info  EXPTICK
elseif CInt(world.getvariable ("EXPTOLEVEL")) < 30 then
  world.InfoColour "darkorange"
  world.InfoFont "Arial", 12, 0
  world.info EXPTICK
elseif CInt(world.getvariable ("EXPTOLEVEL")) < 40 then
  world.InfoColour "orange"
  world.InfoFont "Arial", 12, 0
  world.info EXPTICK
elseif CInt(world.getvariable ("EXPTOLEVEL")) < 50 then
  world.InfoColour "goldenrod"
  world.InfoFont "Arial", 12, 0
  world.info EXPTICK
elseif CInt(world.getvariable ("EXPTOLEVEL")) < 60 then
  world.InfoColour "gold"
  world.InfoFont "Arial", 12, 0
  world.info EXPTICK
elseif CInt(world.getvariable ("EXPTOLEVEL")) < 70 then
  world.InfoColour "yellow"
  world.InfoFont "Arial", 12, 0
  world.info EXPTICK
elseif CInt(world.getvariable ("EXPTOLEVEL")) < 80 then
  world.InfoColour "blue"
  world.InfoFont "Arial", 12, 0
  world.info EXPTICK
elseif CInt(world.getvariable ("EXPTOLEVEL")) < 90 then
  world.InfoColour "mediumblue"
  world.InfoFont "Arial", 12, 0
  world.info EXPTICK
else
  world.infocolour "darkblue"
  world.InfoFont "Arial", 12, 0
  world.info EXPTICK
end if

world.infocolour "dimgray"
world.info TICKERBLANK
world.InfoColour "white"

world.InfoFont "Arial", 12, 1
world.info "] (" 
world.infocolour "yellow"  

if CInt(world.getvariable ("EXPTOLEVEL")) < 100 then
  world.info space
  world.info world.getvariable ("EXPTOLEVEL")
else
  world.info world.getvariable ("EXPTOLEVEL")
end if

world.infocolour "white"
world.info "%)   Last (" 
world.infocolour "yellow"
world.info world.getvariable ("XPDIFF")
world.infocolour "white"
world.info "%)   Level: "
world.infocolour "yellow"

if world.getvariable ("level2") = "subhero" then
  world.info world.getvariable ("Level")
else
  world.infocolour "red"
  world.info world.getvariable ("level2") & world.getvariable ("level")
end if

world.EnableGroup "SHighlight", 0
Amended on Sat 11 Dec 2004 07:25 PM by Nick Gammon
Australia Forum Administrator #3
The next thing I want to do is get rid of the "world." prefix, which is not necessary in VBscript or Lua, and just causes extra clutter and typing, and more importantly, fix the capitalisation of your script commands.

Whereas VBscript is not case-sensitive, Lua is. So things like "world.note" will not work, it must be "world.Note".

To save myself a certain amount of tedium, and possible errors, I wrote a small Lua script to do that for me ...

Script function capitalisation fixer


function fixscript (s)

  fixed = string.gsub (s, "world%.([%a%u]+)", function (w)
    for v in world do
      if string.upper (v) == string.upper (w) then
         return v;
      end -- if
    end -- for
    return w
  end)	-- of gsub function

  print (fixed)

end -- fixscript 



What this does is a single call of string.gsub (global substitute) looking for a word consisting of upper or lower-case letters. When found it calls the anonymous function passing down the word.

The function scans all known functions (in the world table) and tries to match the word in your script, converted to upper case, to the known function, also converted to upper case. If a match is found it returns the correctly capitalised word. If not (ie. it is one of your script variables) it simply returns the same word.

To use this I call it, passing the entire script as a multi-line string. The results appear in the output window, where I can copy and paste them back into the script file.

The double brackets are important before and after, they indicate a multi-line quoted string.

ie.


fixscript [[
... your script here, copied and pasted ...
]]


VBscript with "world." removed and functions correctly capitalised



SetVariable "EXPTOLEVEL", "%1"
SetVariable "XPNEW", "%1"
dim EXPTICK, TICK, TICKERNEW, TICKERBLANK, EXPTOLEVEL, EXPFROMLEVEL, count
dim XPOLD, XPNEW, XPDIFF
XPOLD = CInt(GetVariable ("XPOLD"))
XPNEW = CInt(GetVariable ("XPNEW"))
XPDIFF = (XPOLD - XPNEW)

if XPDIFF < 0 then
  XPDIFF = (XPDIFF + 100)
  SetVariable "XPOLD", XPNEW
  SetVariable "XPDIFF", XPDIFF
elseif XPDIFF > 0 then
  SetVariable "XPOLD", XPNEW
  SetVariable "XPDIFF", XPDIFF
end if

EXPTOLEVEL = CInt(GetVariable ("EXPTOLEVEL"))
EXPFROMLEVEL = (100 - EXPTOLEVEL)
SetVariable "EXPFROMLEVEL", EXPFROMLEVEL
TICKERNEW = "|"
TICKERBLANK = ""
TICK = "|"
EXPTICK = ""

for count = 1 to CInt(GetVariable ("EXPFROMLEVEL"))
  TICKERBLANK = (TICKERBLANK + TICKERNEW)
next

for count = 1 to CInt(GetVariable ("EXPTOLEVEL"))
  EXPTICK = (EXPTICK + TICK)
next

dim space
space = "  "
InfoClear
InfoBackground "black"
InfoFont "Arial", 12, 1
InfoColour "white"
Info "("

if CInt(GetVariable ("aaHP")) < 100 then
  Info space
  InfoColour "white"
  Info GetVariable ("aaHP") & "%"
else
  InfoColour "white"
  Info GetVariable ("aaHP") & "%"
end if

InfoColour "red"
Info "HP"
InfoColour "white"
Info "|"

if CInt(GetVariable("aaMana")) < 100 then
  Info space
  Info GetVariable ("aaMana")
else
  Info GetVariable ("aaMana")
end if

Info "%"
InfoColour "olive"
Info "Mana"
InfoColour "white"
Info "|" 

if CInt(GetVariable ("aaMove")) < 100 then
  Info space
  Info GetVariable ("aaMove")
else
  Info GetVariable ("aaMove")
end if

Info "%"
InfoColour "darkcyan"
Info "Move"
InfoColour "white"
Info ") ("
InfoColour "lightgreen"
Info GetVariable ("aaHunger")
InfoColour "white"
Info ") "
Info "XTL: ["

if CInt(GetVariable ("EXPTOLEVEL")) < 5 then
  InfoColour "red"
  InfoFont "Arial", 12, 0
  Info  EXPTICK
elseif CInt(GetVariable ("EXPTOLEVEL")) < 10 then
  InfoColour "lawngreen"
  InfoFont "Arial", 12, 0
  Info  EXPTICK
elseif CInt(GetVariable ("EXPTOLEVEL")) < 20 then
  InfoColour "green"
  InfoFont "Arial", 12, 0
  Info  EXPTICK
elseif CInt(GetVariable ("EXPTOLEVEL")) < 30 then
  InfoColour "darkorange"
  InfoFont "Arial", 12, 0
  Info EXPTICK
elseif CInt(GetVariable ("EXPTOLEVEL")) < 40 then
  InfoColour "orange"
  InfoFont "Arial", 12, 0
  Info EXPTICK
elseif CInt(GetVariable ("EXPTOLEVEL")) < 50 then
  InfoColour "goldenrod"
  InfoFont "Arial", 12, 0
  Info EXPTICK
elseif CInt(GetVariable ("EXPTOLEVEL")) < 60 then
  InfoColour "gold"
  InfoFont "Arial", 12, 0
  Info EXPTICK
elseif CInt(GetVariable ("EXPTOLEVEL")) < 70 then
  InfoColour "yellow"
  InfoFont "Arial", 12, 0
  Info EXPTICK
elseif CInt(GetVariable ("EXPTOLEVEL")) < 80 then
  InfoColour "blue"
  InfoFont "Arial", 12, 0
  Info EXPTICK
elseif CInt(GetVariable ("EXPTOLEVEL")) < 90 then
  InfoColour "mediumblue"
  InfoFont "Arial", 12, 0
  Info EXPTICK
else
  InfoColour "darkblue"
  InfoFont "Arial", 12, 0
  Info EXPTICK
end if

InfoColour "dimgray"
Info TICKERBLANK
InfoColour "white"

InfoFont "Arial", 12, 1
Info "] (" 
InfoColour "yellow"  

if CInt(GetVariable ("EXPTOLEVEL")) < 100 then
  Info space
  Info GetVariable ("EXPTOLEVEL")
else
  Info GetVariable ("EXPTOLEVEL")
end if

InfoColour "white"
Info "%)   Last (" 
InfoColour "yellow"
Info GetVariable ("XPDIFF")
InfoColour "white"
Info "%)   Level: "
InfoColour "yellow"

if GetVariable ("level2") = "subhero" then
  Info GetVariable ("Level")
else
  InfoColour "red"
  Info GetVariable ("level2") & GetVariable ("level")
end if

EnableGroup "SHighlight", 0
Amended on Sat 11 Dec 2004 09:33 PM by Nick Gammon
Australia Forum Administrator #4
Syntax changes

Now, time to start doing it in Lua. The major things to change now are:

  • Function calls need to be in parenthese (like Jscript), so that:


    SetVariable "XPOLD", XPNEW


    becomes


    SetVariable ("XPOLD", XPNEW)


    I did a regular-expression to do that in my editor, and then highlighted the individual lines (or batches of lines).
  • You don't declare variables in Lua, so the "dim" lines went away.
  • CInt (convert to integer) becomes "tonumber", which does the same thing. A quick find-and-replace fixed that.
  • "end if" is simply "end". I did a find-and-replace to make it "end -- if" - the hyphens are a comment, and the comment makes it more obvious what we are ending.
  • For loops have a slightly different syntax.

    I changed, for example:


    for count = 1 to tonumber (GetVariable ("EXPFROMLEVEL"))
    ...
    next


    to


    for count = 1, tonumber (GetVariable ("EXPFROMLEVEL")) do
    ...
    end -- for

  • String concatenation is done with ".." rather than "&"

    eg..


    Info (GetVariable ("aaHP") & "%")


    becomes:


    Info (GetVariable ("aaHP") .. "%")

  • The equality test is "==" not "=" (like in JScript or C) so for example:


    if GetVariable ("level2") = "subhero" then


    becomes:


    if GetVariable ("level2") == "subhero" then



Lua version - compiles without errors ...



SetVariable ("EXPTOLEVEL", "%1")
SetVariable ("XPNEW", "%1")
XPOLD = tonumber (GetVariable ("XPOLD")) 
XPNEW = tonumber (GetVariable ("XPNEW")) 
XPDIFF = (XPOLD - XPNEW)

if XPDIFF < 0 then
  XPDIFF = (XPDIFF + 100)
  SetVariable ("XPOLD", XPNEW)
  SetVariable ("XPDIFF", XPDIFF)
elseif XPDIFF > 0 then
  SetVariable ("XPOLD", XPNEW)
  SetVariable ("XPDIFF", XPDIFF)
end -- if

EXPTOLEVEL = tonumber (GetVariable ("EXPTOLEVEL"))
EXPFROMLEVEL = (100 - EXPTOLEVEL)
SetVariable ("EXPFROMLEVEL", EXPFROMLEVEL)
TICKERNEW = "|"
TICKERBLANK = ""
TICK = "|"
EXPTICK = ""

for count = 1, tonumber (GetVariable ("EXPFROMLEVEL")) do
  TICKERBLANK = (TICKERBLANK + TICKERNEW)
end -- for

for count = 1, tonumber (GetVariable ("EXPTOLEVEL")) do
  EXPTICK = (EXPTICK + TICK)
end -- for

space = "  "
InfoClear ()
InfoBackground ("black")
InfoFont ("Arial", 12, 1)
InfoColour ("white")
Info ("(")

if tonumber (GetVariable ("aaHP")) < 100 then
  Info (space)
  InfoColour ("white")
  Info (GetVariable ("aaHP") .. "%")
else
  InfoColour ("white")
  Info (GetVariable ("aaHP") .. "%")
end -- if

InfoColour ("red")
Info ("HP")
InfoColour ("white")
Info ("|")

if tonumber (GetVariable("aaMana")) < 100 then
  Info (space)
  Info (GetVariable ("aaMana"))
else
  Info (GetVariable ("aaMana"))
end -- if

Info ("%")
InfoColour ("olive")
Info ("Mana")
InfoColour ("white")
Info ("|" )

if tonumber (GetVariable ("aaMove")) < 100 then
  Info (space)
  Info (GetVariable ("aaMove"))
else
  Info (GetVariable ("aaMove"))
end -- if

Info ("%")
InfoColour ("darkcyan")
Info ("Move")
InfoColour ("white")
Info (") (")
InfoColour ("lightgreen")
Info (GetVariable ("aaHunger"))
InfoColour ("white")
Info (") ")
Info ("XTL: [")

if tonumber (GetVariable ("EXPTOLEVEL")) < 5 then
  InfoColour ("red")
  InfoFont ("Arial", 12, 0)
  Info ( EXPTICK)
elseif tonumber (GetVariable ("EXPTOLEVEL")) < 10 then
  InfoColour ("lawngreen")
  InfoFont ("Arial", 12, 0)
  Info ( EXPTICK)
elseif tonumber (GetVariable ("EXPTOLEVEL")) < 20 then
  InfoColour ("green")
  InfoFont ("Arial", 12, 0)
  Info ( EXPTICK)
elseif tonumber (GetVariable ("EXPTOLEVEL")) < 30 then
  InfoColour ("darkorange")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif tonumber (GetVariable ("EXPTOLEVEL")) < 40 then
  InfoColour ("orange")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif tonumber (GetVariable ("EXPTOLEVEL")) < 50 then
  InfoColour ("goldenrod")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif tonumber (GetVariable ("EXPTOLEVEL")) < 60 then
  InfoColour ("gold")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif tonumber (GetVariable ("EXPTOLEVEL")) < 70 then
  InfoColour ("yellow")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif tonumber (GetVariable ("EXPTOLEVEL")) < 80 then
  InfoColour ("blue")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif tonumber (GetVariable ("EXPTOLEVEL")) < 90 then
  InfoColour ("mediumblue")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
else
  InfoColour ("darkblue")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
end -- if

InfoColour ("dimgray")
Info (TICKERBLANK)
InfoColour ("white")

InfoFont ("Arial", 12, 1)
Info ("] (" )
InfoColour ("yellow"  )

if tonumber (GetVariable ("EXPTOLEVEL")) < 100 then
  Info (space)
  Info (GetVariable ("EXPTOLEVEL"))
else
  Info (GetVariable ("EXPTOLEVEL"))
end -- if

InfoColour ("white")
Info ("%)   Last (" )
InfoColour ("yellow")
Info (GetVariable ("XPDIFF"))
InfoColour ("white")
Info ("%)   Level: ")
InfoColour ("yellow")

if GetVariable ("level2") == "subhero" then
  Info (GetVariable ("Level"))
else
  InfoColour ("red")
  Info (GetVariable ("level2") .. GetVariable ("level"))
end -- if

EnableGroup ("SHighlight", 0)



Note, there are still run-time problems, see the next post.
Amended on Sun 12 Dec 2004 05:11 AM by Nick Gammon
Australia Forum Administrator #5
Run-time changes

Having changed the above I now got runtime errors. The distinction is that Lua first does a syntax check, and then if that is OK, it actually attempts to run the code.

Things like bad arithmetic only show up at runtime, as Lua has untyped variables. For example:


b = "x"
a = b + 2


This is only a runtime error, as it doesn't know at compile time that you will attempt to add 2 to a string.

  • The first errors I got were "attempting to do arithmetic on a nil value", caused by the lines:


    XPOLD = tonumber (GetVariable ("XPOLD"))
    XPNEW = tonumber (GetVariable ("XPNEW"))


    To work around that, I used a Lua trick of using the short-circuit evaluation of an "or" ...


    XPOLD = tonumber (GetVariable ("XPOLD")) or 0
    XPNEW = tonumber (GetVariable ("XPNEW")) or 0


    What this does is take the variable, however if it is not present (ie. nil) then it substitutes zero.
  • I got an error on this line:


    EXPTICK = (EXPTICK + TICK)


    Again, for string concatenation you need ".." and not "+".


    EXPTICK = (EXPTICK .. TICK)

  • I had a few problems with "doing arithmetic on nil values", principally caused by missing variables. This might not be an issue for you, if the variables exist in advance, but a workaround is something like this:

    Change:


    if tonumber (GetVariable ("aaHP")) < 100 then


    to:


    if tonumber (GetVariable ("aaHP")) or 0 < 100 then


    Again, this substitutes zero if the variable doesn't exist.
  • Similarly, near the bottom:

    Change:


    Info (GetVariable ("level2") .. GetVariable ("level"))


    to:


    Info ((GetVariable ("level2") or "") .. (GetVariable ("level") or ""))



Below is the script converted to Lua, which compiles and runs OK (I'm not sure about all the figures, I think I need some more variables for it to work perfectly) ...

Lua version - compiles and runs ...



SetVariable ("EXPTOLEVEL", "%1")
SetVariable ("XPNEW", "%1")
XPOLD = tonumber (GetVariable ("XPOLD")) or 0
XPNEW = tonumber (GetVariable ("XPNEW")) or 0
XPDIFF = (XPOLD - XPNEW)

if XPDIFF < 0 then
  XPDIFF = (XPDIFF + 100)
  SetVariable ("XPOLD", XPNEW)
  SetVariable ("XPDIFF", XPDIFF)
elseif XPDIFF > 0 then
  SetVariable ("XPOLD", XPNEW)
  SetVariable ("XPDIFF", XPDIFF)
end -- if

EXPTOLEVEL = tonumber (GetVariable ("EXPTOLEVEL"))
EXPFROMLEVEL = (100 - EXPTOLEVEL)
SetVariable ("EXPFROMLEVEL", EXPFROMLEVEL)
TICKERNEW = "|"
TICKERBLANK = ""
TICK = "|"
EXPTICK = ""

for count = 1, tonumber (GetVariable ("EXPFROMLEVEL")) do
  TICKERBLANK = (TICKERBLANK .. TICKERNEW)
end -- for

for count = 1, tonumber (GetVariable ("EXPTOLEVEL")) do
  EXPTICK = (EXPTICK .. TICK)
end -- for

space = "  "
InfoClear ()
InfoBackground ("black")
InfoFont ("Arial", 12, 1)
InfoColour ("white")
Info ("(")

if tonumber (GetVariable ("aaHP")) or 0 < 100 then
  Info (space)
  InfoColour ("white")
  Info (GetVariable ("aaHP") or "" .. "%")
else
  InfoColour ("white")
  Info (GetVariable ("aaHP") or "" .. "%")
end -- if

InfoColour ("red")
Info ("HP")
InfoColour ("white")
Info ("|")

if tonumber (GetVariable("aaMana")) or 0 < 100 then
  Info (space)
  Info (GetVariable ("aaMana"))
else
  Info (GetVariable ("aaMana"))
end -- if

Info ("%")
InfoColour ("olive")
Info ("Mana")
InfoColour ("white")
Info ("|" )

if tonumber (GetVariable ("aaMove")) or 0 < 100 then
  Info (space)
  Info (GetVariable ("aaMove"))
else
  Info (GetVariable ("aaMove"))
end -- if

Info ("%")
InfoColour ("darkcyan")
Info ("Move")
InfoColour ("white")
Info (") (")
InfoColour ("lightgreen")
Info (GetVariable ("aaHunger"))
InfoColour ("white")
Info (") ")
Info ("XTL: [")

if tonumber (GetVariable ("EXPTOLEVEL")) < 5 then
  InfoColour ("red")
  InfoFont ("Arial", 12, 0)
  Info ( EXPTICK)
elseif tonumber (GetVariable ("EXPTOLEVEL")) < 10 then
  InfoColour ("lawngreen")
  InfoFont ("Arial", 12, 0)
  Info ( EXPTICK)
elseif tonumber (GetVariable ("EXPTOLEVEL")) < 20 then
  InfoColour ("green")
  InfoFont ("Arial", 12, 0)
  Info ( EXPTICK)
elseif tonumber (GetVariable ("EXPTOLEVEL")) < 30 then
  InfoColour ("darkorange")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif tonumber (GetVariable ("EXPTOLEVEL")) < 40 then
  InfoColour ("orange")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif tonumber (GetVariable ("EXPTOLEVEL")) < 50 then
  InfoColour ("goldenrod")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif tonumber (GetVariable ("EXPTOLEVEL")) < 60 then
  InfoColour ("gold")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif tonumber (GetVariable ("EXPTOLEVEL")) < 70 then
  InfoColour ("yellow")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif tonumber (GetVariable ("EXPTOLEVEL")) < 80 then
  InfoColour ("blue")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif tonumber (GetVariable ("EXPTOLEVEL")) < 90 then
  InfoColour ("mediumblue")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
else
  InfoColour ("darkblue")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
end -- if

InfoColour ("dimgray")
Info (TICKERBLANK)
InfoColour ("white")

InfoFont ("Arial", 12, 1)
Info ("] (" )
InfoColour ("yellow"  )

if tonumber (GetVariable ("EXPTOLEVEL")) < 100 then
  Info (space)
  Info (GetVariable ("EXPTOLEVEL"))
else
  Info (GetVariable ("EXPTOLEVEL"))
end -- if

InfoColour ("white")
Info ("%)   Last (" )
InfoColour ("yellow")
Info (GetVariable ("XPDIFF"))
InfoColour ("white")
Info ("%)   Level: ")
InfoColour ("yellow")

if GetVariable ("level2") == "subhero" then
  Info (GetVariable ("Level"))
else
  InfoColour ("red")
  Info ((GetVariable ("level2") or "") .. (GetVariable ("level") or ""))
end -- if

EnableGroup ("SHighlight", 0)

Amended on Sat 11 Dec 2004 09:07 PM by Nick Gammon
Australia Forum Administrator #6
Now let's see if we can neaten it all up a bit. First, there is a lot of GetVariable/SetVariable stuff in it.

Based on ideas in my post:


http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=4904


... let's change all GetVariable/SetVariable to use the var idea ...



var.EXPTOLEVEL = "%1"
var.XPNEW = "%1"
XPOLD = tonumber (var.XPOLD) or 0
XPNEW = tonumber (var.XPNEW) or 0
XPDIFF = (XPOLD - XPNEW)

if XPDIFF < 0 then
  XPDIFF = (XPDIFF + 100)
  var.XPOLD = XPNEW
  var.XPDIFF = XPDIFF
elseif XPDIFF > 0 then
  var.XPOLD = XPNEW
  var.XPDIFF = XPDIFF
end -- if

EXPTOLEVEL = tonumber (var.EXPTOLEVEL)
EXPFROMLEVEL = (100 - EXPTOLEVEL)
var.EXPFROMLEVEL = EXPFROMLEVEL
TICKERNEW = "|"
TICKERBLANK = ""
TICK = "|"
EXPTICK = ""

for count = 1, tonumber (var.EXPFROMLEVEL) do
  TICKERBLANK = (TICKERBLANK .. TICKERNEW)
end -- for

for count = 1, tonumber (var.EXPTOLEVEL) do
  EXPTICK = (EXPTICK .. TICK)
end -- for

space = "  "
InfoClear ()
InfoBackground ("black")
InfoFont ("Arial", 12, 1)
InfoColour ("white")
Info ("(")

if tonumber (var.aaHP) or 0 < 100 then
  Info (space)
  InfoColour ("white")
  Info (var.aaHP or "" .. "%")
else
  InfoColour ("white")
  Info (var.aaHP or "" .. "%")
end -- if

InfoColour ("red")
Info ("HP")
InfoColour ("white")
Info ("|")

if tonumber (var.aaMana) or 0 < 100 then
  Info (space)
  Info (var.aaMana)
else
  Info (var.aaMana)
end -- if

Info ("%")
InfoColour ("olive")
Info ("Mana")
InfoColour ("white")
Info ("|" )

if tonumber (var.aaMove) or 0 < 100 then
  Info (space)
  Info (var.aaMove)
else
  Info (var.aaMove)
end -- if

Info ("%")
InfoColour ("darkcyan")
Info ("Move")
InfoColour ("white")
Info (") (")
InfoColour ("lightgreen")
Info (var.aaHunger)
InfoColour ("white")
Info (") ")
Info ("XTL: [")

if tonumber (var.EXPTOLEVEL) < 5 then
  InfoColour ("red")
  InfoFont ("Arial", 12, 0)
  Info ( EXPTICK)
elseif tonumber (var.EXPTOLEVEL) < 10 then
  InfoColour ("lawngreen")
  InfoFont ("Arial", 12, 0)
  Info ( EXPTICK)
elseif tonumber (var.EXPTOLEVEL) < 20 then
  InfoColour ("green")
  InfoFont ("Arial", 12, 0)
  Info ( EXPTICK)
elseif tonumber (var.EXPTOLEVEL) < 30 then
  InfoColour ("darkorange")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif tonumber (var.EXPTOLEVEL) < 40 then
  InfoColour ("orange")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif tonumber (var.EXPTOLEVEL) < 50 then
  InfoColour ("goldenrod")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif tonumber (var.EXPTOLEVEL) < 60 then
  InfoColour ("gold")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif tonumber (var.EXPTOLEVEL) < 70 then
  InfoColour ("yellow")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif tonumber (var.EXPTOLEVEL) < 80 then
  InfoColour ("blue")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif tonumber (var.EXPTOLEVEL) < 90 then
  InfoColour ("mediumblue")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
else
  InfoColour ("darkblue")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
end -- if

InfoColour ("dimgray")
Info (TICKERBLANK)
InfoColour ("white")

InfoFont ("Arial", 12, 1)
Info ("] (" )
InfoColour ("yellow"  )

if tonumber (var.EXPTOLEVEL) < 100 then
  Info (space)
  Info (var.EXPTOLEVEL)
else
  Info (var.EXPTOLEVEL)
end -- if

InfoColour ("white")
Info ("%)   Last (" )
InfoColour ("yellow")
Info (var.XPDIFF)
InfoColour ("white")
Info ("%)   Level: ")
InfoColour ("yellow")

if var.level2 == "subhero" then
  Info (var.Level)
else
  InfoColour ("red")
  Info ((var.level2 or "") .. (var.level or ""))
end -- if

EnableGroup ("SHighlight", 0)



This looks a bit less cluttered. It relies upon this being in your main script file:


var = {}	-- variables table

-- warning - parenthesis must be on same line as setmetatable

setmetatable (var, 
 { 
 -- called to access an entry
 __index = 
 function (t, name) 
  return GetVariable (name) 
 end;
 
 -- called to change or delete an entry
 __newindex = 
 function (t, name, val) 
 local result
   if val == nil then	-- nil deletes it
     result = DeleteVariable (name)
   else
     result = SetVariable (name, tostring (val)) 
   end 
   -- warn if they are using bad variable names
   if result == error_code.eInvalidObjectLabel then
     error ("Bad variable name '" .. name .. "'")
   end
 end;
 })
Amended on Sat 11 Dec 2004 09:08 PM by Nick Gammon
Australia Forum Administrator #7
We still have a lot of "tonumber" in it. Perhaps a rejig of the "var" table will eliminate them?

Let's give ourselves three pseudo-tables.

  • var - for straight variables of any type
  • nvar - for numeric variables.

    Getting a variable from this table will automatically convert it to a number, and substitute zero if not there.
  • svar - for string variables.

    Getting a variable from this table will automatically substitute an empty string if the variable is not there.


Here is the code for the new tables (put that in your global script file) ...


var = {}	-- variables table
nvar = {}	-- number variables table
svar = {}	-- string variables table

-- function called to change variables
function changevar (t, name, val)
local result
 if val == nil then	-- nil deletes it
   result = DeleteVariable (name)
 else
   result = SetVariable (name, tostring (val)) 
 end 
 -- warn if they are using bad variable names
 if result == error_code.eInvalidObjectLabel then
   error ("Bad variable name '" .. name .. "'")
 end
end  -- function changevar 

setmetatable (var, 
 { 
 __index = 
 function (t, name) 
  return GetVariable (name) 
 end;

 __newindex = changevar; 
 }
)

setmetatable (nvar, 
 { 
 __index = 
 function (t, name) 
   return tonumber (GetVariable (name)) or 0
 end;

 __newindex = changevar; 
 }
)

setmetatable (svar, 
 { 
 __index = 
 function (t, name) 
   return GetVariable (name) or ""
 end;

 __newindex = changevar; 
 }
)




Now we can get rid of all the "tonumber" references in the script, and the "or 0" stuff which was in case the variable did not exist ...

Lua script using nvar and svar for variable access



var.EXPTOLEVEL = "%1"
var.XPNEW = "%1"
XPOLD = nvar.XPOLD 
XPNEW = nvar.XPNEW 
XPDIFF = (XPOLD - XPNEW)

if XPDIFF < 0 then
  XPDIFF = (XPDIFF + 100)
  var.XPOLD = XPNEW
  var.XPDIFF = XPDIFF
elseif XPDIFF > 0 then
  var.XPOLD = XPNEW
  var.XPDIFF = XPDIFF
end -- if

EXPTOLEVEL = nvar.EXPTOLEVEL
EXPFROMLEVEL = (100 - EXPTOLEVEL)
var.EXPFROMLEVEL = EXPFROMLEVEL
TICKERNEW = "|"
TICKERBLANK = ""
TICK = "|"
EXPTICK = ""

for count = 1, nvar.EXPFROMLEVEL do
  TICKERBLANK = (TICKERBLANK .. TICKERNEW)
end -- for

for count = 1, nvar.EXPTOLEVEL do
  EXPTICK = (EXPTICK .. TICK)
end -- for

space = "  "
InfoClear ()
InfoBackground ("black")
InfoFont ("Arial", 12, 1)
InfoColour ("white")
Info ("(")

if nvar.aaHP < 100 then
  Info (space)
  InfoColour ("white")
  Info (svar.aaHP .. "%")
else
  InfoColour ("white")
  Info (svar.aaHP .. "%")
end -- if

InfoColour ("red")
Info ("HP")
InfoColour ("white")
Info ("|")

if nvar.aaMana < 100 then
  Info (space)
  Info (svar.aaMana)
else
  Info (svar.aaMana)
end -- if

Info ("%")
InfoColour ("olive")
Info ("Mana")
InfoColour ("white")
Info ("|" )

if nvar.aaMove < 100 then
  Info (space)
  Info (svar.aaMove)
else
  Info (svar.aaMove)
end -- if

Info ("%")
InfoColour ("darkcyan")
Info ("Move")
InfoColour ("white")
Info (") (")
InfoColour ("lightgreen")
Info (svar.aaHunger)
InfoColour ("white")
Info (") ")
Info ("XTL: [")

if nvar.EXPTOLEVEL < 5 then
  InfoColour ("red")
  InfoFont ("Arial", 12, 0)
  Info ( EXPTICK)
elseif nvar.EXPTOLEVEL < 10 then
  InfoColour ("lawngreen")
  InfoFont ("Arial", 12, 0)
  Info ( EXPTICK)
elseif nvar.EXPTOLEVEL < 20 then
  InfoColour ("green")
  InfoFont ("Arial", 12, 0)
  Info ( EXPTICK)
elseif nvar.EXPTOLEVEL < 30 then
  InfoColour ("darkorange")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif nvar.EXPTOLEVEL < 40 then
  InfoColour ("orange")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif nvar.EXPTOLEVEL < 50 then
  InfoColour ("goldenrod")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif nvar.EXPTOLEVEL < 60 then
  InfoColour ("gold")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif nvar.EXPTOLEVEL < 70 then
  InfoColour ("yellow")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif nvar.EXPTOLEVEL < 80 then
  InfoColour ("blue")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
elseif nvar.EXPTOLEVEL < 90 then
  InfoColour ("mediumblue")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
else
  InfoColour ("darkblue")
  InfoFont ("Arial", 12, 0)
  Info (EXPTICK)
end -- if

InfoColour ("dimgray")
Info (TICKERBLANK)
InfoColour ("white")

InfoFont ("Arial", 12, 1)
Info ("] (" )
InfoColour ("yellow"  )

if nvar.EXPTOLEVEL < 100 then
  Info (space)
  Info (svar.EXPTOLEVEL)
else
  Info (svar.EXPTOLEVEL)
end -- if

InfoColour ("white")
Info ("%)   Last (" )
InfoColour ("yellow")
Info (svar.XPDIFF)
InfoColour ("white")
Info ("%)   Level: ")
InfoColour ("yellow")

if svar.level2 == "subhero" then
  Info (svar.Level)
else
  InfoColour ("red")
  Info (svar.level2 .. svar.level)
end -- if

EnableGroup ("SHighlight", 0)
Amended on Sat 11 Dec 2004 09:09 PM by Nick Gammon
Australia Forum Administrator #8
Finally let's do a bit more tidying up. One thing you do a lot is use InfoColour followed by Info. We can make a local function to do that (infoct), thus saving typing. Also we can use string.rep to make a repeated string (for your bars).

Final Lua version


do

  local function infoct (c, t)
    assert (c and t, "Info Colour and text must be specified")
    InfoColour (c)
    Info (t)
  end -- function infoct

  var.EXPTOLEVEL = "%1"
  var.XPNEW = "%1"
  XPOLD = nvar.XPOLD 
  XPNEW = nvar.XPNEW 
  XPDIFF = (XPOLD - XPNEW)

  if XPDIFF < 0 then
    XPDIFF = (XPDIFF + 100)
    var.XPOLD = XPNEW
    var.XPDIFF = XPDIFF
  elseif XPDIFF > 0 then
    var.XPOLD = XPNEW
    var.XPDIFF = XPDIFF
  end -- if

  EXPTOLEVEL = nvar.EXPTOLEVEL
  EXPFROMLEVEL = (100 - EXPTOLEVEL)
  var.EXPFROMLEVEL = EXPFROMLEVEL
  TICKERNEW = "|"
  TICKERBLANK = ""
  TICK = "|"
  EXPTICK = ""


  TICKERBLANK = string.rep (TICKERNEW, nvar.EXPFROMLEVEL)
  EXPTICK = string.rep (TICK, nvar.EXPTOLEVEL)

  space = "  "
  InfoClear ()
  InfoBackground ("black")
  InfoFont ("Arial", 12, 1)

  -- ---------- HP ---------------

  infoct ("white", "(")

  if nvar.aaHP < 100 then
    Info (space)
  end -- if

  Info (svar.aaHP .. "%")

  infoct ("red", "HP")
  infoct ("white", "|")

  -- ---------- Mana ---------------

  if nvar.aaMana < 100 then
    Info (space)
  end -- if

  Info (svar.aaMana .. "%")

  infoct ("olive", "Mana")
  infoct ("white", "|")

  -- ---------- Move ---------------

  if nvar.aaMove < 100 then
    Info (space)
  end -- if

  Info (svar.aaMove .. "%")

  infoct ("darkcyan", "Move")

  infoct ("white", ") (")
  infoct ("lightgreen", svar.aaHunger)

  -- ---------- XTL ---------------

  infoct ("white", ") XTL: [")

  if nvar.EXPTOLEVEL < 5 then
    InfoColour ("red")
  elseif nvar.EXPTOLEVEL < 10 then
    InfoColour ("lawngreen")
  elseif nvar.EXPTOLEVEL < 20 then
    InfoColour ("green")
  elseif nvar.EXPTOLEVEL < 30 then
    InfoColour ("darkorange")
  elseif nvar.EXPTOLEVEL < 40 then
    InfoColour ("orange")
  elseif nvar.EXPTOLEVEL < 50 then
    InfoColour ("goldenrod")
  elseif nvar.EXPTOLEVEL < 60 then
    InfoColour ("gold")
  elseif nvar.EXPTOLEVEL < 70 then
    InfoColour ("yellow")
  elseif nvar.EXPTOLEVEL < 80 then
    InfoColour ("blue")
  elseif nvar.EXPTOLEVEL < 90 then
    InfoColour ("mediumblue")
  else
    InfoColour ("darkblue")
  end -- if

  InfoFont ("Arial", 12, 0)
  Info ( EXPTICK)

  infoct ("dimgray", TICKERBLANK)
  InfoFont ("Arial", 12, 1)

  infoct ("white", "] (" )
  InfoColour ("yellow"  )

  if nvar.EXPTOLEVEL < 100 then
    Info (space)
  end -- if

  Info (svar.EXPTOLEVEL)

  infoct ("white", "%)   Last (" )
  infoct ("yellow", svar.XPDIFF)
  infoct ("white", "%)   Level: ")
  
  InfoColour ("yellow")

  if svar.level2 == "subhero" then
    Info (svar.Level)
  else
    InfoColour ("red")
    Info (svar.level2 .. svar.level)
  end -- if

  EnableGroup ("SHighlight", 0)

end -- do
USA #9
Couple of points:

"You don't declare variables in Lua, so the "dim" lines went away."

You don't have to in VBScript or most others either. It is still done by convention to pre-declare global variables or to make it easier to keep track of what variables you are using, since you can stick all the 'dim' statements at the start of a script/function.

"Things like bad arithmetic only show up at runtime, as Lua has untyped variables."

Ok.. This is one major strike against it imho. I am tired of languages you can't define the types for. You get the same rediculous runtime issues in VBScript, for precisely the same reason. Strict typing helps avoid mistakes, it isn't a 'feature' as far as I am concerned for a language to be missing it. There is after all a reason why most languages have strict types. ;)

Anyway, nice to know before hand that these issues exist.
Australia Forum Administrator #10
No, you don't have to declare them in VBscript, unless you use "option explicit". I was explaining why those lines had to go.

Lua gives you the flexibility to do that or not. As the Lua author points out in his book, you can add explicit variables if you want to.

In chapter 14.2 of his book (or see the equivalent in the online manual) he points out that you can make a metatable for the global environment, that will catch attempts to access non-existent variables and throw an error.

Then to create variables in the first place you add a method "declare" that creates them. This effectively gives you "dim" and "option explicit" back.

Quote:

This is one major strike against it imho. I am tired of languages you can't define the types for. You get the same rediculous runtime issues in VBScript, for precisely the same reason.


Well, Lua has automatic type conversion, so most of the problems go away, depending on the arithmetic operator. For example, adding is for numbers, right? So if you add together two things it tries to convert them to numbers, unlike VBscript which gives strange behaviour.

eg.

Lua:

Note ("10" + "5") --> result 15

VBscript:

Note "10" + "5" ' result 105


Lua has a separate operator for concatenation, so if that is what you want, you use the appropriate operator.

Similarly in Lua, if you want to concatenate, numbers get converted to strings:

Note (10 .. 5) --> 105

In most cases you are controlling the data, so you know what type it is anyway (and if you use the explicit declarations idea, you shouldn't get nil data).

If you aren't sure you can find the type:

Note (type ("10")) --> string

And in my example above, you can make a special table (like nvar) that takes things like strings from GetVariable and converts them to numbers for you.

If you are writing pre-canned functions, then it is a simple matter to check the types of the variables as they are being passed in, eg.


function foo (x, y)

assert (type (x) == "string", "X must be a string")
assert (type (y) == "number", "Y must be a number")

end -- foo


Admittedly this is a runtime check, not a compile-time check, but in things like "send to script" the difference is moot, as they aren't compiled anyway until runtime (that is, until the trigger fires).
Australia Forum Administrator #11
My other comment about explicitly typed languages is this. Although I like the idea personally, it tends to cut down on coding errors, in a scripting environment you tend to simply move the problem.

Say we have a trigger script. The stuff arriving is text anyway, so in order to store it into a (typed) variable we need a runtime conversion, and that conversion may still fail.

eg. int x = ConvertToNumber (wildcard (5))

So, we still have the possibility of runtime errors, we have just moved where they occur around a bit.
USA #12
Nothing saying you will have to switch to Lua anyway.

If you have a feature you want, make it a plugin. Thats the beauty of the plugin system, different script languages.
So you can (in certain cases) have the majority of your scripts/etc in one language that you are comfortable with, and then have a plugin to say... make another window, in lua. You just call the plugin (from the script, in VB) and then the lua stuff (which you didnt write per say, you took it from nicks example and adapted it, or whatever) will get called.
Its the equivalent of calling a subroutine in VBScript, except youre calling a subroutine in a plugin (which is language independant).

Of course, thats assuming Nick will still answer questions in the other language forum sections ;)
Amended on Sat 11 Dec 2004 11:00 PM by Flannel
#13
That's amazing... The only problem is now that it's converted I don't have the slightest idea what to do with it.


In the VBscript version, I had 2 triggers, even though I could have condensed it down to 1.

The first set all my variables, and the second ran the script and made the infobar.


Do I place this script code in a trigger?
Or in the script file?
If in the trigger, which one?
The old variable trigger?(The second xml format trigger in my first posting)
Or in the execute trigger, the one with all the infobar code?
Also, In the sandbox in the global preferences, do I need to add the script file?(vaguely recalling something in another post: dofile something or other).

Believe it or not, I actually understand the scripting and how the language works, the problem I'm having, like I did with vbscript when I started with it, is how to tie MC and Lua together.

I can code the script, but how do I make it work with MC?

Australia Forum Administrator #14
I only converted one trigger, you said if you saw how it was done you could do the rest.

The trigger itself will be the same, just in the "send" box replace the VBscript stuff with the Lua stuff.

Then you would change the scripting language to Lua and instead of myfile.vbs for your script commands that are not "send to script" use myfile.lua.

It's not supposed to be that complicated. Just do whatever you used to do in VBscript, just using Lua as the language.

However you can't have some triggers using Lua and others using VBscript. If you have a lot you'll have to convert them all, OR put the Lua ones into a plugin.

Plugins can have a different language from the main file.

Don't just change over for the sake of it, if it is all working now I wouldn't bother changing.

Don't touch the global preferences unless you have a reason to. All I was saying was that if you wanted to have a script shared between every world you could put that into a file, and then just put:

dofile "myfile.lua"

into the global preferences.

However just stick to what you normally do - put the script file name into the box per world, in the scripting prefs.
#15
That's what I thought originally, but when I setup the triggers, the regular expressing XTL trigger, It didn't work. I setup the variable trigger, it wasn't working

Quote:
<triggers>
<trigger
enabled="y"
group="InfoBarScript"
ignore_case="y"
keep_evaluating="y"
match="^\&lt;(.*)\%HP\|(.*)\%Mana\|(.*)\%Move\&gt; \&lt;(.*)\&gt;$"
regexp="y"
repeat="y"
send_to="12"
sequence="1"
>
<send>SetVariable ("aaHP", "%1")
SetVariable ("aaMana", "%2")
SetVariable ("aaMove", "%3")
SetVariable ("aaHunger", "%4")</send>
</trigger>
</triggers>


Also, I have Lua scripting enabled, however... when the triggers that send to script go off I get an error:

Send-to-script cannot execute because scripting is not enabled.

Also, ontop of that... when I reload the script, or make changes to it.

Error number: 0
Event: Run-time error
Description: [string "Script file"]:9: attempt to index global `var' (a nil value)
Called by: Immediate execution

I get that.
Amended on Mon 13 Dec 2004 12:52 AM by David Berthiaume
Australia Forum Administrator #16
The runtime error disables the script, so it won't work. The runtime error talks about "var" being nil, which I presume is because you didn't add the extra code to your script file. I mentioned on page 1 of this thread:

Quote:

This looks a bit less cluttered. It relies upon this being in your main script file:


The "this" I talk about (directly below that statement) is necessary to make "var" work. It is on the posting, and also in the exampscript.lua file that ships with recent versions of MUSHclient.
#17
Ok, I changed the script file to the examscript file that comes with 3.58, The script loaded this time around... But I got a different error...

Quote:
Error number: 0
Event: Run-time error
Description: [string "Trigger: InfobarScript"]:11: attempt to index global `nvar' (a nil value)
Called by: Immediate execution


The Variable trigger, works quite well now that I got the scripting enabled properly.

But as you can see, there's an error there.

Quote:
Don't just change over for the sake of it, if it is all working now I wouldn't bother changing.


I like the versitility of Lua over VBscript. Like the whole idea of being able to run a looping script in the background. That will come in very hand in the near future. I'm also thinking of checking out that whole notepad idea again, instead of using your multi-line infobar. I'm not to sure if that little window is capable of doing what I want, so I'll give notepads another shot.

The main issue I had, was in using multiple notepads. I couldn't figure out how to make the triggers use one notepad for 1 trigger, and a new notepad for a different trigger... Oh well, I'll get it eventually. Plus, I like the idea of changing the colours of the notepads.
#18
Ok, I added that part, I still get a run-time error.


I added:
var = {}	-- variables table

-- warning - parenthesis must be on same line as setmetatable

setmetatable (var, 
 { 
 -- called to access an entry
 __index = 
 function (t, name) 
  return GetVariable (name) 
 end;
 
 -- called to change or delete an entry
 __newindex = 
 function (t, name, val) 
 local result
   if val == nil then	-- nil deletes it
     result = DeleteVariable (name)
   else
     result = SetVariable (name, tostring (val)) 
   end 
   -- warn if they are using bad variable names
   if result == error_code.eInvalidObjectLabel then
     error ("Bad variable name '" .. name .. "'")
   end
 end;
 })


Like you said... I think I might still be missing something.

The error:
Quote:
Error number: 0
Event: Run-time error
Description: [string "Trigger: InfobarScript"]:11: attempt to index global `nvar' (a nil value)
Called by: Immediate execution
#19
Ok then:
var = {}	-- variables table
nvar = {}	-- number variables table
svar = {}	-- string variables table

-- function called to change variables
function changevar (t, name, val)
local result
 if val == nil then	-- nil deletes it
   result = DeleteVariable (name)
 else
   result = SetVariable (name, tostring (val)) 
 end 
 -- warn if they are using bad variable names
 if result == error_code.eInvalidObjectLabel then
   error ("Bad variable name '" .. name .. "'")
 end
end  -- function changevar 

setmetatable (var, 
 { 
 __index = 
 function (t, name) 
  return GetVariable (name) 
 end;

 __newindex = changevar; 
 }
)

setmetatable (nvar, 
 { 
 __index = 
 function (t, name) 
   return tonumber (GetVariable (name)) or 0
 end;

 __newindex = changevar; 
 }
)

setmetatable (svar, 
 { 
 __index = 
 function (t, name) 
   return GetVariable (name) or ""
 end;

 __newindex = changevar; 
 }
)


Found the second part, I missed. I added that in as well, and it worked like a charm. Ok, now in my last posting I put up some of the code from the prior page, my question is: Is that first var () code debunk, due to the second but of var(), nvar(), and svar() code? Meaning, is ut redundant?
#20
Lastly, can you gimme the link to the word replacement script you wrote in Lua... that was another reason I wanted to switch to Lua.
Amended on Mon 13 Dec 2004 01:21 AM by David Berthiaume
Australia Forum Administrator #21
Yes, the first one is redundant because the second one replaces it. For a start, there is a new:

var = {}

This replaces whatever the first one might have done.

As for the word replacement script, you mean the one that fixes the capitalisation? That is on the first page of this thread. There is no link, it just about 8 lines of code.

You can copy and paste that into a command window (prefixing with the script prefix, usually "/") or use the "Immediate" window, or put it into the script file. All of these methods alter the "global script space" and are interchangeable.

You can experiment with this. Try doing something like:

a = 5

in the immediate window, and then in the command window type:

/print (a)

You should see 5 printed, which shows they are sharing the same script space.
Australia Forum Administrator #22
Quote:

I couldn't figure out how to make the triggers use one notepad for 1 trigger, and a new notepad for a different trigger...


When you do "AppendToNotepad" the first argument is the notepad title. A different title gives you a different window.
#23
No, not the one that fixes the capitalization.

The one where you change the output of words.

I believe the example you used was the word "was", which you changed to "*WAS*" Or something like that, I searched the forums, but I haven't had any luck with it.

I know it's in there somewhere, I saw the posting about it.
Australia Forum Administrator #24
I think you mean this link:

http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=2727
#25
Ok, I'm a dolt... I found it:
http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=4912&page=2

That's what I meant.

Quote:
function my_trigger (name, line, wildcards, styles)

  for _, v in pairs (styles) do
    
    ColourNote (RGBColourToName (v.textcolour), 
                RGBColourToName (v.backcolour), 
                (string.gsub (v.text, "will", "*WILL*")))  
  end

end


First, could you explain this a little bit, the whole styles aspect of it that is.

Secondly, will this work as well?

Quote:
  for _, v in pairs (styles) do
    
    ColourNote (RGBColourToName (v.textcolour), 
                RGBColourToName (v.backcolour), 
                (string.gsub (v.text, "will", "*WILL*")))  
  end


Placed in a trigger as send to script?
Haven't tested it, don't have the time right now, perhaps later on after work.
USA #26
You can also (now) do that replacement on the packet level, if you want a trigger to match on *WILL* for whatever reason.

Which is also handy if you want it to be still in the output, and not a note.
Amended on Mon 13 Dec 2004 04:45 AM by Flannel
#27
Ok, now that I have time to play around, this is my results.

    -=Immortals=-
[ Eternal ] [AFK] Altair got owned by the dentist, (censored*)... got another round coming 


*I censored the cuss word*


Now then... I wanted to replace the name Altair with Dummy, as a joke mind you, just to test it. It was the first name on the Immortal list, so poor Altair got to be the test dummy.

Now then, I successfully got the above mentioned script to replace the name... HOWEVER! It didn't come out quite as planned.

This was the result:
    -=Immortals=-
[ 
Et
ern
al
 ] 
[
AFK
]
 Dummy got owned by the dentist, (censored)... got another round coming


UGLAH!

I should note however that there is a lot of colourized text in that. I'll break it down.

"[" is normal text colour
"Et" is dark cyan
"ern" is light cyan
"al" is dark cyan
"]" normal text colour
"[" dark blue
"AFK" light blue
"]" dark blue
The rest was in normal text colour.

It works great, but for some reason it doesn't like changes in text colour. XML trigger to follow.

<triggers>
<trigger
enabled="y"
keep_evaluating="y"
match="Altair"
omit_from_output="y"
regexp="y"
repeat="y"
script="textreplace"
sequence="100"
>
</trigger>
</triggers>

Any idea's?

Additionally, how does "or" work in Lua?

if (hunger = "H") or (hunger = "T") or (hunger = "HT") then
Amended on Mon 13 Dec 2004 05:18 AM by David Berthiaume
Australia Forum Administrator #28
First, the linebreaks. I suggest changing ColourNote to ColourTell. The ColourNote would do a new line for each style run (colour change).

As for the 'or', bear in mind that equality test is ==, you would say:

if (hunger == "H") or (hunger == "T") or (hunger == "HT") then
Australia Forum Administrator #29
Looks like my example was slightly wrong. Shows you can't believe everything you read. ;)

Still, changing to ColourTell should do it, followed by a final ColourNote to finish off the line.
Australia Forum Administrator #30
No, it won't work in "send to script".

For one thing, notes done in "send to script" are not displayed, if the line is omitted from output.

For another thing, there is no fourth argument in "send to script". It isn't called as a function with arguments.

If you want to do it that way, it has to go into the script file. As Flannel says, the alternative is to use the preprocessing at the packet level.
#31
Next small issue in your help file...

I checked out that AppendToNotepad... Works, but not quite the way the helpfile shows.
Quote:
AppendToNotepad("Nick's window", "More stuff\r\n",
                "another line")


Now, the \r\n is to make a new line? Doesn't seem to work properly, I keep getting errors.
Quote:
Still, changing to ColourTell should do it, followed by a final ColourNote to finish off the line.
Not sure where you gotta put the final ColourNote in there, it's seeming to be working just fine with only ColourNote.
Quote:
If you want to do it that way, it has to go into the script file. As Flannel says, the alternative is to use the preprocessing at the packet level.

reprocessing on the packet level would work, but I don't want to mess with the ANSI coding on it, I like the colours as it is for now. Perhaps in the future.

Quote:
No, it won't work in "send to script".

For one thing, notes done in "send to script" are not displayed, if the line is omitted from output.

For another thing, there is no fourth argument in "send to script". It isn't called as a function with arguments.

If you want to do it that way, it has to go into the script file. As Flannel says, the alternative is to use the preprocessing at the packet level.
That isn't a problem for me, the question is of course, how do we modify a table/metatable from an alias?
Quote:
Everything below this quote is an off shoot of our discussion about replacing text.
First. Alias to add word replacements into a script file.

Alias match on: set replace text "*" "*"
That's all I got so far(Upon editing, re-editing, and editing the edits... I note that this isn't accurate any longer, but the alias is still important.)

I think a merger of two idea's here will work well. Can you use a table to define the replace text? Hack code job to follow the real code:
function ToTextReplace (name, line, wildcards, styles)

  for _, v in pairs (styles) do
    
    ColourTell (RGBColourToName (v.textcolour), 
                RGBColourToName (v.backcolour), 
                (string.gsub (v.text, "Altair", "Dummy")))  
  end

end

here's the pseudo table:
text = {}

text.list = {
  1 = 'Altair',
  2 = 'Ceriloch',
  3 = 'Ragnar'
  }
text.replacelist = {
  1 = 'Moe',
  2 = 'Larry',
  3 = 'Curly'
  }

Ok, time for a buncha pseudo-code of my own creation, of course it'll be wrong, but you'll get the idea

function textreplace (name, line, wildcards, styles)

Ok, first compare the wildcard to the text.list table, does any of them match the criteria? 

Yes, Ok, then set it as text.match(see below)
       text.match = text.list.1

Compare the text.list table, to the text.replace table.
Match them up accordingly, and set text.replacetext to the corresponding text.list match.

text.replacetext = text.replace.1

Continue with rest of the code, but with the modification as follows

  for _, v in pairs (styles) do
    
    ColourTell (RGBColourToName (v.textcolour), 
                RGBColourToName (v.backcolour), 
                (string.gsub (v.text, text.match, text.replacetext)))  
  end

else -- Pseudo code is basically an if statement. 

end -- if statement
end -- function


I'm certain there is an easier way, I'm can't seem to think of it at the moment, but this seems pretty straight foreward.

Make a table with the matches, make that table with the replace text, when a trigger, which is setup by the alias, goes off, it runs the script, which checks the lists(gonna find out who's naughty or nice), converts into text.match and text.replacetext, and substitutes it. Hell, I got most of the idea down, the problem is coding it, which I'm not sure about.

Alias sets up trigger to match on the match word.
Alias adds to tables text.list and text.replace

Trigger goes off, runs through script.
Script checks its text.list table, converts to text.match(for the match)
Script checks its text.replace table, converts the corresponding replace text to text.replacetext

Script runs through the gambit, and bam, you have a fully customizable auto-word replacement script.

A second alias, would remove the Trigger, and the appropriate information within the tables.

Alias match on: remove replace text "*"
Amended on Mon 13 Dec 2004 09:06 AM by David Berthiaume
#32
Ok, considering I think we'll be talking about tables, and serialize quite a bit, I think we should move over to this thread:

http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=5022
USA #33
You want to switch his name with 'dummy'. You CAN do that with the packet callback thing. You dont have to change/mess with the colors either. You can just subsitute text for text.
Australia Forum Administrator #34
Quote:

I checked out that AppendToNotepad... Works, but not quite the way the helpfile shows ...


That works for me. What was the error? In Lua (not other languages) you can have multiple arguments after the notepad name, and they all appear in the notepad. And yes, \r\n is a carriage-return linefeed.

Quote:

Not sure where you gotta put the final ColourNote in there, it's seeming to be working just fine with only ColourNote.


I thought you were getting a line per style. The ColourTell stays on the same line. A final ColourNote (after the loop) would start a new line.
Australia Forum Administrator #35
Quote:

here's the pseudo table:

text = {}

text.list = {
1 = 'Altair',
2 = 'Ceriloch',
3 = 'Ragnar'
}
text.replacelist = {
1 = 'Moe',
2 = 'Larry',
3 = 'Curly'
}


I suggest you read the Lua manual about tables:


http://www.lua.org/pil/2.5.html


Tables can be basically two things (or both), a list of things keyed by number, as you illustrate above, or an associative array. Here is an example of doing a list:


t = {
  'Altair',
  'Ceriloch',
  'Ragnar'
  }

table.foreach (t, print)

-- Output:

1 Altair
2 Ceriloch
3 Ragnar


In this case Lua automatically assigns incrementing keys to each item, effectively making a vector. Now you can get at invidivual items:


print (t [2]) --> Ceriloch


However for a word-replacement thing you really want an associative array:


t =  {
  ['Altair'] = 'Moe',
  ['Ceriloch'] = 'Larry',
  ['Ragnar'] = 'Curly'
  }

table.foreach (t, print)

-- Output:

Ceriloch Larry
Ragnar Curly
Altair Moe


Now each item is keyed by its name, and the replacement can be found directly:


print (t ['Ragnar']) --> Curly


If the keys are straight names, you can save a bit of typing:


t =  
  {
  Altair = 'Moe',
  Ceriloch = 'Larry',
  Ragnar = 'Curly'
  }


Given our table of replacement words, we can rewrite the gsub nice and simply:


t =  
  {
  Altair =  'Moe',
  Ceriloch =  'Larry',
  Ragnar =  'Curly'
  }

line = "Altair went for a walk, he met Ceriloch but Ragnar surprised them"

repl = string.gsub (line, "(%a+)", function (w)
         if t [w] then
            return t [w]
         else
            return w
         end -- if
       end) -- function

print (repl)

-- Output:

Moe went for a walk, he met Larry but Curly surprised them



What this is doing is searching for a word (%a+) and if found looking it up in the associative array. If found, it uses the replacement, if not, it returns the original word.
#36
Quote:
That works for me. What was the error? In Lua (not other languages) you can have multiple arguments after the notepad name, and they all appear in the notepad. And yes, \r\n is a carriage-return linefeed.

<triggers>
<trigger
enabled="y"
match="* oocs '*'"
send_to="12"
sequence="100"
>
<send>AppendToNotepad("Nick's window", "More stuff\r\n",
"another line")</send>
</trigger>
</triggers>

Error number: 0
Event: Compile error
Description: [string "Trigger: "]:1: unfinished string near `"More stuff
'
Called by: Immediate execution

I used the sample code in the helpfile, and I just put it in send to script. That was the error I got.

I didn't even bother to change it to what it's supposed to be, if the helpfile example didn't work for me, then I know the setup I was going to use wasn't going to work either.
#37
Regarding that associative array, I hear ya. I know exactly what you mean. When I was reading the manual late last night, I saw the difference.

The only problem with what you put up, and there's nothing wrong with it, but it's missing something.

if I make an alias to add a name into the array, which is piece of cake

Alias: add "*" "*"
send to script: t ['%1'] = '%2'

That will add a new name and replace text into the array, but it's in memory, it's not actually hardcoded, so when you quit out, you're going to lose that array.

So, how about OnWorldConnect you load the saved array
and OnWorldDisconnect you serialize the memory array, that'll save it as a variable... That'll work I think. Actually, I think that'll be less work than trying to code it as changing the scriptfile itself.... Yeah, I like that.
Australia Forum Administrator #38
OK, I see what is happening. That trigger is a bit of a trap. The example code works pasted into the command window, however in the "send to script" box it seems MUSHclient is preprocessing the \r\n before passing it to Lua (or any script language). Thus it effectively makes it:


AppendToNotepad("Nick's window", "More stuff
",
"another line")


This make Lua complain about the unterminated quote on the first line.

You can fix it by using another backslash:


<triggers>
  <trigger
   enabled="y"
   match="* oocs '*'"
   send_to="12"
   sequence="100"
  >
  <send>AppendToNotepad("Nick's window", "More stuff\\r\\n", "another line")</send>
  </trigger>
</triggers>


However my code as given in the example works in a script file.
#39
Was playing around with the replacetext script

function textreplace (name, line, wildcards, styles)

  for _, v in pairs (styles) do
    
    ColourTell (RGBColourToName (v.textcolour), 
                RGBColourToName (v.backcolour), 
                (string.gsub (v.text, "Altair", "Dummy")))  
  end

end
Was the original code... Now, I'm kinda confused, granted I haven't slept in over 24 hours, so that could be it... but I'm not making the connection how to go from:
t =  
  {
  Altair =  'Moe',
  Ceriloch =  'Larry',
  Ragnar =  'Curly'
  }

line = "Altair went for a walk, he met Ceriloch but Ragnar surprised them"

repl = string.gsub (line, "(%a+)", function (w)
         if t [w] then
            return t [w]
         else
            return w
         end -- if
       end) -- function

print (repl)

-- Output:

Moe went for a walk, he met Larry but Curly surprised them
To using both in conjunction...

I'm still kinda stumped on the trigger aspect. I really don't want 50 million single triggers. I was thinking of something along the lines of (fdhgh|arhh|ahathaeh|bob|fdahah|great) And when I add a new word, to be replaced, it adds into the trigger, but I don't remember how to do that... I know the code is in the forums, I've used it before, but it's a bit beyond my current ability in Lua.
Australia Forum Administrator #40
Quote:

That will add a new name and replace text into the array, but it's in memory, it's not actually hardcoded, so when you quit out, you're going to lose that array.

So, how about OnWorldConnect you load the saved array
and OnWorldDisconnect you serialize the memory array ...


Yes, exactly. See my posts in the Lua section for doing that.
#41
Acutally, I picked up on serializing rather quickly, it's a really neat function, not sure how function save works though.
USA #42
The matching on multiple (and dynamic) things can be done with expand variables and a variable that contains a regexp for what you want to match on.

bob|joe becomes
bob|joe|billy when you add to it. So its a simple string concatenation. You can do 95% of it without using any form of scripting (just the inbuilt functions) you only need the lua code to add "|[name]" to the variable.
Australia Forum Administrator #43
After writing that I saw a couple of shortcomings in the serialization idea. Namely, when do you actually serialize the variable?

See my addition to this thread:

http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=4960

I have added a couple of new things to MUSHclient 3.60. The first one lets you do a script just before MUSHclient saves its world to disk. This is a logical spot to serialize from internal variables to the external variables.

The second is a function that lets you set the "world has changed" flag, to make sure the saving is done in the first place.

I added this short script to my script file to make it work:


function OnWorldSave ()
  var.skills = serialize ('skills')
end -- function


That caused the skills to be serialized. Then in the world open:


function OnWorldOpen ()
  loadstring (var.skills) 
end


That loads them back in.

#44
I think this alias is going to be a lot more complex than we both think it's going to be.

Ok, really tired, I can't even think of how to do what Flannel said...

Mainly, I got the SetVariable ("replacetext", "@replacetext" .. "%1")

But that's all I got so far... and I know I have to put in the "|" in there, and I'm drawing a blank as to how to do that. I know I gotta script this into it as well:

text ['%1'] = '%2"

Then I'm drawing a blank.
#45
Quote:
I have added a couple of new things to MUSHclient 3.60. The first one lets you do a script just before MUSHclient saves its world to disk. This is a logical spot to serialize from internal variables to the external variables.


yeah, I used to have a timer that did that every 5 minutes or so, but I don't remember the exact syntax... Not to mention when, I re-scripted it after my computer meltdown, it didn't save in the spot that I wanted it too, it kept saving in C:\My Documents, which I didn't want, I wanted it saved in D:\Program Files\MUSHclient\worlds

Anyways... I'll figure that out eventually.
Australia Forum Administrator #46
A save with no filename should save in the default place (ie. the current file).

eg.

Save ""
USA #47
I think you can use .. "|%1"
But if that doesnt work, you can probably also use .. "|" .. "%1"

And then you have expand variables checked, and (@replacetext) in your match text.
#48
The only issue I see with that is a possible nil return when there is no variable there in the first place.

run it through a script(you're gonna be scripting in it already to set the table element):
if GetVariable ("replacetext") == nil then
SetVariable ("replacetext", "%1")
else
SetVariable ("replacetext", "@replacetext" .. "|" .. "%1")
end -- if



On a side note, I was just thinking of my infobar script, I could do away with variables completely, I think. Use table's to store the information, nothing would really change, but instead of saving to the variable list, it would be updating the table... Then along with all my other tables, when I save the world, or whatever, it'll save that into a single variable, which will reload itself aferwards. Man, I like this table thing... I never understood it in VBscript before, but Lua seems pretty straight forward in how the tables work.
Amended on Mon 13 Dec 2004 11:11 PM by David Berthiaume
Australia Forum Administrator #49
You can make that a bit shorter. For one thing testing for not-nil can be done without the == nil bit.

Second, if you use the "var" table you can save the GetVariable/SetVariable stuff. So it could read:



if var.replacetext then
  var.replacetext = var.replacetext .. "|%1"
else
  var.replacetext = "%1"
end -- if

Australia Forum Administrator #50
In many ways it is easier to stick with tables anyway, and use table.concat to put in the "|" symbols. Here is an example:


t = { "fish", "chips", "cat", "dog" }

print (table.concat (t, "|"))

-- Ouput: fish|chips|cat|dog

#51
Yeah, that's true, it would be easier to stick with tables, but that doesn't change the fact that I need a regexp trigger to match against the table...

That reminds me, if we get the replace text thing working perfectly, then they'll be one last issue, it's CAPS sensitive. even if you're matching ignore case, it won't work. I tested that earlier when I first started playing with it.
Australia Forum Administrator #52
In what context are you doing the test? Triggers can be made case-insensitive. So can regexps.

The output from that table concatenation (fish|chips|cat|dog) can be used in a regexp.
Amended on Tue 14 Dec 2004 02:06 AM by Nick Gammon
USA #53
Why would the variable be empty to begin with?

and I dont see how sticking with tables would help.

Youd need to have a table to keep your targets, as well as a MC variable.

Edit:
I see, youre using the table to store the information for the switch. So you add to the table, and then regenerate your MC variable. Wouldnt the output be both columns though?

As for a long term storage solution, which could just be a MC variable for each thing (name, and replacement names), or you can store it in a database.

Amended on Tue 14 Dec 2004 12:21 AM by Flannel
#54
All right:
function textreplace (name, line, wildcards, styles)

  for _, v in pairs (styles) do
    
    ColourTell (RGBColourToName (v.textcolour), 
                RGBColourToName (v.backcolour), 
                (string.gsub (v.text, "Altair", "Dummy")))  
  end

end
This is the case sensitive part:
(string.gsub(v.text, "Altair", "Dummy")))


<triggers>
<trigger
enabled="y"
ignore_case="y"
keep_evaluating="y"
match="Altair"
omit_from_output="y"
regexp="y"
repeat="y"
script="textreplace"
sequence="100"
>
</trigger>
</triggers>

We have success, this works, Altair(script version) == Altair(Trigger Version)

Ok, lets change it now. Now we match on "altair"

altair(Trigger with ignore case) does not match Altair in the script

Flip it around again, Make the Trigger Altair, and the script altair, it doesn't match up.

Now if you match on altair, and you type say altair, then it will work, if you type: say Altair, no dice, it won't work...

So what I mean is that the code that you put up is case senstive, even thought the trigger says it's not supposed to be... That might be a slight bug... Perhaps. I don't know.
USA #55
You can check the "convert wildcards to lowercase" OR you can just cast the name (wildcard, once its passed) to lowercase while you're checking.

Then you'll have to have your match table be all lower case (you convert to lowercase (.lower) when you add it).
#56
yeah, converting to lowercase works, but annoying when you have to script AddTrigger... *shrugs* Oh well, such is life.

I'm still trying to work out how to combine the first replace text script, and the second example Nick gave us.

I should probably stop for the night, go to bed, and think about it tommorrow morning. when I'm not brain dead tired.
USA #57
Why are you scripting addtrigger?

Thats why were using the variable, so you can match on anyone inside your list, and then convert. All in one trigger.
#58
Ok, so you set the variable... how do you match lines of the mud to a variable?

You have to use a trigger.

That's why you have to script an AddTriger

AddTrigger("Textreplace", var.replacetext , "", trigger_flag.Enabled , custom_colour.Custom15, 0, "", "")

make it regexp and lowercase wilds, and what not. Anyways, you have to keep replacing the trigger that matches the replacetext that you want. Otherwise setting up the variable is useless, and like Nick said, we don't even need the variable really, we can script it right into a table and that will speed things up.
USA #59
But then you have a trigger for each name.
Which you might as well ditch the table for, and hard code it directly into the trigger (no more lookup, just a subroutine which replaces X with Y).

You can have a trigger match ANY name in your table (which is also in your variable) using expand variables and a variable-regexp. So the same trigger matches constantly, and you dont use AddTrigger anywhere.

Oh, youre hard-coding the variable into the trigger. The problem with that is then you have to add the parenthesis to the outsides of the list. Which, is doable.

You would lose the information about the trigger (number of matches and such) which may or may not be an issue.

And I'd imagine setting the variable takes less time than adding a trigger. You'd need to set the MC variable eventually to save your list between sessions (or use a database, but I think a database might be overkill).
#60
Well, you do need an external variable eventually, but either way, when you use the alias to add names and replace text, you also have to add the trigger match to it's own table, else you can't do anything with it.

It's like having a car, and having a tin of gas, but no way to put the gas in the car. That trigger is the tube that lets you put the gas in the car. The car is the trigger, and the alias is the fuel... Hey, that's a pretty nifty analogy.

Anyways, you can do it 1 of 2 ways, with or without a variable. Serializing the tables is easy, I have it happening every 30 seconds(with a world save)

The tricky part of this whole process is translating the table to the script. We got 2 pieces of code, and I don't know how to link them together to get the effect we want.
USA #61
Yes, Serializing, but instead of adding it to a trigger, you can store it in the variable.

The trigger WILL still match with using the variable as match text (see link below). If you want to use your analogy, the funnel is the variable. Well, and the can, for long term storage.

If you store it in the variable, and at the same time you update a second variable of conversions, both of which are overwritten with the serialization, then you wont have to worry about storing it to a variable later, and you can save the world as soon as you finish editing the variables. To make sure you never lose anything.

You wont have to save the world (and write to the variable) every 30 seconds, only when needed, which will save considerable computation time, if you have it happening twice a minute currently.

And then when you open the world, you extract that information to the table, and never worry about losing anything.

That way you only have your table existing in the variables (one for before, one for after) and the script environment. Instead of variables (storing it for long term), your script environment, AND the match text of the trigger.
If you're keeping your variable up to date already, why are you wasting your time with the addtrigger?

Edit:
In case you dont quite understand using the variable with the trigger, you can look at an example here:
http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=4603
Amended on Tue 14 Dec 2004 02:00 AM by Flannel
#62
Tell ya what, lemme get about 15 hours of sleep, and I'll get back to you. It's 10pm EST, Monday night, I've been up since 12pm EST, Sunday afternoon. Getting close to 36 hours up, 12 of it at work, 3 of it traveling, the rest at the computer.

I see what your saying. I don't know if it's better or not. I haven't thought about it, can't really think about it right now... Let me get back to you....

Ok, basically you're doing the same thing I am, just in reverse.

Interesting, it has possibilities. Ultimately, do I write the code for the addtrigger, and be done with it? It's not that much more complicated than writing a Variable. As for CPU and Memory, Athlon XP 2600+, with 512 PC2700 DDR 333Mhz FSB. Not too woried... I can loop up to 10,000 commands at once before I even start to notice a glitch, at 100,000 commands I get a second or two pause, and at 1,000,000 MC locks up, but the computer is just fine.
Amended on Tue 14 Dec 2004 02:28 AM by David Berthiaume
#63
All right, you're right, it's easier:

<aliases>
<alias
match="addtext &quot;*&quot; &quot;*&quot;"
enabled="y"
expand_variables="y"
send_to="12"
sequence="100"
>
<send>replacetext = "@replacetext" .. "|" .. "%1"
Note ("" .. replacetext)
SetVariable ("replacetext", replacetext)

text ['%1'] = '%2'
</send>
</alias>
</aliases>


That works quite well, I can add into the text {} table with that.

Now all I need to do is link up the 2 pieces of code I have.

This is the code to do the replace and output on the same line:
function textreplace (name, line, wildcards, styles)

  for _, v in pairs (styles) do
    
    ColourTell (RGBColourToName (v.textcolour), 
                RGBColourToName (v.backcolour), 
                (string.gsub (v.text, "Altair", "Dummy")))  
  end

end


This code is the one that the trigger actually changes the the text:
t =  
  {
  Altair =  'Moe',       ---- Used here as an example
  Ceriloch =  'Larry',   ---- this would actually be an
  Ragnar =  'Curly'      ---- internal table
  }

line = "Altair went for a walk, he met Ceriloch but Ragnar surprised them"

repl = string.gsub (line, "(%a+)", function (w)
         if t [w] then
            return t [w]
         else
            return w
         end -- if
       end) -- function

print (repl)
I just don't know how to link the two together, once that happens, we'll be golden I believe.
Amended on Tue 14 Dec 2004 05:46 PM by David Berthiaume
#64
Woot! Success!

I got it ALL working, just gotta set up the replace script for my skills now.

function textreplace (name, line, wildcards, styles)
 loadstring (GetVariable ("text"))

line = wildcards[1]

repl = string.gsub (line, "(%a+)", function (w)
         if text [w] then
            return text [w]
         else
            return w
         end -- if
       end) -- function
  for _, v in pairs (styles) do
        ColourTell (RGBColourToName (v.textcolour), 
                RGBColourToName (v.backcolour), 
                (string.gsub (v.text, line, repl)))  
  end

end

With that you use:
<triggers>
<trigger
custom_colour="2"
enabled="y"
expand_variables="y"
ignore_case="y"
keep_evaluating="y"
match="(@!replacetext)"
omit_from_output="y"
regexp="y"
repeat="y"
script="textreplace"
sequence="100"
>
</trigger>
</triggers>

And you use:

<aliases>
<alias
match="addtext &quot;*&quot; &quot;*&quot;"
enabled="y"
expand_variables="y"
send_to="12"
sequence="100"
>
<send>replacetext = "@replacetext" .. "|" .. "%1"
Note ("" .. replacetext)
SetVariable ("replacetext", replacetext)

text ['%1'] = '%2'

SetVariable ("text", serialize("text"))
</send>
</alias>
</aliases>

Now, When you're me, you have a script serializing every 30 seconds or so, so don't set a replace text that you don't want, cause it can be a pain in the arse to get it out of the table once it's in. Now then, the next thing is to make an alias to do that for us. I'll do that later tonight after work.

One problem left... That'll be fixed in 3.60 when Nick releases it, untill then the variable doesn't seem to want to stay saved when you close the program out.
Amended on Tue 14 Dec 2004 06:16 PM by David Berthiaume
USA #65
Why do you need to serialize every 30 seconds? You dont update the list(s) every 30 seconds, do you? Can't you just serialize when you update?

And cant you join them like this:
@variable .. "|%1" or does that not work? Not that it'd offer much of anything, Im just wondering.
Amended on Tue 14 Dec 2004 07:01 PM by Flannel
#66
Yes, you can, but I did it that way, don't ask me why. I just did. It took me a few tries to figure out how to get it to work, once I got it working, I left it as it was. No need to change something once it's working.


Flannel, since you showed me how to use the variable trigger, how do I remove a specific name from the variable if I want to remove it from the list?
Australia Forum Administrator #67
Quote:


repl = string.gsub (line, "(%a+)", function (w)
         if text [w] then
            return text [w]
         else
            return w
         end -- if
       end) -- function
  for _, v in pairs (styles) do
        ColourTell (RGBColourToName (v.textcolour), 
                RGBColourToName (v.backcolour), 
                (string.gsub (v.text, line, repl)))  
  end



I am glad to hear it is working, but again I think you have combined a couple of my ideas into one.

What you are doing above is two gsubs, one for the entire line, and one per style. I would do one or the other. This will only work if the entire line is a single style (ie. a single colour).

The second gsub is trying to match the entire line, and replacing it with the replacement line, this will only work if the entire line is one style.
USA #68
Im not quite sure what all you have to work with, however...

You just have to remove the name (and the | either before or after). Do you already have a table of the names? Just remove the name from the table (which you still have, I believe) and then regenerate the variable.

That regeneration might be easier than trying to find, and then determine what to remove (since if its the first name, youll have to remove the | afterwards, but if its the last, youll have to remove the | beforehand, so regeneration might be better. It will also solve any problems you might have with the data unsynching from each other).
#69
Quote:
I am glad to hear it is working, but again I think you have combined a couple of my ideas into one.


Yep, I did, was the only way I could figure out how to get it to work.

I knew the first half of the code would change the line into the new words, and I knew the second half of the code would do the ColourTell.

I knew I could always match the apropriate capitolization if I used the line for the match, and the apropriate replace text with the repl, so it's not pretty, but it works.