I want to be able to give an entity damage for a command I’m making, but instant damage effect is way too much, how do I apply other amounts of damage with command blocks?
Minecraft – How to apply damage to entities without instant damage effect
minecraft-commandsminecraft-java-edition
Related Solutions
This question is very difficult. Testing if two blocks are somehow connected is already difficult, two entities being in the same body of water is even harder. I have a solution, but it's not a great one. There are probably solutions that work a lot better.
I'd recommend instead looking back the actual problem that you want this solution for; see if there's another way to solve it without testing if two entities are in the same body of water.
This part is to make sure that a search will actually work and won't break your world.
First, we can easily make sure the entities are actually both in water. If either of them is not, then we can skip everything else as they can't both be in the same body of water if one of them isn't even in any water. Put an AND gate with these two commands:
/execute @e[name=Entity1] ~ ~ ~ /testforblock ~ ~ ~ water
/execute @e[name=Entity2] ~ ~ ~ /testforblock ~ ~ ~ water
Next I'd next check that the entities are at least somewhat near eachother. This is kind of a safeguard; they could still be in the same body of water thousands of blocks away, but it's unlikely and you'd crash the game trying to work it out anyway.
/execute @e[name=Entity1] ~ ~ ~ /testfor @e[name=Entity2,r=R] ~ ~ ~
Change R
out with however far you want the search to go for. This solution is laggy, so you may want to keep it small.
If that succeeds (the entities are both in water, and aren't ridiculously far away from each-other) then it's time to do the actual search that'll work out if they're in the same body of water.
This part is the actual search.
The following commands make both Entity1
and Entity2
summon marker
ArmorStands in every adjacent direction around them in which there is water. The -1 data type means that any type of water (flowing, source, etc.) will work:
/execute @e[name=Entity1] ~ ~ ~ detect ~1 ~ ~ water -1 /summon ArmorStand ~1 ~ ~ {CustomName:"Entity1",Marker:1b,NoGravity:1b}
/execute @e[name=Entity1] ~ ~ ~ detect ~-1 ~ ~ water -1 /summon ArmorStand ~-1 ~ ~ {CustomName:"Entity1",Marker:1b,NoGravity:1b}
/execute @e[name=Entity1] ~ ~ ~ detect ~ ~1 ~ water -1 /summon ArmorStand ~ ~1 ~ {CustomName:"Entity1",Marker:1b,NoGravity:1b}
/execute @e[name=Entity1] ~ ~ ~ detect ~ ~-1 ~ water -1 /summon ArmorStand ~ ~-1 ~ {CustomName:"Entity1",Marker:1b,NoGravity:1b}
/execute @e[name=Entity1] ~ ~ ~ detect ~ ~ ~1 water -1 /summon ArmorStand ~ ~ ~1 {CustomName:"Entity1",Marker:1b,NoGravity:1b}
/execute @e[name=Entity1] ~ ~ ~ detect ~ ~ ~-1 water -1 /summon ArmorStand ~ ~ ~-1 {CustomName:"Entity1",Marker:1b,NoGravity:1b}
/execute @e[name=Entity2] ~ ~ ~ detect ~1 ~ ~ water -1 /summon ArmorStand ~1 ~ ~ {CustomName:"Entity2",Marker:1b,NoGravity:1b}
/execute @e[name=Entity2] ~ ~ ~ detect ~-1 ~ ~ water -1 /summon ArmorStand ~-1 ~ ~ {CustomName:"Entity2",Marker:1b,NoGravity:1b}
/execute @e[name=Entity2] ~ ~ ~ detect ~ ~1 ~ water -1 /summon ArmorStand ~ ~1 ~ {CustomName:"Entity2",Marker:1b,NoGravity:1b}
/execute @e[name=Entity2] ~ ~ ~ detect ~ ~-1 ~ water -1 /summon ArmorStand ~ ~-1 ~ {CustomName:"Entity2",Marker:1b,NoGravity:1b}
/execute @e[name=Entity2] ~ ~ ~ detect ~ ~ ~1 water -1 /summon ArmorStand ~ ~ ~1 {CustomName:"Entity2",Marker:1b,NoGravity:1b}
/execute @e[name=Entity2] ~ ~ ~ detect ~ ~ ~-1 water -1 /summon ArmorStand ~ ~ ~-1 {CustomName:"Entity2",Marker:1b,NoGravity:1b}
Note that all of the new ArmorStands being summoned have the name of their summoner. This means that in the next iteration of the search, each of these ArmorStands will also summon more ArmorStands around them in directions that there is water, and so on. The entity that they come from will also be remembered by their name.
Follow all of that up with:
/execute @e[name=Entity1] ~ ~ ~ /setblock ~ ~ ~ red_sandstone
/execute @e[name=Entity2] ~ ~ ~ /setblock ~ ~ ~ red_sandstone
Any solid block will do fine. This is to mark the water blocks as already having a marker ArmorStand on them, so that the future water detects will not spawn another one on that tile.
Repeat all of this search on a clock that terminates when the search succeeds, or the search has gone on for a certain number (I'd recommend R) of iterations (or it'll keep on going forever if they aren't in the same body of water). This search should look like this for each entity:
To test if the search has succeeded, all you need to do is:
/execute @e[name=Entity1] ~ ~ ~ /testfor @e[r=1,Entity2]
Which will make each Entity1 ArmorStand look for adjacent Entity2 ArmorStands, at which point the two entities have been connected by an adjacent route.
To cleanup the all the red_sandstone and marker ArmorStands you just created for this search, all you need to do is:
/execute @e[name=Entity1] ~ ~ ~ /setblock ~ ~ ~ water
/execute @e[name=Entity2] ~ ~ ~ /setbock ~ ~ ~ water
/kill @e[name=Entity1, type=ArmorStand]
/kill @e[name=Entity2, type=ArmorStand]
And that's it done. This is very messy, but works well from what I've tried. It can detect if entities are connected even through mazes of water.
There is a way to do this in vanilla using commands. I got the general idea from betathedata on reddit, but the commands below are my own implementation of the technique.
This method relies on the fact, that a villager without trade offers has no trade interface, but right-clicking it will still count as "talking" to him. Therefore, having an invisible villager at your location while holding a specific item will do the trick.
Scoreboard objectives
For this to work, we need three objectives set up.
scoreboard objectives add holdingItem dummy
scoreboard objectives add holdTime stat.playOneMinute
scoreboard objectives add rightClick stat.talkedToVillager
The first two are for tracking when a player has just selected a specific item, the third one is what we want to unobtrusively set to 1.
Clock commands
First, set up a fill clock large enough to run at least 8 commands. Start off with
scoreboard players set @a holdingItem 0
scoreboard players set @a holdingItem 1 {SelectedItem:{id:minecraft:iron_ingot}}
scoreboard players reset @a[score_holdingItem=0] holdTime
Replace the SelectedItem
tag with whatever you like. You can add multiple of this second command if you want it to work for multiple items.
execute @a[score_holdTime=1] ~ ~ ~ summon Villager ~ ~ ~ {CustomName:"RightClicky",Offers:{Recipes:[]},NoAI:1,Silent:1,ActiveEffects:[{Id:14,Duration:9999,ShowParticles:0b},{Id:11,Amplifier:4,Duration:9999,ShowParticles:0b}]}
execute @a[score_holdTime_min=2] ~ ~ ~ tp @e[type=Villager,name=RightClicky,r=2,c=1] @a[c=1]
execute @a[score_holdingItem=0] ~ ~ ~ tp @e[type=Villager,name=RightClicky,r=2,c=1] ~ -100 ~
The first will summon a villager called RightClicky, who does not move, does not speak and has Invisibility and Resistance V (=Invulnerability), when you swap to the item(s) you specified above.
The second and third commands will either teleport that Villager to you, or into the void (killing him without particle effects showing), depending on whether you are still holding your item or not. This teleporting causes the villager to lag behind you a little, so it does not always work when you are running.
After putting in these commands, your RightClick
score will go up every time you right click while holding your item. At this point, place any commands that are supposed to be triggered by the right-click. Use @a[score_RightClick_min=1]
for targetting. For example:
effect @a[score_RightClick_min=1] minecraft:jump_boost 10 5
At the very end of your clock, run
scoreboard players set @a RightClick 0
to reset the system to detect another right-click.
Detecting a Left-Click should also possible. After summoning the villager, you can detect if a player hits it, as detailed in this question. Putting the two together is left as an exercise to the reader.
Best Answer
1.16+
Note: This data pack is in beta, and is in the works. If you have any bugs please let me know, and I'll add it to the known bugs list. Also, this is not tested in any version other then 1.16.4
I created a data pack that allows you to set health and deal damage to a player(for mobs use data modify instead). First off, you can get the data pack here. After installing it, make sure it says in chat that it was installed.
How To Use
Dealing Damage
To damage a player, set that player's
damage
scoreboard to how much damage you want to apply(negatives heal players), then run the functioneditor:deal_damage
as the player you want to damage and you are done.Setting Health
To set the health of a player, set that player's
sethealth
scoreboard to what health you want that player to have, then run the functioneditor:set_health
as the player you want to edit health and you are done.Remember: 1 heart is 2 HP, and a half a heart is 1 HP, default max health is 20 HP(10 hearts)
The Commands
To damage players:
To set player health:
How It Works
What the data pack does is set the max health of the player to what health you want to set, and gives the player the instant health effect so it will update the player health, setting the player's health to max, then it sets the max health to be what it originally was.
Known Bugs
Incompatibilities
All Incompatibilities are being worked on to be compatible
Finding Bugs/Issues
Bugs
If you find any bugs, please report it. Also add how you found the bug, so I can recreate it, and fix it, videos/screenshots of bugs are preferred.
Issues
If you have any performance issues while running the data pack, please report it. Also add what performance issues you are getting, low tps, low fps, etc. Videos/screenshots and computer specs do help!
Where to report
To report bugs/issues, use either comments on this answer, or the issues page on the GitHub download link.
Terms of Use
If you use this in a data pack to publish, I would like for you to put the GitHub link to the data pack somewhere for others who may want it, Thanks. You are welcome to edit the data pack to whatever you want, just don't break it! :)