• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[JASS] Need math solution

Status
Not open for further replies.
Level 18
Joined
Oct 18, 2007
Messages
930
Need math solution [ Updated ~ but still need the fix :) ]

Ok i kinda need something quick :p it would be better to explain if i showed you this picture :)
ASASAWED.png


If the target is close the angle gets shorter and if it far away the angle gets wider, get it?? The Black is the caster, the Red is the target and the Green triangle missing a side is the angle :p

Hope you all get what i am saying :) because i realy need this :p
 
Last edited:
Level 11
Joined
Dec 31, 2007
Messages
780
do you really need it in jass... i can make one in gui or at least give you an idea of how it could be


set a real value for the distance between position of caster and position of target

create 2 offsets from position of caster to position of caster offset by distance between caster and target towards facing of caster + 90 and another -90 degrees

and then create an angle between those 2 offsets and position of target

if you didnt understand my complicated syntax tell me and later i can make the trigger for you ^^
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Arc Tangent should return what you need.

So, Atan(distance/something) should return the angle.

Now, distance is the distance between the caster and the target.
Something is the distance between the caster and the ends of the green lines.

So, for your case, I guess you'll want something like angle = Atan(distance/(distance/3)) or something like that.
 
Level 22
Joined
Dec 31, 2006
Messages
2,216
Here:

JASS:
constant function missile takes nothing returns integer
    return 'hpea'//Put the raw code of your missile here
endfunction

function Cast takes nothing returns nothing
    local unit caster = GetTriggerUnit()
    local unit target = GetSpellTargetUnit()
    local unit array missiles
    local player p = GetOwningPlayer(caster)
    local real x1 = GetUnitX(caster)
    local real y1 = GetUnitY(caster)
    local real x2 = GetUnitX(target)
    local real y2 = GetUnitY(target)
    local real x3
    local real y3
    local real a
    local real dist = SquareRoot((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))

    set a = Atan2(y2-y1, x2-x1) + 1.57
    set x3 = x1 + ((dist / 2) * Cos(a))
    set y3 = y1 + ((dist / 2) * Sin(a))
    set a = Atan2(y2-y3, x2-x3) * bj_RADTODEG
    set missiles[1] = CreateUnit(p, missile(), x3, y3, a)

    set a = Atan2(y2-y1, x2-x1) - 1.57
    set x3 = x1 + (dist * Cos(a))
    set y3 = y1 + (dist * Sin(a))
    set a = Atan2(y2-y3, x2-x3) * bj_RADTODEG
    set missiles[2] = CreateUnit(p, missile(), x3, y3, a)

    set caster = null
    set target = null
    set missile[1] = null
    set missile[2] = null
    set p = null
endfunction
 
Level 18
Joined
Oct 18, 2007
Messages
930
Hehe, thx il check it out when i have time :) +REP

Edit: Hey it works, but!! it always ends up in an 90 degree angle and its like this:
fffffffffffffffffff.png


The problem is that its far off and that the angle aint gettin smaller or larger as the caster moves, only the location moves. please fix this, it is a real "bummer" in the spell :'(
 
Last edited:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,259
angle = arc*360/2piR
angle = arc*180/piR (I think)
(above for degrees).

Arc is a constant for how much width you want the unit to represent, R is the distance between the 2 units and pi is the mathimatical constant that has no truely difined number.

For radians it is.
angle = arc/R (again I think).
 
Level 18
Joined
Oct 18, 2007
Messages
930
Ok Thx :) then, i might need some help gettin it all fit inside a jass document.

And Dr Super Good, what is a good value on arch?? 45??

