HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Create patrols for creeps?

03-27-2007, 06:03 PM#1
BattleBotv8.2
I want to make it so when the hero enters a region creeps are spawned within the area (Like you enter a swamp and they are created there). I'd like it so creep A patrols to points 1,2,3 while creep B patrols points 4,5,6,7.

Right now I'm making the map use different regions, like swamp, destroyed town, forest for the areas where the creeps patrol.

If I could make it so if a creep enters a region in this Region Variable Array I think I could figure it out, but I can't
03-28-2007, 05:24 AM#2
Pyrogasm
Well, here's a JASS solution that I whipped up, though I don't know if it'll work.

Detect your unit entering the region, create the units to patrol, add them to a group, pick a number of circuits, and run this function:
Collapse JASS:
function GroupPatrol4Rects takes group Group, rect Patrol1, rect Patrol2, rect Patrol3, rect Patrol4, integer Circuits returns nothing
    local group g = Group
    local group g2
    local unit u
    local rect array PatrolRect
    local region array PatrolRegion
    local boolean In = false
    local boolean In2 = false
    local integer i
    local integer Target = 1
    local integer CircuitNumber = 1
    local integer TargetTotal = 4
    local location l = GetRectCenter(Patrol1)
    local real x = GetLocationX(l)
    local real y = GetLocationY(l)

    call RemoveLocation(l)

    set PatrolRect[1] = Patrol1
    set PatrolRect[2] = Patrol2
    set PatrolRect[3] = Patrol3
    set PatrolRect[4] = Patrol4

    loop
        set i = i+1
        exitwhen i > 4
        set PatrolRegion[i] = CreateRegion()
        if PatrolRect[i] == null then
            set TargetTotal = TargetTotal-1
        else
            call RegionAddRect(PatrolRegion[i], PatrolRect[i])
        endif
    endloop

    set g2 = g
    loop
        set u = FirstOfGroup(g2)
        exitwhen u == null
        call IssuePointOrder(u, "attack", x, y)
        if IssuePointOrder(u, "attack", x, y) == false then
            call GroupRemoveUnit(g, u)
       endif
        call GroupRemoveUnit(g2, u)
    endloop
    call DestroyGroup(g2)

    loop
        if Circuits == 0 then
            exitwhen (CountUnitsInGroup(g) == 0)
        else
            exitwhen (CountUnitsInGroup(g) == 0) or (CircuitNumber > Circuits)
        endif
        loop
            exitwhen Target > TargetTotal
            loop
                exitwhen In2
                set g2 = g
                set l = GetRectCenter(PatrolRect[Target+1])
                set x = GetLocationX(l)
                set y = GetLocationY(l)
                call RemoveLocation(l)
                loop
                    set u = FirstOfGroup(g2)
                    exitwhen u == null or In
                    if GetUnitCurrentOrder(u) != 851983 then
                        call IssuePointOrder(u, "attack", x, y)
                    endif
                    set In = IsUnitInRegion(PatrolRegion[Target], u)
                    call GroupRemoveUnit(g2, u)
                endloop
                call DestroyGroup(g2)
                if In then
                    set In = false
                    set g2 = g
                    set l = GetRectCenter(PatrolRect[Target+1])
                    set x = GetLocationX(l)
                    set y = GetLocationY(l)
                    call RemoveLocation(l)
                    loop
                        set u = FirstOfGroup(g2)
                        exitwhen u == null
                        call IssuePointOrder(u, "attack", x, y)
                        call GroupRemoveUnit(g2, u)
                    endloop
                    call DestroyGroup(g2)
                    set In2 = true
                endif
                call PolledWait(0.25)
            endloop
            set In2 = false
            set Target = Target+1
        endloop
        set Target = 1
        set CircuitNumber = CircuitNumber+1
    endloop

    set i = 0
    loop
        set i = i+1
        exitwhen i > 4
        call RemoveRegion(PatrolRegion[i])
        set PatrolRect[i] = null
        set PatrolRegion[i] = null
    endloop

    call DestroyGroup(g)
    set g = null
    set g2 = null
    set u = null
    set l = null
