Skip to content

create effect

Ella Coat edited this page May 18, 2026 · 17 revisions

エフェクトは、 Mob やプレイヤーに一定期間 / 永続で効果を付与する仕組みだよ。Asset/data/asset/functions/effect/<ID>.<エフェクト名>/に実装が置かれていて、 ID で参照する。

神器のEquipment.Effectsから自動で付与されたり、api:entity/mob/effect/giveから手動で付与したりするよ。

1. 事前に済ませてね

2. テンプレートを作成する

MCDatapackUtilityを利用してエフェクトアセットのテンプレートを作成するよ。
Datapack: Create Datapack templateを実行してね。デフォルトだとShift + Alt + D -> Shift + Alt + Tを押すと動作するよ。

下記のメニューが出てくるからデータパックにテンプレートを追加するを選択してね。

image

データパックはAssetフォルダを指定。命名規則は神器・モブと同じ。

エフェクト名の命名規則

  • <四桁のID>.<エフェクト名(snake_case)>で名前を記述してね

  • エフェクト名は基本的に英語に翻訳したものを使うよ (英語が出来ない場合はGoogle翻訳みらい翻訳, DeepLとか使ってみてね)

  • 各単語を_区切ってね

  • 英語に翻訳できないような物はローマ字にしてね

    ローマ字にしたときに表記ゆれがあるような物はヘボン式に従ってね

テンプレートの種別では「エフェクト/テンプレート」を選んでね。さらに必要な処理 (given/tick/end/remove/re-given) のチェックも入れる。

これでテンプレートがAsset/data/asset/functions/effect/<エフェクト名>/~に生成されてるはずだよ。生成されるファイル構成はおおまかにこんな感じ:

asset/functions/effect/<エフェクト名>/
    register.mcfunction          # ID/Name/Duration等の基本情報定義
    _/register.mcfunction        # context.idで自分宛か判別するdispatcher
    _/given.mcfunction           # dispatcher (given用)
    _/tick.mcfunction            # dispatcher (tick用)
    _/end.mcfunction             # dispatcher (end用)
    _/remove.mcfunction          # dispatcher (remove用)
    _/re-given.mcfunction        # dispatcher (re-given用)
    given/.mcfunction            # 実装本体 (付与時)
    tick/.mcfunction             # 実装本体 (毎tick)
    end/.mcfunction              # 実装本体 (効果時間終了時)
    remove/.mcfunction           # 実装本体 (外部からの削除)
    re-given/.mcfunction         # 実装本体 (再付与)

