Filtering Groups

XeRo13g

New Member
Reaction score
3
Ok, I thought I was doing well in learning Jass, until I've reached to the point that i wanted to convert something like this:

Code:
Set Temp_Group = (Units within 512.00 of Temp_Point matching (Several conditions))

Following the lead of a tutorial, I've created this:

Code:
set i=0
loop
  set i=i+1
  exitwhen i==6
  set g = GetUnitsInRangeOfLocAll(500.00, o)
    loop
      set u1 = FirstOfGroup(g)
      exitwhen u1==null
      if  (IsUnitAlly(u1, GetOwningPlayer(u))!=true or GetOwningPlayer(u1) == Player(PLAYER_NEUTRAL_PASSIVE)) and GetUnitState(u1, UNIT_STATE_LIFE) > 0 and IsUnitType(u1, UNIT_TYPE_UNDEAD) != true then
       call GroupRemoveUnit(g,u1)
      if IsUnitType (u1, UNIT_TYPE_STRUCTURE) == true then
       set r=500
       else
     set r=( 700+(GetUnitStateSwap(UNIT_STATE_MAX_LIFE, u1) * 0.03 ))
    endif
  call DisplayTextToPlayer( Player(0),0,0, R2S(r) )
       call UnitDamageTargetBJ( u, u1, r, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNKNOWN )
        else
         call GroupRemoveUnit(g,u1)
      endif
    endloop

Yet, after reading several posts about how FirstOfGroup can be buggy and how ForGroup is faster in most cases, i've tried to find out more about ForGroup. But then again, there is boolexpr as callback which sound promising...After several hours, I've ended up more confused than ever...

According to Vexorian, there are ways to deal with this by Dynamic Arrays(???), without creating groups?!? What?/How?

I've tried to examine Jass spells but that confused me even more with scary codes like "antileak function" which does nothing but returns true.

At the moment and for the last 3 days, I'm totally stuck.
Can someone please direct me to a helpful tutorial or anything that includes examples? If there was an example of each usage, I think I could try and figure out the rest, or at least ask questions that point somewhere specific.
All those posts refer to everything as if the reader has deep knowledge or at least a decent background knowledge. Well, I'm a total newbie and I found myself very close in giving up.

All I want to replicate is codes like the first GUI line I've posted.
Thanks for taking the time to read.-
 

XeRo13g

New Member
Reaction score
3
This might be graveyard, but works like a charm and it's very very fast.
http://www.thehelper.net/forums/showthread.php/167137-GroupTools

Thanks for the reply Dirac.
I'll have to study the Group tool you've made but I can't adopt a system that I'm unable to fully understand. I have no clue about methods or how to use them...I wouldn't even know how to implement it, let alone use it.

One would tell that examples found here:
http://wiki.thehelper.net/wc3/jass/common.j/Group_API#FirstOfGroup

Would be sufficient but somehow I fail to understand how to use those commands in practice. I know that the Jass code in the OP works(at least it seems to) but how would I use "ForGroup", "boolexpr as callback", "dynamic arrays" or any of the ways mentioned in various posts, instead of FirstOfGroup?
 

Dirac

22710180
Reaction score
147
JASS:
scope Test
    function B takes nothing returns boolean
        call KillUnit(GetFilterUnit()) //kills the unit being filtered
        return false //determines the permanence of the unit inside the group, if false, the unit is deleted from it
    endfunction
    function A takes nothing returns nothing
        local group g=CreateGroup() //new empty group
        call GroupEnumUnitsInRange(g,0,0,600,Filter(function B)) //Picks every unit withing 600 disntace from point 0,0 of the map and runs it through "B"
        call DestroyGroup(g)
    endfunction
endscope
JASS:
scope Test
    function B takes nothing returns nothing
        call KillUnit(GetEnumUnit()) //kills the unit being filtered
    endfunction
    function A takes nothing returns nothing
        local group g=CreateGroup() //new empty group
        call GroupEnumUnitsInRange(g,0,0,600,null) //Picks every unit withing 600 disntace from point 0,0 of the map and adds it to the group
        call ForGroup(g,function B) //runs every unit from the group g into "B"
        call DestroyGroup(g)
    endfunction
endscope
 

Dirac

22710180
Reaction score
147
Yes and i also "forgot" to null the boolexpr used to enum groups, but i was trying to explain something, not uploading a resource.
Also if i were using GroupTools there would be no need for nulling or destroying stuff.

PD: Your mood msg matches my avatar :D
 

XeRo13g

New Member
Reaction score
3
Apologies for taking that long to reply.
After Dirac's reply, I went through everything once more and tried to recreate the simple spell I've posted at the OP with both ways. They seem to work, yet I feel that they leak and there are still a few things I can't get a grasp on.

