はじめに
「独自の攻撃処理にはカスタムエンチャントが良い"という話"」
ともある通り、技術をそのまま話すよりも語りが多くなっています。(スミマセン)
この記事は以下の前提を踏まえての話です。
- Minecraft Java Edition 1.21.10
- データパックを作ったことがある
基礎的なデータパックの作り方についてはこの世にたくさん存在する (と信じているので) 省略します。
独自の攻撃処理の必要条件
- それぞれをセレクターで選択しやすい
- Tick内に何回も処理が可能
- 条件を満たした上でサーバー負荷に影響が少ない
事の経緯
独自の攻撃処理が必要になった経緯についてです。 (ぶっちゃけ読まなくてもいい!!!)
私はまっしゅさん1に影響を受け、データパック製作に足を踏み入れた1人なのですが、データパックのできることの広さに気づいた時、うっすらと「マイクラでちゃんとしたRPG作れるんじゃね...?」という構想が思い浮かんでいました。
ちょうどその時、まっしゅさん1のチャンネルにて「マイクラバニラで本格RPGを作ろう!」というシリーズが投稿され始め、よく影響を受けました。
そして(投稿日時より)2年前に原神を始め、これも影響します。
(投稿日時より)1年前、ついにマイクラでRPGを作ろうと動き出しました。
当時の戦闘システムは攻撃力 ダメージ倍率 クリティカル ダメージアップ 防御力がダメージ計算に関与し、ダメージのスケールも終盤あたりでは1万ダメージから100万ダメージの想定という壮大なスケールで、完全にバニラの「攻撃力上昇エフェクト」などを使用することが出来ませんでした。
なおかつ、advancementは敵のステータスを取得しづらいので、採用が難しくなっていました。(条件1)
今思うとscoreboard使えば簡単にで実装できたな...
なおかつダメージは同Tick内に10回以上与えられる場面もあり、#minecraft:tickが使いづらいという状況でした。(条件2)
当時のダメージ計算式(クリティカル確率に的中した時)
(ATK * DMG Multiplier)*(1+Additive DMG)*(1+CriticalDMG)*(TargetDEF)
そんな時に目をつけたのがカスタムエンチャント(Enchantment)でした
カスタムエンチャントとは
ここで指すエンチャントとは「ダメージ増加」「アンデット特攻」「火炎耐性」「棘の鎧」などのアレのことです。
1.21あたりでエンチャントをデータパックでカスタマイズが可能になりました。
バニラのエンチャントの効果(攻撃力+1する等)以外にもAdvancementと同様に特定条件で関数(mcfunction)を実行することが出来ます。
また、有志の生成ツールとしてMisode氏のEnchantment Generatorがとても使いやすくおすすめします。
作ろう
カスタムエンチャントはeffectsの中に効果を書きます。
今回使用するエンティティ基準型のeffectsの場合、トリガーと作用内容を書きます。
エンチャントの中身
仕組みはエンティティ基準型のeffectsであるpost_attackを使用しています。
post_attackはエンティティを攻撃したときに引かれるトリガーです。
Tickに影響されません(条件2)
以下のeffectsを追加します。
{
"effect": {
"type": "minecraft:run_function",
"function": "namespace:function"
},
"enchanted": "victim",
"affected": "attacker"
}
enchantedについて
attacker damaging_entity victimが選択可能です。
これは「この効果はこのエンチャントが誰についていると発動するか」という欄です。
| 選択可能 | 意味 |
|---|---|
| attacker | 攻撃者 |
| damaging_entity | ダメージを与えたエンティティ |
| victim | 被害者 |
damaging_entityはそのダメージを直接与えたエンティティです。
例えば弓矢の場合は矢、投げたトライデントの場合は"投げられたトライデント"のことです。
これらは私的にはvictimがおすすめでが、attacker victimのどちらかであればなんでもいいです。
affectedについて
先程と同じくattacker damaging_entity victimが選択可能です。
これは「この効果を誰が発動するか」という欄です。
処理の流れ
ざっくり図解すると以下のとおりです。
矢印の数字は処理の順番です。
カスタムエンチャントのJSONファイルに記述したeffectsは記入内容の上から順に実行されます。
タグを付与することで、セレクターでの選択を@n[tag=tagName]のように、1回で済ませられるようにしています。(条件1)
なぜ [攻撃者]->[投射物]->[被害者] の順番かというのは投射物の都合です。
この[投射物](post_attack:projectile)は、弓矢で攻撃した場合には矢が当たりますが、直接攻撃した場合はプレイヤーが選択されます。
そのため先に[攻撃者]のタグを付与し、post_attack:projectileを実行した時、自身に[攻撃者]のタグが付与されている場合は切り返すようにしています。
そうなると必然的に[被害者]がいちばん最後に来るということです。
実装
必要な関数のmcfunctionファイル
tag @s add damage.attacker
execute if entity @s[tag=damage.attacker] run return 0
tag @s add damage.projectile
tag @s add damage.victim
# ここに処理
title @a title [{"bold":true,text:""},{selector:"@n[tag=damage.attacker]",color:red},"-",{selector:"@n[tag=damage.projectile]",color:"green"},"->",{selector:"@n[tag=damage.victim]",color:"blue"}]
tag @e remove damage.attacker
tag @e remove damage.projectile
tag @e remove damage.victim
最終的なエンチャントのJSONファイル
{
"anvil_cost": 0,
"description": "バニラ攻撃検知用",
"effects": {
"minecraft:post_attack": [
{
"effect": {
"type": "minecraft:run_function",
"function": "namespace:attacker"
},
"enchanted": "victim",
"affected": "attacker"
},
{
"effect": {
"type": "minecraft:run_function",
"function": "namespace:projectile"
},
"enchanted": "victim",
"affected": "damaging_entity"
},
{
"effect": {
"type": "minecraft:run_function",
"function": "namespace:victim"
},
"enchanted": "victim",
"affected": "victim"
}
]
},
"max_cost": {
"base": 0,
"per_level_above_first": 0
},
"max_level": 1,
"min_cost": {
"base": 0,
"per_level_above_first": 0
},
"slots": [
"saddle"
],
"supported_items": "minecraft:saddle",
"weight": 1
}
"anvil_cost" "description" "max_cost" "min_cost" "weight"
は何でもいいです。適当に値を入れてください。
"slots"にはエンチャントが有効になるスロットを記入してください。
"supported_items"にはエンチャントが有効になるアイテムを記入してください。
サドルはプレイヤーにもコマンドを用いることで装備させることが出来ます。
"slots" "supported_items"は必ず記入してください
検証
今回制作したものはそのままGitHubに置いていますのでカスタムしたい方はぜひ。
最後に
最初はeffectsが上から順に実行されると知らず、「バグかたまたまだろうし不安定っぽいな...」とか思ってました。
カスタムエンチャントは使えるようになるとかなり便利です。
私はRPG以外の配布マップ2でも同じ処理方法を採用したりしています。
ぜひオリジナルのデータパックや配布マップに組み込んでください!
-
配布マップ(宣伝): BridgeField ↩

