Goto page 1, 2, 3  Next Public Macros Macro basics - a tutorial
Reply
Macro basics - a tutorial
Pretty much all macroquest commands, and all eq commands are co-mingled while MQ2 is loaded. This means that while you are in game you can type /target npc, and it will target the closest npc. This is a mq command. Alternatively if you are writing a macro, you can put /rude or /salute in it, and it will perform the same funciton it does when you type it in game.

Hello.mac

Macro
More +
#turbo

Sub Main
  /say Hello EQ!
/return



Way the start overly simple eh... dunno who's gonna be reading this so here we go.
#turbo can be set from 1 to 20. It declares the number of lines that can be executed per iteration. This stops bad macros from crashing eq.

Code is broken down into smaller modular parts called Subs. Imagine these as parts on an engine. The engine isn't built as 1 solid piece, its several modular chunks. If you carburetor goes bad you just pull it off and swap it. Same with subs, if your sub that makes you follow your tank goes bad you just have to work on that small sub, and not anything else in your program.

Sub Main - always remember that this is the first line of your code that macroquest will start executing. So the "/say Hello EQ!", which does the same thing it would in game will be the first thing out of this macro.

/return - for right now, all you need to know about this is it is the end of your Sub.

firstvariable.mac
Hello.mac

Macro
More +
#turbo

Sub Main
  /declare myvariable string inner Hello EQ!
  /say ${myvariable}
/return



A variable is a place to save information. Like a percentage that you want your cleric to heal your warrior at. Before you use your variable you have to declare it. /declare <name> <type> <scope> <value>. The name is just what you want to call it, it is case sensitive. The type is typically going to be string or int, which is text or number. The scope... this is where your code first starts to become neat or sloppy. Mine is really sloppy =). Inner means that it can be used within the Sub it was declared in, if you try to use it in another sub it wont exist there. This is very important. Say for instance you are using a variable to count a number "Index" and you use it to count spawns withing 100ft of you, and in another place you use it to count guild members within 10 feet of you. If those two subs execute at the same time, those values could get mixed up. If you declare them as "inner" then they only exist withing their own subprogram, and each one would be unique to its own sub, and they won't get mixed up. If you do need a value across all subs then you declare it as "Outer". The value is optional, default is NULL which means nothing. Since it is optional I could have set it later, like this:

Macro
More +
/declare myvariable string inner
/varset myvariable Hello EQ!
/say ${myvariable}


Referencing variables: There are two ways to use a variable, by reference and by value. By reference is like saying someones house address. By value is like saying "Blue house, with red door." A byvalue looks like this "${myvariable}" ANYWHERE this apears in your script will get replaced at runtime with whatever value is there. This can sometimes be hard to wrap your mind around. Notice /varset and /declare dont use the ${} syntax. Thats because those are byreference methods. By reference is looking at the location... the house address. It represents a location in memory. Declare creates the location, and /varset puts a value into the address.

To maybe Illustrate this a little better take a look at this.

Macro
More +
/declare myint int inner 4
/varcalc myint ${myint}+1
/say ${myint}



New command here.. /varcalc, this is used to not just set a value in a variable, but to do some basical calculation to it. What I'm going to do to try to illustrate what is going on here behind the scense is im going to change the referent access to a memory address, and the value access to the actual value save there.


Macro
More +
/declare 9AB9 int inner 4
/varcalc 9AB9 4+1
/say 5



I hope that makes a little more sence like that. in the declare your opening memory slot 9AB9 up to hole an integer, and putting a 4 into it. In varcalc you putting 4+1 into that meomry slot. And in /say your saying 5, the value saved in that memory spot. It might be worthwhile for me to say that byreference only works with certain commands. By value works pretty much anywhere. If i put /say myint, you will literally say "myint" on your screen, not some wierd memory address or something.