The test spell works like flamestrike and damages units in the area for 5 seconds, simple as that.

Using a Boolexpr:

JASS:
function Hell_001 takes nothing returns boolean
 local unit u=GetTriggerUnit() //<-----Should I replace this somehow?
 local unit u1=GetFilterUnit()
 local real r
    if  (IsUnitAlly(u1, GetOwningPlayer(u))!=true or GetOwningPlayer(u1) == Player(PLAYER_NEUTRAL_PASSIVE)) and GetUnitState(u1, UNIT_STATE_LIFE) > 0 and IsUnitType(u1, UNIT_TYPE_UNDEAD) != true then
        if IsUnitType (u1, UNIT_TYPE_STRUCTURE) == true then
            set r=500
        else
            set r=( 700+(GetUnitState(u1,UNIT_STATE_LIFE) * 0.03 ))
        endif
      call UnitDamageTarget(u, u1, r, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNKNOWN, WEAPON_TYPE_WHOKNOWS)
    endif
    set u=null
    set u1=null
        return false
    endfunction

function Trig_Hell_Bool_Actions takes nothing returns nothing
    local location o=GetSpellTargetLoc()
    local group g=CreateGroup()
    local effect array sfx
    local integer i=0
    local filterfunc f = Filter(function Hell_001)
set sfx[1]=AddSpecialEffectLoc("Abilities\\Spells\\Human\\FlameStrike\\FlameStrikeTarget.mdl", o)
call TriggerSleepAction(0.50)
set sfx[2]=AddSpecialEffectLoc("Abilities\\Spells\\Human\\FlameStrike\\FlameStrike1.mdl", o)
call TriggerSleepAction(0.50)
set sfx[3]=AddSpecialEffectLoc("Abilities\\Spells\\Human\\FlameStrike\\FlameStrike2.mdl", o)
set sfx[4]=AddSpecialEffectLoc("Abilities\\Spells\\Human\\FlameStrike\\FlameStrike.mdl", o)
call TriggerSleepAction(0.50)

loop
  set i=i+1
  exitwhen i==6
    call GroupEnumUnitsInRangeOfLoc(g,o,500,f)
    call TriggerSleepAction(1.00)
  endloop
    call DestroyGroup(g)
    set g=null
    call DestroyFilter(f)
    set f = null
set i=0
    loop
    set i=i+1
    exitwhen i>4
    call DestroyEffect(sfx<i>)
    set sfx<i>=null
    endloop
call RemoveLocation(o)
set o = null
endfunction</i></i>


Since there is a wait in there, should I change "local unit u=GetTriggerUnit()" in the Hell_001 function with a global or is this fine? How should I go about it?

Using ForGroup:

JASS:
function Hell_002 takes nothing returns boolean
 local unit u=GetTriggerUnit()
 local unit u1=GetEnumUnit()
 local real r
    if  (IsUnitAlly(u1, GetOwningPlayer(u))!=true or GetOwningPlayer(u1) == Player(PLAYER_NEUTRAL_PASSIVE)) and GetUnitState(u1, UNIT_STATE_LIFE) &gt; 0 and IsUnitType(u1, UNIT_TYPE_UNDEAD) != true then
        if IsUnitType (u1, UNIT_TYPE_STRUCTURE) == true then
            set r=500
        else
            set r=( 700+(GetUnitState(u1,UNIT_STATE_LIFE) * 0.03 ))
        endif
      call UnitDamageTarget(u, u1, r, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNKNOWN, WEAPON_TYPE_WHOKNOWS)
    endif
    set u=null
    set u1=null
        return false
    endfunction

    
    function Hell_NoLeak takes nothing returns boolean
    return true
    endfunction
 
 
function Trig_Hell_ForGroupp_Actions takes nothing returns nothing
    local unit u=GetTriggerUnit()
    local location o=GetSpellTargetLoc()
    local group g=CreateGroup()
    local effect array sfx
    local integer i=0
    local filterfunc f = Filter(function Hell_NoLeak)
    
set sfx[1]=AddSpecialEffectLoc(&quot;Abilities\\Spells\\Human\\FlameStrike\\FlameStrikeTarget.mdl&quot;, o)
call TriggerSleepAction(0.50)
set sfx[2]=AddSpecialEffectLoc(&quot;Abilities\\Spells\\Human\\FlameStrike\\FlameStrike1.mdl&quot;, o)
call TriggerSleepAction(0.50)
set sfx[3]=AddSpecialEffectLoc(&quot;Abilities\\Spells\\Human\\FlameStrike\\FlameStrike2.mdl&quot;, o)
set sfx[4]=AddSpecialEffectLoc(&quot;Abilities\\Spells\\Human\\FlameStrike\\FlameStrike.mdl&quot;, o)
call TriggerSleepAction(0.50)

