Reapply Bad Omen if a player drinks milk until player triggers a raid?

Solution 1:

Caveats

  • With the following methods, Death and Totem of Undying are both ways to get ride of both effects

Avoiding clearing Bad Omen

First, We create a scoreboard to track when a player drinks milk and track who has the effect:

/scoreboard objectives add milk minecraft.used:minecraft.milk_bucket
/scoreboard objectives add bad_omen dummy

To prevent a player from using milk to remove the effect, we will do 3 steps:

  • Mark who has the effect, setting their bad_omen score to the level of the effect. We will need one block of command for each level, you can only get up to level V (5) in vanilla.
  • Apply the effect in anyone who has at least score 1 of bad_omen
  • Reset milk and bad_omen (In case the bad omen effect ran out naturally, either because of time or raid)

So we translate those to:

Step 1:

/execute as @a[nbt={ActiveEffects:[{Id:31b,Amplifier:0b}]}] run scoreboard players set @s bad_omen 1
/execute as @a[nbt={ActiveEffects:[{Id:31b,Amplifier:1b}]}] run scoreboard players set @s bad_omen 2
/execute as @a[nbt={ActiveEffects:[{Id:31b,Amplifier:2b}]}] run scoreboard players set @s bad_omen 3
/execute as @a[nbt={ActiveEffects:[{Id:31b,Amplifier:3b}]}] run scoreboard players set @s bad_omen 4
/execute as @a[nbt={ActiveEffects:[{Id:31b,Amplifier:4b}]}] run scoreboard players set @s bad_omen 5

Step 2:

/execute as @a[scores={bad_omen=1,milk=1}] run effect give @s minecraft:bad_omen 999999 0
/execute as @a[scores={bad_omen=2,milk=1}] run effect give @s minecraft:bad_omen 999999 1
/execute as @a[scores={bad_omen=3,milk=1}] run effect give @s minecraft:bad_omen 999999 2
/execute as @a[scores={bad_omen=4,milk=1}] run effect give @s minecraft:bad_omen 999999 3
/execute as @a[scores={bad_omen=5,milk=1}] run effect give @s minecraft:bad_omen 999999 4

Step 3:

/scoreboard players set @a milk 0
/execute as @a unless entity @s[nbt={ActiveEffects:[{Id:31b}]}] run scoreboard players set @s bad_omen 0

Also, responding to your extra question, the way to dettect lvl is actually using Amplifier:<N>b where N is the level of the effect starting from 0.


Avoiding clearing Hero of the Village

We will need:

/scoreboard objectives add HeroTime dummy
/scoreboard objectives add HeroLevel dummy

For that we do:

  • Decrease one from the player HeroTime
  • Check if he has HeroTime 0 and potion effect. If so, store his lvl and set his time to 24 minutes
  • If he has HeroTime bigger than 0, reapply effect
  • If his HeroTime is exactly 1, we clear the effect. This command needs to be at the end. As soon as the next cycle begins, the person with HeroTime of 1 will have 0 (Because of Step 1)

Translation:

Step 1:

/execute as @a[scores={HeroTime=1..}] run scoreboard players remove @s HeroTime 1

Step 2.1:

/execute as @a[nbt={ActiveEffects:[{Id:32b,Amplifier:0b}]}] unless score @s HeroTime matches 1.. run scoreboard players set @s HeroLevel 0
/execute as @a[nbt={ActiveEffects:[{Id:32b,Amplifier:0b}]}] unless score @s HeroTime matches 1.. run scoreboard players set @s HeroLevel 1
/execute as @a[nbt={ActiveEffects:[{Id:32b,Amplifier:0b}]}] unless score @s HeroTime matches 1.. run scoreboard players set @s HeroLevel 2
/execute as @a[nbt={ActiveEffects:[{Id:32b,Amplifier:0b}]}] unless score @s HeroTime matches 1.. run scoreboard players set @s HeroLevel 3
/execute as @a[nbt={ActiveEffects:[{Id:32b,Amplifier:0b}]}] unless score @s HeroTime matches 1.. run scoreboard players set @s HeroLevel 4

Step 2.2:

/execute as @a[nbt={ActiveEffects:[{Id:32b}]}] unless score @s HeroTime matches 1.. run scoreboard players set @s HeroTime 28800

Step 3:

/execute as @a[scores={HeroTime=1..,HeroLevel=0}] run effect give @s minecraft:hero_of_the_village 9999 0
/execute as @a[scores={HeroTime=1..,HeroLevel=1}] run effect give @s minecraft:hero_of_the_village 9999 1
/execute as @a[scores={HeroTime=1..,HeroLevel=2}] run effect give @s minecraft:hero_of_the_village 9999 2
/execute as @a[scores={HeroTime=1..,HeroLevel=3}] run effect give @s minecraft:hero_of_the_village 9999 3
/execute as @a[scores={HeroTime=1..,HeroLevel=4}] run effect give @s minecraft:hero_of_the_village 9999 4

And step 4:

/execute as @a[scores={HeroTime=1}] run effect clear @s minecraft:hero_of_the_village