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

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

Lua for Dummies

eqsubi15

Ultimate seasoned veteran member
Joined
Jul 11, 2020
RedCents
953¢
I'm still trying to learn Lua and be able to build scripts. I haven't been too successful so far. However, one of the things that I believe is needed is some kind of dumbed down explanation of how a Lua script works and what each line exactly does. So, with the help of ChatGPT, I think this might be useful to many.

Used the Aten Ra Mission LEM as the test subject:

[CODE lang="Lua" title="Text Event: Run away with silence emote"]local mq = require('mq')
local function event_handler(line, target)
if not mq.TLO.Zone.ShortName() == 'vexthaltwo_mission' then return end
local my_class = mq.TLO.Me.Class.ShortName()
local i_am_ma = mq.TLO.Group.Member(0).MainAssist()
local my_name = mq.TLO.Me.CleanName()
local ma_name = mq.TLO.Group.MainAssist.CleanName()
if not i_am_ma and (target == my_name or target == ma_name) then
if my_class == 'BER' and mq.TLO.Me.ActiveDisc.Name() == mq.TLO.Spell('Frenzied Resolve Discipline').RankName() then
mq.cmd('/stopdisc')
end
mq.cmdf('/%s mode 0', my_class)
mq.cmd('/mqp on')
mq.cmd('/twist off')
mq.cmd('/timed 5 /afollow off')
mq.cmd('/nav stop')
mq.cmd('/target clear')
mq.delay(100)
mq.cmd('/nav locxyz 1222.67 -48.97 236.41')
mq.delay(15000)
mq.cmdf('/%s mode 2', my_class)
mq.cmd('/mqp off')
mq.cmd('/twist on')
end
end
return {eventfunc=event_handler}[/CODE]

The ChatGPT explanation of each line of the script:

1. local mq = require('mq')

  • Imports the MacroQuest library (mq) into the script, giving access to its functions and objects.

2. local function event_handler(line, target)

  • Defines a function named event_handler that takes two parameters:
    • line: Likely the full text of an event or trigger line.
    • target: The specific entity involved in the event.

3. if not mq.TLO.Zone.ShortName() == 'vexthaltwo_mission' then return end

  • Checks if the player is not in the zone with the short name vexthaltwo_mission. If true, the function exits early (return).

4. local my_class = mq.TLO.Me.Class.ShortName()

  • Retrieves the player's class short name (e.g., BER for Berserker) and stores it in my_class.

5. local i_am_ma = mq.TLO.Group.Member(0).MainAssist()

  • Checks if the player is the group's main assist and stores the result (true/false) in i_am_ma.

6. local my_name = mq.TLO.Me.CleanName()

  • Retrieves the player's clean name (stripped of special characters or titles) and stores it in my_name.

7. local ma_name = mq.TLO.Group.MainAssist.CleanName()

  • Retrieves the clean name of the group's main assist and stores it in ma_name.

8. if not i_am_ma and (target == my_name or target == ma_name) then

  • Proceeds only if:
    • The player is not the main assist (not i_am_ma), and
    • The target matches either the player’s name or the main assist's name.


9. if my_class == 'BER' and mq.TLO.Me.ActiveDisc.Name() == mq.TLO.Spell('Frenzied Resolve Discipline').RankName() then

  • If the player’s class is Berserker (BER) andthey are currently using the discipline Frenzied Resolve Discipline:
    • Executes the block inside this if.

10. mq.cmd('/stopdisc')

  • Stops the active discipline (e.g., Frenzied Resolve Discipline).


Actions Taken Regardless of Class:​

The following commands are executed if the conditions of the outer if statement are met:

11. mq.cmdf('/%s mode 0', my_class)

  • Sends a formatted command to set the player’s class mode to 0 (passive mode). %s is replaced with the player’s class name.

12. mq.cmd('/mqp on')

  • Enables /mqp, which prevents queuing additional commands.

13. mq.cmd('/twist off')

  • Turns off twisting (used for bards to cycle songs).

14. mq.cmd('/timed 5 /afollow off')

  • Schedules the command /afollow off to run after 5 seconds.

15. mq.cmd('/nav stop')

  • Stops navigation or pathing.

16. mq.cmd('/target clear')

  • Clears the current target.

