1

Context:

In order to trigger a chat message "from" NPCs - say villagers - when approaching them, I am using an always-active repeat-command block (A), a redstone-signal-sensitive impulse-command block (B) and a redstone comparator between them, pointing from A to B.

enter image description here

Since I want to let the NPCs run free, I can't use absolute coordinates, so what I'm currently doing is:

A: execute at @e[name=Gary] if entity @p[distance=..2]
B: execute at @e[name=Gary] run tellraw @a[distance=..2] "Hey!"

This results in the chat message "Hey!" to appear once for every player with distance 2 blocks or less to an entity named Gary as soon as a player is detected in that space.


Question:

Since it is odd that Gary talks to people in front of him as well as to people behind him, is it possible to alter the commands in a way that the center of the area in which players are detected (and in which players have to be to get the message) is not at exactly Gary's position, but 1 block in front of him?

enter image description here


Deliberations:

  • If Gary always stood in the same spot, it would be easy by using absolute coordinates like this:

    A: execute if entity @p[x=x_,y=y_,z=z_,distance=..2]
    B: tellraw @a[x=x_,y=y_,z=z_,distance=..2] "Hey!"
    

    x_, y_ and z_ being the desired coordinates 1 block in front of Gary.

  • Since version 1.13 it is possible to use caret notation for coordinates in some commands making them relative coordinates considering the command's executor's viewing direction, but it seems that target selector arguments only support absolute coordinates in Java edition.

  • See if this works: /execute at @e[type=villager] as @s positioned ^ ^ ^2 run tellraw @a[distance=..2] {"text":"Hey!"} – SpiceWeasel Jan 15 at 3:21
  • @SpiceWeasel This seems to work if I paste it into the chat by myself standing in front of a villager (regardless of my viewing direction which is good), but running in a command block it does nothing. Isn't "at" the same as "positioned" with the difference that "at" uses all three, the position, the rotation and the dimension of the subject and "positioned" only uses the position? So "execute at @e[type=villager]" would be the same as "execute positioned as @e[type=villager] rotated as @e[type=villager] in minecraft:overworld" if the villager resides in the overworld? – Maevur Jan 15 at 4:14
  • I haven't read the entire question yet, but I'm wondering about your setup. When do you expect the comparator to activate? How I understand it, it would never do it. – Fabian Röling Jan 15 at 7:10
  • I can't access Minecraft currently, so my answer will have to wait some hours, but you can definitely use the caret notation with execute positioned, then you don't even need xyz in the selector anymore. Also, your two commands don't need to be two. Just make one, it does the same. Not sure what your comparator is supposed to do, but if you want to tell the player only once, just give him a tag and make the speaking command only target players without the tag. – Fabian Röling Jan 15 at 8:15
  • @Fabian: Why this setup? You guessed it: I want the message to only show up once instead of every tick the player is standing in the right area. (A) constantly checks if a player is standing in the area and if so, the comparator activates and stays activated as long as the player's position matches the condition. As a result, (B) gets only activated once, that is when the player enters the area and (A)'s output is true for the first time. Both of my example command pairs work perfectly. – Maevur Jan 15 at 11:05
0

You can use the caret notation (^) in execute positioned, which removes the need for the x, y and z target selectors entirely (except in some really niche cases). The command you need is this one:

execute at @e[type=villager] positioned ^ ^ ^2 run tellraw @a[distance=..2] "Hey!"

As a bonus, you can get rid of the comparator (and also prevent that players why enter the radius multiple times get the message multiple times) by putting this command after the first:

execute at @e[type=villager] positioned ^ ^ ^2 run tag @a[distance=..2] add heardVillagerTalk

and modifying the first command to:

execute at @e[type=villager] positioned ^ ^ ^2 run tellraw @a[distance=..2,tag=!heardVillagerTalk] "Hey!"

This will prevent the issue the comparator had that players could walk in and out of the area and get the message every time.


If you're using a state scoreboard in your map, you can of course do the same with that. Let's say that state 0 is before having "heard" the "villager" "talk" and state 1 is afterwards. Make this command the second command in the row:

execute at @e[type=villager] positioned ^ ^ ^2 if entity @a[distance=..2] run scoreboard players set $game state 1

And make both only activate in state 0. This assumes that your state scoreboard is called "state" and the holder "$game".

  • Additional hint: Never use scoreboard players add for the game state, otherwise there might be bugs that increase it multiple times, skipping important states or even parts of the map. Credits warp! – Fabian Röling Jan 15 at 17:23
  • Ah, so SpiceWeasel's code can either be fixed by swapping at with as or by leaving out as completely. Good to know! Also thanks for the instructions for tags and the game state (and the additional hint). – Maevur Jan 15 at 17:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.