Conditionals:
Conditionals are pieces of code that only execute if a value is TRUE. This may seem at first a little odd.. what if I want to do something if a value is false... well there is a way around it so just wait. Some information first. TRUE, and anything greater than 0 is TRUE. FALSE,NULL, and 0 are all FALSE. || means OR. && means AND. ! means NOT. So there are all the values you need to know to work with conditionals. TRUE FALSE AND OR NOT. The basic format of an /if statement is "/if ( <condition here> ) <command here>" if you do a single command. Multiple command looks like this"
Macro
More +
/if ( <condition here> ) {
<command here>
<command here>
}


Game data:
MQ also makes a large ammount of data available to you at runtime. For instance ${Me} will give you access to your name. ${Me.Attacking} will give a TRUE if you are attacking FALSE if not. Pretty cool eh? Now lets put this together.


Macro
More +
Sub Main
  /if (!${Me.Sitting}) /sit on
/return  


If you are standing this will make you sit. If you are sitting it does nothing. Lets break it down. The ! is a NOT. So now its "NOT${Me.Sitting}" If you are sitting then Me.Sitting returns a true. So now its "NOT TRUE", and no true is "FALSE". and remember the code only gets executed if the condition is TRUE. We got a false so it doesnt make you sit. If your standing the Oposite would happen. You would get a "NOT FALSE" and it would get changed to "TRUE" it would execute and you would sit down.

This only does it one time... i wanna do it constantly so my caster is always sitting. Well we need a loop then. We wil start with the infirnite loop that is usually found in the Sub Main. We will also add some extra stuff to the condition to make sure you don't interupt casting and stuff. I'll also change the /if to the multiline format so you can see it.


Macro
More +
Sub Main
  :mainloop
    /if (!${Me.Sitting}&&!${Me.Casting}&&!${Me.Moving}) {
      /sit on
    }
    /delay 1
  /goto :mainloop
/return



OK! :mainloop is a placeholder, a label, it does nothing =). The /goto we added at the end sends program flow back up to that label. You can name them whatever you want. The /delay 1 i added in there makes it wait a tenth of a second wanna be careful in infinite loops you can spam so much crap out of a loop that the your chat screen will keep spaming text even after you turn the macro off. The loop is easy. The most confusing part is the (!${Me.Sitting}&&!${Me.Casting}&&!${Me.Moving}) so lets break it down to see what is happening. Sitting, Casting, and Moving all return True of False. So I'm just going to take them out of variable form and replace them with words. (!SITTING &&!CASTING&&!MOVING)
&& is AND. (!SITTING AND !CASTING AND !MOVING) and lastly the ! is NOT. IF (NOT SITTING AND NOT CASTING AND NOT MOVING) THEN SIT. I hope that makes sence.

So if you are running it wont make you sit, as soon as you stop moving. Same with casting. as soon as you stop casting you will sit.
_________________
Give me your land!
Fri Feb 27, 2009 4:34 pm
Co-Founder (Retired)
what about doing something when you recived a tell/group/guild/chat channel msg?
Thu Aug 26, 2010 10:25 pm
Macro
More +
#event example "#1# says, 'heal #2#'"

Sub Main
:loop
/doevents
/goto :loop
/return

sub event_example
/target ${Param2}
/cast ${HEALSPELL}
/tell ${Param1} I healed, ${Param2}
/return


the #event line sets up an event, the sub event_xxx is the handler.

the #1# is a wildcard that saves its value as Param1, a #*# is a wildard that wont save.

If you need more in depth let me know.
Last edited by Maudigan on Sun Dec 05, 2010 8:39 pm; edited 1 time in total
Thu Aug 26, 2010 10:40 pm
Project Lead
also, if you followed that, you might look at some of the other macros people have posted for more elaborate examples.
Thu Aug 26, 2010 10:40 pm
Project Lead
Maudigan, I think that right there might be enough thank you. Ive been trying to figure out by looking at others macros that i been able to find but there soooo..... well cluster fucked IMO

I just need some vary Basic macros that can listen to what i tell them lol.
Thu Aug 26, 2010 10:59 pm
nice what about grabbing the location and heading of someone?.