17. mq.delay(100)

  • Pauses the script for 100 milliseconds.

18. mq.cmd('/nav locxyz 1222.67 -48.97 236.41')

  • Navigates the player to the specific location (1222.67, -48.97, 236.41).

19. mq.delay(15000)

  • Pauses the script for 15 seconds, likely to wait for movement or an event.

20. mq.cmdf('/%s mode 2', my_class)

  • Resumes the player’s class mode to 2 (active or combat mode).

21. mq.cmd('/mqp off')

  • Disables /mqp, allowing normal command queuing.

22. mq.cmd('/twist on')

  • Turns twisting back on.


23. end (Closing Braces)

  • Ends the if block and concludes the main logic of the function.

24. return {eventfunc=event_handler}

  • Returns a table (dictionary) that assigns the event_handler function to the key eventfunc. This makes it accessible to MacroQuest as an event handler.
 
Mostly a fairly reasonable list.

Some Nuance, though on a couple:

11./20. - specifically for changing status of the CWTN plugins
12./21. - pauses a running macro (KissAssist, MuleAssist, ModBot, etc.) second unpauses.
13./22. - pauses twist running from MQ2Twist plugin, unpause twist - not used with CWTN, pretty sure.
24. - this keeps the event running, I think - basically makes a loop of it, so it will run through event_handler over and over, until the line hits.
 
/Lua run @Algar make my bot better
/Lua run yay!😁
/dance

And now vahshir manual roombas…

funny cat GIF
 
This is wrong:

if not mq.TLO.Zone.ShortName() == 'vexthaltwo_mission' then return end


This is also wrong:

if not i_am_ma and (target == my_name or target == ma_name) then



you want ~=


Instead, you're using unary "not" on the first value which makes no sense.


ChatGPT is an awful programmer. never trust it.
 
I need to make a second post to emphasize this:

ChatGPT is an AWFUL teacher. You will learn WRONG THINGS because it will teach you stuff it literally made up on the spot. Inexperienced programmers will not be able to tell the difference. Case in point above
 
sad.. i stillhave a sample event in LEM all this time with not and == like that? that's one of those things i continuously write wrong and never notice til forever later in Lua, over and over and over again.
 
This is wrong:
if not mq.TLO.Zone.ShortName() == 'vexthaltwo_mission' then return end

This is also wrong:
if not i_am_ma and (target == my_name or target == ma_name) then

you want ~=

Instead, you're using unary "not" on the first value which makes no sense.
This is a good time to teach, as an experienced programmer, then. (not me, You)

In this instance, to my inexperienced eyes, "if not mq.TLO.Zone.ShortName() == 'vexthaltwo_mission' then return end" seems fine, although it feels like it reads funny.

You're specifying to use ~= which i interpret as "not equal to", and saying that a unary 'not' is in use. Maybe other people are smarter than me, but I don't understand what that means, let alone why it would not make sense. To an experience programmer, I'm sure it's quite clear and obvious, but there is a reason novice programmers are novices - they don't know better or don't know a better way or why the other way is better. That's the case here.

For example, when I do these lems, i do it this way, which is probably wrong too:
Lua:
local required_zone = 'zone_short_name_here'

local function doSomething(line, variableName)
    if mq.TLO.Zone.ShortName() ~= required_zone then return end
    -- actual function code here
end
 
not thing

this gives true or false. this "not" is unary, meaning it takes one parameter (the thing). its a boolean not. so false -> true and true -> false.

if the thing is falsey, it gives true. if the thing is truthy it gives false.

the only things that are falsey are nil and false.

so "not {anything other than nil or false}" is false

so

if not mq.TLO.Zone.ShortName() == 'vexthaltwo_mission' then return end

expands to

if false == 'vexthaltwo_mission' then return end

this condition will never be true.
 
This is wrong:

if not mq.TLO.Zone.ShortName() == 'vexthaltwo_mission' then return end


This is also wrong:

if not i_am_ma and (target == my_name or target == ma_name) then



you want ~=


Instead, you're using unary "not" on the first value which makes no sense.


ChatGPT is an awful programmer. never trust it.
Before you shoot the messenger, I did NOT write any part of the LEM script that was used in this example. I copied it directly from the LEM library and asked ChatGPT to breakdown and explain in common terms what each line is meant to do.

