HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Extrapolating a Wave's Endpoint

12-05-2009, 05:37 PM#1
Panto
Greetings.

I imagine this is a pretty simple problem, but my command of maths isn't what it once was.

I want to find the endpoint of a wave effect. If a unit casts a wave, he selects a unit or a point on the ground.

Zoom (requires log in)

However, the wave travels to that point and continues whatever distance the spell is set to; we'll say 1000. I'd like to find out what that point is that's the farthest point of the wave.

Zoom (requires log in)

Note that the path of the spell is not related to the facing angle of the caster.
Thanks for your help!
Attached Images
File type: gifdragon-diagram-A.gif (1.3 KB)
File type: gifdragon-diagram-B.gif (2.0 KB)
12-05-2009, 05:43 PM#2
Rising_Dusk
I'm guessing by wave, you don't actually mean a wave. Anyways, you just polar project the caster's X/Y coordinates SPELL_RANGE distance in the direction of the angle between caster's coordinates and coordinate's of target point of spell.
Collapse JASS:
local real xi = GetUnitX(Caster)
local real yi = GetUnitY(Caster)
local real xf = GetSpellTargetX()
local real yf = GetSpellTargetY()
local real an = Atan2(yf-yi,xf-xi)
local real di = 1000. //This is true for your example only
local real rx = xi + di*Cos(an)
local real ry = yi + di*Sin(an)
//Coordinate pair (rx,ry) is the endpoint of the spell
Actual WC3 doesn't project the point 1000 away from the target point of the spell, but rather from the caster's coordinate pair. If you wanted to project (as your picture shows) from the target point (why not?), then you could do the same as above, but with the rx/ry lines looking like:
Collapse JASS:
local real rx = xf + di*Cos(an)
local real ry = yf + di*Sin(an)
12-06-2009, 05:38 AM#3
Panto
Thank you, sir!

EDIT: By the way, you're right, this is what I meant to diagram:

Zoom (requires log in)

EDIT2: And, it worked absolutely flawlessly. Thanks!
Attached Images
File type: gifdragon-diagram-c.gif (2.2 KB)
12-17-2009, 12:51 AM#4
Panto
It has been suggested that this might be a pretty straightforward way to make the visual effect even better! I'm looking for the X,Y coordinates for parallel lines to the one you helped me find in earlier posts. See this diagram.

Zoom (requires log in)

I'd like to get the coordinates for the endpoints of two lines as shown, 50 units away from the original line on either side.

I expect this is a similar matter of knowing the right equation, which I don't. Any thoughts?

Thanks for your help!
Attached Images
File type: gifdragon-diagram-D.gif (2.5 KB)
12-17-2009, 01:10 AM#5
Kueken
If you know the angle already (variable "an" in Dusks calculation), you can use the angle and add 90° to it.
Collapse JASS:
local real xi = GetUnitX(Caster)
local real yi = GetUnitY(Caster)
local real xf = GetSpellTargetX()
local real yf = GetSpellTargetY()
local real an = Atan2(yf-yi,xf-xi)
local real di = 1000. //This is true for your example only
local real ds = 50.   //side distance, your offset
local real rx = xi + di*Cos(an)
local real ry = yi + di*Sin(an)
//Coordinate pair (rx,ry) is the endpoint of the spell
local real r = 0.5*bj_PI            //.5*pi= 90* in radians
local real sx1 =  xi+ds*Cos(an+r)   //sx1 -> "side x 1" :P
local real sy1 =  xi+ds*Sin(an+r)   //(sx1,sy1) and (sx2,sy2) are the offset start points
local real sx2 =  xi+ds*Cos(an-r)
local real sy2 =  xi+ds*Sin(an-r)    
//now calc end points just like the wave end point; angle and distance is the same for them

Not the best method to do that, but kinda obvious. By looking at how dusk made it, you should have been able to come up with something similar yourself.
12-17-2009, 01:16 AM#6
Zerzax
First you have to project initial point's x and y coordinates 50 units "down" or "up". This first angle of projection is the facing angle rotated + or - 90 degrees. Instead of taking the cosine of (theta+-90) you can just use

Collapse JASS:
// for an upper projection
x + 50.00*-Sin(theta)
y + 50.00*Cos(theta)
// for a lower projection
x + 50.00*Sin(theta)
y + 50.00*-Cos(theta)

// Then you just project your regular old distance from this new point. The two steps can easily be combined into one for an upper or lower projection, upper in this case.
x + 50.00*-Sin(theta) + di*Cos(theta)
y + 50.00*Cos(theta) + di*Sin(theta)



