#MC Dungeons lost health chunk

1 messages · Page 1 of 1 (latest)

mellow umbraBOT
#

It keeps getting stuck at 10 because the first IF runs every tick while the timer is running: prev_health_percent never updates until the timer hits 0 (that’s what your second IF is doing), so as soon as health drops you forever satisfy current < prev and you constantly reset the timer back to 10. That’s why it only starts to count down again once current finally equals prev.

You can fix it by only triggering the “start flash” block when the timer is zero (or by immediately copying the new health into prev_health_percent before the countdown begins). That way the timer is only reset once per damage event and can actually tick down instead of being constantly reset.

You can read more about how variables work and how to manage them here: Variables

violet vortex
#

how would this fix look in an action script

mellow umbraBOT
# violet vortex how would this fix look in an action script

Add the timer check so the flash only restarts once per hit. For example:

▶ IF (Is Number: {"placeholder":"getvariable","values":{"name":"health_flash_timer"}} = 0)
  └─ IF (Is Number: {"placeholder":"current_player_health_percent"} < {"placeholder":"getvariable","values":{"name":"prev_health_percent"}})
       └─ Set Variable Value: health_flash_timer:10
       └─ Set Variable Value: health_flash_alpha:1
       └─ Set Variable Value: prev_health_percent:{"placeholder":"current_player_health_percent"}

Then keep your countdown actions below (timer decrement + alpha calc). This way you only reset the timer when it’s finished, so it can actually count down instead of being forced back to 10 every tick. You can read more about using variables in action scripts here: Variables

violet vortex
#

this makes the timer countdown but now the prev health and current health always match

mellow umbraBOT
# violet vortex this makes the timer countdown but now the prev health and current health always...

Exactly—don’t copy current_player_health_percent into prev_health_percent at the same time you start the flash. That’s what makes them match every tick and kills the < check.

Keep the “start flash” block guarded by timer = 0 (so it only runs once per hit), but leave the prev_health_percent update in the second IF that fires when the timer actually reaches zero. That way prev still holds the pre-damage value while the flash is running, and only gets synced to the new health after the countdown finishes.

So your action script should look like this:

▶ IF (Is Number: {"placeholder":"getvariable","values":{"name":"health_flash_timer"}} = 0)
  └─ IF (Is Number: {"placeholder":"current_player_health_percent"} < {"placeholder":"getvariable","values":{"name":"prev_health_percent"}})
       └─ Set Variable Value: health_flash_timer:10
       └─ Set Variable Value: health_flash_alpha:1

▶ IF (Is Number: {"placeholder":"getvariable","values":{"name":"health_flash_timer"}} = 0)
  └─ Set Variable Value: prev_health_percent:{"placeholder":"current_player_health_percent"}

▶ Set Variable Value: health_flash_timer:{"placeholder":"maxnum","values":{"first":"0","second":"{"placeholder":"calc","values":{"decimal":"true","expression":"{"placeholder":"getvariable","values":{"name":"health_flash_timer"}} - 1"}}"}}
▶ Set Variable Value: health_flash_alpha:{"placeholder":"calc","values":{"decimal":"true","expression":"{"placeholder":"getvariable","values":{"name":"health_flash_timer"}} / 10"}}

Notice prev_health_percent is still only updated in the second IF after the timer hits zero, so the / < check keeps seeing the old health until the flash finishes.

violet vortex
#

this doesent work, it constantly keep prev and current health as equal

mellow umbraBOT
# violet vortex this doesent work, it constantly keep prev and current health as equal

Got it. The reason prev_health_percent keeps matching the current value is because your “set prev” block runs every tick the timer is 0, even on the ticks before a fresh damage hit. As soon as that block executes, prev is overwritten with current again, so the < check never sees a difference.

To fix it, gate the prev update so it only happens when you aren’t starting a new flash. Something like this keeps the old health value while the flash is active and only syncs it once the timer finished:

▶ IF (Is Number: {"placeholder":"getvariable","values":{"name":"health_flash_timer"}} = 0)
  └─ IF (Is Number: {"placeholder":"current_player_health_percent"} < {"placeholder":"getvariable","values":{"name":"prev_health_percent"}})
       └─ Set Variable Value: health_flash_timer:10
       └─ Set Variable Value: health_flash_alpha:1
  └─ ELSE
       └─ Set Variable Value: prev_health_percent:{"placeholder":"current_player_health_percent"}

Then keep your countdown + alpha calculations afterwards. This way the timer only resets when a new hit happens, and prev only updates when there isn’t an active flash (i.e., when the timer hit zero and no new damage was detected).