loop
  set i=i+1
  exitwhen i==6
    call GroupEnumUnitsInRangeOfLoc(g,o,500,f)
    call ForGroup(g,function Hell_002)
    call GroupClear(g)  //&lt;----Not sure if this necessary but it seems logical
    call TriggerSleepAction(1.00)
  endloop
    call DestroyGroup(g)
    set g=null
    call DestroyFilter(f)
    set f = null  
    
    set i=0
    loop
    set i=i+1
    exitwhen i&gt;4
    call DestroyEffect(sfx<i>)
    set sfx<i>=null
    endloop
call RemoveLocation(o)
set o=null
set u=null
endfunction</i></i>


Was the function Hell_NoLeak, used correctly?!
Clearing the group was necessary?

I would be most grateful if someone more experienced, took the time to go through these two variations and tell me if I did anything wrong, if it leaks or if anything should or could be improved?!
Any suggestions would be appreciated!

PS. Dirac, you can't imagine how helpful your reply was... +Rep, seems a very lowly reward for it. Cheers!!
 

Dirac

22710180
Reaction score
147
Don't ever use waits on your triggers, always clean up the indentation
JASS:
globals
	private group ENUM_GROUP=CreateGroup()
endglobals

function Actions takes nothing returns nothing
	local unit u=GetTriggerUnti()
	local unit f
	local real x=GetSpellTargetX()
	local real y=GetSpellTargetY()
	call GroupEnumUnitsInRange(ENUM_GROUP,x,y,500,null)
	loop
		set f=FirstOfGroup(ENUM_GROUP)
		exitwhen (null=f)
		call UnitDamageTarget(u,f,true,false,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNIVERSAL,null)
	endloop
	set u=null
	set f=null
endfunction
That's the unsafe way to do it using FirstOfGroup()

Using GroupTools
JASS:
function Actions takes nothing returns nothing
	local unit u=GetTriggerUnti()
	local unit f
	local real x=GetSpellTargetX()
	local real y=GetSpellTargetY()
	local integer i=0
	local SimpleGroup g=SimpleGroup.create()
	call g.enumUnitsInRange(x,y,500)
	loop
		set f=g.NextOfGroup
		exitwhen i==g.count
		call UnitDamageTarget(u,f,true,false,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNIVERSAL,null)
		set i=i+1
	endloop
	call g.destroy()
	set u=null
	set f=null
endfunction
 

XeRo13g

New Member
Reaction score
3
Don't ever use waits on your triggers, always clean up the indentation
JASS:
globals
	private group ENUM_GROUP=CreateGroup()
endglobals

-How can I avoid waits, if the group needs to take damage over a period of time? While using FirstOfGroup, I didn't use any waits in the part of the code that takes each unit and deals with it, if that is what you mean.

-Not sure what you mean by clean up the Indentation:(

-private group ENUM_GROUP=CreateGroup() - is this Jass or vJass?

Using GroupTools
JASS:
function Actions takes nothing returns nothing
	local unit u=GetTriggerUnti()
	local unit f
	local real x=GetSpellTargetX()
	local real y=GetSpellTargetY()
	local integer i=0
	local SimpleGroup g=SimpleGroup.create()
	call g.enumUnitsInRange(x,y,500)
	loop
		set f=g.NextOfGroup
		exitwhen i==g.count
		call UnitDamageTarget(u,f,true,false,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNIVERSAL,null)
		set i=i+1
	endloop
	call g.destroy()
	set u=null
	set f=null
endfunction

This looks extremely like FirstOfGroup usage. Do you mean that I should use the filter function -only- for filtering and do what is to be done with the group in the main trigger?
 

Dirac

22710180
Reaction score
147
It's like you forgot the post i wrote before that one, explaining how the for group and enumeration call works.

If you don't use vJass i cannot help you
 

XeRo13g

New Member
Reaction score
3
I don't mind to study vJass but I just started on Jass and I can't say I have a grip on it yet.

In any case...
Those two codes I did for the test spell using your example, were made correctly or do they leak like hell?
 

Dirac

22710180
Reaction score
147
Well i can't spot a leak at plain sight however, you do use lots of Locations, which should always be avoided by instead using X and Y.
 

Bribe

vJass errors are legion
Reaction score
67
What exactly is intended to be achieved here by using waits? The only time to use waits is maybe in a cinematic? Maybe.
 

XeRo13g

New Member
Reaction score
3
What exactly is intended to be achieved here by using waits? The only time to use waits is maybe in a cinematic? Maybe.

It takes a group of units and damage it once per second for 5 seconds, thus the: call TriggerSleepAction(1.00) in the code. It's my 3rd post if you want to check.

Is there another way?
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Ghan Ghan:
    Howdy
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top