HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

jass units in range matching condition

07-04-2006, 07:24 AM#1
StRoNgFoE_2000
What I am trying to do this time, is eliminate the function for the condition that the WE creates when using "Units in range matching Condition" so I can use a global variable (DUnit in this case) in the condition.

The action in the editor looks like this but this will not do because it creates a new function:
Trigger:
Set WoVGroup_AffectedUnits = (Units within 550.00 of TempPoint matching ((IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(udg_DUnit)) and IsUnitAliveBJ(GetFilterUnit()))))

I converted to JASS and this is what it becomes with the new function created:
Collapse JASS:
unction Trig_Untitled_Trigger_002_Func001002003 takes nothing returns boolean
    return  ( IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(udg_DUnit)) and IsUnitAliveBJ(GetFilterUnit()) )
endfunction

function Trig_Untitled_Trigger_002_Actions takes nothing returns nothing
    set udg_WoVGroup_AffectedUnits = GetUnitsInRangeOfLocMatching(550.00, udg_TempPoint, Condition(function Trig_Untitled_Trigger_002_Func001002003))
endfunction

//===========================================================================
function InitTrig_Untitled_Trigger_002 takes nothing returns nothing
    set gg_trg_Untitled_Trigger_002 = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Untitled_Trigger_002, function Trig_Untitled_Trigger_002_Actions )
endfunction

Finally, I tried to replace where it calls the function with the condition itself but this does not work:
Collapse JASS:
set udg_WoVGroup_AffectedUnits = GetUnitsInRangeOfLocMatching(550.00, udg_TempPoint, Condition(IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(udg_DUnit)) and IsUnitAliveBJ(GetFilterUnit()))

I've tried many different variations of the above script but it's just errors galore. A few times I got "expected a (", so I put a "(" in there and i get "invalid number of arguments". So after a little more messing around with it I know I did it correctly, I get "invalid argument type (boolean)" which is the error I recieve now with the above script.

My question is, is there an easier way around this without creating a new function, or at least is there a way that I can make this work so I can use global variables?
07-04-2006, 07:32 AM#2
Naakaloh
Condition is actually function that a "code" parameter (a function that returns a boolean) and returns a conditionfunc type, so you can't give it any parameters that it isn't designed to take. Also, what's so bad about that method? If it's really that much of an issue you can just use GroupEnumUnitsInRange with a null for the boolexpr, then loop through the group and take out the units that don't match the condition and achieve the exact same effect with more work.
07-04-2006, 07:44 AM#3
StRoNgFoE_2000
I'm still a noob to JASS so a lot of that sounded greek to me, but I do understand the meaning you are trying to get across. I'll do a little more research and if I'll post again if I have anymore concerns.
07-04-2006, 07:50 AM#4
The)TideHunter(
To be honest, i would stay away from Blizz functions like that.
If you want them done good, so them yourself =).
Something that does the same, is here:
This is alot longer, but MUCH better.
Collapse JASS:
function Trig_Untitled_Trigger_002_Actions takes nothing returns nothing
    local group g = CreateGroup()
    local group Final = CreateGroup()
    local unit CurrentUnit
    call GroupEnumUnitsInRangeOfLoc(g, udg_TempPoint, 550., null)
    loop
        set CurrentUnit = FirstOfGroup(g)
        exitwhen CurrentUnit == null
        if(IsPlayerEnemy(GetOwningPlayer(udg_DUnit), GetOwningPlayer(CurrentUnit))) and ((GetWidgetLife(CurrentUnit) <= 0) == false) then
            call GroupAddUnit(Final, CurrentUnit)
        endif
        call GroupRemoveUnit(g, CurrentUnit)
    endloop
    call DestroyGroup(g)
    set g = null
    set udg_WoVGroup_AffectedUnits = Final
