HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Help with a spawning trigger

06-19-2014, 06:59 PM#1
SC_player
Hey guys, used to use this site a few years ago when working on wc3 maps. I decided to start one up again and i need help with this spawn trigger.
function that gets all buildings.
Collapse JASS:
function spawn takes nothing returns nothing
    //Group of spawn buildings.
    local group spawners 
    //Iterator
    local integer i=0
    loop
        exitwhen i>1
        set spawners = CreateGroup()
        set spawners=GetUnitsOfPlayerAndTypeId(currentEnemies[i], 'h01Y')
        call ForGroup(spawners, function spawnFunc)
        call DestroyGroup(spawners)
        set spawners = null
        set i=i+1
    endloop
endfunction
This function spawns the units.
Collapse JASS:
function spawnFunc takes nothing returns nothing
    if IsUnitAliveBJ(GetEnumUnit()) then
        call PlaceRandomUnit(spawnPool, GetOwningPlayer(GetEnumUnit()), GetUnitX(GetEnumUnit()), GetUnitY(GetEnumUnit()), 
    endif
endfunction
for now i am working on having each spawner spawning a random unit from a unitpool with only one unit in it every 15 seconds. later, i want different units to have different weights that change over time to increase or decrease the prevalence of units. I also will have different buildings which will spawn different types later but for now this is what im working on. Any help finding the reason this isnt working would be much appreciated.
06-19-2014, 10:45 PM#2
Anitarf
I don't see where you define the spawnPool variable and the currentEnemies array, so maybe the problem lies there. Looking at the code you posted, I don't see any functional errors.
06-20-2014, 02:28 AM#3
SC_player
They are globals
Collapse JASS:
globals
    //To hold spawned units, to be filled later.
    unitpool spawnPool = CreateUnitPool()
    //Keep track of players and units.
    player array currentPlayers
    integer totalPlayers
    player array currentEnemies
    unit array currentSpawnUnits
    //Income per building, the unit types of the buildings, and each players income.
    integer array incAmountPer
    integer array incBuildings
    integer array playerInc
    //Timers
    timer gameTimer
    timerdialog timeWindow
    //Counter for game time counter that counts up.
    real counter=0
    //Leaderboard variable
    leaderboard scoreBoard
endglobals
Edit:changed it so that it didn't need to put two different players into the same group, still doesnt work... im guessing its a problem with unitpools, so heres where i add the unit in
Collapse JASS:
function gametimer takes nothing returns nothing
    local integer i=0
    set gameTimer=CreateTimer()
    set timeWindow=CreateTimerDialog(gameTimer)
    call TimerDialogSetTitle(timeWindow, "Game Time")
    call TimerDialogDisplay(timeWindow, true)
    loop
        exitwhen i==totalPlayers
        call SetCameraFieldForPlayer( currentPlayers[i], CAMERA_FIELD_TARGET_DISTANCE, 2000.00, 0)
    endloop
    //Add starting unit.
    call UnitPoolAddUnitType(spawnPool, 'o000', 100.00)
endfunction
06-20-2014, 10:08 PM#4
Anitarf
Try replacing the PlaceRandomUnit with CreateUnit, it's the quickest way to confirm if the problem is in the unit pool.
06-21-2014, 12:07 AM#5
SC_player
it worked somewhat but what does that mean? what am i doing wrong with unitpools?
06-21-2014, 07:19 AM#6
Anitarf
Ah, I see the error now. The gametimer function has an infinite loop so it never reaches the point where it sets up the unit pool.

By the way, GetUnitsOfPlayerAndTypeId creates a new group, so you don't need to create one yourself first. The code you have now leaks unit groups. In general, it is more efficient to just reuse groups instead of creating and destroying them, like this:
Collapse JASS:
globals
    group spawners = CreateGroup()
endglobals

function spawn takes nothing returns nothing
    local integer i=0
    loop
        exitwhen i>1
        set bj_groupEnumTypeId = 'h01Y'
        call GroupEnumUnitsOfPlayer(spawners, currentEnemies[i], filterGetUnitsOfPlayerAndTypeId)
        call ForGroup(spawners, function spawnFunc)
        set i=i+1
    endloop
endfunction
06-22-2014, 01:53 AM#7
SC_player
i dont see the infinite loop problem. also, i have determined that it is getting every spawning building, it just isnt spawning the units.

edit: i changed it how you told me to but instead of making it global could i just leave it local?
06-22-2014, 02:17 AM#8
Anitarf
Quote:
Originally Posted by SC_player
i dont see the infinite loop problem. also, i have determined that it is getting every spawning building, it just isnt spawning the units.
You're missing set i=i+1.

Quote:
edit: i changed it how you told me to but instead of making it global could i just leave it local?
You could, but then you'd need to create and destroy the group every time the function runs.
06-22-2014, 02:17 AM#9
SC_player
i see. memory leak aside, it still doesnt work...
06-22-2014, 02:30 AM#10
SC_player
ok i fixed it by deleting the old local. Thanks. Now on to moving them randomly everywhere.
06-28-2014, 07:24 AM#11
SC_player
Sorry for the triple post, but i have made considerable progress and am now into moving units. my movement trigger works fine but it starts to lag, i think because of memory leaks. Could someone help me find the ones im missing? i went through it and fixed as much as i could.
Collapse JASS:
function bullshit takes nothing returns nothing
endfunction
function spawnFunc takes nothing returns nothing
    local unit u
    if GetUnitState(GetEnumUnit(), UNIT_STATE_LIFE)<=0 then
        set u = PlaceRandomUnit(spawnPool, GetOwningPlayer(GetEnumUnit()), GetUnitX(GetEnumUnit()), GetUnitY(GetEnumUnit()), 0)
        call GroupAddUnit(currentSpawnUnits, u)
        set u = null
    endif
endfunction
function spawnCheck takes nothing returns boolean
    if counter>300 then
        return true
    else
        return false
   endif
endfunction
function move takes nothing returns nothing
    local real x
    local real y
    local group g = CreateGroup()
    local integer i = 0
    local integer u = 0
    loop
        exitwhen currentEnemies[i]==null
        set g=GetUnitsOfPlayerAll(currentEnemies[i])
        set bj_wantDestroyGroup = true
        set u=u+CountUnitsInGroup(g)
        set g=null
        set i=i+1
    endloop
//    call DisplayTextToForce(GetForceOfPlayer(Player(0)), I2S(u))
    if GetUnitCurrentOrder(GetEnumUnit())== String2OrderIdBJ("none") then
        if u>500 and counter-I2R(R2I(counter/3))*3==0 then
//            call DisplayTextToForce(GetForceOfPlayer(Player(0)), "smartmove")
            set g=CreateGroup()
            set g=GetUnitsOfPlayerAll(currentPlayers[GetRandomInt(0, totalPlayers)])
            call IssuePointOrder(GetEnumUnit(), "attack", GetUnitX(FirstOfGroup(g)), GetUnitY(FirstOfGroup(g)))
            call DestroyGroup(g)
            set g = null
        else
            set g=CreateGroup()

            set x=GetRandomReal(GetRectMinX(bj_mapInitialPlayableArea), GetRectMaxX(bj_mapInitialPlayableArea))
            set y=GetRandomReal(GetRectMinY(bj_mapInitialPlayableArea), GetRectMaxY(bj_mapInitialPlayableArea))
            if(y< -8460) and (x< -1770) then
                call move()
            endif
            call IssuePointOrder(GetEnumUnit(), "attack", x, y)
        endif
    endif
endfunction
function income takes nothing returns nothing
    //First iterator, each number represents a player.
    local integer i = 0
    //Second iterator, each number represents an income building.
    local integer a = 0
    //Current selection of buildings we are looking at.
    local group inc = CreateGroup()
    //For each player, find all of each income building, save the amount, add income per amount of buildings, and clean the group.
    loop
        exitwhen i>totalPlayers
        set playerInc[i] = 0
        loop
            exitwhen a>10
            set inc = GetUnitsOfPlayerAndTypeId(currentPlayers[i], incBuildings[a])
            set playerInc[i] = playerInc[i]+incAmountPer[a]*CountUnitsInGroup(inc)
            call DestroyGroup(inc)
            set inc = null
            set a=a+1
        endloop
        call SetPlayerState(currentPlayers[i], PLAYER_STATE_RESOURCE_GOLD, (GetPlayerState(currentPlayers[i], PLAYER_STATE_RESOURCE_GOLD)+playerInc[i]))
        call LeaderboardSetItemValue(scoreBoard, i, playerInc[i])
        set i=i+1
    endloop
endfunction
function spawn takes nothing returns nothing
    local integer i=0
    local group spawners = CreateGroup()
    loop
        exitwhen i>1
        set bj_groupEnumTypeId = 'h01Y'
        call GroupEnumUnitsOfPlayer(spawners, currentEnemies[i], filterGetUnitsOfPlayerAndTypeId)
        call ForGroup(spawners, function spawnFunc)
        set i=i+1
    endloop
    call DestroyGroup(spawners)
    set spawners=null
endfunction
function seconds takes nothing returns nothing
    set counter=(counter+1)
    call TimerStart(gameTimer, counter, false, function bullshit)
    call PauseTimer(gameTimer)
    if ModuloReal(counter, 5)==0 then 
        call income()
    endif
    if GetBooleanAnd(ModuloReal(counter, 15)==0, spawnCheck()) then
        call spawn()
    endif
    call ForGroup(currentSpawnUnits, function move)
endfunction

//===========================================================================
function InitTrig_Seconds takes nothing returns nothing
    set gg_trg_Seconds = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic(gg_trg_Seconds, 1.00)
    call TriggerAddAction( gg_trg_Seconds, function seconds )
endfunction
The point of my move function is to tell random enemy units to attack to a player's base when their are too many units on the map. I'm not positive i implemented it correctly, as it starts lagging before i can tell.
06-30-2014, 08:17 PM#12
Anitarf
Like I said, GetUnitsOfPlayerAndTypeId creates a new group, so you do not need to create it yourself before calling the function like you do in the move function:
Collapse JASS:
            set g=CreateGroup()
            set g=GetUnitsOfPlayerAll(currentPlayers[GetRandomInt(0, totalPlayers)])
If you ever get to 500 units, I'd say this is your biggest leak. Actually, no, your biggest leak is in the "else" actions where you again create a group for no reason and don't destroy it. I'm not sure if that's what's causing the lag though, your trigger only runs once a second, while the memory leaks are bad they don't seem that bad. On the other hand, wc3 isn't very good at handling hundreds of units even on better computers, so it is possible that the units themselves along with the heavy computations you're doing for each of them is what's causing the lag and fixing the memory leak won't fix that. You need to improve your efficiency and if that isn't enough then cut down on the number of units you are generating.

Also, whenever you declare a local group variable, you seem to automatically initialize it by creating a group, even though that's not needed because later when you use the variable you create the group again.


This part:
Collapse JASS:
            if(y< -8460) and (x< -1770) then
                call move()
            endif
This is just my guess, you're trying to make units attack to a random point anywhere in a region except one corner, so if the random coordinates are in that corner you repeat the function again. That's a very crude way of doing it, but more important than that if you're going to do it this way you need to terminate the original function afterwards, like this:
Collapse JASS:
            if(y< -8460) and (x< -1770) then
                call move()
                return
            endif

Parts of the code are unclear to me so I can't offer any further suggestions, if you could explain a bit more how you want the system to behave I can write you some more efficient code examples. There's a lot of room for improvement since you currently still seem to be heavily influenced by the structure of the GUI triggers.
07-01-2014, 01:55 AM#13
SC_player
That corner is an area that i plan to use later. If you like, i could just upload the map for you to look over. It is inspired by custom castle defense. Ill upload both. Got rid of a couple of those group leaks but i might have missed some.
Attached Files
File type: w3xCustom Castle Defense v3.0.1.w3x (881.8 KB)
File type: w3xDefense.w3x (158.2 KB)
Help with a spawning trigger - Wc3C.net