• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[vJASS] Function seems to just stop executing after a few lines

Status
Not open for further replies.
Level 2
Joined
May 24, 2019
Messages
21
Edit2:

Finally solved it, the global integer var hasn't been set to a value in the global vars section... I thought it would be 0 at default but apparently was wrong and this causes the whole code to stop working.

Edit:

So I'm building a TD and I've simply tried to periodically spawn creeps for a TD and make them run towards their goal. This didn't seem to work, so after I asked my original question below, I've investigated further myself and after hundreds of test iterations, I was able to isolate one of the code-breaking bugs, but I can't figure out in gods name what causes it.

The following code works and will spawn one creep per player every 2 seconds at a location and ordering him to move to a certain target location:

JASS:
scope CreepSpawnThirdTry initializer init

    private function spawn takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer i = 0
        local integer it = 0
        local integer inte = 0   
        local unit u

        loop
            exitwhen it == 3

            loop
                exitwhen i == 1
                set u = CreateUnit(nh, id_cw[0], cspxc[it], cspyc[it], 0)
                call IssuePointOrder(u,"move", vcx, vcy) 
                set inte = inte + 1 
                set i = i + 1
                set u = null
            endloop

            set i = 0
            set it = it + 1

        endloop


        set t = null

    endfunction


    private function spawncountdown takes nothing returns nothing
        local timer t = CreateTimer()
   
        call TimerStart(t,2,true,function spawn)

        set t = null

    endfunction


    private function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterTimerEventSingle(t,10)
        call TriggerAddAction( t, function spawncountdown)
        set t = null
    endfunction

endscope