for example, if i targeted a player and wanted the macro to grab his location then use that location in the next command like sending that that bot to that location to stay there?. dunno if that made any sense at all.

Sub Hold
/target ${parma2}
/get.location?
/moveto $location?
/return
Thu Aug 26, 2010 11:44 pm
Use the ID

WHen I send a command to one of my toons from my warrior I tell them to targe the ID of my target. Same for /moveto

don't use a macro, jsut have the commander issue a moveto command I use eqbc for this.
First aquire your target. then simply use the below command.

/bct BOTNAME //moveto ID ${Target.ID}

or to tell everyone else to move
/bca //moveto ID ${Target.ID}

or to tell everyone including myself
/bcaa //moveto ID ${Target.ID}
_________________
Sorvani
Fri Aug 27, 2010 12:00 am
Senior Project Member
now is that gonna cause them to follow me? or just move to me and stay there?. i was gonna use the HOLD command as a "This is camp" type deal. but for indivual bots.
Fri Aug 27, 2010 12:26 am
I havent used it in awhile but I think its the /stick command that makes them follow. Check out the documentation on mq2moveutils.
Fri Aug 27, 2010 8:25 am
Project Lead
That is a move to command. so it only moves them to the targeted person.

Follow is the /stick command. For following I use the following two lines in my button
Macro
More +
/pause 2, /bca //squelch /target clear
/bca //stick ID ${Me.ID} hold !front uw


Then a stop follow button
Macro
More +
/bcaa //stick off

I used /bcaa as a lazy way to make sure I stop my main from any /stick i manually had him doing too.

If you want to set a camp, that is the /makecamp command. It requires a set of XY coordinates. Again I would not do it with a macro. I do not use the /makecamp function so this may require a tweak for syntax or something. Again, use /bct TOONNAME, /bca or /bcaa as nedded in your hotkey. They below is telling everyone except me (/bca)
Macro
More +
/bca //makecamp ${Target.Y} ${Target.X}
/bca //makecamp /leash 10

First set the camp at the target's coordinates. then turn on the leash with a 10 unit leash. That should make anyone outside of 10 units run to the camp.
_________________
Sorvani
Fri Aug 27, 2010 8:25 am
Senior Project Member
how do i fix a "failed to parse /if statement" error?
Thu Oct 28, 2010 12:05 am
Post your macro
It could be 100 diff issues
Thu Oct 28, 2010 6:20 am
Project Lead
sorry it was late when i posted that let me be a little more specific.

I am trying to do a simple macro that checks if my bard is casting and if not then to use /melody. I used this guide to set up an if statement and a loop but i continue to get that error

Macro
More +

#turbo
Sub Main
  :mainloop
  /if (!${Me.Casting}) { /melody 1 2 3 4 }
  /delay 1
  /goto :mainloop
/return  


I am extremely new to this so sorry if it is an obvious mistake.
Thu Oct 28, 2010 6:45 am
Me.Casting returns a spell, the default element of a spell is ToString. So it's the same as typing Me.Spell.ToString with a NOT in front of it. NOT a string isn't computable. It needs to be a number or a true/false to use !. try Me.Casting.ID

If you are casting it will be the spell Id, otherwise it's 0
Thu Oct 28, 2010 7:22 am
Project Lead
You didn't reply so i assume you figured it out, but I would like to add you don't need to use the { } on a single line /if. This is all you need.

Macro
More +
/if (!${Me.Casting.ID}) /melody 1 2 3 4


Also I personally prefer MQ2Twist to /melody.

Macro
More +
/plugin MQ2Twist

/if (!${Me.Casting.ID}) /twist 1 2 3 4


/stopsong will stop a twist or you can use /twist off
_________________
Sorvani
Wed Nov 03, 2010 8:18 pm
Senior Project Member
Goto page 1, 2, 3  Next Public Macros Macro basics - a tutorial
Reply