• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[JASS] struct.create & ForGroup problem

Status
Not open for further replies.
Level 3
Joined
Feb 23, 2009
Messages
16
Hi,

I have got two problems with an "unit spawn system". On map init his system should simply pick all "spawnpoint" units on the map and save the coordinates of those.

Here's problem one (red marked): The system shall pick those units as explained, but it doesnt. With BJDebug messages I found out, that the function does not recognizes any unit of the type 'h002' (there are 3 of them on the map).
The strange thing is, as I counted the units with the DebugMsg he said, that there are "0" units of the type 'h002' but the ForGroup-Function runned three times. As I not counted the units with the DebugMsg the function does not run.

-> The first thing i thought was, that the delay, caused by the DebugMsg, was the reason for "it works" and "it works not", so i made some changes that the "GetSpawnPoints" function does not run in the Init. (yellow marked) But that was not the reason.

As it worked, with the DebugMsg, the function only went to "XYSET" for each unit of the type 'h002' (orange marked). So the mistake has to be in the blue marked area.

It would be nice when someone can tell me where the failure is and how to fix it. If my problem description is incomprehensible please tell me, then I try to explain it more detailed.

btw. I used the code-tags, because the Jass-tags doesnt allow color codes...

Code:
library unitspawnsys initializer init
    globals        
        private integer DATABASE
        private hashtable unitdatabase = InitHashtable()
        // _ Parent _
        // 0 = Wald
        // 
        // <parent> * 100 +1 bis <parent * 100 +25 = creeplevel
        
        // _ Child _
        // 0 = amount
        // 1 - [...] = creeptype
        
        private hashtable spawnpointunits = InitHashtable()
        // _Parent_
        // = UnitID
        // _Child_
        // 0 = spawnpoint
    endglobals
    
    private function unitdied takes nothing returns nothing
        local unit u = GetDyingUnit()
        local spawnpoint sp = LoadInteger(spawnpointunits, GetHandleId(u), 0)
        
        set sp.u = null
        call FlushChildHashtable(spawnpointunits, GetHandleId(u))
        call sp.respawn()
        
        set u = null
    endfunction
    
    private function GetAverageLevel takes nothing returns integer   
        local integer avrg
        local integer i
        local integer heroamount
        
        loop
            if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then
                set heroamount = heroamount + 1
                set avrg = avrg + GetHeroLevel(udg_Hero[i])
            endif
            
            exitwhen i >= 5
            set i = i + 1
        endloop
        
        return avrg
    endfunction
    
    private function respawnunit takes nothing returns nothing
        local spawnpoint sp = LoadInteger(spawnpointunits, GetHandleId(GetExpiredTimer()), 0)
        
        call FlushChildHashtable(spawnpointunits, GetHandleId(GetExpiredTimer()))
        
        call sp.addunit(CreateUnit(Player(7), LoadInteger(unitdatabase, (sp.database*100) + GetAverageLevel(), GetRandomInt(1, LoadInteger(unitdatabase, sp.database, 0))), sp.x, sp.y, bj_UNIT_FACING))
        
        call DestroyTimer(GetExpiredTimer())
    endfunction
    
    private function addspawnpoints takes nothing returns nothing
        local real x 
        local real y 
        local spawnpoint sp 
        
        call BJDebugMsg("EXED")
        
        set x = GetUnitX(GetEnumUnit())
        set y = GetUnitY(GetEnumUnit())
        [COLOR="DarkOrange"]call BJDebugMsg("XYSET")[/COLOR]
        [COLOR="Blue"]set sp = spawnpoint.create(x, y, DATABASE)[/COLOR]
        call BJDebugMsg("SPADD")
        call sp.addunit(CreateUnit(Player(7), LoadInteger(unitdatabase, (sp.database*100) + GetAverageLevel(), GetRandomInt(1, LoadInteger(unitdatabase, sp.database, 0))), sp.x, sp.y, bj_UNIT_FACING))
        call BJDebugMsg("CRTD")
        call RemoveUnit(GetEnumUnit())
        call BJDebugMsg("REMVD!")
    endfunction
    
    private function GetSpawnPoints takes nothing returns nothing
        set DATABASE = 0
        set bj_wantDestroyGroup = true
        
        [COLOR="Red"]call ForGroupBJ( GetUnitsOfTypeIdAll('h002'), function addspawnpoints)[/COLOR]
    endfunction

    private function init takes nothing returns nothing
        local trigger trg = CreateTrigger()
       [COLOR="Yellow"] local trigger t = CreateTrigger()[/COLOR]
        
      [COLOR="Yellow"]  //call GetSpawnPoints()[/COLOR]
        
[COLOR="Yellow"]        call TriggerRegisterTimerEvent(t, 0.20, false)
        call TriggerAddAction(t, function GetSpawnPoints)[/COLOR]
        call TriggerRegisterPlayerUnitEvent(trg, Player(7),EVENT_PLAYER_UNIT_DEATH, null)
        call TriggerAddAction(trg, function unitdied)
    endfunction
    
    struct spawnpoint
        static spawnpoint array all[200]
        static integer amount
        
        real x
        real y
        unit u
        integer database
        
        [COLOR="Blue"]static method create takes real x, real y, integer database returns spawnpoint
            local spawnpoint n = spawnpoint.allocate()
            
            set n.x = x
            set n.y = y
            set n.database = database
            
            set spawnpoint.all[amount] = n
            set amount = amount + 1
            
            return n
        endmethod[/COLOR]
        
        method addunit takes unit u returns nothing
            set .u = u
            
            call SaveInteger(spawnpointunits, GetHandleId(u), 0, this)
        endmethod
        
        method respawn takes nothing returns nothing
            local timer t = CreateTimer()
            
            call SaveInteger(spawnpointunits, GetHandleId(t), 0, this)
            call TimerStart(t, 50, false, function respawnunit)            
        endmethod
    endstruct
endlibrary

Highlighted
German description

Additional Information:
I am an noob using structs :O
Please dont tell me, that BJ's are bad, i know it. But i dont see a reason to "unbj" it, when i just copy the code, runned by the BJ, into my trigger...
 
Last edited:
Level 23
Joined
Nov 29, 2006
Messages
2,482
My guess would be that it result into some sort of crash, since you forgot to give "amount" any value (in your spawnpoint struct).

static integer amount = 0
should make it run properly.

See, otherwise it attempts to store the spawnpoint at an index which is undefined, and also amount = amount + 1 would be messed up in the same way.
 
Level 3
Joined
Feb 23, 2009
Messages
16
@Eccho thanks it works! Such a simple mistake... i'll never make it again :D

There is still the problem with the "ForGroup".
The Mistake has to be in the function "GetUnitsOfTypeIdAll('h002')".

Okay in the german thread the other problem got solved, thanks to eccho and Quillraven
 
Last edited:
JASS:
call SaveInteger(hash, this * 2 + 0, this.prev * 4 + 0, integer) // 2x0x4x0
call SaveInteger(hash, this * 2 + 1, this.prev * 4 + 0, integer) // 2x1x4x0
call SaveInteger(hash, this * 2 + 1, this.prev * 4 + 1, integer) // 2x1x4x1
call SaveInteger(hash, this * 2 + 0, this.prev * 4 + 1, integer) // 2x0x4x1

It's rough. I have nothing physical to work with, because I can't think of any scenario that could require more than three dimensions.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
From what I see, hashtables are as four dimensional as integers are two dimensional. I wouldn't really claim that all four dimensions are fully functional, since you hinder the limits of each of the dimensions with every additional dimension.
 
Status
Not open for further replies.
Top