Here's how you can do this without any iteration.
So I assume that once you shoot, you generate a group of widgets that *could* get hit. Then you want to check each widget in order. That is you want to check the closest widget first, farthest widget last, and then just stop the bullet once it hits. Ok lets assume you have that. Now lets figure out if a unit is actually hit.
Here's the simple way that you've already figured out:
If widget's height > bullet height, then the widget is hit. The widget height = GetLocationZ(widgetlocation) + GetDestructableOccluderHeight(widget) + GetUnitFlyHeight(widget). The bullet height = 200 (or whatever random number you pick, perhaps based on the shooter's height). Ok we got that. But you want to know how high the bullet will *actually* be by the time you hit the target, right?
Here's how you figure out the bullet's height:
Height_at_given_Time = Initial Height + Initial Vertical Velocity * Time + (1/2)Gravity*Time^2
You have the initial height (height of your shooter), you have the initial vertical velocity (you get to make that up), you have gravity (you get to make that up). You just need time and height. You can get that, too:
Distance= Velocity*Time
Distance you can calculate between the point of the shooter and the point of the target (using DistanceBetweenPoints()), velocity you get to make up, and time we can now replace with the two things we do know.
Time = Distance/Velocity
So now if you substitute Distance/Velocity for time you have this equation:
Height_at_given_Time = Initial Height + Initial Vertical Velocity * (Distance/horizontal_velocity)+ (1/2)Gravity*(Distance/horizontal_velocity)^2
Height_at_given_time is now your bullet height once it reaches the widget. Now you're set. If widget's height > bullet height, then the widget is hit. You don't have to iterate anything at all, you can calculate all this the moment you cast your spell.
So the jass code for this would be:
Code:
local location shooter_location = GetUnitLoc(shooter)
local location target_location = GetUnitLoc(target)
local real horizontal_velocity = however fast you want the bullet to move
local real vertical_velocity = however fast you want the bullet to be moving up
local real gravity = whatever you want
local real shooter_height = GetLocationZ(shooter_location) + GetDestructableOccluderHeight(shooter) + GetUnitFlyHeight(shooter)
local real target_height = GetLocationZ(target_location) + GetDestructableOccluderHeight(target) + GetUnitFlyHeight(target)
local real distance = DistanceBetweenPoints(target_location,shooter_location)
local real bullet_height_on_impact = shooter_height + vertical_velocity* (distance/horizontal_velocity)+ (1/2)gravity*Pow(distance/horizontal_velocity,2)
if (bullet_height_on_impact < target_height) and (bullet_height_on_impact > 0) then
.... // whatever you do to a target that is hit
Note: I didn't actually check any of this. So it'd be best to do everything again yourself =P