_/*.mcfunctionはテンプレート生成時に自動で作られて、asset:context idが自分の ID と一致するかチェックして本体を呼ぶ仕組み。基本的に触る必要はないよ。

3. エフェクトの基本情報の設定

注: ここから先基本的に function 名は下記のような省略した形で記載するよ

Asset/data/asset/functions/effect/<エフェクト名>/register.mcfunction -> ~/register.mcf

生成されたテンプレートの~/register.mcfを編集していくよ。

register.mcfunction で設定する項目

設定名 必須 設定する型 説明 デフォルト
ExtendsSafe × boolean 他のエフェクトから継承されることを許可するか false … value true
ID o int エフェクトの ID
スプレッドシートの ID 欄の物
- … value 31
Name o TextComponent エフェクトの名前 - … value '{"text":"低速落下"}'
Description o TextComponent[] エフェクトの説明文 - … value ['{"text":"落下速度が低下する"}']
Duration o* int 効果時間 (tick)。
*API 呼び出し側で指定するなら省略可能
- … value 200
Stack × int 初期スタック数 1 … value 3
DurationOperation × string 再付与時の効果時間の計算方法
"replace"/"add"/"forceReplace"
"replace" … value "add"
StackOperation × string 再付与時のスタックの計算方法
"replace"/"add"/"forceReplace"
"replace" … value "forceReplace"
MaxDuration × int 最大効果時間 2147483647 … value 1200
MaxStack × int 最大スタック数 (フルセット防具用なら 4 にする) 2147483647 … value 4
IsBadEffect o boolean 悪い効果か (UI の色分け用) - … value true
ProcessOnDied × string 死亡時のエフェクト処理 ("remove" / "keep") "remove" … value "keep"
RequireClearLv × int 解除難易度 (運用上は 1 〜 3 、 4 は未使用領域) 1 … value 3
Visible × boolean エフェクト一覧 UI に表示するか true … value false
StackVisible × boolean スタック数を UI に表示するか true … value false
Field × compound カスタムフィールド (given/tick 時にasset:context this.<key>で参照可能) {} … value {Power:3,Color:16777215}

DurationOperation / StackOperation について

再付与時 (= 既に同じエフェクトが付いてる状態で再度付与された時) の値の決め方を指定する。

動作
"replace" 既存値と新規値の大きい方を採用 (デフォルト)
"add" 既存値に新規値を加算
"forceReplace" 新規値で強制上書き

例: Duration:"add"を指定したエフェクトに、 Duration=100 で 2 回付与すると、合計 200tick になる。

ProcessOnDied について

プレイヤーや Mob が死亡した時、そのエフェクトをどう扱うかを決める。

動作
"remove" 死亡時に即座に削除 (デフォルト)
"keep" 死亡しても継続。リスポーン後もそのまま残る

フルセット防具用の EffectAsset は"keep"にすることが多いよ (装備が外れない限り効果を維持したいので)。

RequireClearLv について

エフェクトの「解除難易度」。 api:entity/mob/effect/remove/from_levelArgument.ClearLv を指定したエフェクト削除 API でのみ消える (= RequireClearLv <= Argument.ClearLv のエフェクトが削除対象)。牛乳 (UsedMilk スコアが立つ操作) で消えるのは RequireClearLv:1 のみ。

解除条件 デバフの想定 バフの想定
1 牛乳 or レベル 1 以上の解除 API で消える 雑に敵から付与される一般デバフ (未使用領域)
2 レベル 2 以上の解除 API でのみ消える 雑魚の中でも強い敵や天使から付与されるデバフ (未使用領域)
3 レベル 3 以上の解除 API でのみ消える (基本的に解除されない) 解除不可デバフ (主に神器で付与、解除されない想定) バフはすべて Lv3 固定 (解除されない想定)
4 (内部対応はあるが、運用上未使用) - -

運用上のポイント

  • Lv3 はバフ・デバフ共に「解除されない」 想定 : デバフ側は神器付与の解除不可デバフ、バフ側は装備中ずっと続くもの (フルセット効果等)。どちらも Lv3 で書く
  • Lv1 / Lv2 のバフは未使用領域 : バフは Lv3 固定運用
  • Lv1 デバフも実質解除困難 : 牛乳は TSB の世界で Asset 内のものしか入手できないため、 Lv1 でも普通には消えない (= 通常プレイで「牛乳で解除可能」 という想定は成立しにくい)
  • Lv4 は使わない : 内部実装上は ClearLv:4 の API 呼び出しで消せるが、運用では使用しない領域
  • 専用の解除アイテム・解除イベント等で api:entity/mob/effect/remove/from_level を呼ぶ設計にする時は、対象 Lv を考えて呼び出す

4. エフェクトの処理を記述する

処理ごとに実装ファイル (given/.mcf, tick/.mcf 等) を書いていくよ。実行コンテキストは全部 as 対象エンティティ at @s。必要なデータは asset:context 経由で参照する。

4.1. 処理一覧

イベント 呼ばれるタイミング 実装ファイル
given 初回付与時 (まだそのエフェクトを持っていない状態からの付与) given/.mcfunction
re-given 再付与時 (既に持っている状態に再付与、スタック変化を含む) re-given/.mcfunction
tick 毎 tick (持っている間ずっと) tick/.mcfunction
end 効果時間が 0 になった時 end/.mcfunction
remove 外部から削除された時 (api:entity/mob/effect/remove/* 等) remove/.mcfunction

実行コンテキストでは以下が参照可能:

  • @s = 対象エンティティ
  • storage asset:context this = Field の中身 (このエフェクト個体のデータ)
  • storage asset:context Stack = 現在のスタック数
  • storage asset:context Duration = 現在の残り時間
  • storage asset:context PreviousField = re-given 時のみ、 1 つ前の Field の状態

4.2. given (付与時)

初回付与時の処理。主にバニラエフェクトの付与や、状態の初期化に使う。

例: 低速落下エフェクト

#> asset:effect/0031.slow_falling/given/
#
# Effectが付与された時の処理
#
# @within function asset:effect/0031.slow_falling/_/given

# バニラの低速落下を付与
    effect give @s slow_falling 1 0 true

エフェクトに合わせて、バニラエフェクトの付与 / particle での初期演出 / scoreboard の初期化 などを書く。

4.3. re-given (再付与時)

既に付与された状態で再度同じエフェクトが付与された時に呼ばれる。

例: フルセット防具 (4 部位そろった瞬間にフルセット効果を発動)

re-given で「直前の状態」 と「今の状態」 を比較するために、 Field に PrevStack を持たせて手動で記録するパターン。これを動かすには given 側でも同じ記録処理が必要なので、セットで書く。

#> asset:effect/0233.flame_armor/given/

# 初回付与時にもフルセット判定 (4部位を一度に装備した場合)
    execute if data storage asset:context {Stack:4} run function asset:effect/0233.flame_armor/fullset/equip

# 現在のスタックを Field に記録 (次回 re-given 時の PreviousField として使う)
    data modify storage asset:context this.PrevStack set from storage asset:context Stack
#> asset:effect/0233.flame_armor/re-given/

# フルセットだった状態から崩れた → フルセット効果を解除
    execute if data storage asset:context PreviousField{PrevStack:4} unless data storage asset:context {Stack:4} run function asset:effect/0233.flame_armor/fullset/dis_equip

# フルセットでなかった状態から成立 → フルセット効果を発動
    execute unless data storage asset:context PreviousField{PrevStack:4} if data storage asset:context {Stack:4} run function asset:effect/0233.flame_armor/fullset/equip

# 現在のスタックを Field に記録 (次回の re-given で PreviousField として参照される)
    data modify storage asset:context this.PrevStack set from storage asset:context Stack

storage asset:context PreviousField には、 1 つ前の Field の中身 (このエフェクトが直前に持っていた状態) が入ってる。これと現在の Stack を比較することで、「フルセット成立」 「フルセット崩壊」 のエッジを検出できる。

4.4. tick (毎 tick)

該当エフェクトが付与されている間、毎 tick で呼ばれる処理。重い処理を書きすぎると負荷が重くなるので注意。

例: 低速落下 (バニラ効果を付け直し続ける)

#> asset:effect/0031.slow_falling/tick/

# 低速落下を付与 (effect give は重ねがけしてもduration1tickなので軽量)
    effect give @s slow_falling 1 0 true

例: 出血デバフ (DoT ダメージ)

#> asset:effect/0307.bleeding/tick/

# 毎tickダメージ (神器のtriggerを発火させない = IsDoT扱い)
    execute if score @s Sec matches 20 run function asset:effect/0307.bleeding/tick/damage

# 1秒に1回だけ実行する用のカウンタ
    scoreboard players add @s Sec 1
    execute if score @s Sec matches 21.. run scoreboard players set @s Sec 0
#> asset:effect/0307.bleeding/tick/damage
    data modify storage api: Argument.Damage set value 2.0f
    data modify storage api: Argument.AttackType set value "Magic"
    data modify storage api: Argument.ApplyTrigger set value false   # ← DoT 扱いにする
    function api:damage/
    function api:damage/reset

4.5. end (効果時間終了時)

Durationが 0 になって効果時間が終了した時の処理。バニラエフェクトの解除など、後片付けを書く。

#> asset:effect/0031.slow_falling/end/
    effect clear @s slow_falling

4.6. remove (外部からの削除)

API や牛乳等で外部から削除された時の処理。

#> asset:effect/0031.slow_falling/remove/
    effect clear @s slow_falling

endremoveで同じ処理を書きたい場合、共通処理を別の mcfunction に切り出して、 end/.mcfremove/.mcf の両方からそれを function で呼ぶ設計にしてね。

4.7. 補正 (Modifier) の付与

Attribute 補正 (攻撃力、魔法耐性 等) を付けたい場合、 givenapi:modifier/<カテゴリ>/<種類>/add を呼んで補正を加え、 remove (および必要なら end) で対応する remove API を呼んで取り除く。識別は Argument.UUID で行うよ。

エフェクト modifier の UUID 形式

[I;1,3,<エフェクトID>,0]
位置 意味
1 1 固定
2 3 エフェクト由来を示すマーカー
3 <エフェクトID> このエフェクトの ID
4 0 固定

つまり ID 272 のエフェクトなら [I;1,3,272,0]

実装パターン

慣例として modifier/add.mcfunctionmodifier/remove.mcfunction をエフェクト直下に切り出して、各処理側からは function 呼びにする。

例: 0272.inspiration (物理攻撃 +20%)

#> asset:effect/0272.inspiration/modifier/add
# 物理攻撃 +20%
    data modify storage api: Argument.UUID set value [I;1,3,272,0]
    data modify storage api: Argument.Amount set value 0.2
    data modify storage api: Argument.Operation set value "multiply"
    function api:modifier/attack/physical/add
#> asset:effect/0272.inspiration/modifier/remove
# 物理攻撃 +20% を解除
    data modify storage api: Argument.UUID set value [I;1,3,272,0]
    function api:modifier/attack/physical/remove

given/.mcfunction から modifier/add を、 remove/.mcfunction (および必要なら end/.mcfunction) から modifier/remove を呼ぶ。

複数の補正を 1 つのエフェクトで付ける場合

modifier API を複数並べる。 UUID は 全部同じ [I;1,3,<エフェクトID>,0] で OK ── modifier 種別 (attack/physical / receive_heal 等) が違うので別管理される。

例: 0231.wandering_dream (魔法耐性 +12% / 被回復量 +12%)

#> asset:effect/0231.wandering_dream/modifier/add
# 魔法耐性
    data modify storage api: Argument.UUID set value [I;1,3,231,0]
    data modify storage api: Argument.Amount set value 0.12
    data modify storage api: Argument.Operation set value "multiply"
    function api:modifier/defense/magic/add

# 被回復量
    data modify storage api: Argument.UUID set value [I;1,3,231,0]
    data modify storage api: Argument.Amount set value 0.12
    data modify storage api: Argument.Operation set value "multiply"
    function api:modifier/receive_heal/add

remove 側もペアで両方の API を順番に呼ぶ。 UUID は付与時と同じ。

5. Field を使ったカスタムデータ

register.mcfFieldを定義しておくと、各エフェクト個体に固有のデータを持たせられるよ。 tick などからasset:context this.<キー>で参照可能。

例: 色付きの灯火エフェクト

#> asset:effect/0999.colored_light/register
data modify storage asset:effect ID set value 999
data modify storage asset:effect Name set value '{"text":"灯火"}'
data modify storage asset:effect Description set value ['{"text":"色を持つ灯り"}']
data modify storage asset:effect Duration set value 200
data modify storage asset:effect IsBadEffect set value false
# カスタムフィールドの定義
data modify storage asset:effect Field set value {Color:16777215, Intensity:5}

tick の中で Field の値をコマンド引数として使いたい時 (例: particle ... <個数><個数> に Field の値を入れたい等) は、そのままでは書けないから マクロ関数 にしてね。マクロ関数の中では $(Intensity) のような書き方で値を差し込めるよ。

#> asset:effect/0999.colored_light/tick/

# Field の値をマクロ引数として渡す
function asset:effect/0999.colored_light/tick/m with storage asset:context this
#> asset:effect/0999.colored_light/tick/m
#
# @input args
#   Intensity: int

# Intensity 個の particle を出す ($(Intensity) で個数を差し込む)
$particle dust 1.0 0.5 0.2 ~ ~1 ~ 0.3 0.3 0.3 0 $(Intensity) force @a

マクロ関数の決まりごと :

  • ファイル名末尾を m.mcfunction または .m.mcfunction にする (例: tick/m.mcfunctionsummon/m.mcfunction)
  • 値を差し込みたい行の 冒頭$ を付ける
  • 差し込む値は $(<キー>) の形で書く
  • 呼び出し側は function <パス> with storage <storage> <パス> で引数 storage を渡す

Field を付与時に上書きする

api:entity/mob/effect/giveArgument.FieldOverrideで、個別の付与時に Field を上書きできる。

data modify storage api: Argument.ID set value 999
data modify storage api: Argument.Duration set value 100
data modify storage api: Argument.FieldOverride set value {Color:16711680, Intensity:10}    # 赤色、強度10
execute as <target> run function api:entity/mob/effect/give
function api:entity/mob/effect/reset    # 必須

PreviousField で前状態と比較する

re-given 時には、storage asset:context PreviousFieldに「直前の Field の内容」が自動で入る。これを使って、状態遷移の検出ができるよ。

# 直前のStackが3未満で、今回4以上になった → 何か発動
execute if data storage asset:context PreviousField{Stack:3} if data storage asset:context {Stack:4} run

フルセット防具やシナジー系のエフェクトで多用するパターン。

6. 継承 (extends) の仕組み

他のエフェクトを継承して、共通処理を親に集約できる。神器のシリーズ (例: 同じ陣営の装備全部) で共通効果を持たせたい時に便利。 ただし ExtendsSafe: true、要するに継承元はスコアボードを使わない設計にしなければならない(これはコアシステムの都合によるもの)。

親エフェクト側 (継承される側)

#> asset:effect/0500.flame_base/register
data modify storage asset:effect ExtendsSafe set value true        # ← 継承可能にする
data modify storage asset:effect ID set value 500
data modify storage asset:effect Name set value '{"text":"炎の祝福"}'
data modify storage asset:effect IsBadEffect set value false
data modify storage asset:effect Duration set value -1

子エフェクト側 (継承する側)

#> asset:effect/0501.flame_strong/register
# 継承宣言
data modify storage asset:effect Extends append value 500
function asset:effect/extends

# 自分の情報を上書き
data modify storage asset:effect ID set value 501
data modify storage asset:effect Name set value '{"text":"強化された炎の祝福"}'

親メソッドの呼び出し

tick 等の各実装ファイルでsuper.tick相当を呼びたい時は、function asset:effect/super.tickを実行する。

#> asset:effect/0501.flame_strong/tick/

# 親の tick も呼ぶ
function asset:effect/super.tick

# 子独自の処理
particle flame ~ ~1.5 ~ 0.3 0.3 0.3 0.05 5

7. エフェクトの付与・削除 (API から呼ぶ側)

詳細はAPIを参照。簡単な使い方だけ:

# 付与 (例 : 範囲内の敵全員にデバフを付与)
    data modify storage api: Argument.ID set value 31           # エフェクトID
    data modify storage api: Argument.Duration set value 200    # 効果時間 (tick) -- register側で指定済みなら省略可
    execute as @e[type=#lib:living_without_player,tag=Enemy,distance=..8] run function api:entity/mob/effect/give
    function api:entity/mob/effect/reset    # 必須

# 削除 (IDから)
    data modify storage api: Argument.ID set value 31
    execute as <target> run function api:entity/mob/effect/remove/from_id
    function api:entity/mob/effect/reset    # 必須

# 削除 (解除レベルから)
    data modify storage api: Argument.ClearLv set value 3
    execute as <target> run function api:entity/mob/effect/remove/from_level
    function api:entity/mob/effect/reset    # 必須

重要 (reset): 上記 3 つ (give / remove/from_id / remove/from_level) は 複数対象への連続適用 を想定して内部で Argument を消さない設計なので、呼び出し後に api:entity/mob/effect/reset を呼ぶ責任がある (1 回 set → 複数対象に execute as で適用 → 最後に reset、という流れ)。一方 get/* は内部で自動 remove するので reset 不要。

神器のEquipment.Effectsで指定したエフェクトは、装備時に自動で api:entity/mob/effect/give 経由で付与される。詳細は 神器の作り方 - 装備時効果 を参照。

8. ハマりポイント

  • given と re-given を取り違える → 初回付与はgiven、再付与・スタック変化はre-given。両方で同じ処理が必要な場合は共通処理を別ファイルに切り出して両方から呼ぶ
  • end と remove の片方しか書かない → 効果時間終了 (end) と外部からの削除 (remove) のうち、書いてない方のケースで後片付けが走らない。
  • modifier の UUID を間違える / 揃え忘れる → 形式は [I;1,3,<エフェクトID>,0] 固定。付与時と削除時で UUID がズレると remove API が「対象なし」 で何もせず、補正が残り続ける。共通化のために modifier/remove.mcfunction に切り出すのが定型
  • give / remove/*reset を呼び忘れる → これらは複数対象への連続適用を想定して内部で Argument を自動 remove しない設計。呼び出し後に function api:entity/mob/effect/reset を必ず実行する。忘れると次の呼び出しに Duration/Stack/FieldOverride などの前回値が混ざる (get/* は自動 remove なので reset 不要)
  • tick で重い処理を書く → 全プレイヤー × 持ってるエフェクト数だけ毎 tick 実行される。 1 秒に 1 回でいい処理は scoreboard カウンタで間引く
  • DoT で神器が連発されるapi:damage/を呼ぶ前に Argument.ApplyTrigger:false で IsDoT 扱いに (神器の作り方 - IsDoT / IsHoT のルール参照)
  • PreviousField を見ずに re-given を書く → Stack が変化したことを検出できず、フルセット効果がうまく動かない原因に
  • ProcessOnDied を指定し忘れる → 死亡で消えるのが嫌なエフェクトは "keep" を明示する

Clone this wiki locally