North, East, South and West is represented as -X, -Y, +X, +Y.
Note, it may be +X, +Y, -X, -Y, cannot remember.
This is similar to sin, cos, -sin, -cos in calculus. The same rules apply: You can calculate angles and distances between different points to create what you want. For example:
Code:
function ZG.VAR.FireballExplode(pUnit)
local x2 = pUnit:GetX()
local y2 = pUnit:GetY()
pUnit:CastSpell(76010) -- visual
pUnit:RemoveAura(71706) -- main visual
for _,plr in pairs(pUnit:GetInRangePlayers()) do
local distance = plr:GetDistanceYards(pUnit)
if plr:GetPhase() == 2 and distance < 20 then
local minimum = distance*40
local maximum = distance*50
pUnit:Strike(plr, 2, 72134, minimum, maximum, 0.1)
local x1 = plr:GetX()
local y1 = plr:GetY()
local x = x2 - x1
local y = y2 - y1
local angle = math.pi + math.atan2(-y, -x)
local x = x1 - ((math.random(25,30)-distance) * math.cos(angle))
local y = y1 - ((math.random(25,30)-distance) * math.sin(angle))
local z = pUnit:GetLandHeight(x, y)
if z > 200 or z < 20 then
z = plr:GetZ()
end
plr:MoveKnockback(x, y, z, 2, 9)
end
end
end
I use this code to get the point between the npc and the player, then calculate a location based on the distance following that line:

You could use a similar formula to get a location slightly further away each time. Or you can just add/take away to X and Y and use the following function to get land height:
unit:GetLandHeight(x,y) -- returns Z at location of X, Y if maps and vmaps are enabled.