Getting Units Behind

wraithseeker

Tired.
Reaction score
122
Any simple and efficient alternative other then using LineSegments to detect whether units are behind another unit?

For example

Unit Caster :banghead: into Unit Target in his path. Something like a SetUnitPosition thing when it knocks into another unit while moving.
 

roXplosive

New Member
Reaction score
15
Well I refrained from posting here but how I see the matter is the folowing : I consider untis behind a unit the units in a rectangle of length y and width x situated behind the target unit and rotated with an angle equal with the angle the attacker and defender make . (maybe I didn't make myself clear but hopefully this will settle the matter :

[img=http://img190.imageshack.us/img190/1004/units.th.png]


And saya trigger action

JASS:

function Actions takes nothing returns nothing
//if event fires on damage use GetEventDamageSource()
local real attX=GetUnitX(GetAttacker())
local real attY=GetUnitY(GetAttacker())
local real defX=GetUnitX(GetTriggerUnit())
local real defY=GetUnitY(GetTriggerUnit())
local real X=250 //units 250 ??? behind the target
local real Y=75  // units 75 distance to the left/right of the target
local real tgtsize=25 //consider target size around 50 for simplicity so here we get units behind it
//now our desired rectangle will be rotated and so we need 4 points for (it)
local real x1
local real y1
local real angle1
local real x2
local real y2
local real angle2
local real dist_close
local real x3
local real y3
local real angle3
local real x4
local real y4
local real angle4
local real dist_far
local real xc //center of rectangle X
local real yc //center of rectangle Y
local real sign1
local real sign2
local real sign3
local real sign4
//signs used for apartenence inequations
local real dist=SquareRoot((attX-defX)*(attX-defX)-(attY-defY)*(attY-defY))+tgtsize
local real angle
local group g1
local group g2
local unit un
local real unX
local real unY

set x1=attX+dist
set y1=attY-Y
set angle1=Atan((y1-attY)/(x1-attX))
set x2=attX+dist
set y2=attY+Y
set angle2=Atan((y2-attY)/(x2-attX)) //or -angle1 but it's more readable this way
set dist_close=SquareRoot((x1-attX)*(x1-attX)+(y1-attY)*(y1-attY))
set x3=attX+dist+X
set y3=attY-Y
set angle3=Atan((y3-attY)/(x3-attX))
set x4=attX+dist+X
set y4=attY+Y
set angle4=Atan((y4-attY)/(x4-attX))
set dist_far=SquareRoot((x3-attX)*(x3-attX)+(y3-attY)*(y3-attY))

if attX-defX<0 then //if attacker is to the left of defender then we are in quadrant 1,4
  set angle=Atan((defY-attY)/(defX-attX))
else
 set angle= bj_PI+Atan((defY-attY)/(defX-attX))
endif

//rotating the new rectangle
set x1=attX+dist_close*Cos(angle1+angle)
set y1=attY+dist_close*Sin(angle1+angle)
set x2=attX+dist_close*Cos(angle2+angle)
set y2=attY+dist_close*Sin(angle2+angle)
set x3=attX+dist_far*Cos(angle3+angle)
set y3=attY+dist_far*Sin(angle3+angle)
set x4=attX+dist_far*Cos(angle4+angle)
set y4=attY+dist_far*Sin(angle4+angle)

//obtaining the rectangle's center
set xc=(x1+x2+x3+x4)/4
set yc=(y1+y2+y3+y4)/4

//obtaining the inequation signs
set sign1=RsignBJ((yc-y1)*(x2-x1)-(xc-x1)*(y2-y1))
set sign2=RsignBJ((yc-y2)*(x3-x2)-(xc-x2)*(y3-y2))
set sign3=RsignBJ((yc-y3)*(x4-x3)-(xc-x3)*(y4-y3))
set sign4=RsignBJ((yc-y4)*(x1-x4)-(xc-x4)*(y1-y4))

call GroupEnumUnitsInRange(g1,defX,defY,dist_far,Filter(function True)) //make a function that returns true because null here leaks
loop
  set un=FirstOfGroup(g1)
  exitwhen un==null
  set unX=GetUnitX(un)
  set unY=GetUnitY(un)
  if sign1*((unY-y1)*(x2-x1)-(unX-x1)*(y2-y1))>=0 and sign2*((unY-y2)*(x3-x2)-(unX-x2)*(y3-y2))>=0 and sign3*((unY-y3)*(x4-x3)-(unX-x3)*(y4-y3)) and sign4*((unY-y4)*(x1-x4)-(unX-x4)*(y1-y4)) then
  call GroupAddUnit(g2,un)
  endif
  call GroupRemoveUnit(g1,un)
endloop

//now at the end of this loop the group g2 contains units 25 distance behind the target and situated in a rectangle of 150x250 dimensions , the latter meaning how far back we seeked for units behind
//add instructions for using units in group 2 or just change the function so you can return the group g2 if necessary 
//add instructions to remove leakage

endfunction


On second thought you might not like mats as much as I do . Do the following : retain the angle (angle0) between the attacker and defender with my (see the first if condition then action ) ; set up how far behind you thing behind the attacked unit is ("tgtsize" variable) ; set yourself to how far behind units will be targeted . Use 2 groups to get units in range of the defender that are situated in a tgtsize variable ; get in group 2 units situated as far as you want from that defending unit . Now pick up all the units in group 2 and do : if they do not belong to group1 and the angle they make with the defending unit - angle0 is between some values insert them into another group or do some actions on them .
 

Dinowc

don't expect anything, prepare for everything
Reaction score
223
you mean like when backstabing a unit?
if you don't want to mess with roXplosive's giant code, here:

JASS:
globals
    private constant real MaxRange = 500.00 // this should be higher than your unit's attack range
    private constant real MinRange = 100.00 // this should be lower than your unit's attack range, the lower it is, the greater angle between
endglobals

private function Distance takes real x1, real y1, real x2, real y2 returns real
    local real dx = x2 - x1
    local real dy = y2 - y1
    return SquareRoot(dx * dx + dy * dy)
endfunction
    
    
function CheckIfBehind takes unit caster, unit target returns boolean
    local real x1 = GetUnitX(target)
    local real y1 = GetUnitY(target)
    local real x2 = GetUnitX(caster)
    local real y2 = GetUnitY(caster)
    
    local real angle = GetUnitFacing(target)
    
    local real polarX = x1 + MaxRange * Cos(angle * 0.174)
    local real polarY = y1 + MaxRange * Sin(angle * 0.174)
    
    if Distance(x2, y2, polarX, polarY) > MaxRange + MinRange then
        return true
    endif

    return false
endfunction
 

roXplosive

New Member
Reaction score
15
What if the target isn't facing the attacker ? Or did I misunderstand the question . I was thinking of selecting the units situated in a rectangle on the other side of the attacked unit with regards to the attacker .
 

roXplosive

New Member
Reaction score
15
If what I did before wasn't what you intended I have another solution here :

JASS:

function behind unit tested , unit source returns boolean
local distance = 25 //how many length units behind we consider to be behind a unit
local real facing
local real x0
local real y0
local real m

//getting unit's facing and points on a line that is perpendicular to the facing but behind the selected unit
set facing=GetUnitFacing(source)
set x0=GetUnitX(source)+distance*Cos(facing+bj_PI)
set y0=GetUnitY(source)+distance*Sin(facing+bj_PI)
set m=-1/Tan(facing) // elevation of the perpendicular to "facing"

return RsignBJ((GetUnitY(source)-y0)-m*(GetUnitX(source)-x0))*((GetUnitY(tested)-y0)-m*(GetUnitX(tested)-x0))<=0
endfunction



 

wraithseeker

Tired.
Reaction score
122
That rectangle thing is what I need but it seems to be even more complicated then the maths of LineSegments, is there shorter alternative?
 

roXplosive

New Member
Reaction score
15
I reconsidered my strategy and you can choose all units around the target of attack , get the distance to the attacker , rotate them clockwisw and check if they are inside the rectangle . This condition is one checking if P(x,y) is between certain coordinates (this will put up a bit of load on the computer but I don't think it's anything relevant):

JASS:

function Actions takes nothing returns nothing
//if event fires on damage use GetEventDamageSource()
local real attX=GetUnitX(GetAttacker())
local real attY=GetUnitY(GetAttacker())
local real defX=GetUnitX(GetTriggerUnit())
local real defY=GetUnitY(GetTriggerUnit())
local real X=250 //units 250 ??? behind the target
local real Y=75  // units 75 distance to the left/right of the target
local real tgtsize=25 //consider target size around 50 for simplicity so here we get units behind it
//now our desired rectangle will be rotated and so we need 4 points for (it)
local real xmin
local real ymin
local real xmax
local real ymax
local real dist_far

local real dist=SquareRoot((attX-defX)*(attX-defX)-(attY-defY)*(attY-defY))+tgtsize

local real angle
local group g1
local group g2
local unit un
local real unX
local real unY
local real unAngle
local real unDist

set xmin=attX+dist
set ymin=attY-Y
set xmax=attX+dist+X
set ymax=attY+Y
set dist_far=SquareRoot((attX-xmax)*(attX-xmax)+(attY-ymax)*(attY-ymax))

if attX-defX<0 then //if attacker is to the left of defender then we are in quadrant 1,4
  set angle=Atan((defY-attY)/(defX-attX))
else
 set angle= bj_PI+Atan((defY-attY)/(defX-attX))
endif


call GroupEnumUnitsInRange(g1,defX,defY,dist_far,Filter(function True)) //make a function that returns true because null here leaks
loop
  set un=FirstOfGroup(g1)
  exitwhen un==null
  set unX=GetUnitX(un)
  set unY=GetUnitY(un)
  set unDist = SquareRoot((unX-attX)*(unX-attX)+(unY-attY)*(unY-attY))
  if attX-unX<0 then
      set unAngle = Atan((unY-attY)/(unX-attX))
  else
     set unAngle = bj_PI + Atan((unY-attY)/(unX-attX))
 endif
  //rotating clockwise 
  set unX=attX+unDist*Cos(unAngle-angle)
  set unY=attY+unDist*Sin(unAngle-angle)
  if xmin<=unX and unX<=xmax and ymin<=unY and unY<=ymax then
    call GroupAddUnit(g2,un)
  endif
  call GroupRemoveUnit(g1,un)
 endloop
//now at the end of this loop the group g2 contains units 25 distance behind the target and situated in a rectangle of 150x250 dimensions , the latter meaning how far back we seeked for units behind
//add instructions for using units in group 2 or just change the function so you can return the group g2 if necessary 
//add instructions to remove leakage

endfunction
 

chobibo

Level 1 Crypt Lord
Reaction score
48
Could you clarify what you want, I don't understand what you said in your first post.

Do you want to detect collisions from behind the unit? Is it an instant detection or maintained?
 

Jesus4Lyf

Good Idea™
Reaction score
397
I have an old algorithm using vector math to detect units in a rectangle starting from a certain point, given an angle. Is that what you need?
______________
|
|
+ Point
|
|_____________

That's for 0 degrees. See, your question actually makes no sense. It could be:

..../
../
/
+ Point
\
..\
....\

Or:

|
|
|
+ Point
|
|
|

Clarify. :)
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top