在塞尔达mod中,有一个名为“大鹏的羽毛”的道具。相信看过Pi视频的朋友一定对这个道具不陌生。
这个道具的主要作用是:拿在手中,玩家就能增加跳跃高度,从高空下落的速度减慢,并且落地时不受摔落伤害。
今天我们就来用命令方块重现这个神奇的道具吧!
道具使用方法:主手或副手持有“大鹏的羽毛”即可触发上述效果。
理论适用版本:1.9-1.12.2
一键命令方块适用版本:1.11.2-1.12.2
老规矩,浏览器用户可通过楼顶的目录选择想要阅读的内容。想要了解原理的朋友可以阅读“大致原理”,也可以跳过原理直接阅读“命令部分”和“一键命令方块”部分。
大致原理:
要重现这个道具的效果,跳跃高度的提升基本不是问题(使用effect给持有道具的玩家提供跳跃提升效果即可),问题在于如何减缓下落速度并减免摔落伤害。
我们知道,1.9版本及之后的MC状态效果中,有一个名为“漂浮”(levitation)的状态效果,受该效果影响的玩家会缓慢向上漂浮。然而“漂浮”还有一个效果:当漂浮的效果等级为“负等级”(129-256等级)时,实际效果改为缓慢下落。这边是我们所想要的效果。
这样一来,很容易想到实现方法:当检测到玩家处于空中的时候,给予玩家一个负等级的漂浮效果,然后等检测到玩家落地后,取消漂浮效果。
那么这样是不是就完成了呢?答案是否定的。实际上,如果玩家从极高的位置下落,即使拥有缓慢下落的效果,同样会受到摔落伤害。这是因为MC判定摔落伤害的准则是在空中期间的累计摔落高度,无论多么缓慢地从高处下落,该摔伤还是得摔伤。(注:wiki里所说的“坠落伤害不受影响”并不是指“不受坠落伤害”。感兴趣的读者可以在游戏中亲自试验效果。)
通过进一步查阅wiki我们可以得知,等级为256的跳跃提升可以完全减免摔落伤害,且跳跃高度不受影响。因此,我们可以给处于缓落状态的玩家再加一个256级的跳跃提升来保证玩家坠落时不受伤害。
由于MC的判定机制比较迷,有时拥有漂浮状态的玩家站在地面会被游戏认为并不在地面(OnGround:0b),这就给命令方块组的条件判定带来了一些障碍。由于高等级的状态效果会强制覆盖低等级的效果,为了防止之前附加用于提升跳跃高度的跳跃提升效果失效,需要额外增加一些条件。这里我们通过检测玩家周围及下方的方块是否为空气方块来决定是否给予玩家负等级的漂浮效果和256等级的跳跃提升效果。
顺便一提,MC还有一个很迷的机制:一般而言,玩家从极高的地方摔下来会就地阵亡。但如果中途获得过负等级的漂浮效果并且没有摔落减免,则无论落地时是否还有漂浮效果,玩家都会被再次弹到很高的高度。这个问题会导致一些预想之外的情况出现。为了避免这个问题,我们做如下处理:若玩家使用羽毛的过程中途变为了不持有羽毛的状态,且处于空中,则取消玩家的缓落效果,但保留摔落伤害减免效果,直至玩家着地。
另外,我们还需要考虑到一般生存中原本可以获得的状态效果:等级为1和2的跳跃提升(通过药水和信标获得),和等级为1的漂浮(通过潜影贝的攻击获得)。由于我们设置了落地或非手持羽毛状态取消状态效果,我们要尽量避免这个举动对原版存在的状态效果的影响。此外,还要注意所有的操作不能影响其他没有这个道具的玩家。这些都将在命令中得到体现。
最后需要说明一点,本文中的“大鹏的羽毛”和塞尔达mod中的羽毛还是有区别的。比如塞尔达mod中的羽毛在持有的状态下不会破坏耕地,但本文中的羽毛不行。这是因为虽然摔落伤害减免了,但实际的摔落高度还是存在的。
命令部分:
首先是获得羽毛的命令:
/give @p minecraft:feather 1 0 {display:{Name:"大鹏的羽毛",Lore:["握在手上,可以让身体变得轻盈"]},HideFlags:1,ench:[{id:2,lvl:1}],Fly:1b}
以下是命令方块中的命令:
(注:第一个命令方块是保持开启的循环命令方块,其他均为连锁命令方块。#代表注释)
#标记主手或副手持有羽毛的玩家
R:scoreboard players tag @a add Fly {SelectedItem:{id:"minecraft:feather",tag:{Fly:1b}}}
scoreboard players tag @a add Fly {Inventory:[{Slot:-106b,id:"minecraft:feather",tag:{Fly:1b}}]}
#区分生存模式存在的相似状态效果
scoreboard players tag @a add levi {ActiveEffects:[{Id:25b,Amplifier:0b}]}
scoreboard players tag @a add jump.b {ActiveEffects:[{Id:8b,Amplifier:0b}]}
scoreboard players tag @a add jump.b {ActiveEffects:[{Id:8b,Amplifier:1b}]}
#标记处于空中的玩家
scoreboard players tag @a[tag=Fly] add Flying {OnGround:0b}
#检测周围方块是否为空气,进一步确定是否给予玩家缓落及摔落伤害减免效果
execute @a[tag=Flying] ~ ~-1 ~ detect ~ ~ ~ air 0 execute @p ~1 ~-1 ~ detect ~ ~ ~ air 0 execute @p ~-1 ~-1 ~ detect ~ ~ ~ air 0 execute @p ~ ~-1 ~1 detect ~ ~ ~ air 0 execute @p ~ ~-1 ~-1 detect ~ ~ ~ air 0 execute @p ~1 ~-1 ~1 detect ~ ~ ~ air 0 execute @p ~1 ~-1 ~-1 detect ~ ~ ~ air 0 execute @p ~-1 ~-1 ~1 detect ~ ~ ~ air 0 execute @p ~-1 ~-1 ~-1 detect ~ ~ ~ air 0 effect @p[tag=!levi] minecraft:levitation 1 251 true
execute @a[tag=Flying] ~ ~-1 ~ detect ~ ~ ~ air 0 execute @p ~1 ~-1 ~ detect ~ ~ ~ air 0 execute @p ~-1 ~-1 ~ detect ~ ~ ~ air 0 execute @p ~ ~-1 ~1 detect ~ ~ ~ air 0 execute @p ~ ~-1 ~-1 detect ~ ~ ~ air 0 execute @p ~1 ~-1 ~1 detect ~ ~ ~ air 0 execute @p ~1 ~-1 ~-1 detect ~ ~ ~ air 0 execute @p ~-1 ~-1 ~1 detect ~ ~ ~ air 0 execute @p ~-1 ~-1 ~-1 detect ~ ~ ~ air 0 effect @p[tag=!jump.b] minecraft:jump_boost 1 255 true
#当玩家着地时取消缓落及摔落伤害减免效果
execute @a[tag=Fly] ~ ~ ~ execute @p[tag=!Flying] ~ ~ ~ execute @p[tag=!jump.b] ~ ~ ~ effect @p minecraft:jump_boost 0
execute @a[tag=Fly] ~ ~ ~ execute @p[tag=!Flying] ~ ~ ~ execute @p[tag=!levi] ~ ~ ~ effect @p minecraft:levitation 0
#当玩家主手或副手不再持有羽毛时,取消缓落效果,但保留摔落伤害减免效果直至着地
scoreboard players tag @a[tag=!Fly] add Keep {ActiveEffects:[{Id:25b,Amplifier:-5b},{Id:8b,Amplifier:-1b}]}
effect @p[tag=Keep] minecraft:levitation 0
effect @p[tag=Keep] minecraft:jump_boost 1 255 true
scoreboard players tag @a[tag=Keep] add Keepover {OnGround:1b}
effect @p[tag=Keepover] minecraft:jump_boost 0
scoreboard players tag @a[tag=Keepover] remove Keep
scoreboard players tag @a[tag=Keepover] remove Keepover
#使玩家持有羽毛时在地面获得跳跃提升效果
effect @a[tag=Fly] minecraft:jump_boost 1 2 true
#tag回收
scoreboard players tag @a[tag=Fly] remove Fly
scoreboard players tag @a[tag=Flying] remove Flying
scoreboard players tag @a[tag=levi] remove levi
scoreboard players tag @a[tag=jump.b] remove jump.b
一键命令方块:
注意事项:
1、请将命令方块组放置在世界出生点区块,避免失效
3、命令方块组体积为4*2*3,请确保有足够空间放置。
使用方法:
1、按F3确定当前朝向为西面(Facing:west)。
2、从想要放置命令方块的位置(该位置为命令方块组的右上顶点)向前走1步,在地上放一个按钮
3、在按钮前面一个放一个命令方块(获得命令方块:/give @p minecraft:command_block)。
4、将下面的命令全部复制到命令方块中,点击“完成”。
5、按下按钮。
以下是一键命令(可通过三击鼠标左键快速选定):
summon falling_block ~ ~1 ~ {Block:stone,Time:1,Passengers:[{id:falling_block,Block:redstone_block,Time:1,Passengers:[{id:falling_block,Block:activator_rail,Time:1,Passengers:[{id:commandblock_minecart,Command:"gamerule commandBlockOutput false"},{id:commandblock_minecart,Command:"fill ~3 ~-3 ~ ~6 ~-2 ~2 chain_command_block 5"},{id:commandblock_minecart,Command:"fill ~6 ~-2 ~ ~5 ~-2 ~ chain_command_block 4"},{id:commandblock_minecart,Command:"setblock ~6 ~-2 ~1 chain_command_block 2"},{id:commandblock_minecart,Command:"setblock ~3 ~-2 ~2 chain_command_block 2"},{id:commandblock_minecart,Command:"fill ~6 ~-2 ~2 ~4 ~-2 ~2 chain_command_block 4"},{id:commandblock_minecart,Command:"setblock ~6 ~-3 ~2 chain_command_block 1"},{id:commandblock_minecart,Command:"setblock ~3 ~-3 ~1 chain_command_block 3"},{id:commandblock_minecart,Command:"fill ~6 ~-3 ~1 ~4 ~-3 ~1 chain_command_block 4"},{id:commandblock_minecart,Command:"setblock ~6 ~-3 ~ chain_command_block 3"},{id:commandblock_minecart,Command:"setblock ~3 ~-3 ~ repeating_command_block 5"},{id:commandblock_minecart,Command:"blockdata ~5 ~-2 ~ {auto:1,Command:\"scoreboard players tag @a[tag=jump.b] remove jump.b\"}"},{id:commandblock_minecart,Command:"blockdata ~6 ~-2 ~ {auto:1,Command:\"scoreboard players tag @a[tag=levi] remove levi\"}"},{id:commandblock_minecart,Command:"blockdata ~6 ~-2 ~1 {auto:1,Command:\"scoreboard players tag @a[tag=Flying] remove Flying\"}"},{id:commandblock_minecart,Command:"blockdata ~5 ~-2 ~1 {auto:1,Command:\"scoreboard players tag @a[tag=Fly] remove Fly\"}"},{id:commandblock_minecart,Command:"blockdata ~4 ~-2 ~1 {auto:1,Command:\"effect @a[tag=Fly] minecraft:jump_boost 1 2 true\"}"},{id:commandblock_minecart,Command:"blockdata ~3 ~-2 ~1 {auto:1,Command:\"scoreboard players tag @a[tag=Keepover] remove Keepover\"}"},{id:commandblock_minecart,Command:"blockdata ~3 ~-2 ~2 {auto:1,Command:\"scoreboard players tag @a[tag=Keepover] remove Keep\"}"},{id:commandblock_minecart,Command:"blockdata ~4 ~-2 ~2 {auto:1,Command:\"effect @p[tag=Keepover] minecraft:jump_boost 0\"}"},{id:commandblock_minecart,Command:"blockdata ~5 ~-2 ~2 {auto:1,Command:\"scoreboard players tag @a[tag=Keep] add Keepover {OnGround:1b}\"}"},{id:commandblock_minecart,Command:"blockdata ~6 ~-2 ~2 {auto:1,Command:\"effect @p[tag=Keep] minecraft:jump_boost 1 255 true\"}"},{id:commandblock_minecart,Command:"blockdata ~6 ~-3 ~2 {auto:1,Command:\"effect @p[tag=Keep] minecraft:levitation 0\"}"},{id:commandblock_minecart,Command:"blockdata ~5 ~-3 ~2 {auto:1,Command:\"scoreboard players tag @a[tag=!Fly] add Keep {ActiveEffects:[{Id:25b,Amplifier:-5b},{Id:8b,Amplifier:-1b}]}\"}"},{id:commandblock_minecart,Command:"blockdata ~4 ~-3 ~2 {auto:1,Command:\"execute @a[tag=Fly] ~ ~ ~ execute @p[tag=!Flying] ~ ~ ~ execute @p[tag=!levi] ~ ~ ~ effect @p minecraft:levitation 0\"}"},{id:commandblock_minecart,Command:"blockdata ~3 ~-3 ~2 {auto:1,Command:\"execute @a[tag=Fly] ~ ~ ~ execute @p[tag=!Flying] ~ ~ ~ execute @p[tag=!jump.b] ~ ~ ~ effect @p minecraft:jump_boost 0\"}"},{id:commandblock_minecart,Command:"blockdata ~3 ~-3 ~1 {auto:1,Command:\"execute @a[tag=Flying] ~ ~-1 ~ detect ~ ~ ~ air 0 execute @p ~1 ~-1 ~ detect ~ ~ ~ air 0 execute @p ~-1 ~-1 ~ detect ~ ~ ~ air 0 execute @p ~ ~-1 ~1 detect ~ ~ ~ air 0 execute @p ~ ~-1 ~-1 detect ~ ~ ~ air 0 execute @p ~1 ~-1 ~1 detect ~ ~ ~ air 0 execute @p ~1 ~-1 ~-1 detect ~ ~ ~ air 0 execute @p ~-1 ~-1 ~1 detect ~ ~ ~ air 0 execute @p ~-1 ~-1 ~-1 detect ~ ~ ~ air 0 effect @p[tag=!jump.b] minecraft:jump_boost 1 255 true\"}"},{id:commandblock_minecart,Command:"blockdata ~4 ~-3 ~1 {auto:1,Command:\"execute @a[tag=Flying] ~ ~-1 ~ detect ~ ~ ~ air 0 execute @p ~1 ~-1 ~ detect ~ ~ ~ air 0 execute @p ~-1 ~-1 ~ detect ~ ~ ~ air 0 execute @p ~ ~-1 ~1 detect ~ ~ ~ air 0 execute @p ~ ~-1 ~-1 detect ~ ~ ~ air 0 execute @p ~1 ~-1 ~1 detect ~ ~ ~ air 0 execute @p ~1 ~-1 ~-1 detect ~ ~ ~ air 0 execute @p ~-1 ~-1 ~1 detect ~ ~ ~ air 0 execute @p ~-1 ~-1 ~-1 detect ~ ~ ~ air 0 effect @p[tag=!levi] minecraft:levitation 1 251 true\"}"},{id:commandblock_minecart,Command:"blockdata ~5 ~-3 ~1 {auto:1,Command:\"scoreboard players tag @a[tag=Fly] add Flying {OnGround:0b}\"}"},{id:commandblock_minecart,Command:"blockdata ~6 ~-3 ~1 {auto:1,Command:\"scoreboard players tag @a add jump.b {ActiveEffects:[{Id:8b,Amplifier:1b}]}\"}"},{id:commandblock_minecart,Command:"blockdata ~6 ~-3 ~ {auto:1,Command:\"scoreboard players tag @a add jump.b {ActiveEffects:[{Id:8b,Amplifier:0b}]}\"}"},{id:commandblock_minecart,Command:"blockdata ~5 ~-3 ~ {auto:1,Command:\"scoreboard players tag @a add levi {ActiveEffects:[{Id:25b,Amplifier:0b}]}\"}"},{id:commandblock_minecart,Command:"blockdata ~4 ~-3 ~ {auto:1,Command:\"scoreboard players tag @a add Fly {Inventory:[{Slot:-106b,id:\\\"minecraft:feather\\\",tag:{Fly:1b}}]}\"}"},{id:commandblock_minecart,Command:"blockdata ~3 ~-3 ~ {auto:1,Command:\"scoreboard players tag @a add Fly {SelectedItem:{id:\\\"minecraft:feather\\\",tag:{Fly:1b}}}\"}"},{id:commandblock_minecart,Command:"setblock ~ ~ ~1 command_block 0 0 {Command:\"fill ~ ~-3 ~-1 ~ ~ ~ air\"}"},{id:commandblock_minecart,Command:"setblock ~ ~-1 ~1 redstone_block"},{id:commandblock_minecart,Command:"kill @e[type=commandblock_minecart,r=1]"}]}]}]}