When trying to use a global integer variable called "wc" (for wavecount") in the first function, nothing will work. For example if I want to set a local integer var to the value of wc, I'll use the following line:

local integer test123 = wc​

And with the following code (with only this line added), no creeps will spawn:


JASS:
scope CreepSpawnThirdTry initializer init

    private function spawn takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer i = 0
        local integer it = 0
        local integer inte = 0   
        local unit u
        local integer test123 = wc
   

        loop
            exitwhen it == 3

            loop
                exitwhen i == 1
                set u = CreateUnit(nh, id_cw[0], cspxc[it], cspyc[it], 0)
                call IssuePointOrder(u,"move", vcx, vcy) 
                set inte = inte + 1 
                set i = i + 1
                set u = null
            endloop

            set i = 0
            set it = it + 1

        endloop


        set t = null

    endfunction


    private function spawncountdown takes nothing returns nothing
        local timer t = CreateTimer()
   
        call TimerStart(t,2,true,function spawn)
        set t = null

    endfunction


    private function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterTimerEventSingle(t,8)
        call TriggerAddAction( t, function spawncountdown)
        set t = null
    endfunction

endscope

What in hell's name is the issue here? Even if this declaration of the local variable won't work somehow, I still don't see any correlation between this line and the bug it causes. I've just tried renaming it, also doesn't work.

Here's the global variable section with the global integer variable called "wc" is being initiated.
Thanks for any help!

JASS:
globals

//hashtable
hashtable goldhash = InitHashtable() // gold coin hashtable
hashtable chash = InitHashtable() // creep hashtable

//players
player nh = Player(PLAYER_NEUTRAL_AGGRESSIVE) // nh = neutral hostile
player array p // all active players

//doodads
destructable ognw // outside gate north west
destructable ogn // outside gate north
destructable ogne // outside gate north east

//items
item array gc // gc = gold coin

//units
unit array gabfw // gate attacker before first wave

//unitgroup
group array lcfp // living creeps for player

//boolean
boolean array playerisactive

//reals
real array cspxf // cspxf = creep spawn player x-coordinate far
real array cspyf // cspyf = creep spawn player y-coordinate far
real array cspxc // cspxf = creep spawn player x-coordinate close
real array cspyc // cspyf = creep spawn player y-coordinate close

real vcx // vcx = vault center x-coordinate
real vcy // vcy = vault center y-coordinate

//integers
integer wc // wc = wavecount
integer ccpw // creep count per wave
integer array id_cw // id = unit type raw code, cw = creep wave
integer id_gc = 'I000' // id = item type, gc = gold coin
integer count_gc = 50 // counter, gc = gold coin

endglobals

scope GlobalVarsInit initializer init

private function init takes nothing returns nothing
local integer i = 0

// setting players

loop
set p[i] = Player(i)
set i = i + 1
exitwhen i > bj_MAX_PLAYERS
endloop

// setting gates

set ognw = gg_dest_LTg2_0742 //outside gate north west
set ogn = gg_dest_YTcx_0741 //outside gate north
set ogne = gg_dest_LTg4_0739 //outside gate north east


// setting coordinate vars
set cspxc[0] = -5254
set cspyc[0] = 6772
set cspxc[1] = -85
set cspyc[1] = 7612
set cspxc[2] = 4941
set cspyc[2] = 7179
set cspxf[0] = -10728
set cspyf[0] = 11140
set cspxf[1] = 46
set cspyf[1] = 11140
set cspxf[2] = 10855
set cspyf[2] = 11140
set vcx = 46 //vcx = vault center x-coordinate
set vcy = 38

//defining creeps for each wave
set id_cw[0] = 'n003'
set id_cw[1] = 'n000'

endfunction

endscope




Hi guys, I have a very weird problem and I don't even know how to google for it, so I would appreciate any help very much - a function I've written just seems to stop after a few lines of code without any reason to do so.
I've simply tried to periodically spawn creeps for a TD and make them run towards their goal.
The functions "init" and "prepareforspawn" seem to work fine, but no creeps will appear, so I tried some debug messages in the function "periodicspawn" and there's the strange issue:
When I test the code you see below, I get the following output:

i =
0
wc =
i =
0
wc =
(and so on)
So every DebugMsg below that seems to not be executed. I reckoned there might be a limit of consecutive DebugMsgs or something, so I turned the first three Msgs to comments by using //.
Now I didn't receive any output at all.
Then I tried to actually delete the first three DebugMsgs and then my output was:

ccpw =
When I deleted every line besides the last one, the output was

test
So my only logical assumption would be any kind of limit of calling the DebugMsg, but apparently there is none?

So my actual problem is the creep spawn loop not executing at all, but since I can't even work with the DebugMsgs at the moment to look for the bugs in my code, I'm pretty frustrated... I don't have any clue what the problem is here?



JASS:
scope CreepSpawnAfterTime initializer init

    private function periodicspawn takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer i = 0
        local unit u

        call BJDebugMsg("i =")
        call BJDebugMsg(I2S(i))
        call BJDebugMsg("wc =")
        call BJDebugMsg(I2S(wc))
        call BJDebugMsg("ccpw =")
        call BJDebugMsg(I2S(ccpw))
        call BJDebugMsg("test")

        set ccpw = ccpw + 1     //global variable, "creep count per wave"

        if ccpw < 31 then
 
            loop
                exitwhen i == 3
                    set u = CreateUnit(p[i], id_cw[wc], cspxc[i], cspyc[i], 0)
                    call GroupAddUnit(lcfp[i],u)
                    call IssuePointOrder(u,"move", vcx, vcy)

                    call BJDebugMsg("loop works")

                    set i = i + 1
                    set u = null      
            endloop

            set t = null

        else
        set t = null
        call BJDebugMsg("else works")
        call PauseTimer(t)
        call DestroyTimer(t)
        endif

    endfunction



    private function prepareforspawn takes nothing returns nothing
        local integer i = 0
        local timer t = CreateTimer()
        call TimerStart(t,2,true,function periodicspawn)
        set t = null
    endfunction

    private function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterTimerEventSingle(t,5)
        call TriggerAddAction( t, function prepareforspawn)
        set t = null
    endfunction

endscope


What's baffling me the most is that I'm having a pretty similar creep spawn event which happens seconds before and works just fine (but this one is non-periodical).
I'll also paste it in here just to show the actual spawning process as well as the global variables should work just fine:

JASS:
scope GateAttacker initializer init

    private function spawn takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer i = 0
        local integer it = 0
        local integer inte = 0
        local unit u
        local destructable array d

        call PauseTimer(t)
        call DestroyTimer(t)
        set d[0] = ognw
        set d[1] = ogn
        set d[2] = ogne


        loop
            exitwhen it == 3

            loop
                exitwhen i == 3
                set gabfw[inte] = CreateUnit(nh, id_cw[0], cspxc[it], cspyc[it], 0)
                call IssueTargetDestructableOrder( gabfw[inte], "attack", d[it] )
                set inte = inte + 1
                set i = i + 1
            endloop

            set i = 0
            set it = it + 1

        endloop

        set d[0] = null
        set d[1] = null
        set d[2] = null
        set t = null

    endfunction


    private function spawncountdown takes nothing returns nothing
        local timer t = CreateTimer()

        call TimerStart(t,0.1,false,function spawn)   //I work with a very short timer here for testing purposes, it will be a longer period in the future

        set t = null

    endfunction


    private function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterTimerEventSingle(t,2)
        call TriggerAddAction( t, function spawncountdown)
        set t = null
    endfunction

endscope


Also, here are my global vars if you need them for testing purposes:

JASS:
globals

//hashtable
hashtable goldhash = InitHashtable()            // gold coin hashtable
hashtable chash = InitHashtable()               // creep hashtable

//players
player nh = Player(PLAYER_NEUTRAL_AGGRESSIVE)   // nh = neutral hostile
player array p                                  // all active players

//doodads
destructable ognw                               // outside gate north west
destructable ogn                                // outside gate north
destructable ogne                               // outside gate north east

//items
item array gc                                   // gc = gold coin

//units
unit array gabfw                                // gate attacker before first wave

//unitgroup
group array lcfp                              // living creeps for player

//boolean
boolean array playerisactive

//reals
real array cspxf                                // cspxf = creep spawn player x-coordinate far
real array cspyf                                // cspyf = creep spawn player y-coordinate far
real array cspxc                                // cspxf = creep spawn player x-coordinate close
real array cspyc                                // cspyf = creep spawn player y-coordinate close

real vcx                                        // vcx = vault center x-coordinate
real vcy                                        // vcy = vault center y-coordinate

//integers
integer wc                                      // wc = wavecount
integer ccpw                                    // creep count per wave
integer array id_cw                             // id = unit type raw code, cw = creep wave
integer id_gc = 'I000'                          // id = item type, gc = gold coin
integer count_gc = 50                           // counter, gc = gold coin

endglobals

scope GlobalVarsInit initializer init

    private function init takes nothing returns nothing
    local integer i = 0

    // setting players

    loop
        set p[i] = Player(i)
        set i = i + 1
        exitwhen i > bj_MAX_PLAYERS
    endloop

    // setting gates

    set ognw = gg_dest_LTg2_0742           //outside gate north west
    set ogn = gg_dest_YTcx_0741            //outside gate north
    set ogne = gg_dest_LTg4_0739           //outside gate north east


    // setting coordinate vars
 
    set cspxc[0] = -5254
    set cspyc[0] = 6772
    set cspxc[1] = -85
    set cspyc[1] = 7612
    set cspxc[2] = 4941
    set cspyc[2] = 7179
 
    set cspxf[0] = -10728
    set cspyf[0] = 11140
    set cspxf[1] = 46
    set cspyf[1] = 11140
    set cspxf[2] = 10855
    set cspyf[2] = 11140
    set vcx = 46           //vcx = vault center x-coordinate
    set vcy = 38

    //defining creeps for each wave
    set id_cw[0] = 'n003'
    set id_cw[1] = 'n000'

    endfunction
 

endscope



 
Last edited:
Level 39
Joined
Feb 27, 2007
Messages
5,010
wc is, in fact, NOT properly initialized. It is declared but it is not given a value so it it’s not initialized. If you attempt to reference an uninitialized variable in a function that function will threadcrash and nothing after the line will happen. This does not apply to array variables, and any index can be referenced uninitialized without issue.
JASS:
globals
  integer wc
endglobals

function f takes nothing returns nothing
  call BJDebugMsg(I2S(wc)) //thread crash
  call BJDebugMsg(“this message is never shown”)
endfunction

//====

globals
  integer wc = 0
endglobals

function f takes nothing returns nothing
  call BJDebugMsg(I2S(wc)) //no thread crash
  call BJDebugMsg(“this message is shown!”)
endfunction
In general many (most? all?) natives (for example CreateGroup()) and any custom functions can not be used in variable declarations. You can assign simple values like true, false, 0, 157.224, “nothing”, null but for anything more complicated you must set it in an onInit function.
 
Level 2
Joined
May 24, 2019
Messages
21
wc is, in fact, NOT properly initialized. It is declared but it is not given a value so it it’s not initialized. If you attempt to reference an uninitialized variable in a function that function will threadcrash and nothing after the line will happen. This does not apply to array variables, and any index can be referenced uninitialized without issue.
JASS:
globals
  integer wc
endglobals

function f takes nothing returns nothing
  call BJDebugMsg(I2S(wc)) //thread crash
  call BJDebugMsg(“this message is never shown”)
endfunction

//====

globals
  integer wc = 0
endglobals

function f takes nothing returns nothing
  call BJDebugMsg(I2S(wc)) //no thread crash
  call BJDebugMsg(“this message is shown!”)
endfunction
In general many (most? all?) natives (for example CreateGroup()) and any custom functions can not be used in variable declarations. You can assign simple values like true, false, 0, 157.224, “nothing”, null but for anything more complicated you must set it in an onInit function.

I see, thanks for your explanation!
Thread can be closed.
 
Status
Not open for further replies.
Top