ペット行動モジュール
ペット行動モジュールは、ペットに何をすべきか(飼い主についていく、漂う、焚き火の周りを回る、刺すなど)を伝えるLuaファイルです。各ペット種族ファイルは、そのペットが実行するモジュールを列挙し、設定を与えます。このページは、モジュールを変更したり新しく書いたりしたいクリーチャーの作者向けです。同梱のモジュールを使って調整するには、ペットを参照してください。
モジュールは、EliteMobsの行動プログラムと同じLuaの方言を使います。ai.module、ai.behavior、ai.sensor、ai.controls、型付きのメモリ、c.memory、c.perception、c.actuator、c.entityのコンテキストです。共通のルールはそのページで説明しています。このページでは、ペットが追加するもの、つまりモジュールファイル、c.pet、c.settings、ペットが従う制限を説明します。
ファイル
- モジュールは
plugins/FreeMinecraftModels/pet_behaviors/の中にあり、そのフォルダ、または任意のサブフォルダに置きます。そこにあるすべての.luaファイルがモジュールです。 - モジュール名は、
.luaを除いたファイル名を小文字にしたものです。使えるのは、英字、数字、.、_、-だけです。ペットファイルは、この名前でモジュールを列挙します。 - モジュールの
idは、fmm:pet/に名前を続けたものでなければなりません。たとえばpet_behaviors/mine/slow_drift.luaはid = 'fmm:pet/slow_drift'を宣言します。idがファイル名と一致しないモジュールは、警告とともにスキップされます。 - 2つのファイルが同じ名前を持つ場合、パスで先のものが読み込まれ、コンソールはもう一方について
Duplicate content filenameと警告します。バイト単位で同一のコピーは、警告なしでスキップされます。 pet_behaviors/の外にリンクするファイルやフォルダは、スキップされます。- FreeMinecraftModelsは、同梱の15個のモジュールを、その名前のファイルがフォルダのどこにもない場合に書き出します。削除したものは、次回の読み込みで現在の同梱バージョンとして戻ります。すでにあるファイルは、編集の有無にかかわらず、サブフォルダに移動した後でも上書きされません。そのため、あなたの変更は残りますが、同梱モジュールの以降の更新は受け取れません。
/fmm reloadはすべてのモジュールとペットファイルを読み直し、ペットをしまって、新しいモジュールで戻します。メモリは空から始まります。編集後にモジュールのrevisionを上げる必要はありません。
コピーから始める
同梱のモジュールが最良の見本です。drift.luaは飛行するペットを動かし、wander.luaは歩き、night_glow.luaは単一のセンサー、sting.luaは2つのセンサーを持ちます。作りたいものに最も近いものから始めてください。
- 新しい名前でコピーします。たとえば
drift.luaからpet_behaviors/mine/slow_drift.luaを作ります。 - その
idをfmm:pet/slow_driftに変更します。 - メモリ、行動、センサーの名前を、新しい名前で始まるように変更します。
drift_toはslow_drift_toになり、memoriesと、すべてのc.memory呼び出しの両方で変更します。行動のid = 'fmm:pet/drift'はfmm:pet/slow_driftになります。1つのクリーチャー上の2つのモジュールは、メモリ名、行動id、センサーidを共有できません。リストで後のほうは、警告とともに外されます。名前を変更することで、コピーをオリジナルと並べて実行できます。 - ペットファイルで、オリジナルの代わりにそれを列挙します。
- slow_drift、または設定付きで- slow_drift: { speed: 0.03 }です。 /fmm reloadを実行し、コンソールを確認します。
同梱モジュールをその場で編集することもできますが、それを列挙しているすべての種族に影響します。
モジュールファイル
このモジュールは小さいながら完全です。夜になると、ペットは漂う代わりにアンカーの近くの1か所に落ち着き、その地点を選んだ時点から10秒ごとにアニメーションを再生します。
-- At night: settles on one spot near its anchor (its owner, or home when wild) and plays an animation now and then.
return ai.module {
id = 'fmm:pet/night_rest', revision = 1,
-- radius: blocks around the anchor. speed: blocks per tick for a flyer, at species speed 1.
settings = { radius = 3, speed = 0.04, animation = 'interact' },
memories = { night_rest_to = 'position', night_rest_retry = 'integer' },
behaviors = {
ai.behavior {
id = 'fmm:pet/night_rest', priority = 12, probe_interval = 10,
controls = { ai.controls.move, ai.controls.look },
can_start = function(c)
return c.pet.night and not c.pet.staying and c.pet.anchor ~= nil
and c.tick >= (c.memory:get('night_rest_retry') or 0)
end,
can_continue = function(c)
return c.pet.night and not c.pet.staying and c.memory:contains('night_rest_to')
end,
start = function(c)
local anchor = c.pet.anchor
local to = anchor and c.pet:rest_point(anchor, c.settings.radius)
if to ~= nil then
c.memory:set('night_rest_to', to)
else
-- Nothing fits here: look again in 5 seconds instead of every tick.
c.memory:set('night_rest_retry', c.tick + 100)
end
end,
tick = function(c)
local to = c.memory:get('night_rest_to')
if to ~= nil then c.pet:steer_to(to, c.settings.speed * c.pet.species.speed) end
end,
stop = function(c)
c.memory:forget('night_rest_to')
c.pet:stop()
end
}
},
sensors = {
ai.sensor {
id = 'fmm:pet/night_rest_animation', interval = 200,
sense = function(c)
if c.memory:contains('night_rest_to') then c.pet:play_animation(c.settings.animation) end
end
}
}
}
ペットファイルでは、これを- night_rest、または- night_rest: { radius: 5, animation: idle }と列挙します。
| フィールド | 備考 |
|---|---|
id | 必須。fmm:pet/とファイル名 |
revision | 必須。任意の正の整数 |
settings | 任意。ペットファイルが変更できるデフォルト。各デフォルトの型が、ペットファイルが与えるべき型です。数値、true/false、テキスト、テキストのリストのいずれかです。設定値を参照 |
memories | 任意。モジュールが各ペットについて記憶するもの。名前と型(integer、number、boolean、string、uuid、position)で指定します。各名前はモジュール名で始めてください。メモリを参照 |
dependencies | 任意。このモジュールが必要とする、pet_behaviors/内の他のモジュールのid。このモジュールを列挙するすべてのクリーチャーで実行され、ペットファイルがそれらも列挙しない限り、デフォルトの設定で動きます |
behaviors | 任意。ペットを動かす、または向きを変えるai.behavior { ... }のエントリ |
sensors | 任意。ペットを決して動かさないai.sensor { ... }のエントリ |
returnより上のコード(ローカル関数や定数など)は許可されています。wander.luaとidle_look.luaにいくつかあります。
コールバックが受け取るもの
| 名前 | 内容 |
|---|---|
c.pet | ペット(読み取り専用)。c.petを参照 |
c.settings | このモジュールの設定。そのデフォルトの上に、ペットファイルとバリアントの値が重ねられたもので、c.settings.radiusのように使います。各ペットが自分のコピーを持つため、書き込んでもそのペットにしか影響しません |
c.memory | memoriesの名前に対するget(name)、set(name, value)、forget(name)、contains(name)。各ペットが自分のものを持ちます |
c.tick | 現在のゲームティック。タイマー用 |
c.perception、c.actuator、c.entity | EliteMobsの行動プログラムと同じ、MagmaCoreのMindコンテキスト。c.entityはモデルではなく非表示のボディです。Mindプログラムのコンテキストを参照。idle_look.luaはc.perception:nearest_player(range)とc.actuator:look_at(point)を使います |
c.pet
点は、x、y、zと、任意でworldを持つテーブルで、c.pet.positionのようなものです。worldのない点は、ペットのワールドにあります。別のワールドにある点は無として扱われます。メソッドはnil、false、0を返し、distance_toはmath.hugeを返します。c.petが返す点は常にペットのワールドにあり、別の場所になる点はnilとして読み取られます。
- メソッドはコロンで呼び出します。
c.pet:distance_to(point)です。 - 数値の引数は有限でなければなりません。半径、深さ、高さ、レベル、継続時間、その他の範囲は、以下に記載のとおり上限があります。どのメソッドもチャンクを読み込みません。
c.petとc.pet.speciesは読み取り専用です。代入するとエラーになります。ペットごとの値はc.memoryに保持してください。- プロパティと
route_target()はスナップショットです。それぞれペットのティックごとに1回読み取られ、そのティックのすべてのコールバックを通じて同じままです。c.pet:teleport_near_ownerとc.pet:stopはそれらを更新します。c.entity:teleportなど別の方法で行った移動は、次のティックに現れます。speedは例外で、常に最新の値が読み取られます。 - 位置を読み取るたびに新しいテーブルが返され、モジュールはそれを変更できます。
プロパティ
| 名前 | 型 | 値 |
|---|---|---|
wild | bool | 野生のペットならtrue、所有ペットならfalse |
staying | bool | 待機を命じられている |
settled | bool | 待機を命じられておらず、野生であるか飼い主のfollow.distance以内にいる |
baby | bool | 子供である |
migrating | bool | 夜の渡りの経路を飛んでいる |
model | string | そのバリアントのモデル。babyModelをまとっている子供でも、バリアントを読み取ります |
position | point | ボディのある場所 |
home | point/nil | 野生のペットが生息する場所。所有ペットではnil |
anchor | point/nil | ペットがその周りをうろつく対象。飼い主、野生のペットならそのホーム、なければ現在地。飼い主がオフラインか別のワールドにいる場合はnil |
stay_anchor | point/nil | 待機を命じられた場所。待機中でなければnil |
owner_location | point/nil | 野生のペット、または飼い主がオフライン、死亡、別のワールドにいる場合はnil |
owner_distance | number | 飼い主までのブロック数。このワールドに飼い主がいない場合はmath.huge |
night、day | bool | dayは通常のワールドの日中のみ。夕暮れ、夜明け、ネザー、エンドはnightとして扱われます |
raining | bool | ペットに雨が当たっている。最大10ティックごとに確認されます |
speed | number | ボディの現在の速度(ブロック/ティック) |
route_cruise | number | 渡りの間の群れの巡航速度。それ以外は0 |
species | table | 以下の、ペットファイルの数値 |
c.pet.speciesには次が入っています。
| フィールド | ペットファイルのキー |
|---|---|
id | species |
speed | follow.speed |
hover_height | float.hoverHeight |
hover_variance | float.hoverVariance |
roam_radius | follow.roamRadius |
follow_distance | follow.distance |
leash_distance | follow.leashDistance |
teleport_distance | follow.teleportDistance |
scale | scale |
baby_scale | babyScale |
移動
これらは、必要なものをcontrolsに挙げた行動の、start、tick、stopからのみ呼び出してください。can_startやセンサーから呼び出すと、steer_toとstopは、それらがどこに属するかを示すエラーを発生させます。
| メソッド | 戻り値 | 内容 |
|---|---|---|
steer_to(point, cruise) | bool | その点へ向かう1ティック分の移動なので、毎ティック呼び出してください。moveとlookが必要です。飛行するペットはcruiseブロック/ティック(0から4)で飛び、到着に近づくと減速します。歩行や遊泳するペットは、ボディの種類の移動速度の4 × cruise倍(ただし、その移動速度の4分の1以上)で、ネイティブの経路探索によりそこへ進みます。cruiseが0だと停止してfalseを返します。そこへ行けない場合はfalse |
stop() | nil | 移動を止めます。moveが必要です |
teleport_near_owner(radius) | bool | ボディを、飼い主のradiusブロック以内(最大64)の、自身の媒体の中に移動させます。遊泳するペットの水は、少なくとも6ブロック先まで探されます。歩行や遊泳するペットは、飼い主から1ブロック以上離れた場所に着地します。飼い主が離れている、または別のワールドにいる、収まる場所がない、その地点がペットの現在地より飼い主に1ブロック以上近くない場合はfalse。コントロールは不要ですが、follow_ownerのようにmoveを保持する行動から呼び出してください。そうしないと、他の行動からペットを引き離してしまいます |
地点と距離
これらは、どのコールバックからでも動作します。点を返すものは、収まる場所がない、またはチャンクが読み込まれていない場合はnilを返します。半径は最大64までです。
| メソッド | 戻り値 | 内容 |
|---|---|---|
hover_point(center, radius) | point/nil | radius以内の、ホバリング帯の中の点 |
rest_point(center, radius) | point/nil | 自身の媒体の中で休める場所。飛行するペットならホバリング帯、歩行するペットや静止ボディなら立てる地面、遊泳するペットなら水中(centerが水中ならcenterの高さ、そうでなければ水面の0.5から2ブロック下)、両生のボディなら地面、なければ水中 |
ground_point(center, radius) | point/nil | centerのおよそ5ブロック下から4ブロック上までの、立てる場所。液体の上や長い落差の上ではnil |
water_point(center, radius, min_depth, max_depth) | point/nil | 水面から2つの深さ(0から16)の間にある、泳げる場所 |
ground_below(point, depth) | number/nil | 下方depthブロック(1から64)以内にある、地面の上端の高さ。種族がAQUATICでない限り、水面や溶岩面は地面として扱われます。手の届く範囲に地面がない場合は、その点の高さからdepthを引いた値 |
trail_point(back, height) | point/nil | 飼い主が向いている方向のbackブロック後ろで、FLYINGの種族なら足元からheight上、それ以外なら足元。飼い主が離れている、または別のワールドにいる場合はnil |
distance_to(point) | number | ボディからのブロック数 |
route_target() | point/nil | このティックに渡りの経路がペットに望む場所。渡りをしていない、または経路が終わった場合はnil |
find_perch(height, radius) | point/nil | その下にある最も近い葉(横方向に最大radiusブロック(0から4)まで)、またはすぐ下の地面から、heightブロック(0から8)上の地点。所有ペットは、飼い主のfollow.distance以内にある止まり場所だけを得ます |
nearest_campfire(radius, keep_ticks, blocks, soul_variants, height) | point/nil | radius(1から32)以内で、使える最も近い火の灯った焚き火のブロック。blocksは対象とする火の種類(CAMPFIRE、SOUL_CAMPFIRE、または両方)を列挙し、どちらも挙げないリストは両方を対象にします。soul_variantsはソウルキャンプファイアだけを対象にするモデルを列挙し、その場合、他のすべてのモデルは通常の焚き火だけを対象にします。所有ペットは、その上heightの地点が飼い主のfollow.distanceマイナス1以内にある火だけを選びます。各チャンクの検索結果はkeep_ticks(20から1200)の間保持され、すべてのペットで共有されます |
campfire_usable(fire, blocks, soul_variants, height) | bool | 以前に見つけた火が、まだ灯っていて、まだ条件に合っているか |
エフェクト
これらは、どのコールバックからでも動作します。通常はセンサーで使います。
| メソッド | 戻り値 | 内容 |
|---|---|---|
set_glow(light, lantern_bone, animation) | nil | Javaプレイヤー向けに、モデルの表示ボーンをlight(0から15)で照らします。lantern_boneという名前のボーンを持つモデルは、animationもループ再生します。最後の2つは任意です |
clear_glow() | nil | ワールドの光に戻し、そのアニメーションを終了します |
scale_toward(target, span, ticks, elapsed) | nil | ボディのサイズを、基本サイズのtarget倍へ徐々に近づけます。1からspanまでの完全な変化にはticks(最小2)かかります。elapsedは前回の呼び出しからのティック数です。倍率は0.1から16 |
sting_contacts(on, effect, duration, amplifier, damage, cooldown) | number | 直近1秒間に、野生のペットのモデルに触れたプレイヤーを刺します(クリエイティブやスペクテイターモードのプレイヤーは除く)。刺した数を返します。onがfalseでも接触はクリアされます。所有ペットは接触を記録しません |
sting_enemies(reach, effect, duration, amplifier, damage, cooldown) | number | モデルのヒットボックスからreachブロック(0から4)以内にいる敵対Mobを刺します(プレイヤーやペットは決して刺しません)。刺した数を返します |
drizzle(depth, chance) | bool | ペットがdepthブロック(1から8)以内の作物の上で静止してホバリングしている場合、水のパーティクルと、作物が1段階成長する確率chance(0から1)が発生します。作物の上にいる場合はtrue |
owner_effect(effect, duration, amplifier, range) | bool | 飼い主がrangeブロック以内にいる場合に、パーティクルなしでdurationティック(1から6000)のポーションエフェクトを与えます。飼い主がすでに、同じかより強く、同じかより長く続くエフェクトを持っている場合は、手を加えません。飼い主が離れている、別のワールドにいる、範囲外にいる、またはエフェクトが存在しない場合はfalse |
play_animation(name) | bool | モデルのアニメーションの1つを1回再生します。モデルにそれがない場合はfalse |
2つの刺す動作のどちらでも、effectはポーションエフェクトの名前またはNONE、durationはティック(1から6000)、amplifierの0はレベルI(最大255)、damageはハート半分単位、cooldownはこのペットが同じ被害者を再び刺せるようになるまでのティック数(最小1)です。刺すと火花が出て、ハチの針の音が鳴り、成体はattackアニメーションを再生します。存在しないポーションエフェクト名は、種族と名前ごとに1回警告され、何も適用されません。
行動とセンサー
- 行動は、ペットを動かす、または向きを変えます。必要なコントロールを列挙します。
c.petの移動呼び出しにはai.controls.moveとai.controls.lookが必要で、1つのコントロールを保持できる行動は一度に1つだけです。行動が停止している間、MagmaCoreはそのcan_startを問い合わせます。それがtrueを返し、コントロールが空いていれば、行動はそれらを取ってstartを実行し、その後can_continueがtrueを返す間(can_continueがなければcan_startが決めます)毎ティックtickを実行し、最後にstopを実行します。ライフサイクルを参照してください。 priorityの数値が小さいほうが先に実行されます。行動は、数値が大きい実行中の行動からコントロールを奪い、その行動のstopが実行されます。例の12では、追従と待機がこの行動より優先され、この行動は漂いとホバリングより優先されますが、campfireよりも優先されるため、両方を列挙したペットは夜に焚き火を訪れません。15より大きい数値にすれば、焚き火が優先されます。- 行動は、自身が列挙したコントロールについてのみ競合します。
idle_lookはlookだけを取るため、どの行動も視線を保持していない間に実行されます。同梱の移動する行動はすべてlookも取るため、移動は常にそれより優先されます。 - ペットファイルからは優先度を変更できません。順序を変えるには、モジュールをコピーして数値を変更してください。
probe_intervalは任意で、ティックで指定します。行動が停止している間、can_startは、各ペット固有の位相で、その間隔のティックごとにだけ問い合わせられます。多くのペットが外に出ているときのサーバー時間を節約できる一方、行動の開始が最大でそのティック数だけ遅れる代償があります。デフォルトは1で、200を超える値は200として扱われます。実行中の行動は、引き続き毎ティック実行されます。- センサーは、ペットを決して動かしません。ペットのボディが最初にティックされたティックに
senseを実行し、その後は、行動が何をしているかに関係なく、ペット固有の位相でintervalティックごとに実行します。発光、膨らみ、刺す動作、小雨、飼い主へのエフェクトはセンサーです。
同梱のモジュールは次を使用しています。
| モジュール | 優先度 | probe_interval | センサーのinterval |
|---|---|---|---|
migrate | 1 | 10 | |
stay | 5 | 4 | |
follow_owner | 10 | 4 | |
campfire | 15 | 10 | |
day_perch | 18 | 10 | |
rain_bloom | 19 | 10 | 4(膨らみ) |
drift、wander、swim | 20 | 10 | |
hover | 30 | 4 | |
idle_look | 30 | 10 | |
night_glow | 40 | ||
sting | 4(プレイヤー)、10(Mob) | ||
crop_drizzle | 20 | ||
owner_effect | 20 |
ルール
steer_toとstopは、必要なコントロールを列挙した行動の、start、tick、stopからのみ呼び出してください。- ペットごとの状態は、
memoriesの下で宣言したc.memoryに保持し、名前はモジュール名で始めてください。 c.petに書き込まないでください。代入するとエラーになります。- コールバックは短く保ってください。すべてのペットは、モジュールやペットファイルが変更できない、次の固定の制限の下で実行されます。
| 制限 | 値 |
|---|---|
| 1つのコールバック | 1.5 ms |
| 1匹のペットの1ティック内のコールバック | 3 ms、最大32コールバック |
| 全ペットの1ティック内のコールバック | 10 ms |
| 1つのコールバックのCPU時間(ハード制限) | 20 ms |
| 1つのコールバックのLua命令数(ハード制限) | 20,000 |
ペットが最初の3つの制限のいずれかに達すると、その残りのコールバックは次のティックまで待ちます。ハード制限を超えたコールバックは停止され、エラーと同様に失敗します。バジェットを参照してください。
問題が起きたとき
ここにあるものは、サーバーや他のクリーチャーを停止させません。これらの警告を探すには、コンソールでpet behavior、pet_behaviors、.pet.ymlを検索してください。
- モジュールが読み込まれない。 コンパイルできない、idがファイル名と一致しない、ファイル名に他の文字が含まれるモジュールは、ファイル名と、Luaエラーの場合は行を示す警告とともにスキップされます。他のすべてのモジュールは引き続き読み込まれます。
- ペットファイルが存在しないモジュールを指している。 警告はペットファイルを示し、1、2文字違いのモジュール名があれば、最も近い名前を提案します。クリーチャーはそれなしで読み込まれます。モジュールは存在するのに読み込みに失敗した場合、警告はそのファイルに関する警告を指します。
- 設定が誤っている。 モジュールにない設定や、型の誤った値は、ペットファイルの名前とともに報告され、デフォルトが残ります。設定値を参照してください。
- 2つのモジュールが衝突する。 1つのクリーチャー上の2つのモジュールが、同じメモリ名、行動id、センサーidを宣言している場合、クリーチャーはリストで先のものを保ち、警告とともにもう一方なしで実行されます。
- ペットの実行中にコールバックが失敗する。 プログラム、コールバック、失敗の種類ごとに、次のリロードまで1回だけログに出力されます。プログラムは
fmm:pet/creature/<species>/<variant>、コールバックはfmm:pet/drift.tickのように行動またはセンサーのidで名付けられます。失敗した行動は停止される、または開始されず、次のティックからやり直されます。失敗が続く間、ペットを動かす、または向きを変える、優先度の数値が大きい行動は実行されないことがあります。失敗したセンサーは、次の間隔で再び実行されます。 c.petの呼び出しがFreeMinecraftModelsの内部で失敗する。 原因は、種族と呼び出しごとに1回、スタックトレースとともにログに出力され、コールバックはc.pet:<method> failed; the server log has the causeで失敗します。- ポーションエフェクト名が存在しない。 種族と名前ごとに1回警告され、その呼び出しはエフェクトを適用しません。
修正後は、/fmm reloadを実行してください。