endfunction
The 4th rect can be null.
03-28-2007, 03:53 PM#3
BattleBotv8.2
I'm just begining to learn jass so if you could go in more depth about what's what that would help alot.
03-29-2007, 03:25 AM#4
Pyrogasm
Sure, I can do that.

I also tested this, and it doesn't work. Once I get it working, I'll put comments in and upload the working version.
03-29-2007, 05:22 AM#5
Pyrogasm
Ok, so everything works fine except for the line(s) hilighted in red. I could use someone's advice for why it's not detecting that the unit is in the region.
Collapse JASS:
function GroupPatrol4Rects takes group Group, rect Patrol1, rect Patrol2, rect Patrol3, rect Patrol4, integer Circuits returns nothing
    local group g = Group
    local group g2
    local unit u
    local rect array PatrolRect
    local region array PatrolRegion
    local boolean In = false
    local boolean In2 = false
    local integer i = 0
    local integer Target = 0
    local integer CircuitNumber = 0
    local integer TargetTotal = 4
    local location l = GetRectCenter(Patrol1)
    local real x = GetLocationX(l)
    local real y = GetLocationY(l)

    call BJDebugMsg("Something Happened")
    call RemoveLocation(l)

    set PatrolRect[1] = Patrol1
    set PatrolRect[2] = Patrol2
    set PatrolRect[3] = Patrol3
    set PatrolRect[4] = Patrol4

    loop
        set i = i+1
        exitwhen i > 4
        set PatrolRegion[i] = CreateRegion()
        if PatrolRect[i] == null then
            set TargetTotal = TargetTotal-1
        else
            call RegionAddRect(PatrolRegion[i], PatrolRect[i])
        endif
    endloop

    call BJDebugMsg("TargetTotal: " + I2S(TargetTotal))

    set g2 = g
    loop
        set u = FirstOfGroup(g2)
        exitwhen u == null
        if IssuePointOrder(u, "attack", x, y) == false then
            call GroupRemoveUnit(g, u)
            call BJDebugMsg("Removed")
        endif
        call GroupRemoveUnit(g2, u)
    endloop
    call DestroyGroup(g2)
    call GroupPointOrder(g, "attack", x, y)

    loop
        set CircuitNumber = CircuitNumber+1
        call BJDebugMsg("CircuitNumber = " + I2S(CircuitNumber))
        exitwhen CircuitNumber > Circuits
        //if Circuits == 0 then
        //    exitwhen (CountUnitsInGroup(g) == 0)
        //else
        //    exitwhen (CountUnitsInGroup(g) == 0) or (CircuitNumber > Circuits)
        //endif
        loop
            set Target = Target+1
            call BJDebugMsg("Target = " + I2S(Target))
            exitwhen Target > TargetTotal
            loop
                exitwhen In2
                set g2 = g
                set l = GetRectCenter(PatrolRect[Target+1])
                set x = GetLocationX(l)
                set y = GetLocationY(l)
                call RemoveLocation(l)
                loop
                    set u = FirstOfGroup(g2)
                    exitwhen u == null or In
                    if GetUnitCurrentOrder(u) != 851983 then
                        call IssuePointOrder(u, "attack", x, y)
                        call BJDebugMsg("Backup Attack Order'd")
                    endif
                    set In = IsUnitInRegion(PatrolRegion[Target], u)
                    if In then
                        call BJDebugMsg("In region: yes")
                    else
                        call BJDebugMsg("In region: no")
                    endif
                    call GroupRemoveUnit(g2, u)
                endloop
                call DestroyGroup(g2)
                if In then
                    call BJDebugMsg("In == true")
                    set In = false
                    set l = GetRectCenter(PatrolRect[Target+1])
                    set x = GetLocationX(l)
                    set y = GetLocationY(l)
                    call RemoveLocation(l)
                    call GroupPointOrder(g, "attack", x, y)
                    set In2 = true
                endif
                call PolledWait(0.25)
                call BJDebugMsg("Target loop loop'd")
            endloop
            call BJDebugMsg("Target loop exited")
            set In2 = false
        endloop
        set Target = 1
    endloop

    set i = 0
    loop
        set i = i+1
        exitwhen i > 4
        call RemoveRegion(PatrolRegion[i])
        set PatrolRect[i] = null
        set PatrolRegion[i] = null
    endloop

    call DestroyGroup(g)
    set g = null
    set g2 = null
    set u = null
    set l = null
    call BJDebugMsg("Ended")