endfunction
07-04-2006, 08:26 AM#5
iNfraNe
Actually, ithink using a filter is better, since
Quote:
Originally Posted by Known JASS bugs
GroupEnumUnitsInRectCounted and GroupEnumUnitsInRangeCounted
Those two natives seems to show irregular behaviour when used on large numbers of units.
And ithink with a filter that problem would be fixed. Filter is also probably faster than ifs.
07-04-2006, 08:32 AM#6
Captain Griffen
Quote:
Filter is also probably faster than ifs.

On the basis that a filter adds the overhead of a function, also uses GetFilterUnit(), which is slower than a local variable (I think)?

Any time difference is negligable, but the main advantage of putting it into a loop is so you can still use local variables from within the function, while the main disadvantage is that it empties the group (may sometimes not be wanted).
07-04-2006, 08:37 AM#7
iNfraNe
I think it depends on the numer of units not matching the condition. If there is a lot filter will probably be faster.

But ye, the advantage is use of locals, but seeing those arent needed here... I'd say filter is just fine.
07-04-2006, 10:30 AM#8
The)TideHunter(
Your critism's are wrong.
He asked how could he get rid of the other function.
I showed him how, i dident state that it was faster or anything.
Loops have alot more option than filters.
07-04-2006, 10:32 AM#9
StRoNgFoE_2000
Ok im starting to get this better. What I am trying to do is create a spell, which when casted, it casts a form of arial shackles on all units around it for 5 seconds, causing damage then stops. At first I created it in GUI, but I now converted it to JASS and am working on it from there. Reason is because when created with the GUI, the locals weren't working correctly, or I was doing it wrong, i don't know... But I like doing it in JASS better because I'm learning a ton from this. Anyway.. the only reason I needed locals is becasue if multiple players used it at once all the globals were overwritten... but im sure you all know about that already.

This is my trigger, and it doesn't work correctly.. yet.. it works 70% better than a few hours ago. It's messy, but bear in mind im still noob to JASS.

Collapse JASS:
function Trig_WoV takes nothing returns nothing

//THIS IS WHERE I SET THE LOCAL VARIABLES
    local integer localinteger
    local location temppoint
    local effect drageffect
    local unit dragunit
    local unit lastunit
    local unit localunit
    local group affectedunits = CreateGroup()
    local group casters = CreateGroup()
    local group shackletrack = CreateGroup()
    local group localgroup = CreateGroup()

// START THE TRIGGER, PAUSE THE HERO, CREATE EFFECTS
    if (GetSpellAbilityId()=='A04N') then
    set dragunit=GetSpellAbilityUnit()
    call PauseUnitBJ(true, dragunit)
    call AddSpecialEffectTargetUnitBJ("origin", dragunit, "Abilities\\Spells\\Orc\\Voodoo\\VoodooAura.mdl")
    set drageffect = GetLastCreatedEffectBJ()
    call TriggerSleepAction(1.00)

// THIS IS TO GET THE UNITS FOR THE SPELL TO HINDER
    set temppoint = GetUnitLoc(dragunit)
    call GroupEnumUnitsInRangeOfLoc(localgroup, temppoint, 550.00, null)
    loop
       set localunit = FirstOfGroup(localgroup)
       exitwhen localunit == null
       if(IsPlayerEnemy(GetOwningPlayer(dragunit), GetOwningPlayer(localunit))) and ((GetWidgetLife(localunit) <= 0) == false) then
       call GroupAddUnit(shackletrack, localunit)
       endif
       call GroupRemoveUnit(localgroup, localunit)
    endloop
    call DestroyGroup(localgroup)
    set localgroup = null
    call GroupAddGroup(shackletrack, affectedunits)

// THIS PART SHACKLES THE UNITS
    set localinteger = 1
    loop
       exitwhen localinteger > CountUnitsInGroup(shackletrack)
       call CreateNUnitsAtLoc(1, 'h005', GetOwningPlayer(dragunit), temppoint, bj_UNIT_FACING )
       set lastunit = GetLastCreatedUnit()
       call GroupAddUnitSimple(lastunit, casters)
       call UnitAddAbilityBJ('A04O', lastunit)
       call SetUnitAbilityLevelSwapped('A04O', lastunit, GetUnitAbilityLevelSwapped('A04N', dragunit))
       call IssueTargetOrderBJ(lastunit, "magicleash", FirstOfGroup(shackletrack))
       call GroupRemoveUnit(shackletrack, FirstOfGroup(shackletrack))
       set localinteger = localinteger + 1
    endloop
    call RemoveLocation(temppoint)

// MAKE SURE ARENA IS NOT IN PROGRESS AND MAKE THE SPELL LAST 5 SECONDS(FOR THE FORUM, DISREGARD THIS PART)
    set localinteger = 1
    loop
       exitwhen localinteger > 5
       if (udg_ArenaBoolean) then
       call GroupAddGroup(casters, localgroup)
          loop
             set localunit = FirstOfGroup(localgroup)
             exitwhen localunit == null
             call RemoveUnit(localunit)
             call GroupRemoveUnit(localgroup, localunit)
          endloop
       call DestroyGroup(localgroup)
       call GroupRemoveGroup(casters, casters)
       call GroupRemoveGroup(shackletrack, shackletrack)
       call DestroyEffectBJ(drageffect)
       set dragunit = null
       return
       endif
       call TriggerSleepAction(1.00)
       set localinteger = localinteger + 1
    endloop

// ARENA IS NOT IN PROGRESS SO CONTINUE
    call GroupAddGroup(affectedunits, localgroup)
    loop
       set localunit = FirstOfGroup(localgroup)
       exitwhen localunit == null
       set temppoint = GetUnitLoc(localunit)
       call AddSpecialEffectLocBJ(temppoint, "Abilities\\Spells\\Other\\Incinerate\\FireLordDeathExplode.mdl")
       call DestroyEffectBJ(GetLastCreatedEffectBJ())
       call RemoveLocation(temppoint)
       call GroupRemoveUnit(localgroup, localunit)
    endloop
    call DestroyGroup(localgroup)
    call TriggerSleepAction(0.80)
    call GroupAddGroup(casters, localgroup)
    loop
       set localunit = FirstOfGroup(localgroup)
       exitwhen localunit == null
       call RemoveUnit(localunit)
       call GroupRemoveUnit(localgroup, localunit)
    endloop
    call DestroyGroup(localgroup)
    call GroupRemoveGroup(casters, casters)
    call GroupRemoveGroup(affectedunits, affectedunits)
    call DestroyEffectBJ(drageffect)
    if not(udg_ArenaBoolean) then
    call PauseUnitBJ(false, dragunit)
    endif
    set dragunit = null
    endif
endfunction

//================================================================

function InitTrig_WoV takes nothing returns nothing
    set gg_trg_WoV = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ(gg_trg_WoV, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddAction(gg_trg_WoV, function Trig_WoV)
endfunction

So far what happens is, the hero casts the spell, the dummy units are created to shackle, and the hero unpauses at the end. The bugs so far are.. not all units get shackled even though they are nearby, and the shackle lasts forever because the casters are not removed. The GUI was easier to follow but I'm gonna get this working, it will be my first trigger in total JASS (and I'm all excited).

Edit: Oh yeah, im looking for suggestions if i'm doing anything wrong :)
07-04-2006, 10:52 AM#10
The)TideHunter(
Ok, iv removed BJ's and optimized it a bit, lets look at it from there.

Collapse JASS:
function Trig_WoV takes nothing returns nothing
    local integer localinteger
    local location temppoint
    local effect drageffect
    local unit dragunit
    local unit lastunit
    local unit localunit
    local group affectedunits = CreateGroup()
    local group casters = CreateGroup()
    local group shackletrack = CreateGroup()
    local group localgroup = CreateGroup()
    local timer time = CreateTimer()
    if (GetSpellAbilityId()=='A04N') then
        set dragunit=GetSpellAbilityUnit()
        call PauseUnit(dragunit, true)
        set drageffect = AddSpecialEffectTarget("Abilities\\Spells\\Orc\\Voodoo\\VoodooAura.mdl", dragunit, "origin")
        call TimerStart(time, 1., false, null)
        loop
            exitwhen TimerGetRemaining(time) == .
            call TriggerSleepAction(1)
        endloop
        set temppoint = GetUnitLoc(dragunit)
        call GroupEnumUnitsInRangeOfLoc(localgroup, temppoint, 550, null)
        loop
            set localunit = FirstOfGroup(localgroup)
            exitwhen localunit == null
            if(IsPlayerEnemy(GetOwningPlayer(dragunit), GetOwningPlayer(localunit))) and ((GetWidgetLife(localunit) <= 0) == false) then
                call GroupAddUnit(shackletrack, localunit)
            endif
            call GroupRemoveUnit(localgroup, localunit)
        endloop
        call DestroyGroup(localgroup)
        call GroupAddGroup(shackletrack, affectedunits)
        set localinteger = 1
        loop
            set localunit = FirstOfGroup(shackletrack)
            exitwhen localunit == null
            set lastunit = CreateUnit(GetOwningPlayer(dragunit), 'h005', GetLocationX(temppoint), GetLocationY(temppoint), bj_UNIT_FACING )
            call GroupAddUnit(casters, lastunit)
            call UnitAddAbility(lastunit, 'A04O')
            call SetUnitAbilityLevel(lastunit, 'A04O', GetUnitAbilityLevel(dragunit, 'A04N'))
            call IssueTargetOrder(lastunit, "magicleash", localunit)
            call GroupRemoveUnit(shackletrack, localunit)
        endloop
        call RemoveLocation(temppoint)
        set localinteger = 1
        loop
            exitwhen localinteger > 5
            if (udg_ArenaBoolean) then
                call GroupAddGroup(casters, localgroup)
                loop
                    set localunit = FirstOfGroup(localgroup)
                    exitwhen localunit == null
                    call RemoveUnit(localunit)
                    call GroupRemoveUnit(localgroup, localunit)
                endloop
                call DestroyGroup(localgroup)
                call GroupRemoveGroup(casters, casters)
                call GroupRemoveGroup(shackletrack, shackletrack)
                call DestroyEffect(drageffect)
                return
            endif
            call TimerStart(time, 1, false, null)
            loop
                exitwhen TimerGetRemaining(time) == .
                call TriggerSleepAction(.1)
            endloop
            set localinteger = localinteger + 1
        endloop
        call GroupAddGroup(affectedunits, localgroup)
        loop
            set localunit = FirstOfGroup(localgroup)
            exitwhen localunit == null
            set temppoint = GetUnitLoc(localunit)
            call DestroyEffect(AddSpecialEffectLoc("Abilities\\Spells\\Other\\Incinerate\\FireLordDeathExplode.mdl", temppoint))
            call RemoveLocation(temppoint)
            call GroupRemoveUnit(localgroup, localunit)
        endloop
        call DestroyGroup(localgroup)
        call TimerStart(time, .8, false, null)
        loop
            exitwhen TimerGetRemaining(time) == .
            call TriggerSleepAction(.1)
        endloop
        call GroupAddGroup(casters, localgroup)
        loop
            set localunit = FirstOfGroup(localgroup)
            exitwhen localunit == null
            call RemoveUnit(localunit)
            call GroupRemoveUnit(localgroup, localunit)
        endloop
        if not(udg_ArenaBoolean) then
            call PauseUnit(dragunit, false)
        endif
    endif
    call RemoveLocation(temppoint)
    call DestroyEffect(drageffect)
    call DestroyTimer(time)
    call DestroyGroup(affectedunits)
    call DestroyGroup(casters)
    call DestroyGroup(shackletrack)
    call DestroyGroup(localgroup)
    set drageffect = null
    set temppoint = null
    set dragunit = null
    set lastunit = null
    set localunit = null
    set affectedunits = null
    set casters = null
    set shackletrack = null
    set localgroup = null
endfunction

EDIT: Watch out with your indents, it took me 10 minutes to align them correctly =).
Its usually 4 spaces per wrapper, a loop/if/function opens a wrapper, endloop/endif/endfunction closes a wrapper.
EDIT2: Removed some more BJ's and 1 LevelAbilitySwapped
EDIT3: Removed excess 0's after decimal point
EDIT4: Set handles to null, and removed setting null in the middle of the function.
EDIT5: Improved the first 2 loops alot, now im going to cut down on the amount of unit groups, and try and use less.
EDIT6: Removed normal TriggerSleepActions. Thats it from me for now, iv got a headache.
07-04-2006, 11:03 AM#11
iNfraNe
Quote:
Originally Posted by The)TideHunter(
Your critism's are wrong.
He asked how could he get rid of the other function.
I showed him how, i dident state that it was faster or anything.
Loops have alot more option than filters.
I'm not saying you did anything, you should stop getting on your nerves each time I state something. I just stated the negatives on using a loop, thats all.
07-04-2006, 11:25 AM#12
StRoNgFoE_2000
Please lets not argue

Anyway, as always thank you everyone for your help and input, and thank you tidehunter for your optimizations. I still face one problem though, for some reason in the part below (where it shackles all the units), it's only shackling half of the units.

Collapse JASS:
// THIS IS TO GET THE UNITS FOR THE SPELL TO HINDER
        set temppoint = GetUnitLoc(dragunit)
        call GroupEnumUnitsInRangeOfLoc(localgroup, temppoint, 550., null)
        loop
            set localunit = FirstOfGroup(localgroup)
            exitwhen localunit == null
            if(IsPlayerEnemy(GetOwningPlayer(dragunit), GetOwningPlayer(localunit))) and ((GetWidgetLife(localunit) <= 0) == false) then
                call GroupAddUnit(shackletrack, localunit)
            endif
            call GroupRemoveUnit(localgroup, localunit)
        endloop
        call DestroyGroup(localgroup)
        call GroupAddGroup(shackletrack, affectedunits)

// THIS PART SHACKLES THE UNITS
        set localinteger = 1
        loop
            exitwhen localinteger > CountUnitsInGroup(shackletrack)
            call CreateNUnitsAtLoc(1, 'h005', GetOwningPlayer(dragunit), temppoint, bj_UNIT_FACING )
            set lastunit = GetLastCreatedUnit()
            call GroupAddUnitSimple(lastunit, casters)
            call UnitAddAbility(lastunit, 'A04O')
            call SetUnitAbilityLevel(lastunit, 'A04O', GetUnitAbilityLevel(dragunit, 'A04N'))
            call IssueTargetOrder(lastunit, "magicleash", FirstOfGroup(shackletrack))
            call GroupRemoveUnit(shackletrack, FirstOfGroup(shackletrack))
            set localinteger = localinteger + 1
        endloop
        call RemoveLocation(temppoint)

For some reason there is a flaw in either getting the units around the hero, or when removing the units from the group. My guess is it's either getting half of the units within range in the first part or it's removing 2 at a time in the second part... but I can't seem to figure out where the flaw is...
07-04-2006, 11:31 AM#13
The)TideHunter(
It will get exactly half, yes.
Collapse JASS:
exitwhen localinteger > CountUnitsInGroup(shackletrack)
That is not good.
The group size is getting smaller every time.
AND the localinteger is getting bigger. It will meet right in the middle, not shackling half the units.
I fixed this in the optimized bit.

Use the CurrentUnit == null and the Set CurrentUnit = FirstOfGroup(shackletrack).
That method is flawless.

Im sorry Infrane, it seemed as though it was aimed at me.
Im paraniod since the thread where you flamed the shit out of me in general.
07-04-2006, 11:34 AM#14
StRoNgFoE_2000
Ahh didn't see the other optimizations right away, thanks. Im gonna give it a whirl.

Edit: Yay it works as intended, and I actually understand everything you did. I'm so happy right now! Thanks a ton, it would have probably taken me a couple more hours to accomplish this simple feat, and still not work the way it was supposed to.