More Branching Options/ja

From RPTools Wiki
Revision as of 23:09, 14 March 2023 by Taustin (talk | contribs)
Jump to navigation Jump to search

Languages:  English  • 日本語

INTERMEDIATE
THIS IS AN INTERMEDIATE ARTICLE


はじめに

This is a guide to the "advanced" macro branching option, [macro():].

これはマクロの分岐オプションの中でも「高度」な [macro():] についてのガイドだ。

MACRO: 他のマクロを実行する

One of the best practices when you write macros - especially when they become complex - is to keep them streamlined and lean, and only have them do what they need to do - for instance, if you have a macro that adds a skill to a token, it doesn't need to be the same macro that checks to see if an attack hits, or records damage taken. It just adds skills.

マクロを書くとき、特に複雑なものを書くときに一番いいのは、すっきりと簡潔なものにして、必要以外の処理だけに絞ることだ。例えば、トークンに技能を与えるマクロを既に持っているとしたら、、攻撃の命中判定やダメージ・トークンを記録するといった機能をそのマクロに追加するべきではない。技能だけにするのだ。

Writing macros this way - each macro doing something relatively small - is a good way to keep yourself organized and keep your macros clear (it also makes them easier to fix if something goes wrong!). What's more, it helps keep your memory use lower, so you don't get run into stack overflow errors or, more commonly, slow macros.

こういう、つまり比較的小さな機能のみを持つようにするやり方は、中身を理解しやすいし、見通しもよくなる(し、何かおかしなことが起こったときに修理もしやすい)。さらに、メモリの使用量も減らせるから、stack overflow errorsや、よくある実行速度の低下を起こさないで済む。

But if you do this, how can you make one macro run based on another one - surely, you don't want to have to hit each button every time something happens, right? Enter the [macro():] roll option.

だが、これを実践するためには複数のマクロを連携させる必要があるが、それはどうやったらできるだろうか? 当然だが何か起こるたびに自分でいちいちボタンを押すなんてごめんだよね? そこで [macro():] ロール・オプションの出番だ。

どんなことをするのか?

The [macro():] roll option is they way you can have one macro - the calling macro - trigger another macro, which we call the called macro. The calling macro can send some information to the called macro, where that information will be handled and processed and probably changed, and then, if you like, the called macro can send some information back to the caller.

[macro():] ロール・オプションは、あるマクロ(呼び出し側)が別のマクロ(呼び出され側)のマクロを起動できるようにする。呼び出し側マクロは呼び出され側マクロに情報を送り、その呼び出され側マクロでこの情報を処理し、だいたいは編集して、それからもし必要なら呼び出され側から呼び出し側に別の情報を送り返す。

どうしてそんなものを使わなきゃならないの?

Where this comes in handy is in three circumstances: first, when you have some operation that you're always doing, but you have several different ways that it might come up. Second, if you have a macro that everyone uses. The second, and more powerful use, is when you want to manipulate another token besides your own - then you frequenly need to use called macros, because there are some things only a called macro can do!

このオプションが便利なのは以下の三つの場合だ: 第一に、通常行っている処理とは別の処理を時々やらなければならない場合。第二に、みんなで使うマクロが欲しいとき。第三に、この中でも一番強力な使い道だが、自分自身以外の複数のトークンを操作したいとき、だ。この場合、呼び出され側のマクロを頻繁に使うことになる。なぜなら、呼び出され側のマクロにしかできないことがあるからだ。

複数箇所から共通の処理を呼び出す

Let's look at the first benefit: take, for example, a macro that applies damage to a token in accordance with the Sample Ruleset (in other words, it looks at a token's properties, and then deducts damage from the token's HitPoints property). How many ways can you think a token might get damaged?

第一の利点について見てみよう。例として、Sample Ruleset に合わせてトークンにダメージを与えるマクロを考えてみる(つまり、トークンの属性値を参照し、そのトークンのHitPoints属性値からダメージ分を減らすマクロだ)。そのトークンがダメージがどれほど沢山のパターンでダメージを受ける可能性があるか分かるかな?

  1. It could get damaged by an attack from an enemy
  2. It could get damaged by an attack from a friend (accidental or otherwise)
  3. It could get damaged by falling
  4. It could be damaged by a trap
  1. 敵の攻撃
  2. 味方の攻撃(事故だったり、そうでなかったり)
  3. 落下
