Getting Units Behind

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
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
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
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
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



 
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
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
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™
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 The Helper:
    basically it is linux
  • The Helper The Helper:
    OMG it is BanLord as Blackveiled on the forum
  • The Helper The Helper:
    what is up buddy
  • jonas jonas:
    thanks for the tip, that sounds cool. Never heard about the VCS before but seems like it should be a good match
  • tom_mai78101 tom_mai78101:
    The winter vacation left a toll on me. I missed staying up late and sleeping in late.
  • C Cherry.Grove:
    i haven't looked into it yet
  • C Cherry.Grove:
    If I could use something Python compatible it would save me some learning
  • C Cherry.Grove:
    But Unity might be easiest
  • C Cherry.Grove:
    looking at old posts here makes me happy. Makes me be all like "wow I was pretty smart in 2009"
  • C Cherry.Grove:
    mostly failing at life through adulthood really demotivated me for a while
  • C Cherry.Grove:
    ....what I don't get is why the fuck they would force us to permanently convert to a version of the game everyone fucking hated : \
  • C Cherry.Grove:
    Raid Shadow Legends texture pack smh
  • jonas jonas:
    Most people fail at life throughout their adulthood. Sometimes we get to learn from it. Usually it just feels like crap.
    +1
  • The Helper The Helper:
    What does not kill you makes you stronger is what they say
  • C Cherry.Grove:
    for real! :cool:
  • Varine Varine:
    Are we still on the topic of failing? I failed lots!
  • jonas jonas:
    If you ever want to talk about it we're here. The way I see it, you're still around. That required a few very difficult successes if you ask me:)
  • Varine Varine:
    I posted a thing here a while ago about my failures if it makes you feel better to hear about other people failing. Drugs and whatnot, I had a lot more fun than was healthy. I'm still a failure, but very few of us actually get to be the self made billionaire. Luck is the only thing that will take you as far as already having money a lot of the time, and the easiest way to get catch that is with a very wide net and the willingness to let other things loose.
  • Varine Varine:
    Have fun, do your best, something about Edison's light bulb not working until he stole it.
  • jonas jonas:
    Eh. Don't define success as being a billionaire or even millionaire. Success is about overcoming your personal challenges. And if you can get to a place in life where you can love yourself, that is winning it big time
  • jonas jonas:
    Being a billionaire probably sucks, you can't go out in public like a random person anymore and you always need a bunch of big guys following you around discreetly
  • jonas jonas:
    And you'll never know if anyone you know really likes you or is just seeing you as a big money sack
  • jonas jonas:
    Most of the best fun I've ever head was with a group of friends eating pizza or drinking a good 10$ bottle of wine, when I had maybe 100$ on my account. Or the time when I was so broke, my friends visited me with bags of ingredients and I cooked for us, because I didn't have money to buy ingredients anymore
  • jonas jonas:
    Or walking with my then-fiancee through the night until dawn, just talking

    Members online

    No members online now.

    Affiliates

    Hive Workshop NUON Dome
    Top