violet vortex
#

show me the whole updated action script

mellow umbraBOT
# violet vortex show me the whole updated action script

Sure! Here’s the full script with the fixes applied:

▶ IF (Is Number: {"placeholder":"getvariable","values":{"name":"health_flash_timer"}} = 0)
  └─ IF (Is Number: {"placeholder":"current_player_health_percent"} < {"placeholder":"getvariable","values":{"name":"prev_health_percent"}})
       └─ Set Variable Value: health_flash_timer:10
       └─ Set Variable Value: health_flash_alpha:1
  └─ ELSE
       └─ Set Variable Value: prev_health_percent:{"placeholder":"current_player_health_percent"}

▶ Set Variable Value: health_flash_timer:{"placeholder":"maxnum","values":{"first":"0","second":"{"placeholder":"calc","values":{"decimal":"true","expression":"{"placeholder":"getvariable","values":{"name":"health_flash_timer"}} - 1"}}"}}
▶ Set Variable Value: health_flash_alpha:{"placeholder":"calc","values":{"decimal":"true","expression":"{"placeholder":"getvariable","values":{"name":"health_flash_timer"}} / 10"}}

This keeps prev_health_percent locked to the old health while the flash timer runs, and only syncs it to the new health once the timer reaches zero (i.e., when no flash is active). The maxnum countdown still runs every tick. You can read more about variables and action scripts in the docs here: Variables.

violet vortex
#

this doesent work, the prev health is still equal to current health upon taking damage

mellow umbraBOT
# violet vortex this doesent work, the prev health is still equal to current health upon taking ...

It still happens because there’s another branch somewhere that writes prev_health_percent to the current health whenever the timer is “ready,” so every time you drop health the script immediately overwrites the “old” value before the < check can see it. The fix is to keep the prev update inside the same branch where you only execute it when you’re not starting a flash—in other words, only copy {"placeholder":"current_player_health_percent"} into prev_health_percent when the timer is zero and the damage check didn’t trigger.

If you still see the values match, double-check that there aren’t any other actions (even in other layouts/listeners) that run Set Variable Value for prev_health_percent. You can use the /fmvariable command or a Ticker to log the value so you can tell exactly when it changes.
More on managing variables: Variables

violet vortex
#

the timer wont tick now either

mellow umbraBOT
# violet vortex the timer wont tick now either

Alright, let’s fix it properly:

Goal

  • Start the flash timer only once per damage event.
  • Keep prev_health_percent at the pre-damage value while the flash runs.
  • Let the timer count down every tick.

Working Action Script

▶ IF (Is Number: {"placeholder":"getvariable","values":{"name":"health_flash_timer"}} = 0)
  └─ IF (Is Number: {"placeholder":"current_player_health_percent"} < {"placeholder":"getvariable","values":{"name":"prev_health_percent"}})
       └─ Set Variable Value: health_flash_timer:10
       └─ Set Variable Value: health_flash_alpha:1
  └─ ELSE
       └─ Set Variable Value: prev_health_percent:{"placeholder":"current_player_health_percent"}

▶ Set Variable Value: health_flash_timer:{"placeholder":"maxnum","values":{"first":"0","second":"{"placeholder":"calc","values":{"decimal":"true","expression":"{"placeholder":"getvariable","values":{"name":"health_flash_timer"}} - 1"}}"}}
▶ Set Variable Value: health_flash_alpha:{"placeholder":"calc","values":{"decimal":"true","expression":"{"placeholder":"getvariable","values":{"name":"health_flash_timer"}} / 10"}}

Why it works

  • The outer timer = 0 guard ensures we only evaluate the damage condition when the flash finished.
  • When damage is detected, the timer is set to 10 and prev_health_percent stays at the old value (so the < condition stays true while the timer runs).
  • Once the timer hits 0 and no new damage is detected, the ELSE branch copies the current health into prev_health_percent, preparing for the next hit.

If the timer still doesn’t tick, make sure nothing else (other layouts/listeners) is writing to health_flash_timer or prev_health_percent. Also check that the action script runs every tick (e.g., via a Ticker element).

violet vortex
#

this doesent work, try another solution

mellow umbraBOT
# violet vortex this doesent work, try another solution

Let’s try a different approach that keeps the “pre-damage” value in a separate variable and only updates it once the flash actually begins. This way the timer isn’t reset constantly and prev_health_percent stays equal to the health you had just before the hit:

▶ IF (Is Number: {"placeholder":"getvariable","values":{"name":"health_flash_timer"}} = 0)
  └─ IF (Is Number: {"placeholder":"current_player_health_percent"} < {"placeholder":"getvariable","values":{"name":"last_health_percent"}})
       └─ Set Variable Value: health_flash_timer:10
       └─ Set Variable Value: health_flash_alpha:1
       └─ Set Variable Value: prev_health_percent:{"placeholder":"getvariable","values":{"name":"last_health_percent"}}

▶ Set Variable Value: health_flash_timer:{"placeholder":"maxnum","values":{"first":"0","second":"{"placeholder":"calc","values":{"decimal":"true","expression":"{"placeholder":"getvariable","values":{"name":"health_flash_timer"}} - 1"}}"}}
▶ Set Variable Value: health_flash_alpha:{"placeholder":"calc","values":{"decimal":"true","expression":"{"placeholder":"getvariable","values":{"name":"health_flash_timer"}} / 10"}}

▶ Set Variable Value: last_health_percent:{"placeholder":"current_player_health_percent"}

Key idea:

  • last_health_percent is always set to the current health at the end of the script.
  • When health drops and the timer is zero, you capture the previous value from last_health_percent, start the flash, and keep prev_health_percent unchanged while the timer runs.
  • The countdown can now proceed because you never reset the timer mid-flash.

You can read more about using variables and action scripts here: Variables.

violet vortex
#

the code does not work, try a solution without checking for health_flash_timer = 0 at the start because that isnt working

mellow umbraBOT
# violet vortex the code does not work, try a solution without checking for health_flash_timer =...

Try this version that uses a small “triggered” flag instead of gating the whole thing on health_flash_timer being 0. It only starts the flash once per damage event and keeps prev_health_percent untouched until health has recovered (so current < prev stays true while the timer runs):

▶ IF (Is Number: {"placeholder":"current_player_health_percent"} < {"placeholder":"getvariable","values":{"name":"prev_health_percent"}})
  └─ IF (Is Number: {"placeholder":"getvariable","values":{"name":"health_flash_triggered"}} = 0)
       └─ Set Variable Value: health_flash_timer:10
       └─ Set Variable Value: health_flash_alpha:1
       └─ Set Variable Value: health_flash_triggered:1

▶ IF (Is Number: {"placeholder":"current_player_health_percent"} >= {"placeholder":"getvariable","values":{"name":"prev_health_percent"}})
  └─ Set Variable Value: prev_health_percent:{"placeholder":"current_player_health_percent"}
  └─ Set Variable Value: health_flash_triggered:0

▶ Set Variable Value: health_flash_timer:{"placeholder":"maxnum","values":{"first":"0","second":"{"placeholder":"calc","values":{"decimal":"true","expression":"{"placeholder":"getvariable","values":{"name":"health_flash_timer"}} - 1"}}"}}
▶ Set Variable Value: health_flash_alpha:{"placeholder":"calc","values":{"decimal":"true","expression":"{"placeholder":"getvariable","values":{"name":"health_flash_timer"}} / 10"}}
  • health_flash_triggered keeps track of whether a damage flash is already active, so the timer block won’t be re-triggered while the timer is still counting down.
  • prev_health_percent only updates when the player’s health recovers (or stays equal), letting the < comparison hold the old value during the flash.

That should let the timer tick down while still showing the pre-damage health chunk.

violet vortex
#

it works. now how can i make the damage overlay drop into the main health bar to mimic the effect in minecraft dungeons?

mellow umbraBOT
# violet vortex it works. now how can i make the damage overlay drop into the main health bar to...

You can fake the “damage chunk dropping into the bar” by moving an overlay image vertically while the flash timer runs. Here’s one easy approach:

  1. Create the overlay image (an Image element shaped like the lost-heart chunk) and anchor it near the health bar.
  2. Use a helper variable (e.g. damage_drop_offset) that you set to a negative value when damage happens (e.g. -14). Have your ticker/action script gradually increase it back to 0 every tick (use a calc nested in maxnum or a ticker to add +1 or +2 until it hits zero).
  3. Drive the element’s position with advanced positioning: enable Advanced Positioning on the Image element and set its Y position to something like
    {"placeholder":"calc","values":{"decimal":"true","expression":"baseY + {"placeholder":"getvariable","values":{"name":"damage_drop_offset"}}"}}
    
    where baseY is the normal Y position to align with your health bar.
  4. Blend it with your flash timer so the drop animation happens in sync: when you start the flash, also reset damage_drop_offset; the ticker that decreases health_flash_timer can also nudge damage_drop_offset toward 0 (or use a separate ticker/action script).