All kinds of ways. Now, suppose you have three macro to handle damage. These macros are called Enemy Attack, Friendly Fire, and Environmental Damage. Each of these causes a token's HitPoints to be reduced, but each also has some special processing to determine just how much HP reduction takes place (it's not important what the special processing is at the moment).

ありとあらゆるパターンがありうる。さて、ダメージを扱うマクロを三つ持っているとしよう。このマクロはそれぞれEnemy AttackFriendly FireEnvironmental Damageと呼ばれている。それぞれのマクロはどれも対象となるトークンの HitPoints を減らすが、どれだけ減らすかはマクロごとに別の特別の処理を持っている(この特別な処理の中身は、今は重要ではない)。

So you have three macros, but each has a common element: they all in the end reduce the token's HitPoints. Consider a couple alternatives - you can:

三つのマクロがあるが、共通の要素を持っている。そのどれもが最後にはトークンの HitPoints を減らすということだ。いくつか選択肢を考えてみよう。こういうことが考えうる:

  1. Write each macro separately, including the calculations to reduce HitPoints; or
  2. Write a fourth macro, containing just the calculations to reduce HitPoints, and have the three damage handler macros call that fourth to handle the final calculations.
  1. それぞれ HitPoints を減らす部分を含むマクロを別々に書く
  2. 単に HitPoints を減らすだけの第四のマクロを書き、ダメージを扱うその他三つのマクロからこの第四のマクロを 呼び出し て、最終的な計算を行う
The advantages of the first option are that you only need to write three macros, and you're done. On the other hand, what if you realize you made a mistake in your damage macro? You then have to edit it in three places. In the second option, you only edit one copy of the damage macro.

最初の選択肢の利点は、マクロの数が三つで済むことだ。だが、逆に考えると、もしそのマクロに何かの間違いがあることに気づいたらどうなるだろうか? 書き直すべき箇所が三ヶ所あることになる。二番目の選択肢では、ダメージを与えるマクロだけを修正すればいい。

みんながやる作業

Building on the example above, if you have a whole bunch of macros that everyone uses (perhaps everyone needs to have a way to attack, to defend, and to take and heal damage), you can create a single set of macros that everyone simply calls, rather than duplicating every macro on every token, every time you need a new token on the map.

上の例に基づいてマクロを作っていくと、みんなで使うようなマクロ(攻撃、防御、ダメージを受ける、ダメージから回復するなどは誰もが使うだろう)が沢山あった場合、みんなが呼び出して使うマクロが一そろいあればよくて、新しいトークンがマップ上に生まれるたびにそこに全てのマクロをコピーしなくて済む。

So, for example, you may want to build a "library" of macros to handle your game (whatever game it happens to be), and then create a single set of macros on your tokens that do nothing but call macros in the library.

そんなわけで、あなたは自分のゲーム用の「ライブラリ」を作ろうと思うかも知れない(どんなゲームかはさておき)。そしてそれから、自分のトークンを作って、ライブラリ上のマクロを呼び出すマクロだけを載せておくのだ。

You'll note that it doesn't mean you have fewer macros overall - every token still needs a set of macros to call on the library; however, it does mean that your actual complex macros (the ones that took you a long time to write) are all in one place, and you only need to alter one copy in order to fix an error. If you'd copied the entire macro set to every token, you'd have to fix every single token one at a time to fix any mistakes you made.

必ずしもマクロの総数が減らせるとは限らないということに気づいた人もいるだろう。それぞれのトークンにはライブラリを呼び出すためのマクロが必要だ。だが、あなたが(手間隙かけて)作る本当に複雑な部分のマクロは一ヶ所にまとめておくことができるのだ。そしてエラーがあったなら、その一ヶ所を修正するだけで済む。もし全てのトークンにありとあらゆるマクロをコピーしておくのだとしたら、エラーを修正するには一つ残らず全てのトークンを修正しなければならないのだ。