There is a bunch of great infomation on RG about Lua. However, to me, I still struggle to understand what I was reading. Having a basic rundown explaining the purpose of each line makes a ton of sense IMO :)
 
Before you shoot the messenger, I did NOT write any part of the LEM script that was used in this example. I copied it directly from the LEM library and asked ChatGPT to breakdown and explain in common terms what each line is meant to do.

There is a bunch of great infomation on RG about Lua. However, to me, I still struggle to understand what I was reading. Having a basic rundown explaining the purpose of each line makes a ton of sense IMO :)

In case it wasn't clear, I was attacking Chat GPT for not explaining it properly.

I probably should've said "The explanation of this is wrong". cest la vie
 
This is a good time to teach, as an experienced programmer, then. (not me, You)

In this instance, to my inexperienced eyes, "if not mq.TLO.Zone.ShortName() == 'vexthaltwo_mission' then return end" seems fine, although it feels like it reads funny.

You're specifying to use ~= which i interpret as "not equal to", and saying that a unary 'not' is in use. Maybe other people are smarter than me, but I don't understand what that means, let alone why it would not make sense. To an experience programmer, I'm sure it's quite clear and obvious, but there is a reason novice programmers are novices - they don't know better or don't know a better way or why the other way is better. That's the case here.

For example, when I do these lems, i do it this way, which is probably wrong too:
Lua:
local required_zone = 'zone_short_name_here'

local function doSomething(line, variableName)
    if mq.TLO.Zone.ShortName() ~= required_zone then return end
    -- actual function code here
end
not wrong per se, if it works.

it all depends on what is written around it. think of it like math, you don't want a bunch of extra positive and negative signs floating around, you want the lowest common denominator, all that jazz.

The code you listed could also look something like this (speaking generally):

Lua:
local function doSomething()
    if mq.TLO.Zone.ShortName() == "nameofshortzone" then
         -- actual function code here
   end
end

Just want to remind you guys that the #coding-questions channel on discord is... really awesome! You have a direct line to people that will commonly teach you things without even realizing it and are willing to answer questions. I've consistently seen people go the extra mile (especially for people who are also willing to help themeselves). I'm an amateur and I've soaked up a crap-ton of knowledge just from lurking. Don't sell yourself short, you may be closer than you think to running with all of this stuff.
 
This is a good time to teach, as an experienced programmer, then. (not me, You)

In this instance, to my inexperienced eyes, "if not mq.TLO.Zone.ShortName() == 'vexthaltwo_mission' then return end" seems fine, although it feels like it reads funny.

You're specifying to use ~= which i interpret as "not equal to", and saying that a unary 'not' is in use. Maybe other people are smarter than me, but I don't understand what that means, let alone why it would not make sense. To an experience programmer, I'm sure it's quite clear and obvious, but there is a reason novice programmers are novices - they don't know better or don't know a better way or why the other way is better. That's the case here.

For example, when I do these lems, i do it this way, which is probably wrong too:
Lua:
local required_zone = 'zone_short_name_here'

local function doSomething(line, variableName)
    if mq.TLO.Zone.ShortName() ~= required_zone then return end
    -- actual function code here
end

Theres nothing wrong in your example. I wasn't being subjective. The example i was quoting was actually broken.
 
not wrong per se, if it works.

it all depends on what is written around it. think of it like math, you don't want a bunch of extra positive and negative signs floating around, you want the lowest common denominator, all that jazz.

The code you listed could also look something like this (speaking generally):

Lua:
local function doSomething()
    if mq.TLO.Zone.ShortName() == "nameofshortzone" then
         -- actual function code here
   end
end

Just want to remind you guys that the #coding-questions channel on discord is... really awesome! You have a direct line to people that will commonly teach you things without even realizing it and are willing to answer questions. I've consistently seen people go the extra mile (especially for people who are also willing to help themeselves). I'm an amateur and I've soaked up a crap-ton of knowledge just from lurking. Don't sell yourself short, you may be closer than you think to running with all of this stuff.
I agree. I have learned a ton just lurking, asking questions, and backreading. I also do a search when I have a quesiton to see if it has been asked and answered previously.
 
Lua for Dummies

Users who are viewing this thread

Back
Top
Cart