That way, damage spawns the overlay slightly above the bar and it “falls” down thanks to the variable-driven Y position. For setup details on using placeholders inside sizing/positioning and animating values, see the advanced positioning docs: Advanced Positioning & Sizing.

violet vortex
#

dont make a new variable, just use what we already have and write an expression in the advanced positioning Y Position that drops the overlay while keeping its anchor

mellow umbraBOT
# violet vortex dont make a new variable, just use what we already have and write an expression ...

You can re-use health_flash_timer to drive the drop in the Y position without extra variables. Enable Advanced Positioning on the overlay image, and set the Y field to a calculator placeholder that pulls the timer value and moves the image down as the timer counts down, for example:

{
  "placeholder":"calc",
  "values":{
    "decimal":"true",
    "expression":"5 + (10 - {"placeholder":"getvariable","values":{"name":"health_flash_timer"}}) * 1.5"
  }
}

Adjust the + 5 base offset and the 1.5 multiplier until the start/end positions look good. The overlay will start higher (when timer = 10) and then “drop” into place as the timer ticks toward zero, while the anchor stays as configured.

If you need help with the syntax or using placeholders in positioning, check the Advanced Positioning & Sizing docs here: Advanced Positioning & Sizing.

violet vortex
#

the overlay doesent follow the main health bar, rewrite the expression so it uses the y anchor of the health bar

mellow umbraBOT
# violet vortex the overlay doesent follow the main health bar, rewrite the expression so it use...

Make the overlay use the health bar’s own Y position as its base and then add the drop offset that’s driven by health_flash_timer. Enable Advanced Positioning on the overlay, then set its Y position to a calculator placeholder like this:

{
  "placeholder": "calc",
  "values": {
    "decimal": "true",
    "expression": "{"placeholder":"elementposy","values":{"id":"health_bar"}} + (10 - {"placeholder":"getvariable","values":{"name":"health_flash_timer"}}) * 1.5"
  }
}

This keeps the overlay tied to the health bar’s anchor (make sure the overlay shares the same anchor as the bar) and makes it “fall” down as the timer counts from 10 → 0. Adjust the 1.5 multiplier or the 10 start value until the drop distance matches your bar.

For more on using placeholders in positioning values, see the advanced positioning docs: Advanced Positioning & Sizing.

violet vortex
#

the overlay wont move down

mellow umbraBOT
# violet vortex the overlay wont move down

If the overlay still stays put, it’s probably because it isn’t actually anchored to the hotbar, so {"placeholder":"elementposy","values":{"id":"health_bar"}} keeps returning the overlay’s own Y position instead of the health bar’s. Make sure:

  1. The overlay and the health bar share the same anchor point (the overlay’s anchor should be the health bar element, not the screen center).
  2. The overlay’s editor ID is exactly what you use in the placeholder (replace health_bar above with the actual element ID).

Then use this Advanced Positioning Y value for the overlay:

{
  "placeholder": "calc",
  "values": {
    "decimal": "true",
    "expression": "{"placeholder":"elementposy","values":{"id":"health_bar"}} - (10 - {"placeholder":"getvariable","values":{"name":"health_flash_timer"}}) * 1.5"
  }
}

Adjust the 1.5 multiplier to control how far it drops. The subtraction makes the overlay start above the bar when the timer is 10 and slide back down as the timer approaches 0, while the base elementposy keeps it tied to the bar’s anchor.

violet vortex
#

code isnt working. come up with something different

mellow umbraBOT
# violet vortex code isnt working. come up with something different

Let’s switch to a different technique: animate the overlay with the Element Animator instead of trying to do everything through advanced positioning math.

  1. Anchor the overlay to the health bar so it follows its movement (set its anchor to the health bar element).
  2. Add an Element Animator to the layout and set it up to animate the overlay’s Y offset from e.g. -140 over the same duration as your flash (10 ticks).
  3. Trigger the animator inside your action script when the damage flash starts (same spot where you set health_flash_timer to 10). Use the Play Animator action and point it at the animator you set up.
  4. The animator will move the overlay down “into” the bar while the flash plays, and because the overlay is anchored to the bar, it will always follow its position.

This keeps the drop logic entirely inside the animator (no extra math), and the overlay stays tied to the health bar thanks to the anchor. You can read more about animating elements here: Element Animator.

violet vortex
#

guide me step by step on how to use the element animator

mellow umbraBOT
# violet vortex guide me step by step on how to use the element animator