Edit: Ok i have tried, but it dosent seem to be working.
JASS:
    local unit caster = GetTriggerUnit()
    local unit target = GetSpellTargetUnit()
    local unit array missiles
    local player p = GetOwningPlayer(caster)
    local real x1 = GetUnitX(caster)
    local real y1 = GetUnitY(caster)
    local real x2 = GetUnitX(target)
    local real y2 = GetUnitY(target)
    local real x3
    local real y3
    local real a = 0
    local real arc = 45
    local real R = SquareRoot((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
    local real angle1 = arc*360/(2*pi()*R)
    local real angle2 = arc*180/(pi()*R)


    set x3 = x2 + R * Cos(angle1 * bj_DEGTORAD)
    set y3 = y2 + R * Sin(angle1 * bj_DEGTORAD)
    set missiles[1] = CreateUnit(p, missile(), x3, y3, a)

    set x3 = x2 + R * Cos(angle2 * bj_DEGTORAD)
    set y3 = y2 + R * Sin(angle2 * bj_DEGTORAD)
    set missiles[2] = CreateUnit(p, missile(), x3, y3, a)
 
Level 22
Joined
Dec 31, 2006
Messages
2,216
There is no function called pi, but there is a constant called bj_PI.
Dynasti said:
Edit: Hey it works, but!! it always ends up in an 90 degree angle and its like this:


The problem is that its far off and that the angle aint gettin smaller or larger as the caster moves, only the location moves. please fix this, it is a real "bummer" in the spell :'(
That was weird. I tested the script before I posted it and though the angle didn't change it wasn't like that.

Edit: I'll try to fix this later. Right now I have to go.
 
Last edited:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,259
JASS:
    local unit caster = GetTriggerUnit()
    local unit target = GetSpellTargetUnit()
    local unit array missiles
    local player p = GetOwningPlayer(caster)
    local real x1 = GetUnitX(caster)
    local real y1 = GetUnitY(caster)
    local real x2 = GetUnitX(target)
    local real y2 = GetUnitY(target)
    local real R = SquareRoot((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
    local real angle = 45/R //This is the angle in radians in the formula of "arc/R" (I think) and is highly efficent as it is purly a single division opperation.

Angle is the conical angle that the cone should be, you need to use that combined with an offset angle. The off set angle is the angle between the caster and the target. It is then offset + angle for the first angle and the second is offset - angle for the second angle (make sure both are radians).

Radians are basically a scale were 360° = 2pi
Thus 180° = pi
90° = pi/2

So in this case is is highly efficent to use them as it avoids any type conversions and also greatly optimizes the formula.

Warning, because this takes into account that the arc is part of a circle, if the unit is very close to the caster, it will start to gain an insane value (under 1 distance unit). If the caster is the target it will crash due to division by 0 error. It should work fine for distance units like 45 or 1000 etc.

To avoid this problem you need an entirly different calculation requiring quite a few angle measurmenets between points and polar projection of points. The above method should work fine thou if the units have a big enough collision.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,259
Angle1 = AngleofTargetFromCaster+angle
Angle2 = AngleofTargetFromCaster-angle

Thats your 2 angles

AngleofTargetFromCaster you have to work out yourself. There is even a GUI function that does that if I remember correctly so all you need to do is make sure it is in radians.

JASS:
    local unit caster = GetTriggerUnit()
    local unit target = GetSpellTargetUnit()
    local unit array missiles
    local player p = GetOwningPlayer(caster)
    local real x1 = GetUnitX(caster)
    local real y1 = GetUnitY(caster)
    local real x2 = GetUnitX(target)
    local real y2 = GetUnitY(target)
    local real R = SquareRoot((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
    local real baseangle = Atan2(x2-x1, y2-y1)
    local real angle = 45/R //in form of arc/R where arc is the half arc from unit center.
    local real angle1 = baseangle-angle //Angle 1 in radians
    local real angle2 = baseangle+angle //Angle 2 in radians
 
Level 18
Joined
Oct 18, 2007
Messages
930
does it get smaller when i go closer??

Edit: So how should i use those angels?? like polar projection without those *bj_DEGTORAD or RADTODEG??

Edit: This should work right?
JASS:
    local unit Caster = GetTriggerUnit()
    local unit Target = GetSpellTargetUnit()
    local unit MissileA
    local unit MissileB
    local player P = GetOwningPlayer(Caster)
    local real x1 = GetUnitX(Caster)
    local real y1 = GetUnitY(Caster)
    local real x2 = GetUnitX(Target)
    local real y2 = GetUnitY(Target)
    local real x3
    local real y3
    local real R = SquareRoot((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
    local real baseangle = Atan2(x2-x1, y2-y1)
    local real angle = 45/R //in form of arc/R where arc is the half arc from unit center.
    local real angle1 = baseangle-angle //Angle 1 in radians
    local real angle2 = baseangle+angle //Angle 2 in radians
    set x3 = x2 + R * Cos(angle1)
    set y3 = y2 + R * Sin(angle1)
    set MissileA = CreateUnit(P,Missile_Type(),x3,y3,angle1 - 180)
    set x3 = x2 + R * Cos(angle2)
    set y3 = y2 + R * Sin(angle2)
    set MissileB = CreateUnit(P,Missile_Type(),x3,y3,angle2 - 180)
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
I'm pretty sure this is all the info you will need

JASS:
local unit u = GetTriggerUnit() // caster
local unit targ = GetSpellTargetUnit() // target

// coordinates
local real ux = GetUnitX(u)
local real uy = GetUnitX(u)
local real targx = GetUnitX(targ)
local real targy = GetUnitX(targ)

local real angle = Atan2(targy-uy,targx-ux) // angle from caster to target
local real dist = SquareRoot((ux-targx)*(ux-targx) + (uy-targy)*(uy-targy)) // distance from caster to target
local real distFrom = dist/3 // the distance between the caster and the ends of the lines

// the coordinates of the end points of the lines
local real x1 = ux + distFrom * Cos(angle+90) // does Atan2 return radians?
local real y1 = uy + distFrom * Sin(angle+90) // if not, it should be 
local real x2 = ux + distFrom * Cos(angle-90) // ((angle+90)*bj_DEGTORAD)
local real y2 = uy + distFrom * Sin(angle-90) // etc

local real angle1 = Atan(dist/distFrom) // the angle of the left line
local real angle2 = angle1 + 180 // the angle of the right line

Not really sure if this is accurate though, as I didn't really learn this math stuff yet, just read a bit about it in my math book.
 
Level 22
Joined
Dec 31, 2006
Messages
2,216
GhostWolf said:
JASS:
local real ux = GetUnitX(u)
local real uy = GetUnitX(u)
local real targx = GetUnitX(targ)
local real targy = GetUnitX(targ)
There's a little error in that part.
It should be like this:
JASS:
local real ux = GetUnitX(u)
local real uy = GetUnitY(u)
local real targx = GetUnitX(targ)
local real targy = GetUnitY(targ)
Don't worry, I do that mistake very often.
 
Level 18
Joined
Oct 18, 2007
Messages
930
I'm pretty sure this is all the info you will need

JASS:
local unit u = GetTriggerUnit() // caster
local unit targ = GetSpellTargetUnit() // target

// coordinates
local real ux = GetUnitX(u)
local real uy = GetUnitX(u)
local real targx = GetUnitX(targ)
local real targy = GetUnitX(targ)

local real angle = Atan2(targy-uy,targx-ux) // angle from caster to target
local real dist = SquareRoot((ux-targx)*(ux-targx) + (uy-targy)*(uy-targy)) // distance from caster to target
local real distFrom = dist/3 // the distance between the caster and the ends of the lines

// the coordinates of the end points of the lines
local real x1 = ux + distFrom * Cos(angle+90) // does Atan2 return radians?
local real y1 = uy + distFrom * Sin(angle+90) // if not, it should be 
local real x2 = ux + distFrom * Cos(angle-90) // ((angle+90)*bj_DEGTORAD)
local real y2 = uy + distFrom * Sin(angle-90) // etc

local real angle1 = Atan(dist/distFrom) // the angle of the left line
local real angle2 = angle1 + 180 // the angle of the right line

Not really sure if this is accurate though, as I didn't really learn this math stuff yet, just read a bit about it in my math book.

Question: Is there anyway of optimizing it??? :D
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,259
My way should have worked fine.
angle1 and 2 were radians of the angles for the cone.
Thus you needed to convert them to degrees and then create the units at those angles.

Wow, I thought the red was the caster and the black the target. . . . Anyway a quick fix.

Try
JASS:
    local unit Caster = GetTriggerUnit()
    local unit Target = GetSpellTargetUnit()
    local unit MissileA
    local unit MissileB
    local player P = GetOwningPlayer(Caster)
    local real x1 = GetUnitX(Caster)
    local real y1 = GetUnitY(Caster)
    local real x2 = GetUnitX(Target)
    local real y2 = GetUnitY(Target)
    local real x3
    local real y3
    local real R = SquareRoot((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
    local real baseangle = Atan2(x1-x2, y1-y2)
    local real angle = 45/R //in form of arc/R where arc is the half arc from unit center.
    local real angle1 = baseangle-angle //Angle 1 in radians
    local real angle2 = baseangle+angle //Angle 2 in radians
    set x3 = x2 + R * Cos(angle1)
    set y3 = y2 + R * Sin(angle1)
    set MissileA = CreateUnit(P,Missile_Type(),x3,y3,angle1*bj_RADTODEG - 180)
    set x3 = x2 + R * Cos(angle2)
    set y3 = y2 + R * Sin(angle2)
    set MissileB = CreateUnit(P,Missile_Type(),x3,y3,angle2*bj_RADTODEG - 180)
 
Level 18
Joined
Oct 18, 2007
Messages
930
Shouldn't that be like this: local real baseangle = Atan2(y2-y1, x2-x1)


No its stil 180 degrees off

Edit: Ok im testing it and i find a critical bug!! its like the missiles always spawn in a stupid direction! THIS IS REAL STUPID!
adsfaerdgazzzz.png


If you stand in that direction shown in "A." then the angle gets wierd and the same for the "B." picture!!! OMG! why does this happen??

REMEMBER: The BLACK is the caster and the RED is the target. the Green is the Angle!

Edit: Map here
 

Attachments

  • bleh.w3x
    21.8 KB · Views: 41
Last edited:
Level 22
Joined
Dec 31, 2006
Messages
2,216
I made a little improvement to DSG's code though it's not 100% perfect it's better.
JASS:
constant function Missile_Type takes nothing returns integer
    return 'hpea'//Replace this with the raw code of your dummy
endfunction

function Trig_dg_Actions takes nothing returns nothing
    local unit Caster = GetTriggerUnit()
    local unit Target = GetSpellTargetUnit()
    local unit MissileA
    local unit MissileB
    local player P = GetOwningPlayer(Caster)
    local real x1 = GetUnitX(Caster)
    local real y1 = GetUnitY(Caster)
    local real x2 = GetUnitX(Target)
    local real y2 = GetUnitY(Target)
    local real x3
    local real y3
    local real R = SquareRoot((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
    local real baseangle = Atan2(y2-y1, x2-x1)
    local real angle = 45/R+90
    local real angle1 = baseangle-angle
    local real angle2 = baseangle+angle
    set x3 = x2 + R * Cos(angle1)
    set y3 = y2 + R * Sin(angle1)
    set MissileA = CreateUnit(P,Missile_Type(),x3,y3,angle1*bj_RADTODEG - 180)
    set x3 = x2 + R * Cos(angle2)
    set y3 = y2 + R * Sin(angle2)
    set MissileB = CreateUnit(P,Missile_Type(),x3,y3,angle2*bj_RADTODEG - 180)
endfunction
 
Level 22
Joined
Dec 31, 2006
Messages
2,216
My code makes it wider when further away and smaller when close.
Here's a little drawing I made that's shows what my script does:

attachment.php
 

Attachments

  • Drawing.png
    Drawing.png
    18.9 KB · Views: 209

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,259
Well you did not exactly make that clear.
The_Reborn_Devil, your changes did not exactly do that eithor.

Hopefully this is what you wanted.

Yes I got the 2 parameters in Atan2 mixed up and the wrong formula but I have tested it now and it definatly does work the way you want it (or I think you want it to).
 

Attachments

  • bleh.w3x
    22.6 KB · Views: 45
Last edited:
Level 29
Joined
Jul 29, 2007
Messages
5,174
Since you have so many problems with this, I just went and made it.
Seems like Atan doesn't do what I thought it does (it doesn't seem to work like Tangent works... what the hell Arc stands for anyways?), so I used Atan2 for the last two angles too.

JASS:
    local unit u = GetTriggerUnit() // caster
    local real ux = GetUnitX(u)
    local real uy = GetUnitY(u)
    
    // if spell is targeted on units
    local unit targ = GetSpellTargetUnit() // target
    local real targx = GetUnitX(targ)
    local real targy = GetUnitY(targ)
    
    // if spell is targeted on a location
    //local location l = GetSpellTargetLoc()
    //local real targx = GetLocationX(l)
    //local real targy = GetLocationY(l)
    

    local real angle = bj_RADTODEG * Atan2(targy-uy,targx-ux) // angle from caster to target
    local real dist = SquareRoot((ux-targx)*(ux-targx) + (uy-targy)*(uy-targy)) // distance from caster to target
    local real distFrom = dist/3 // the distance between the caster and the ends of the lines
  
    // the coordinates of the end points of the lines
    local real x1 = ux + distFrom * Cos(bj_DEGTORAD * (angle+90))
    local real y1 = uy + distFrom * Sin(bj_DEGTORAD * (angle+90))
    local real x2 = ux + distFrom * Cos(bj_DEGTORAD * (angle-90))
    local real y2 = uy + distFrom * Sin(bj_DEGTORAD * (angle-90))

    local real angle1 = bj_RADTODEG * Atan2(targy-y1,targx-x1) // the angle of the left line
    local real angle2 = bj_RADTODEG * Atan2(targy-y2,targx-x2) // the angle of the right line
    
    // if the location was used
    //call RemoveLocation(l)
    //l = null

Currently the distance between the caster and the end points of the lines is dist/3, you can change that 3 to whatever you want.

Notice that if you cast at short distances it will bug because of warcraft's collisions system (I guess that they'll be locust'd so that problem is solved).

Here's a test map.
 

Attachments

  • bla.w3m
    17.1 KB · Views: 40

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,259
arc purly means the inverse. Atan2 returns the angle in radians between +pi and -pi which is the correct angle (actual facing of the x and y inputed) thus needs both x and y values. Normal Atan returns the smallest angle whos tan gets the correct output between +pi/2 abd -pi/2 (not the correct angle as it will always be towards the right of the screen).

My method worked in the end with some minor adjustments. The map I attached definatly works how I think he wants it to.
 
Status
Not open for further replies.
Top