Store the sine and cosine as variables, and this will be quite fast. The whole -sin and -cos stuff comes from the angle addition and angle subtraction formulas.
12-17-2009, 01:48 AM#7
DioD
Collapse JASS:
local real xi = GetUnitX(GetSpellAbilityUnit())
    local real yi = GetUnitY(GetSpellAbilityUnit())
    local real xf = GetSpellTargetX()
    local real yf = GetSpellTargetY()
    local real an = Atan2(yf-yi,xf-xi)
    local real di = 1000. //This is true for your example only
    local real rx = xi + di*Cos(an)
    local real ry = yi + di*Sin(an)
    
    local real tx = rx + 200*Cos(an+ (90 * bj_DEGTORAD))
    local real ty = ry + 200*Sin(an+ (90 * bj_DEGTORAD))
    
    local real zx = rx + 200*Cos(an+ (-90 * bj_DEGTORAD))
    local real zy = ry + 200*Sin(an+ (-90 * bj_DEGTORAD))
    
    
    
    //Coordinate pair (rx,ry) is the endpoint of the spell
    call DestroyEffect(AddSpecialEffect("war3mapImported\\Blue_WarStompCaster.mdx",rx,ry))
    call DestroyEffect(AddSpecialEffect("war3mapImported\\Blue_WarStompCaster.mdx",tx,ty))
    call DestroyEffect(AddSpecialEffect("war3mapImported\\Blue_WarStompCaster.mdx",zx,zy))

This will generate 2(two) locations 200 from endpoint with 90 angle.

Iam sure you will enum units inside this range, there is "fast" way to calculate any unit inside area, i will post it later (cannot find).
12-17-2009, 02:07 AM#8
DioD
Collapse JASS:
function Trig_Untitled_Trigger_003_Actions takes nothing returns nothing
    local real xi = GetUnitX(GetSpellAbilityUnit())
    local real yi = GetUnitY(GetSpellAbilityUnit())
    local real xf = GetSpellTargetX()
    local real yf = GetSpellTargetY()
    local real an = Atan2(yf-yi,xf-xi)
    local real di = 1000. //This is true for your example only
    local real rx = xi + di*Cos(an)
    local real ry = yi + di*Sin(an)
    
    local real tx = rx + 200*Cos(an+ (90 * bj_DEGTORAD))
    local real ty = ry + 200*Sin(an+ (90 * bj_DEGTORAD))
    
    local real zx = rx + 200*Cos(an+ (-90 * bj_DEGTORAD))
    local real zy = ry + 200*Sin(an+ (-90 * bj_DEGTORAD))
    
    local group UNITS = CreateGroup()
    local integer i = 0
    local unit zeta = null
    
    
    local real tmpatan = 0.0
    
    local real tmpx = 0
    local real tmpy = 0
    
    local real sx = 0
    local real sy = 0
    
    //Coordinate pair (rx,ry) is the endpoint of the spell
    call DestroyEffect(AddSpecialEffect("war3mapImported\\Blue_WarStompCaster.mdx",rx,ry))
    call DestroyEffect(AddSpecialEffect("war3mapImported\\Blue_WarStompCaster.mdx",tx,ty))
    call DestroyEffect(AddSpecialEffect("war3mapImported\\Blue_WarStompCaster.mdx",zx,zy))
    
    call GroupEnumUnitsInRange(UNITS,0.0,0.0,999999.0,null)
    //now we have all possible units.
    //for test only.
    
    loop
        set zeta = FirstOfGroup(UNITS)
        exitwhen zeta == null
        call GroupRemoveUnit(UNITS,zeta)
        
        set tmpatan = Atan2(GetUnitY(zeta)-yi,GetUnitX(zeta)-xi)
        
        if tmpatan > an then
        
            set tmpx = GetUnitX(zeta) + 200*Cos(an+ (-90 * bj_DEGTORAD))
            set tmpy = GetUnitY(zeta) + 200*Sin(an+ (-90 * bj_DEGTORAD))
            
            set tmpatan = Atan2(tmpy-yi,tmpx-xi)
            if tmpatan < an then
                call AddSpecialEffectTarget("war3mapImported\\HeroGlow_Chest.mdx",zeta,"chest")
            endif
        else
            set tmpx = GetUnitX(zeta) + 200*Cos(an+ (90 * bj_DEGTORAD))
            set tmpy = GetUnitY(zeta) + 200*Sin(an+ (90 * bj_DEGTORAD))
            
            set tmpatan = Atan2(tmpy-yi,tmpx-xi)
            if tmpatan > an then
                call AddSpecialEffectTarget("war3mapImported\\HeroGlow_Chest.mdx",zeta,"chest")
            endif
        
        endif
    
    endloop
    
endfunction


This damn simple function will enum units in line 400 wide and create sfx on enumed units.

THIS IS DAMN NOT OPTIMIZED - too many useless calculations, but this is simple and effective.
12-17-2009, 07:36 PM#9
Panto
Quote:
Originally Posted by Zerzax
this will be quite fast. The whole -sin and -cos stuff comes from the angle addition and angle subtraction formulas.
Brilliant, perfect, thank you. I'll give it a shot now.

Quote:
Originally Posted by DioD
Iam sure you will enum units inside this range
Nope, but thanks. If I can implement Zerzax's formulae I'll be good to go.

EDIT: And it does work, splendidly. Thanks all for your help!