• 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.
  • It's time for the first HD Modeling Contest of 2025. Join the theme discussion for Hive's HD Modeling Contest #7! Click here to post your idea!

[JASS] Boolexpr Question

Status
Not open for further replies.
Level 12
Joined
Dec 10, 2008
Messages
850
I was wondering, how does Boolexpr work? Like, what can I pass to it for the GroupEnumUnitsInRange() function? I need it to include only enemie units of the caster. If somebody could help, I would be forever gratefull. (and I'll give rep :))
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Any function that takes nothing and returns a boolean.

In case you need to reference to the units in the group (which is the main purpose of this) you can use GetEnumUnit().

JASS:
function bla takes nothing returns boolean
    unit u = GetEnumUnit()
    // do whatever you want
    return true/false
endfunction
 
Level 8
Joined
Nov 9, 2008
Messages
502
boolexpr is like making an if statement that will be applied to each unit in that group and effectively filter out the units you don't want.

So I have a boolexpr that checks the player of the unit...

JASS:
function myFilter takes nothing returns boolean
    local unit u = GetFilterUnit()
    local boolean b = GetOwningPlayer(u) == Player(11)
    set u = null
    return b
endfunction

If you need only enemies of the caster, I suggest you find out what that boolexpr would look like by converting it from the GUI. I don't know it off the top of my head.
 
Level 9
Joined
Nov 28, 2008
Messages
704
Gettin an enemy would not work too well with a filter, as you would have to use a global. I suggest using no filter and using a

JASS:
loop
   set Unit = FirstOfGroup(Group)
   exitwhen Unit == null
   //check here!
endloop
 
Level 8
Joined
Nov 9, 2008
Messages
502
JASS:
function myFilter takes nothing returns boolean
    local unit u = GetFilterUnit()
    local boolean b = IsUnitEnemy(u, Player(x))
    set u = null
    return b
endfunction

You need to define Player(x), which is where you need to use a global as someone else said, unless you could use GetTriggerPlayer.
 
Level 11
Joined
Apr 6, 2008
Messages
760
Mooglefrooglian, please. Filter is the best thing u can use.

Don't know if you are using JNGP but here it is anyway

JASS:
scope NAME initializer init

globals
    boolexpr BOOL
endglobals

private function FilterFunc takes nothing returns boolean
    //if you are using structs u can just pass along the struct with a global integer
    local unit u = GetFilterUnit()
    local boolean ok = GetWidgetLife(u) > .405 and IsUnitEnemy(u,GetOwningPlayer(GetTriggerUnit())) // the last one is pretty, but what the heck
    set u = null
    return ok
endfunction

private function Action takes nothing returns nothing
      local unit TempU
      //stuff

      call GroupEnumUnitInRange(Grp,x,y,radius,BOOL)

      loop
          set TempU = FirstOfGroup(Grp)
          exitwhen TempU == null
          call GroupRemoveUnit(Grp,TempU)
          //STUFF!!!
      endloop
  
      //More Stuff
endfunction

private function init takes nothing returns nothing
      local trigger Trig = CreateTrigger()

      //Stuff to run ur trigger for what ever

      set BOOL = Filter(function FilterFunc)
endfunction

endscope


@toofless; Gief Tulip!
 
Level 8
Joined
Aug 4, 2006
Messages
357
It's even better to do your actions inside of the filter func, so you don't have to loop through the group a second time.
JASS:
scope NAME initializer init
    globals
        private group targets
        private boolexpr targetActions
    endglobals

    private function FilterFunc takes nothing returns boolean
        local unit u = GetFilterUnit()
        local boolean ok = GetWidgetLife(u) > .405 and IsUnitEnemy(u,GetOwningPlayer(GetTriggerUnit()))
        if ok then
            //do stuff to the targets
        endif
        return false
    endfunction

    private function Actions takes nothing returns nothing
          //set up local variables like x,y,radius and stuff

          call GroupEnumUnitsInRange(targets,x,y,radius,targetActions)
      
          //More Stuff
    endfunction

    private function init takes nothing returns nothing
          local trigger Trig = CreateTrigger()

          //set up events/conditions
          call TriggerAddAction(Trig, function Actions)
          set targetActions = Filter(function FilterFunc)
          set targets = CreateGroup()
    endfunction
endscope
Just to clarify, use GetFilterUnit() to get the unit in a boolexpr, that is being considered to add to a group. Use GetEnumUnit() to get the current picked unit, when you have already populated a group, and are looping through it using ForGroup(...)
 
Level 9
Joined
Nov 28, 2008
Messages
704
Using a global is messy. It means if your trigger is called simutaneously while one is doing, the global could be overwritten, resulting in unwanted events. You can filter inside your for loop, which is not even less efficient, with the advantage of not having the danger of using globals.

JASS:
call GroupEnumUnitsInRange(X, Y, null)
loop
   set Unit = FirstOfGroup(Group)
   exitwhen Unit == null
   if IsUnitEnemy(Unit, Player(insertplayerhereyouhaveinsideyourfunction) then
      //do all your code here.
   endif
   call GroupRemoveUnit(Group, Unit)
endloop

I think it's foolish to use a filter in this case if you have the danger of using a global.
 
Level 8
Joined
Aug 4, 2006
Messages
357
It is not possible for globals to be overwritten if there are no waits. If there are waits, you can still do what I did, but make a struct to contain the variables instead of making them global. You should learn to use vJASS since it can really make JASS programming easier.
 
Level 9
Joined
Nov 28, 2008
Messages
704
I apologise then, I found out that triggers can not run at the same time as I previously thought. I still disagree with using a global, but that is just me. Water, it is NOT "way" quicker. Nanoseconds, and myabe 200 bytes of memory are used for about 0.001 seconds and you get access to your locals. Seems easier and cleaner to me (since he requires the use of a local variable and you have to spend extra time transferring the memory). Both ways work though, and using the filter + global may be faster. *shrug*
 
Status
Not open for further replies.
Top