他のトークンに対する操作と、信頼されたマクロ

Generally, when a token runs a macro, or calls a macro, the macro assumes that all properties and variables it needs to use apply to the token running the macro. So if Bork the Brave calls a macro in a macro library, that library macro is going to assume that it needs to do its thing on Bork the Brave.

一般に、トークンがマクロを実行したり呼び出したりするときには、実行に必要な属性値や変数はそのマクロを実行しているトークン上にあるものと想定している。従って、勇者ボークがマクロ・ライブラリの中のあるマクロを呼び出した場合、そのマクロは勇者ボーク上のものに対して処理を行うものと考える。

However, sometimes Bork the Brave does not want this - maybe Bork the Brave just whacked a troll with his sword, and wants the damage to be applied to the troll (and, by extension, most definitely does not want the damage applied to himself!). He's going to want a macro that will affect the troll's token, not his own.

しかし、勇者ボークにとってそれでは都合が悪い場合もある。おそらく、勇者ボークは一匹のトロールを剣でぶん殴って、そのダメージをトロールに適用して欲しいのかも知れない(だから、そのダメージが自分に対して適用されるなんてことは絶対あって欲しくないはずだ!)。彼に必要なのは、自分のではなく、トロールのトークンに対して効果を及ぼすようなマクロのはずだ。

As it turns out, however, there are some things, as mentioned, that a regular old macro on a player token simply can't do. For instance, a macro on a player token can't go and determine what an NPC token's properties are. It's simply not permitted to access another token. I think you'll agree this is a good way to go - you may not want players being able to see property values on an NPC. Furthermore, a player token macro can't change values on another token. Nobody wants the players to be able to, for instance, reduce an enemy's armor value to zero just before making an attack.

さて、ここで問題になるのは、これまでも言ってきたとおり、プレイヤー・トークンに載っている昔ながらのマクロでは、これができないのだ。例えば、プレイヤー・トークン上のマクロは NPC トークンの属性値を操作できない。他のトークンへのアクセスは許されていないのだ。この事自体には納得してもらえると思う。プレイヤーたちに NPC の属性値を見られては困るからだ。さらに言えば、プレイヤー・トークンのマクロは他のトークンの値を変更することはできない。NPC に攻撃をかける前にそいつの装甲値をゼロに下げられるようでは困るからだ。

But still, we want to be able to do some things to other tokens, right? In response to that, the concept of trusted macros was developed. Trusted macros are simply macros that can perform certain functions unavailable to other macros, such as the functions that manipulate token properties other than the ones on the token who called the macro.

だが、そうは言っても、他のトークンに対して多少何かをしたいよね? その対応として信頼されたマクロの概念が考案された。信頼されたマクロとは、そのマクロを呼び出したトークン以外のトークンの属性値を操作するなどの、他のマクロにはできないことが可能なマクロのことだ。

どうやって使うの?

[macro():] is a roll option, so, like other roll options you've seen, it is put at the beginning of a line and ends with a colon. The essential format of the [macro():] roll option is:

[macro():] はロール・オプションなので、これまで見てきた他のロール・オプションと同じように、行の先頭に置き、最後はコロンで終わる。[macro():]の基本書式は以下の通り:

[MACRO("macroName@Lib:token"): macro_arguments]
[MACRO("マクロ名@Lib:token"): マクロの引数]


In the above example, there are several parts:

上の例の中にあるパーツは以下の通りだ:

  • The opening and closing square brackets ([ ]), which surround all macro commands in MapTool
  • The word "MACRO" (it does not have to be capitalized; that's done to keep it noticeable!), which is just the name of this particular roll option
  • macroName: this is the name of the macro you wish to call
  • @: this is used in the same sense as in an email address - it means "at"
  • Lib:token: this is the Library Token that contains the macro you wish to call. Library tokens are a complex subject, but you can think of them as a single token that holds a "library" of macros, that can be called by other tokens or call each other.
  • macro_arguments: an argument is a programming term for information that you send to a function (or in this case, a macro) that you want the function to do something to. If you had a function that added two numbers together, the numbers you send to it would be the "arguments" to that function.
  • MapToolが持つあらゆるコマンドを囲む、一組の大カッコ([ ]
  • "MACRO" というワード(大文字でなくても構わない。目立つようにこうしてあるだけだ)。これはこのロール・オプションの名前だ。
  • マクロ名: これはあなたがこのマクロにつけた名前だ。
  • @: これはメールアドレスと同じ使い方だ。意味は「at(=~の場所の)」だ。
  • Lib:token: これは呼び出したいマクロを持つLibrary Tokenだ。ライブラリ・トークンは複雑だが、複数のマクロの「ライブラリ」を持つ一つのトークンと見なすことができる。このトークンは他のトークンを呼び出したり、逆に他のトークンから呼び出されたりできる。
  • マクロの引数引数はプログラミングの用語で、何か仕事をさせたい関数(ここではマクロ)にあなたが与える情報のことだ。例えば二つの数を足し合わせる関数があるとしたら、あなたがその関数に与える二つの数が、その関数の「引数」ということになる。
So in the command above, you've said "run the macro called macroName at the library token Lib:token, and send it macro_arguments to work on." The programming jargon for what you've just done is "calling a macro," or "creating a macro call."

そんなわけで、上に挙げたコマンドの例では、「ライブラリ・トークンLib:tokenの中にあるマクロ名というマクロを実行しろ。そのマクロにはマクロの引数を与えろ」と指示したことになる。プログラミング用語ではこれを、「マクロの呼び出し」とか、「マクロ呼び出しの生成」と呼ぶ。

The next section will have some actual examples to help you get a grasp of using [MACRO():].

次では [MACRO():] の使い方を理解するためにいくつか実例を挙げてみる。

引数と戻り値を扱う

In programming terms, a function is a set of commands that receives arguments (described briefly above), does some processing on those arguments, and then returns a value to the place from where it was called. The macro roll option is not technically a function, but when it is used, the process is mostly similar: it calls on another macro, sends it arguments, and that other macro may - if you write the macro so that it does - return a value to the calling macro.

プログラミング用語で言う関数とは、上で簡単に述べたようにいくつかの引数を受け取り、その引数について何らかの処理をして、それから呼ばれた場所に値を返すもののことだ。マクロのロール・オプションは厳密には関数ではないが、使い方はほぼ同じだ。他のマクロを呼び出し、引数を与える。その呼び出されたマクロは(あなたがそのように書いておけば)呼び出したマクロに値を返すことがある

When you call a macro, you can send it any variable, string, or number as an argument (in other words, you can replace macro_arguments with a variable, a string, or a number, which is sent to the called macro). For example, let us assume the following:

マクロを呼び出す場合には、好きな変数、文字列、数値を引数にすることができる(つまり、マクロの引数と書いてある部分は、変数、文字列、数値に好きに置き換えることができ、それが呼び出すマクロに渡される)。例えば、こういう例を考えてみよう:

  • There is a Library Token called "'Lib:MT which has a macro called Use Power.
  • You have a token for Bork the Brave, which has a macro called Shield Bash. This is one of Bork's powers.
  • You want to send the name of the power to Use Power, which will run the standard procedures to resolve the use of a power.
  • Lib:MTという名前のLibrary Tokenがあり、その中にはUse Powerというマクロがあるとする。
  • 勇者ボークのトークンがあって、そのトークンはShield Bashというマクロを持っている。これはボークのパワーの一つだ。
  • Use Powerマクロに対してパワーの名前を渡したい。このマクロはパワーの使うときの標準処理を行ってくれる。
To have Bork's macro trigger the Use Power macro on Lib:MT, you would create a macro called "Shield Bash", which contained the following command:

ボークのマクロが Lib:MTUse Powerマクロを呼び出すには、以下のコマンドを持つShield Bashマクロを作成しなければならない。

[macro("Use Power@Lib:MT"): "Shield Bash"]
[macro("Use Power@Lib:MT"): "Shield Bash"]
So, that's great. You've sent this information off to the macro Use Power. But...how does Use Power recognize what you sent it?

よろしい。これでマクロUse Powerに情報を渡すことができた。ところで…Use Powerマクロの方はこの情報をどういうふうに認識するのだろうか?

特殊変数 macro.args

Whenever you create a macro call and execute it, a special variable called macro.args is created. This variable is visible (that is, can be accessed, changed, or read) only by the macro being called, and it contains whatever you substituted in for macro_arguments. So, in our example above, macro.args is equal to "Shield Bash". So, for example, in the macro Use Power, you might have a line that says:

マクロを呼び出すと、macro.argsという特殊変数が生成される。これは呼び出された側のマクロだけから見える(つまり、アクセス、変更、読み出しが可能な)変数で、マクロの引数の部分に入れたものがすべて格納されている。だから上の例で言うなら、macro.args は"Shield Bash"と等しいことになる。なので、例えば、Use Powerマクロの中にはこういう部分があるはずだ:

[h:powerName = macro.args]
[h:powerName = macro.args]
What that line says is, "in this macro, take the value of macro.args, and assign it to the variable powerName." From then on out, the variable powerName will have the value "Shield Bash" (if we continue our example from above). Note that you don't have to do this - you can also just refer to macro.args wherever you need to.

ここでは、「このマクロでは、macro.argsの値を読み出し、これを変数powerNameに代入しろ」と言っていることになる。これ以降、変数powerNameは"Shield Bash"という値を取る(上の例のままになっていれば、だが)。なお、必ずしもこの通りにしなくても良いという点には注意。必要ならどこででも macro.args を参照していい。

The macro being called can then use this special variable macro.args like any other variable - it can read it, it can change it, it can add it to something - anything you would do with a variable. You could even ignore it!

ここで、呼び出されたマクロは他の変数と全く同じように macro.args を使うことができる。読み出しても、変更しても、他の何かと連結させてもいい。他の変数に出来ることなら何でもしていい。何なら全く使わなくても構わないんだ。

Of course, if you've sent information in one direction - from the caller to the callee, so to speak - what if you need to send information the other way (in other words, return a value)?

もちろんこの情報は、呼び出し側から呼び出される側への一方通行になる。では、その反対方向に情報を渡したい(つまり、値を返したい)ときにはどうしようか?

特殊変数 macro.return

In the macro that is being called, you can do a lot of processing on the variable macro.args. You can output text to chat and update token properties, even. But you migh also want the results of all that processing to be sent back to the calling macro - maybe you use it to create part of a string, and you need to send that piece back to be assembled into the final output you want to send to chat.

呼び出され側のマクロの中では、 macro.argsにさまざまな処理を加えることができる。テキストをチャットに出力し、トークンの属性値を更新したりも。だが、関数の中で行われた処理の結果を呼び出し側のマクロに送り返したりもしたいんじゃないだろうか。おそらく、それを文字列の一部として組み込み、最後にチャットに出力するようにするのに使えるだろう。

In that case, you can assign whatever value you want to send back to the variable macro.return, which will be sent back to the calling macro. Assume, then, that the macro Use Power creates a variable called powerResultText that needs to be sent back to Bork's macro Shield Bash before it finishes. To do this, somewhere at the end of Use Power, you'd add this line:

この場合、返したい値をmacro.returnに代入すればうまくいく。この変数は呼び出し側のマクロに返されるのだ。では、Use PowerマクロがpowerResultTextという変数を生成したとして、それを戦士ボークのShield Bashマクロへ、それが実行を終える前に返さなければならないのだと考えよう。これを行うには、Use Powerマクロのどこかにこういう部分を追加する必要があるだろう:

[h:macro.return = powerResultText]
[h:macro.return = powerResultText]
You've said in that line that the special variable macro.return will be equal to whatever powerResultText is set to, and Shield Bash can then use the variable macro.return for further processing.

ここで、特殊変数macro.returnの値はpowerResultText と同じになる。そしてShield Bashマクロはこのmacro.returnを使って処理を続けることができるのだ。

二つのマクロを並べて見てみる

The examples below are the two macros discussed above, side by side, to illustrate the use of macro calls and the macro.args and macro.return variables. Make sure to check out the Sample Ruleset if you're not familiar with some of the various game terms. Also, note that these are not complete macros that include all of the possible classes and powers in the game, but a sampling to illustrate the use of [MACRO():].

以下の例はこれまでに述べてきた二つのマクロだ。マクロの呼び出しや、二つの変数macro.argsmacro.return を説明するために二つ並べておいた。 もしまだゲームの用語に不慣れなら、Sample Rulesetで確認してほしい。また、ここにあるのは、ゲーム内に登場するすべてのクラスやパワーを網羅したマクロの完成品ではなく、[MACRO():]の説明のためのサンプルだという点に留意してほしい。

Shield Bash Macro Use Power Macro
<!-- Call the Use Power macro -->

[MACRO("Use Power@Lib:MT"): "Shield Bash"]

<!-- Receive the variable macro.return after Use Power has finished processing.-->

[h:hitValue = macro.return]

<!-- Use IF to check the value of hitValue, and choose an option -->

[h,if(hitValue == 1),CODE:
{
  [damageRoll = floor((1d6+Strength)/2)]
  [special = "Roll 1d6. On a 4 or better, the foe is stunned for three rounds."]
};
{
  [damageRoll = "None"]
  [special = "No special effect."]
}]

<!-- Display the Damage result and special effect -->

<b>Damage: </b> [r:damageRoll]<br>
<b>Special: </b> [r:special]
<!-- Receive macro arguments -->
[h:powerName = macro.args]

<!-- Do a switch to find the power's Attack Bonus -->
[h,switch(powerName):
case "Sword": attackBonus = 2;
case "Bow":  attackBonus = 0;
case "Shield Bash": attackBonus = -1;]

<!--Make the Attack Roll-->

[h:attackRoll = 1d20 + Strength + attackBonus]

<!-- Check to see if the attack succeeds (a roll of 15 or higher is a hit) -->

[h,if(attackRoll >= 15),CODE:
{
  [successText = "a success!"]
  [hit = 1]
};
{
  [successText = "a failure."]
  [hit = 0]
}]

<!--Display the attack result and the success, and then send
 back the success info for final processing-->

The [r:powerName] attack is [r:successText].<br>
[h:macro.return=hit]


Shield Bash マクロ Use Power マクロ
<!-- Use Power マクロを呼び出す -->

[MACRO("Use Power@Lib:MT"): "Shield Bash"]

<!-- Use Powerの実行が終わるまえに、変数 macro.return を受け取る -->

[h:hitValue = macro.return]

<!-- IF を使って変数 hitValue の値をチェックし、オプションを選ぶ -->

[h,if(hitValue == 1),CODE:
{
  [damageRoll = floor((1d6+Strength)/2)]
  [special = "1d6を振り、4以上が出たら敵一体が3ラウンドの間気絶する"]
};
{
  [damageRoll = "None"]
  [special = "特殊効果なし"]
}]

<!-- ダメージの結果と特殊効果を表示する -->

<b>ダメージ: </b> [r:damageRoll]<br>
<b>特殊効果: </b> [r:special]
<!-- マクロ引数を受け取る -->
[h:powerName = macro.args]

<!-- パワーの Attack Bonus を決めるために switch を使う -->
[h,switch(powerName):
case "Sword": attackBonus = 2;
case "Bow":  attackBonus = 0;
case "Shield Bash": attackBonus = -1;]

<!-- 攻撃ロールを行う -->

[h:attackRoll = 1d20 + Strength + attackBonus]

<!-- 攻撃が成功したかどうか判定する(出目が15以上なら命中) -->

[h,if(attackRoll >= 15),CODE:
{
  [successText = "命中!"]
  [hit = 1]
};
{
  [successText = "はずれ!"]
  [hit = 0]
}]

<!-- 攻撃の結果と成否を表示し、最後の処理を行うために成否の情報を返す -->

The [r:powerName] の攻撃は [r:successText].<br>
[h:macro.return=hit]

Languages:  English  • 日本語