Part 1 Ok, here's the deal guys... I love you all, but I can
not write macro after macro after macro for each and every one of you
endlessly. So, to that end, I'm writing this basic tutorial on macros.
If you need help with the finer points, PM, we can talk, get it sorted
out, whatever, but after the posting of this, I'm not writing anybody
anymore macro's. Seven games guys, I've written macros for just shy of
everyone in seven games; I'm burnt out. Now, you may be asking
yourself: "Why do I need macros?" Well, the simple answer is,
simplicity. You can use macros for a huge variety of things, from
special languages, to attack rolls with custom flair, to nice organized
math, you name it. Well, where do we begin? How about with the most
important macro tool of all (my opinion): The Query. The Query, is a question, much as its name implies. It is expressed as >>> ?{Question?|Value} <<< Now, it can get more complicated of course, but let's start with the basics. You've
got a variety of things you can do with a query, like, ask yourself a
question, remind you to fill in that one thing, or quick tabulate
something. Let's look at a few examples and how these affect you: Value: ?{How much are you adding?|0}
Now, typically, this won't be seen alone like this, because,
frankly, what good would it do? It asks you a question, you enter a
number, and then what? Aha, see, now here is where it gets fun. Let's
try adding a current value to it: [[?{How much are you adding?|0}+@{gold}]] Now that's a bit better. What we've done is tell the system, "I want to do math" by adding the [[ ]]
elements. Everything in this "box" will add, subtract, multiply,
divide, use algebra; whatever you tell it really. In this case, we are
asking to pull the value for the element named "attr_gold" and add it to
the number we input. Please put the total number in a boxed roll and
output to chat. But, question? Who's gold value? We'll get into this
more a little later. Target: ?{Who is your {target}?|@{target|token}}
This is a tricky little sucker. Now you are using the query to not just
ask you a question, but to ask you to select, and name something. This
can be useful with a bigger macro to do things like, announce the target
of your next attack: ?{Who is your {target}?|/me points their sword at the next opponent selected to die! @{target|token}!}
What this does, is ask you, "Who is your target?" and then provides you
a click tool with your mouse. This click, when you left click on a
token, will pull the "attr_token_name" and output to chat, in an emote
"Seth points their sword at the next opponent selected to die!
Orc#73,419!" Speech: ?{What do you say in Elvish?| }
But wait, there's no value, right? Wrong, look closer, there's a
[spacer] in there. Ba-boom, you have a text macro query! Now, what good
does this do? Let's try making a language macro: /w Language(Elvish) ?{What do you say in Elvish?| } <enter> /me says something in the singing voice of the Elven people!
Now, what good is that? I'll let you figure out the rest of what goes
into that, but the premise is that you whisper to the language, so
anyone who has it can "hear" you, and everyone who does not have the
language, sees instead "Seth says something in the singing voice of the
Elven people!" Multiple Choice: ?{Which skill are you
using?|@{repeating_section_$0_objectname},/me makes a(n)
@{repeating_section_$0_objectname} check:
[[3d6]]≤[[@{repeating_section_$0_objectstat}]]|@{repeating_section_$1_objectname},/me
tries their hand at a(n) @{repeating_section_$1_objectname} check:
[[3d6]]≤[[@{repeating_section_$1_objectstat}]]} Holy Moses on
a Jalepeno Stick, that got long! Well, no, not really, but it certainly
looks longer eh? Let's examine this. This query gives us two choices,
that are named after the stat names in the desired section of a
repeating field. Whoa! Let's slow down eh? By putting two elements, you can specify a target and value for that target: " ?{Which skill are you using?|@{repeating_section_$0_objectname},/me
makes a(n) @{repeating_section_$0_objectname} check:
[[3d6]]≤[[@{repeating_section_$0_objectstat}]]| " Let's examine
this portion. First, you ask yourself a question. A drop down box
appears with two options. Let's ignore the second option for now. The
first option will have a name, let's say, from the proficiency section.
Let's call this option Healing. So the first option is named Healing,
what does that matter? Well, notice how after that comma, that the same
field is called again? When you select that first option, your output
will be, "Seth makes a(n) Healing check: ....." Using this method allows
you to get creative with your flavor text since you can switch the rows
around in your character sheet and Ba-boom, they are always correct,
and different! Now, what the heck is ≤ ? It's
an html expression that reads as a lesser-than-or-equal-to sign. And
yes, roll20 uses these. You can of course, just put a < sign, but
where's the fun in doing the things the boring old easy way?! Now then, those pesky calls, what are they? Well, those @{}
values, allow you to make a sort of tether between a given attr_ and
some other field. Macros written in your own sheet, in the Attributes
and Abilities section are pretty easy, you just need the name of the
field you want to call: think @{HP} bam, you pulled your HP value. But what about @{HP|max} ?
Mm... that's not "quite" as simple. Because it's a Max value, you need
to define its base parameter first. This is as simple as adding your
character_name. @{Seth|HP|max} sure, it looks a little different, but
this is important to note. As explained here: What if your macro is not in your sheet? Well, you need to call the sheet that has the value you want first. @{Seth|HP} This tells it to find the sheet named Seth, and pull its attr_HP value. Hang
on, what about that "repeating and numbers and dollar signs and stuff?
Ok ok, look, I'm sure you've seen these in your sheet at some point: a
button that says Add on the left, and one that says Modify on the right,
yeah? Those are repeating sections. To define a repeating section call,
you have to first, define it is a repeating field, @{repeating_ then define the name of that section @{repeating_proficiencies_
from here, we need know what line to pull from. The field always starts
at 0, and goes up by 1 per line going down: 0, 1, 2, 3, 4, etc. The
dollar sign is the precursor to pulling this number, so @{repeating_proficiencies_$0_ line 1 as it were. Now we need to define the element we want, @{repeating_proficiencies_$0_abilitystatname} and ba-boom, you have a call for a repeating section. Keep in mind, if you aren't building the macro in your sheet, you will need to specify which sheet you are calling. @{Seth|repeating_etc etc The second selection is built the same way, but, is of course, a second option. Well, now what? I'll tell you what! Let's learn about "either/or" macros. Note: These are not, if then so much as either or. Either/or
are very simple, you give two defined values, and a selector to pick
one or the other depending on the criteria you want. Now, you may be
asking yourself, what does this have to do with anything? I'll show you,
with a D&D classic, Magic Missiles [[ [[ {floor(@{level-class1}/2), 5}kl1]]d4+[[ {floor(@{level-class1}/2), 5}kl1]]]] "ARGH MY BRAIN!!!" Hold up, I got you. Let's break this apart in pieces. First: [[ [[
< That, right there, what are we doing? We are sub parsing math.
What does that mean? Well, you know how in algrebra, is you put 5+(4+2)
you are supposed to add 4 and 2 first, then add the total to 5? Same
thing. We are saying, we want to do an equation, but we need to do this
one first. Why not just use parentheses? Simple, totals. [[ ]] gives you
a total. ( ) defines the order of operations. If you'll notice, there
are parentheses in there, because we need things to happen in a certain
order within that part too. So, what is happening? {floor(@{level-class1}/2)
let's look at this part. We are saying, we want you to take the class
level, and divide by two. Any fractions should be rounded down (floor)
(there is also round for rounding and ceil for rounding up every time) {floor(@{level-class1}/2), 5}kl1
What about that last part? Well, in either or, you can define your
choices with commas. You can have more than 2 choices too, but it starts
to get hairy from there. In this case, if the level divided by two,
rounded down is less than 5, kl1 keeps the lowest result. If 5 is lower,
it keeps that instead. This allows you to "auto-level" your magic
missile, without having to ever bother with it again. The d4 is a
placeholder. It is waiting for the first box to resolve so it knows how
many d4 to roll. The last part is the same as the first, but instead
just outputs a static value. Ok, we've covered some of the basics, so let's go into specifics: Repeating calls: What
is a repeating call? Well, simply, it is you asking the same question
over and over again, and autofilling the same result over and over
again. What good is that? Let me show you. /me lays a
hand on ?{Who?|Seth,Lynn|Mark,Cable|Luke,Anthony} healing them for
[[2d8+1]], Save vs. Spell, if successful, a damage shield is gerenated
on ?{Who?|Seth,Lynn|Mark,Cable|Luke,Anthony} for @{level-class1}
temporary HP! But wait, you already know your target is
(whoever you selected), why do you need to say again? Sorry, I've
played a lot of D&D over the years, and one amazingly constant
factor is, people don't pay attention unless it has to do with them.
They see HP healed, cool... stopped reading right there, I can almost
guarantee it. With their name in there again though, they say, "Hold up,
what's this?" and ba-boom, you've got a fluid and working macro. For
those who aren't following. It will not ask you twice who you are
selecting. The question and answers are all the same, so it will ask
once, and remember the result for the second inquiry. NO, you cannot put
different answers in and expect it to work, because it will not. You
can however, put a different question in, and it will ask you the
second question, even if the answers are all the same as the first. Limits: Queries
have a limit built into them, and macros do as well. I don't know the
actual limits, but suffice it to say, putting a lot of stuff in will
result in some things not being asked, and the whole thing failing to do
anything output wise. I know for example, that putting 60 different
rolls and trying to get a number of either/or sequences to shorten them,
results in about a 30 delay to anything happening while the system
tries to process all of that. Part 2 Now, we're back, please ignore the "words from our sponsor - Taco Bell". So,
you've got a cool query, but, suddenly, a problem arises, "I need to
put a either/or function into my query!" Wait, why is this a problem?
Because either/or functions require the use of, a comma! This break's
queries remember? Well, to be honest, there are other symbols that break
queries too, so lets have a look at those. | the bar, this item, is a necessary piece in macros, but sometimes, using them can break your macro. } a closed curly brace? Yup, believe it or not, these suckers can prematurely end your macro, accidentally. , a comma. You know it. These things spell doom for a would be macro writer. &
the and sign. You know, I've never personally had a problem with these,
but they can sometimes cause all kinds of havoc I hear. So,
we've identified some culprits, now what? What do we do about them?
Well, we'll get to that, first, lets take a look at the wheres of
things. Where does this typically become an issue? Frankly, in
globalized calls. What's a call? Well, you may remember that calling is
what macro's do to attr_ values. Did you know you can also call other
macros? Inside your macro? Yeah, you can. It's called nesting, and it
sucks, horribly. No really, hear me out. A localized (inside the sheet)
macro, can call a globalized (Player level) macro with the denotation #
<that being the pound sign. But the problem is this: Globalized macros reset every time you open them. Globalized macros can only be called from a drop down. I'll explain why these things suck so much in the next little stretch. So you wanna call a macro? Why? Well, here's a few good reasons: You've written a macro that you don't want to write 75 more times, so just write the call instead. No, really, that's like, pretty much the only reason. So,
what's the big deal? Well, we know that those symbols above are going
to give us grief, and we need to get around that. Introducing! HTML
Escapes! These allow you to write those symbols, without writing the
symbols (in all but one case...) (kind of...). These hav eto written fluidly. DO NOT SPACE THEM OUT LIKE THIS. I only did this because the forum formatting autoparses the codes. | the dreaded bar! Can also be written as & # 1 2 4 ; } the curly brace! Also known to some as & # 1 2 5 ; , the deadly comma! Known to a few as & # 4 4 ; & the, weird, and sign... Try this out... & a m p ; <I have no freaking clue... So,
yeah, what do we do with these? Well, we replace stuff that's
problematic in the globalized macro, so it doesn't bite us in the
backside on our localized macro. Hmm... Wasn't there something about
these things resetting all the damn time...? So here's the catch.
Not all symbols are problematic. Replacing ones that aren't will cause
problems, and failing to replace all of the ones that are will cause
problems. You really have to go through it step by step and identify the
troublemakers. But! Once you have identified one, you have to replace
it every time you open the macro to work on it. The reason being... they
reset. Using html escapes will cause the system to replace all of them
with their corresponding symbols once you open it again. It's redundant,
but if you're patient, and persistent, the results can be fabulous. Using this, you can make one macro like, [[ [[ { floor(@{character_name|level-class1}/4), 5}]]d6]]
as a globalized macro, and then come to your localized query: ?{Which
spell effect?|Damage,/me blasts their foe for #DamageMacro
damage!|Sleep,/me causes sleep to befall the opponent!|Nightmares,/me
causes sleep to befall their opponent! They suffer #DamageMacro
additional damage if they don't wake up soon!} So, yeah, bit of a space saver, time saver thing. Super useful, usually boatloads of trouble to get right. Part 3 Hyper-nesting. Yes, I'm aware that the term is incorrect, but, sue me, I'm not a licensed professional... What
is it? Well, it's a shorthand way of saying, "I'm putting a query
inside a query, with a query, that has a query inside it." Confused yet?
Good, this stuff took me 3 whole days to figure out... Now
then, so you want to put a query inside a query? What good would that be
you ask? Allow me to show you, with one of the most overused macros in
any edition of D&D. Cure Light/Serious/etc Wounds. Well,
normally this could be expressed as a simple, [[d8]] right? True, in
AD&D2E core. But what about houserules? What about, having a drop
down list all of your first level spells? Well, let's try that then eh? ?{Cast Which Spell?| @{repeating_spells_$0_spellname} ,/me casts @{repeating_spells_$0_spellname} slamming [[{floor(@{level-class}/2), 5}kl1]] missiles of force into their opponent for [[ [[ {floor(@{level-class1}/2), 5}kl1]]d4+[[ {floor(@{level-class1}/2), 5}kl1]]]] damage!| @{repeating_spells_$1_spellname} ,/me casts @{repeating_spells_$1_spellname} healing ?{Who?|Me,myself|Josh,Rarknald|Mark,Gynnie} for [[d8]] points of health!} Now then, looks alright eh? Yeah, whatever, try running it.... BOOM, errors galore. What's
wrong? Well, remember those html escapes we talked about? This is what
they are good for. Let's re-write that, and I'll explain after what
changed and why ?{Cast Which Spell?| @{repeating_spells_$0_spellname} ,/me casts @{repeating_spells_$0_spellname} slamming [[{floor(@{level-class}/2), 5}kl1]] missiles of force into their opponent for [[ [[ {floor(@{level-class1}/2), 5}kl1]]d4+[[ {floor(@{level-class1}/2), 5}kl1]]]] damage!| @{repeating_spells_$1_spellname} ,/me casts @{repeating_spells_$1_spellname} healing ?{Who?& $ 1 2 4 ;Me& # 4 4 ;myself& # 1 2 4 ;Josh& # 4 4 ;Rarknald& # 1 2 4 ;Mark& # 4 4 ;Gynnie& # 1 2 5 ; for [[d8]] points of health!} Woah...
looks like, and smells like, veganism... complicated and
unsatisfying... What happened? First, I replaced the problem codes, with
html escapes. But, there are still } and | and , in there... Yes, yes
there are. Those are are not problematic though. Well how do you tell
the difference? I'm glad you asked. Primary lines, like functions in the first question, do not need to be replaced. Tertiary lines, like function in sub questions, do need to be replaced. Either/or is not a supported function in a query, so you have to trick it. Take out the problem codes, boom, it works. Attribute calls are supported, all the time. Do not replace the problem } with html escapes or it will not work properly. Following
these seemingly simple guidelines, is deceptive. There's more to it,
but this is just a basic tutorial, not a gold mine, so go digging for
your future in coding elsewhere :) I hope this helps most people
understand the basic of macros in their games. There is stuff that was
not covered, like &{tempalte:default} because it doesn't apply to
many games and the logistics are severely different in others. There is
already a whole section on macros in the roll20 wiki page. If you have
any questions that you feel were not covered here feel free to shoot me a
PM at <a href="https://app.roll20.net/users/877778/sfx" rel="nofollow">https://app.roll20.net/users/877778/sfx</a> and I'll be happy to help however I can.