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

[Solved] Checking if the units left the rect

Status
Not open for further replies.
Level 7
Joined
Feb 9, 2021
Messages
301
What is the best way to check if the unit left the rect? I want to check whether the unit is still inside the rect or not. In this case, checking the distance does not work because it is rect.

Edit: here is my solution, but it does not look efficient
JASS:
            call LineSegment.EnumUnitsEx(temp_group, rect1X, rect1Y, rect2X, rect2Y, RECT_LENGTH , true)
            loop
                set u = FirstOfGroup(temp_group)
                exitwhen u == null
                if (BaseBool(u) and not IsUnitEnemy(u, this.owner)) then
                    call GroupAddUnit(check, u)
                    if not IsUnitInGroup(u, this.barrierDef) then
                        //Turn on Immunities
                        call GroupAddUnit(this.barrierDef, u)
                    endif
                endif
                 
                call GroupRemoveUnit(temp_group, u)
            endloop
         
            set copy = CopyGroup(this.barrierDef)
         
            loop
                set u = FirstOfGroup(copy)
                exitwhen u == null
                if not IsUnitInGroup(u, check) then
                    //Turn off immunities
                    call GroupRemoveUnit(this.barrierDef, u)
                endif
             
                call GroupRemoveUnit(copy, u)
             
            endloop
         
            call GroupClear(check)
 
Last edited:
JASS:
function IsUnitInRect takes unit u, rect r returns boolean
   return (GetRectMinX(r) <= GetUnitX(u)) and (GetUnitX(u) <= GetRectMaxX(r)) and (GetRectMinY(r) <= GetUnitY(u)) and (GetUnitY(u) <= GetRectMaxY(r))
endfunction
Note that this checks unit-center to rect-edge. If you want the units collision to be taken into effect (such as "is unit completely inside" or "is unit at least touching the rect's edge") you'd have to add or subtract collision radius.
 
if called
JASS:
call LineSegment.EnumUnitsEx(this.barrierDef, rect1X, rect1Y, rect2X, rect2Y, RECT_LENGTH , true)
the group already only holds units that are inside rect.
As next step though, one iteration would be required to remove units that don't match BaseBool() and Enemy check.

Optimal solution would be passing a filter function to EnumUnitsEx(), which does BaseBool() and Enemy check, but we currently don't support it. It could avoid the removal iteration then, too. If you want to wait a couple of days I want to add this functionality.
 
Last edited:
ive added filter for vjass version you can download here and use:

JASS:
private static player g_player
static method myFilter takes nothing returns boolean
    local unit u = GetFilterUnit()
    return BaseBool(u) and not IsUnitEnemy(u, g_player)
endmethod

method updateImmunities takes nothing returns nothing
    g_player = this.owner
    call LineSegment.EnumUnitsEx(this.barrierDef, rect1X, rect1Y, rect2X, rect2Y, RECT_LENGTH , true, Filter(function thistype.myFilter)
endmethod
 
Level 7
Joined
Feb 9, 2021
Messages
301
ive added filter for vjass version you can download here and use:

JASS:
private static player g_player
static method myFilter takes nothing returns boolean
    local unit u = GetFilterUnit()
    return BaseBool(u) and not IsUnitEnemy(u, g_player)
endmethod

method updateImmunities takes nothing returns nothing
    g_player = this.owner
    call LineSegment.EnumUnitsEx(this.barrierDef, rect1X, rect1Y, rect2X, rect2Y, RECT_LENGTH , true, Filter(function thistype.myFilter)
endmethod
So, are you saying the only improvement possible to my code is to add filter to reduce if statements?

Note that this checks unit-center to rect-edge. If you want the units collision to be taken into effect (such as "is unit completely inside" or "is unit at least touching the rect's edge") you'd have to add or subtract collision radius.
Since I do not have the "rect", I suppose this does not work (I use line segment system)
 
Level 7
Joined
Feb 9, 2021
Messages
301
loops are gone...
Maybe I do not get something, but I need to give immunity status only to those who are in rect. So, with your code, I need to loop in order to check whether newly selected units in rect are the same and then stop the immunity on those who are not in the second group. How does it remove the need for looping?
 
Level 7
Joined
Feb 9, 2021
Messages
301
"this.barrierDef" will only contain all units that are currently in new rect and pass the filter. I suppose that this is what you want and consider them to be in "immunity group". Old will be already removed from group.
I understand that. To give immunity, I use a boolean. So, I would need to set boolean off for those who are not in rect anymore. It is probably my bad because I didn't add booleans to my code, so it is not clear. Sorry

Edit: I guess your proposal is to set boolean off for all in the immunity group, clear the group, and then set boolean on for updated group? Won't this cause problems?
 
Last edited:
Ah, ok I see. Clearing before should work, and assigning boolean then to true again yes. It might happen even in filter function, to avoid extra loop if you want.

But IsUnitInGroup is a function which already does actually required check if unit is immune, or? It might check if unit is in immunity group and returns boolean. Not sure if separate boolean flag brings benefit.
 
Level 7
Joined
Feb 9, 2021
Messages
301
Ah, ok I see. Clearing before should work, and assigning boolean then to true again yes. It might happen even in filter function, to avoid extra loop if you want.

But IsUnitInGroup is a function which already does actually required check if unit is immune, or? It might check if unit is in immunity group and returns boolean. Not sure if separate boolean flag brings benefit.
I just run immunity with a separate system of mine, but I see what you mean. Thank you.
 
Status
Not open for further replies.
Top