HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Code for walking creeps along a path

07-12-2008, 01:01 PM#1
Bumster
So I've got 4 paths I want creeps to move along. I'm trying to code each step of the path for all 4 paths in a single trigger.

The first move after the units spawn works fine. But here's the second one:

Collapse JASS:
function Trig_Move_2_Conditions takes nothing returns boolean
    return (GetOwningPlayer(GetEnteringUnit()) == Player(11))
endfunction

function Trig_Move_2_Actions takes nothing returns nothing
    local integer i = 0
    
    loop
        exitwhen (RectContainsUnit(udg_Move1Regions[i], GetEnteringUnit()))
        set i = i + 1
        endif
    endloop
    
    call IssuePointOrderLoc(GetEnteringUnit(), "move", GetRandomLocInRect(udg_Move2Regions[i]))
endfunction

//===========================================================================
function InitTrig_Move_2 takes nothing returns nothing
    local integer i = 0
    set gg_trg_Move_2 = CreateTrigger()

    call TriggerRegisterEnterRectSimple(gg_trg_Move_2, gg_rct_Move_Point_1_Top_Left)
    call TriggerRegisterEnterRectSimple(gg_trg_Move_2, gg_rct_Move_Point_1_Top_Right)
    call TriggerRegisterEnterRectSimple(gg_trg_Move_2, gg_rct_Move_Point_1_Bottom_Left)
    call TriggerRegisterEnterRectSimple(gg_trg_Move_2, gg_rct_Move_Point_1_Bottom_Right)

    call TriggerAddCondition( gg_trg_Move_2, Condition( function Trig_Move_2_Conditions ) )
    call TriggerAddAction( gg_trg_Move_2, function Trig_Move_2_Actions )
endfunction

So it fires whenever a Brown unit moves into any of the four Move_1 regions. It then loops to check which region has been triggered and orders the unit to move on to the appropriate next region.

When I run it, I get hammered with "Hit op limit" messages and they don't move on.

I presume this means that the loop is running infinitely. My question is: WHY???

(udg_Move1Regions and udg_Move2Regions are properly initialised)
07-12-2008, 02:25 PM#2
Themerion
I think the event might fire before the unit actually counts as being in the region. You can do this instead:

Collapse JASS:
function Trig_Move_2_Actions takes nothing returns nothing
//.....
        exitwhen GetTriggeringRegion()==udg_MoveREGIONS[i]
// ....
endfunction

function InitTrig_Move_2 takes nothing returns nothing
// Some stuff...

// Now, we take control of the actual regions.
// What is called regions in the Terrain/Map Editor is actually Rects.

local region r = CreateRegion()
call RegionAddRect(r, gg_rct_Move_Point_1_Top_Left)
set udg_MoveREGIONS[1]=r
return TriggerRegisterEnterRegion(gg_trg_Move_1, r, null)

// We do this for each rect!

set r=CreateRegion()
call RegionAddRect(r, gg_rct_Move_Point_2_Top_Left)
set udg_MoveREGIONS[2]=r
return TriggerRegisterEnterRegion(gg_trg_Move_2, r, null)

//etc...
// Some other stuff...
endfunction

This assumes, ofc, that you can declare a global region (not rect) variable. If you are using JNGP (JassNewGenPack) you can just do this in an empty trigger:

Collapse JASS:
library MyGlobals
    globals
        region array udg_MoveREGIONS
    endglobals
endlibrary
07-12-2008, 04:02 PM#3
d07.RiV
Probably that
Why don't you create BJDebugMsg's in different points to see where it loops?

Also whats that endif doing there (in the loop)?
07-12-2008, 11:05 PM#4
Bumster
Themerion: Thanks heaps - but to save myself creating those Region arrays I just used this as the exit condition:
Collapse JASS:
exitwhen IsLocationInRegion(GetTriggeringRegion(), GetRectCenter(udg_Move1[i]))

d07.RiV: Yeah I figured out it was infinite looping using BJDebugMsgs. Whoops @ the endif - it's a relic from a previous attempt to fix it.
07-13-2008, 12:59 PM#5
Themerion
Clever!

Wouldn't it be better to store locations instead of rects then? Otherwise, you'd have to do like this to clean it up:

Collapse JASS:
local location loc

loop
  set loc=GetRectCenter(udg_Move1[i])
// ..exitwhen ......
  call RemoveLocation(loc)
endloop

  call RemoveLocation(loc)

set loc=null
07-13-2008, 01:35 PM#6
Bumster
Oooh very good point!
07-14-2008, 01:51 AM#7
Bumster
Wait I thought about this a bit more and I'm totally confused.

My understanding is that leaks are caused from two things: Creating objects and not destroying them, and failing to null out handle vars when you're done with them.

Why does
Collapse JASS:
GetRectCenter(udg_Move1[i])
cause a leak if it's not being assigned to a variable??
07-14-2008, 09:19 PM#8
T_s_e
GetRectCenter is a bj function that returns a location, hence, it leaks because the location is what the function returns. The GUI version of that is:
Trigger:
Region - Center of REGION
Leakless version would be:
Collapse JASS:
GetRectCenterX(udg_Move1[i])
GetRectCenterY(udg_Move1[i])
Since those functions return reals, not locations.
07-14-2008, 11:46 PM#9
Vexorian
Although GetRectCenter is a BJ it doesn't really leak (provided you handle the location it returns correctly), though it is easier/faster to use the GetRectCenterX/Y natives.
07-15-2008, 12:53 AM#10
Bumster
T_S_e: Thanks :) ... better go recheck all my triggers for leaks!

Vexorian: I take it you mean it wouldn't leak if you kept a handle to the location and then Destroy it afterwards? Also, you seem to be implying that natives never cause leaks - is this correct?
07-15-2008, 02:18 AM#11
Bumster
Okay I've thought about this a bit more... do you decide if it's a leak based on whether it's referring to something that already exists or making something new?

eg if you use GetKillingUnit() then you wouldn't wipe that because it's returning a handle to a real unit in the game. Whereas if you use GetRectCenter() it's had to create a whole new location so you have to destroy it.
07-15-2008, 10:09 AM#12
Themerion
That is correct.