Can you make weapons inflict status effects? [duplicate]
Solution 1:
Firstly, you can give a sword with custom durability pretty easily. Use the Damage
tag, which represents how much damage the item has taken. Since a diamond sword has 1562 durability, a Damage
of 1561 will leave it with one durability left. Damage
can be found on this website in the first row of the chart. See the bottom of this answer to learn more about NBT tags.
Secondly, you can have weapons inflict status effects, but it is a little difficult. You need to first set up a scoreboard which tracks the uses of a particular weapon (let's say that your poison sword is a diamond sword named "Poison Sword" with a dark_green name, given with /give @s minecraft:diamond_sword{display:{Name:"{\"text\":\"Poison Sword\",\"color\":\"dark_green\"}"}}
) so in this case a diamond sword. Using the linked wiki, we would use /scoreboard objectives add swordUsed minecraft.used:minecraft.diamond_sword
. Then, in a tick function in a datapack (we need the datapack so we can raycast) we need to check for any players that have used their sword and run a function that raycasts from them:
execute as @a[scores={swordUsed=1..},nbt={SelectedItem:{tag:{display:{Name:"{\"text\":\"Poison Sword\",\"color\":\"dark_green\"}"}}}}] at @s anchored eyes positioned ^ ^ ^0.1 run function namespace:raycasting_function
The raycasting function that is run will need to do two things: count the amount of blocks that it moves forward (so it doesn't go on indefinitely), and give the first entity it encounters the poison effect. Here is an example function:
#use the swordUsed scoreboard to keep track of function iterations:
scoreboard players add @s swordUsed 1
#if there is no entity and the block is air, water, or lava, run the function but positioned 0.1 blocks in front of where it was run this time
#in this way it will move forwards by .1 blocks each repetition, until it either hits a block or an entity, or has gone 5 blocks (.1 blocks times 50 repetitions max = 5 blocks)
execute if score @s swordUsed matches ..50 if block ~ ~ ~ minecraft:air unless entity @e[dx=0.1,dy=0.1,dz=0.1] positioned ^ ^ ^0.1 run function namespace:raycasting_function
execute if score @s swordUsed matches ..50 if block ~ ~ ~ minecraft:water unless entity @e[dx=0.1,dy=0.1,dz=0.1] positioned ^ ^ ^0.1 run function namespace:raycasting_function
execute if score @s swordUsed matches ..50 if block ~ ~ ~ minecraft:lava unless entity @e[dx=0.1,dy=0.1,dz=0.1] positioned ^ ^ ^0.1 run function namespace:raycasting_function
#if there is an entity where the function is, give it an effect
execute as entity @e[dx=0.1,dy=0.1,dz=0.1] run effect give @s minecraft:poison [<seconds>] [<amplifier>] [<hideParticles>]
#reset the scoreboard if there is an entity
execute if entity @e[dx=0.1,dy=0.1,dz=0.1] run scoreboard players set @s swordUsed 0
The reason we use dx=
, dy=
, and dz=
rather than distance=
while checking for entities is because of this post, where I learned that distance only selects the entity's coordinate location while dx
, dy
, and dz
select their hitbox.
I haven't tested this yet, but I intend to do so within a week. This is a pretty good source on writing datapacks. Hope this helps.