Minecraft – Vertically stacked armor stands should have increasing scores, but don’t

minecraft-commandsminecraft-java-edition

I'm trying to make a goalpost system for a custom map I'm designing. The idea is that a goalpost–consisting of a tall stack of iron bars–would have variable height, and at each block up and down the post there would be an armor stand. These armor stands would have a GoalScore score value which increases from bottom to top, so that when the player comes into contact with one of them, they can have their score increased more the higher they hit it (Mario style). Since this requires a lot of armor stands, and there will be multiple goalposts in the map of varying height, I'm trying to make their generation easy on myself by having any Goal armor stand with air under it automatically generate a goalpost.

Here's the commands I'm using, each in a chain block (except the first, which is in a repeat block so the whole thing runs 20 times per second):

/scoreboard players add @e[type=ArmorStand,name=Goal] GoalScore 0
/scoreboard players set @e[type=ArmorStand,name=Goal] hasAirUnder 0
/execute @e[type=ArmorStand,name=Goal] ~ ~ ~ detect ~ ~-1 ~ minecraft:air -1 /scoreboard players set @e[type=ArmorStand,name=Goal,c=1] hasAirUnder 1
/execute @e[type=ArmorStand,name=Goal,score_hasAirUnder_min=1] ~ ~ ~ /summon ArmorStand ~ ~-1 ~ {CustomName:"Goal", NoGravity:1b}
/execute @e[type=ArmorStand,name=Goal,score_hasAirUnder_min=1] ~ ~ ~ /scoreboard players operation @e[type=ArmorStand,name=Goal,dy=-1,dx=0,dz=0] GoalScore = @e[type=ArmorStand,name=Goal,c=1] GoalScore
/execute @e[type=ArmorStand,name=Goal,score_hasAirUnder_min=1] ~ ~2 ~ /scoreboard players add @e[type=ArmorStand,name=Goal,dy=255,dx=0,dz=0] GoalScore 1
/execute @e[type=ArmorStand,name=Goal,score_hasAirUnder_min=1] ~ ~ ~ /setblock ~ ~-1 ~ minecraft:iron_bars 0

The idea is that any goal armor stands with air under them will summon a new goal armor stand below them, copy their current GoalScore to the new stand, then add 1 to every GoalScore for armor stands above them. Then it sets the block below to iron bars to stop it from triggering again the next tick.

While the idea seems sound, the execution isn't quite working. Depending on the height of the initial armor stand, either a few of the bottom ones have their scores set to 0 and it doesn't start counting up until a few blocks above (only the bottom one should have a score of 0); or, sometimes, it doesn't count all the way to 0 and somehow stops at 2 or 3 or something. It's as though the dy=255 I'm using in the GoalScore-increasing command isn't working properly; rather than selecting all armor stands above (and including) the current one for incrementing, it seems sometimes it selects none, or selects armor stands below it as well.

(If I change the execution coordinates of that to ~ ~ ~, every goal armor stand gets the same final, maximum value; if I change it to ~ ~1 ~, the top value is correct, while every other value is duplicated as top_value - 1. Using ~ ~2 ~ is the only way I get it to count down without skipping or duplicates, but then it has the problems I mentioned above.)

Am I doing something wrong? How can I make this work as expected?

Best Answer

What I would do is summon another ArmorStand under and increment all existing ones within certain range, maybe just those that have same X and Y coordinates. That way it would not interfere with other existing goalposts.

Alternatively, once you reach ground, lock all existing goalposts (by using another scoreboard objective). When you create new goalpost, you could again summon ArmorStands under and increment the score for those that are not locked yet.