Quick answer: Iterate backwards with a manual For loop, or collect indices to remove during a forward pass then delete in a separate descending pass. Don’t delete mid-ForEachElement.
An inventory array holds items. Some events delete used-up items during a ForEachElement loop. Every other expired item survives the deletion sweep — consumables you should have removed sit in slots they should have left.
Why Mid-Iteration Deletes Skip
Construct’s ForEachElement walks indices 0, 1, 2, ... When you delete index N, the array shifts: what was N+1 becomes N. But the iteration counter advances to N+1 anyway — jumping over the promoted item.
If you delete items at positions 0, 2, 4 in a 6-element array, only positions 0 and 2 actually get hit because each deletion shifts the array but the index keeps marching forward.
Fix 1: Iterate Backwards
// Backwards For loop — safe for deletion
For "i" from Array.Width - 1 to 0:
if Array.At(loopindex("i")) == 0:
Array Delete index loopindex("i") on X axis
Deleting at index i shifts only indices > i. Since we iterate down, we never visit those shifted indices, so the iteration stays correct.
Fix 2: Collect-Then-Delete
// Pass 1: identify indices to remove
Local List ToRemove = ""
Array For each element:
if Array.CurValue == 0:
ToRemove Add item Array.CurX
// Pass 2: delete in descending order
For "j" from ToRemove.ItemCount - 1 to 0:
Array Delete index ToRemove.AtIndex(loopindex("j")) on X axis
Pass 1 uses ForEachElement safely (no mutation). Pass 2 walks the removal list backwards to avoid shifting issues.
Why Sort by Index Descending
If your removal indices are [2, 4, 6] and you delete in that order:
- Delete index 2: array shifts; original indices 4 and 6 are now at positions 3 and 5.
- You delete index 4 next — but the intended item is at 3.
Reversed order [6, 4, 2]:
- Delete index 6: nothing at lower indices shifts.
- Delete index 4: still correct because index 2 hasn’t shifted.
- Delete index 2: correct.
This generalizes to any mutation that removes elements — always work from the highest index down.
Alternative: Filter into a New Array
// Build a new array of survivors
NewArray Clear
Array For each element:
if Array.CurValue != 0:
NewArray Push back Array.CurValue on X axis
// Swap
Array Set size NewArray.Width
Array Copy NewArray
Functional-style. Allocates a second array; clearer for complex filter logic.
Verifying
Build an array [1, 0, 2, 0, 3, 0] and remove zeros. Final array should be [1, 2, 3]. If you get [1, 2, 0] or [1, 0, 3], you have the skip bug — apply Fix 1 or Fix 2.
“Mutating during iteration always invites bugs. Backwards loop or two-pass is the universal fix.”
Make “backwards-for to delete” a reflex — saves you reaching for the debugger every time array filtering goes wrong.