endfunction

Additionally, this should work for any number of regions as long as you change a few integers in the code, and/or put "null" as one of the rects. Would that actually work, the way I've set it up?

Lastly, there's this giant commented-out if statement:
Collapse JASS:
        //if Circuits == 0 then
        //    exitwhen (CountUnitsInGroup(g) == 0)
        //else
        //    exitwhen (CountUnitsInGroup(g) == 0) or (CircuitNumber > Circuits)
        //endif

I was attempting to get it to exit when the group was empty, but for some reason the CountUnitsInGroup(g) == 0 part was making it instantly exit. Why?
03-29-2007, 06:19 AM#6
wyrmlord
Just exit when FirstOfGroup(group) == null.

Also, you already destroyed the group you're trying to count the units in.

Group -> g -> g2 -> loop through group -> destroy g2
03-30-2007, 01:24 AM#7
Krysho
As wyrmlord has said, it seems you are destroying the unit group before it's being used in the attack order loop that checks regions. (think of it in handles) You're setting g2 to equal g, which is equal to the Group argument. They all point to the same group. Destroying it once means it should be destroyed for all, I believe. You'd probably want to do:
Collapse JASS:
local g2 = CreateGroup()
//...
call GroupAddGroup(g2, g) //(or just GroupAddGroup(g, Group))

Also, are regions really necessary here? There exists the JASS function "RectContainsUnit" function that returns a boolean.
Collapse JASS:
function RectContainsCoords takes rect r, real x, real y returns boolean
    return (GetRectMinX(r) <= x) and (x <= GetRectMaxX(r)) and (GetRectMinY(r) <= y) and (y <= GetRectMaxY(r))
endfunction
function RectContainsUnit takes rect r, unit whichUnit returns boolean
    return RectContainsCoords(r, GetUnitX(whichUnit), GetUnitY(whichUnit))
endfunction
Doesn't seem to leak at all.

Plus there are these two natives:
Collapse JASS:
native GetRectCenterX           takes rect whichRect returns real
native GetRectCenterY           takes rect whichRect returns real
03-30-2007, 01:41 AM#8
Pyrogasm
Yes! Thank you Krysho. I was looking for a "unit in rect" native, but nothing showed up on the ClanWENW website search. Oh well.


Are groups just funky like that in that if you set one to another and then destroy the second one, it will remove the first? Do other variables do this? I've never noticed that before, but I suppose it could be happening.

Thanks to both of you for your help! Rep'd!

BattleBotv8.2, I should be completed soon.
03-30-2007, 01:50 AM#9
Krysho
Since handles are just references to the real handle data, you'd be copying the reference to the new variable, not the actual data. Therefore, both variables will be pointing to the same data. If you were to destroy the group on one of the variables, it'd still be pointing to the destroyed group until you null the variable or change its value. However, the second variable would also be pointing to a destroyed group. Pretty sure it's the same for most things, and it is, in fact, the idea I use behind clean-up in one of my maps:

Trigger:
Set temploc = RawPoint
Set RawPoint = (RawPoint offset by (YardsLength x 5.00) towards 90.00 degrees)
Custom script: call RemoveLocation(udg_temploc)

Though I could've just saved the X and Y coordinates of the region and destroyed it without reusing it. Suffice to say I'd have done a lot of things differently now in my map that I started over two years ago.

Collapse JASS:
set l = GetRectCenter(PatrolRect[Target+1])
set x = GetLocationX(l)
set y = GetLocationY(l)
call RemoveLocation(l)
You can probably replace that with:
Collapse JASS:
set x = GetRectCenterX(PatrolRect[Target+1])
set y = GetRectCenterY(PatrolRect[Target+1])

Just since you didn't mention considering that part (two functions versus four).