Minecraft 1.14 Command Block Arrow Barrage

minecraft-commandsminecraft-java-edition

I am trying to make an arrow barrage using command blocks and my current method is:

/scoreboard objectives add RClick minecraft.used:minecraft.carrot_on_a_stick

/execute as @a[scores={RClick=1..}] at @s run summon arrow ~ ~ ~ {NoGravity:1,Tags:["Arrow"]}

/execute at @a[scores={RClick=1..}] run tp @e[type=arrow,tag=Arrow,sort=nearest,distance=..1] @p[scores={RClick=..1}]

/execute at @a[scores={RClick=1..}] run tp @e[type=arrow,tag=Arrow,sort=nearest,distance=..1] ~ ~1.5 ~

/execute at @e[type=arrow,tag=Arrow] run tp @e[type=arrow,tag=Arrow,distance=..1] ^ ^ ^1

/scoreboard players reset @a[scores={RClick=1..}] RClick

/scoreboard players add @e[type=arrow,tag=Arrow] RClick 1

/kill @e[type=arrow,tag=Arrow,scores={RClick=100..}]

Is there a better way of going about this? This just seems weird and not as natural as I'd like it to be…

Best Answer

This is my function from a datapack that I wrote which allows you to summon an "arrow of legolas" which will fly in the direction the player is looking at significant speed. It is just called that in the code: it won't actually have a nametag or anything ingame. It is run when the player right clicks with a carrot on a stick.

summon minecraft:arrow ^ ^ ^0.25 {CustomName:"\"legolas_arrow\"",pickup:0,damage:2,crit:1,PierceLevel:5,Color:-1}

execute as @a store result score @s playerX run data get entity @s Pos[0] 100
execute as @a store result score @s playerY run data get entity @s Pos[1] 100
execute as @a store result score @s playerZ run data get entity @s Pos[2] 100    

execute as @e[name=legolas_arrow] store result score @s projectileX run data get entity @s Pos[0] 100
execute as @e[name=legolas_arrow] store result score @s projectileY run data get entity @s Pos[1] 100
execute as @e[name=legolas_arrow] store result score @s projectileZ run data get entity @s Pos[2] 100

execute as @e[name=legolas_arrow] store result score @s projectileX run scoreboard players operation @s projectileX -= @p playerX
execute as @e[name=legolas_arrow] store result score @s projectileY run scoreboard players operation @s projectileY -= @p playerY
execute as @e[name=legolas_arrow] store result score @s projectileZ run scoreboard players operation @s projectileZ -= @p playerZ

execute as @e[name=legolas_arrow] at @s run tp @s ~ ~1.62 ~

execute as @e[name=legolas_arrow] store result entity @s Motion[0] double 0.1 run scoreboard players get @s projectileX
execute as @e[name=legolas_arrow] store result entity @s Motion[1] double 0.1 run scoreboard players get @s projectileY
execute as @e[name=legolas_arrow] store result entity @s Motion[2] double 0.1 run scoreboard players get @s projectileZ

scoreboard players reset @e projectileX
scoreboard players reset @e projectileY
scoreboard players reset @e projectileZ

execute as @e[name=legolas_arrow] at @s run data merge entity @s {CustomName:""}

projectileX, projectileY, and projectileZ are all scoreboards, as are playerX, playerY, and playerZ. What this function (although you could add a condition before every line so that you could use it in a chained command block series) does is summon an arrow, get it's position and the player's position into scoreboards with a scale factor of 100, and then subtract them to get a vector. Then it stores this into the arrow's motion with a one-tenth scale factor rather than a one-hundredth scale factor so that it's a speedy boi. It uses a customName instead of a scoreboard tag just because that was my personal preference, but either would work.

Edit:
As this is supposed to be run as a player, every @s refers to the executing player and in every command executed as @e[name=legolas_arrow] the @p also refers to the executing player. To get around this and allow it to work for command blocks, I suggest adding a command block at the very front of the chain which is repeating and always active which tags the player whose carrot clicks scoreboard has increased with "archer" or something similar, and then replace all of the @s's to be @a[tag=archer] and all of the @p's to also be @a[tag=archer]. This way you can skip the conditional at the beginning of all of them.

I might use @p[tag=archer] on second thought that way in the rare event that two players right click at the same time it will process one of them (and hopefully also the other) in a row rather than mixing up their commands.

Edit 2: I rewrote the commands and will test them when I get home:

tag @a[scores={RClick=1..}] add archer
execute as @p[tag=archer] at @s run summon minecraft:arrow ^ ^ ^0.25 {CustomName:"\"legolas_arrow\"",pickup:0,damage:2,crit:1,PierceLevel:5,Color:-1}

execute as @a store result score @s playerX run data get entity @s Pos[0] 100
execute as @a store result score @s playerY run data get entity @s Pos[1] 100
execute as @a store result score @s playerZ run data get entity @s Pos[2] 100    

execute as @e[name=legolas_arrow] store result score @s projectileX run data get entity @s Pos[0] 100
execute as @e[name=legolas_arrow] store result score @s projectileY run data get entity @s Pos[1] 100
execute as @e[name=legolas_arrow] store result score @s projectileZ run data get entity @s Pos[2] 100

execute as @e[name=legolas_arrow] store result score @s projectileX run scoreboard players operation @s projectileX -= @p[tag=archer] playerX
execute as @e[name=legolas_arrow] store result score @s projectileY run scoreboard players operation @s projectileY -= @p[tag=archer] playerY
execute as @e[name=legolas_arrow] store result score @s projectileZ run scoreboard players operation @s projectileZ -= @p[tag=archer] playerZ

execute as @e[name=legolas_arrow] at @s run tp @s ~ ~1.62 ~

execute as @e[name=legolas_arrow] store result entity @s Motion[0] double 0.1 run scoreboard players get @s projectileX
execute as @e[name=legolas_arrow] store result entity @s Motion[1] double 0.1 run scoreboard players get @s projectileY
execute as @e[name=legolas_arrow] store result entity @s Motion[2] double 0.1 run scoreboard players get @s projectileZ

scoreboard players reset @e projectileX
scoreboard players reset @e projectileY
scoreboard players reset @e projectileZ

execute as @e[name=legolas_arrow] at @s run data merge entity @s {CustomName:""}