Here’s a quick step-by-step:

  1. Add the Element Animator

    • Right-click the layout background → New Element → Element Animator.
  2. Create the animation

    • Right-click the animator → Edit Keyframes.
    • Press R to record, move the preview so the overlay starts above the bar (e.g. -14 offset), then press K to save that keyframe.
    • Move the preview down to align with the bar (offset 0), press K again.
    • You now have two keyframes. Adjust timing so the animation lasts the same as your flash (e.g. 10 ticks). Use the timeline and arrow keys to tweak.
  3. Set targets

    • Right-click animator → Manage Targets → Add Target → select your overlay image.
  4. Trigger it via your action script

    • When you detect damage and set health_flash_timer:10, add a Play Animator action pointing to this animator so it runs each flash.
    • Optionally add a Reset Animator or stop before replaying.
  5. Fine-tune

    • In the animator settings you can enable looping, adjust easing, or keep it from auto-playing so it only moves when the action script fires.

Every time the script runs, the animator will move the overlay down into the bar while keeping the anchor, so it mimics the Minecraft Dungeons drop effect.

violet vortex
#

where can i see the offset for the animator?

mellow umbraBOT
# violet vortex where can i see the offset for the animator?

When you open the Element Animator’s keyframe editor (right-click → Edit Keyframes), you’ll see the preview box in the middle. That box always shows the current offset/position of the animated element.

  • While recording a keyframe, move the preview box to the desired offset (you can also nudge it with the arrow keys).
  • The current X/Y values display at the bottom of the editor (hover over the preview if it hides).
  • Every keyframe you record captures that offset, so you can see what offset the animation will start from / end at.

If you need more help, the doc on animators walks through the keyframe UI and targeting steps: Element Animator.

violet vortex
#

how many seconds is in 10 ticks

mellow umbraBOT
violet vortex
#

what does the trigger looks like in action script?

mellow umbraBOT
# violet vortex what does the trigger looks like in action script?

The trigger is just a Play Animator action inside the same IF block where you start the flash. It looks like this:

▶ IF (Is Number: {"placeholder":"current_player_health_percent"} < {"placeholder":"getvariable","values":{"name":"prev_health_percent"}})
  └─ IF (Is Number: {"placeholder":"getvariable","values":{"name":"health_flash_triggered"}} = 0)
       └─ Set Variable Value: health_flash_timer:10
       └─ Set Variable Value: health_flash_alpha:1
       └─ Play Animator: your_animator_id
       └─ Set Variable Value: health_flash_triggered:1

Replace your_animator_id with the identifier you gave the Element Animator. That action will play the drop animation each time the damage flash starts. If you need a reset, you can also add a Reset Animator action before playing it.

violet vortex
#

how to make the element animator use the anchor of the element

mellow umbraBOT
# violet vortex how to make the element animator use the anchor of the element

To keep the animation tied to the health bar, make sure the overlay’s anchor is the health bar before you record keyframes. Here’s how:

  1. Anchor the overlay: In the editor, drag the overlay until it snaps to the health bar element (or right-click → Anchor Point → choose the health bar). This makes the overlay follow the bar.

  2. Edit the animator: When you record keyframes, the preview box offsets are applied relative to the overlay’s anchor. So the landing position we recorded is automatically anchored to the health bar. You don’t need to re-anchor anything inside the animator itself—just make sure the element’s anchor is set correctly before adding it as a target.

  3. Record the drop: In the keyframe editor, move the preview up (above the bar) for the first keyframe and down to the bar for the second; the animator will respect the anchor because the overlay’s position is anchored already.

If you need a refresher on the animator workflow, the docs walk through it step-by-step: Element Animator.

Let me know if you want me to guide you through a specific offset setup.

violet vortex
#

the animator sends the overlay to the center of the screen

mellow umbraBOT
# violet vortex the animator sends the overlay to the center of the screen

That happens because the Animator defaults to “absolute” mode, so it moves the element relative to the screen center instead of its anchor. To keep the drop tied to your health bar, do these two things:

  1. Anchor the overlay to the health bar (right-click the overlay → Anchor Point → pick the health bar element).
  2. Enable offset mode in the Animator before you record keyframes:
    • Right-click the animator → Edit Keyframes.
    • In the keyframe editor, toggle Offset Mode (the checkbox near the preview). This makes the preview stay centered on the anchor instead of the screen center.
  3. Now record the keyframes: start above the bar, end aligned with it. Because the element is anchored and the animator runs in offset mode, the overlay will drop relative to the bar instead of teleporting to the screen center.

If you need a refresher while in the editor, the Element Animator doc covers this setup step-by-step: Element Animator.

violet vortex
#

there is no offset mode