Wc3C.net (http://www.wc3c.net/forums.php)
-   Triggers & Scripts (http://www.wc3c.net/forumdisplay.php?f=8)
-   -   Known bugs in JASS (http://www.wc3c.net/showthread.php?t=80693)

Blade.dk 02-21-2006 07:58 PM

Known bugs in JASS
This thread is meant to be a list of all the bugs we know in Jass. Both bugs in Blizzard's parser, and serious bug in the natives are listed here, but bugs in specific Blizzard.j or user-created functions will not be listed here. General Warcraft 3 bugs is not welcome either.
NOTE: This list is created for Jass as it is in Warcraft 3 - The Frozen Throne, version 1.20 (the newest).

This thread is made to help people, and to aviod the forums to be filled with the same questions. It contains brief descriptions of the bugs, and links to threads where you can read more about the bugs, eventual solutions or tutorials concerning the bugs. If any tool capable of solving the bugs exists, a link to it will be here aswell (ALWAYS read the Read Me file before using a tool).
If you find that something is missing, post it here or send me a PM and I'll add it.

General bugs

Crashes because of forgotten endif's and endloop's
When saving a map, with unended loops or if statements, the World Editor (WE) will crash.

When this happens, or the editor crashes for other reasons while saving, you can always find the script in the <mapname>Temp folder in the same location you saved the map to. You can then use the File->Import Triggers option in the trigger editor and import the triggers from the other map. NOTE: This often caused problems with some generated globals that needs to be recreated.

I recommend JassCraft:

Invalid integers cause crashes when saving
Invalid integer values, for example rawcodes, can cause a crash upon saving the map in the WE. 'ÆØpo' would for example cause a crash a neither 'Æ' nor 'Ø' is an accepted value.

Use of single backslashes in filenames causes crashes when saving
Whenever you have a string you want to contain a \ use \\ instead, as a single backslash is used for control. Only one of the two will actually be a part of the string.

Functions that should return something but doesn't do it
If you have a function that should returns something but doesn't it causes crashes when saving.

Errors are moved to lines below
WE can't recognize some bugs, and therefore it's parser may say that the bug is in a line below the line where it really is. There is no solution for this problem, but it gives you compile errors and the line where the error is located, according to the WE, is un-bugged, you should check the lines over it. This bug often appear when you, for example, spells endfunction wrong.

String character limit
Strings containing more than 860 characters will cause a crash, when saving the map. The solution to this bug, is simply to use concatenation.
Read more

The return bug
This is a bug, even though it's extremely useful. WE's/Warcraft 3's parser only checks if the last type returned from a function are correct, so you can convert, for example, a handle into an integer by using this simple, yet legendary, function:

Collapse JASS:
function H2I takes handle h returns integer
    return h
    return 0

This bug is a bless more than a bug, as it allows you to store certain types in other variables, giving you a lot more freedom.
Read more
Tutorial: Using the Local Handle Variables functions
The ”Setting variables to null when using the return bug”-bug

In very rare situations, setting a variable (most often a timer) which content’s you use with the return bug can cause problems. It seems like it sometimes resets the object’s handle id.
There’s multiple solutions to this:
  1. Don’t set the variable to null. This is the easiest solution, but it will cause (very minor) memory leaks.
  2. Use another function that takes a timer (or whatever other type you have the problem with) value. You can pass the value null to that function, and simple use the parameter as variable, as it does not need to be set to null. Example:
    Collapse JASS:
    function X2 takes timer t returns nothing
        call DoSomethingWith(t)
        call DoSomethingElseWith(t)
    function X takes nothing returns nothing
        call X2(GetExpiredTimer())
    call TimerStart(yourTimer, duration, periodic, function X)
  3. Lastly, you can temporarily use a global variable to store the object in.

I recommend you to not care about this bug too much unless you have it in your script.

Variables sharing the same name overwrite each other
This bug is really annoying, you are able to have, for example, a parameter with one name, and a local variable with the same name. The last-declared of variables with the same name, in this case the local, is the only one who will keep it's reference, making your script act totally weird if you aren't aware of this.
This bug can, however, also be used to make GUI multiinstanceable (to a certain grade only).
Read more

Limit on the custom script section for users of specific operating systems
The custom script section appears to have a limit when using some operating systems. It happens on computers with Windows 98 and ME, and maybe other versions too.
The solution to this bug, is to create a trigger that is compiled before all other triggers, so you can write your functions there. There is a tool that does this, and therefore also allows people using Reign of Chaos to have a place where they can easily write functions used by multiple triggers:
First Trigger Adder

Windows XP with Service Pack 2 vs. Windows XP without SP2
Yes, this is true and probably the dumbest bug ever.
Several things acts different on computers with SP2 than on computers without. We have no good explanation for this. Thing is that this is so bad that it even can cause desyncs in some cases.

Single %'s are removed from the custom script section when saving the map
Single % signs are removed from the custom script section when a map is saved, and it ONLY happens in the custom script section. To fix this, use double %% instead, then it will only remove the first one.

Sounds do not play first time
First time you try to play a certain sound in Jass, it won’t play. It will be “loaded”, and play correctly the next times.

Native-related bugs

IsUnitType boolexpr bug
IsUnitType(whichUnit, whichUnitType) causes bugs when used alone in boolexpr's and not compared to true or false.
Read more

Gamecache limit
There is a maximum (bugged) limit of 256 for how many game cache you can have, this can cause problems making your maps act weird when you have 256 game cache stored in your profile's campaigns.w3v file.
Read more

Destroyed timers can expire
It appears that when a timer is destroyed in another function than the expiration function, it may still expire. The solution to this problem, is simply to pause the timer before destroying it.
Read more

SetUnitX and SetUnitY crashes
Using the SetUnitX/SetUnitY natives causes crashes if the given coordinate is outside the playable map area (the initial value of the bj_mapInitialPlayableArea rect global). The solution to this problem is simply to check that the coordinate isn't outside that rect before calling the native.

Creating units outside the playable map area causes crashes
Creating a unit outside the playable map area (the initial value of the bj_mapInitialPlayableArea rect global) cayses crashes. The solution to this problem is simply to check that the given coordinates aren't outside that rect before calling the native.

RestoreUnit ignores type protection
The RestoreUnit native seems to ignore the 'type protection' for the returned units, and can therefore cause crashes when used incorrect (with typecasting).
Read more

GroupEnumUnitsInRectCounted and GroupEnumUnitsInRangeCounted
Those two natives seems to show irregular behaviour when used on large numbers of units.

Using ForForce inside ForForce callbacks causes problems
Using ForForce inside a ForForce callback function, seems to set the call back function executed by the first ForForce call to the function of the second call. Example:

Collapse JASS:
 function X3 takes nothing returns nothing
    call BJDebugMsg("2")

function X2 takes nothing returns nothing
    call BJDebugMsg("1")
    call ForForce(udg_f, function X3)
    call BJDebugMsg("3")

function X1 takes nothing returns nothing
    call ForceAddPlayer(udg_f, Player(0))
    call ForceAddPlayer(udg_f, Player(1))
    call ForForce(udg_f, function X2)

This should display the text 1, 2, 2, 3, 1, 2, 2, 3, but it displays the text 1, 2, 2, 3, 2.

GetExpiredTimer() crashes
GetExpiredTimer can cause nasty crashes in some situations where there is no expired timer.
If the “A unit dies” event makes a trigger fire, and the trigger calls GetExpiredTimer(), the game will crash IF the dying unit is owned by a computer player. If it is owned by a human player, the game won’t crash.
Read more

Blade.dk 06-11-2006 07:43 PM

The list has been updated.
The ExecuteFunc limit seems to not exist, but be caused by something else (unfindable) in a test map.
The ForForce, sound and GetExpiredTimer problems have been added.

Some other small fixes, and better ellaboration on some points.

If you find another bug, don't forget to report it :).

Thanks to everybody who has contributed to this thread.

Vexorian 06-11-2006 09:15 PM

If your test map used comments or whitespace to separate the call and the ExecuteFunc then it most likelly wouldn't work, cause wc3 does seem to compile the script into a more compact bytecode before executing it , tried adding a bunch of functions instead?

Blade.dk 06-11-2006 09:32 PM

Problem was that it was a huge map made that wasn't made to be a test map, so it was functions everywhere.

Weird thing is that there was absolutely nothing else that would have sense to stop it, but still something stopped it.. Deleting some of the triggers made it work and nothing in those triggers should be able to affect it.

PipeDream 06-13-2006 10:01 PM


cause wc3 does seem to compile the script into a more compact bytecode before executing it
I am pretty certain that it doesn't compile the script. I've watched in a loop an index from the start of the loop count through each character including whitespace. It seems likely to me that that is how the interpreter hops back to the start of the loop when it hits endloop. However it does do something since the code is not in memory as plaintext which must be what you've noticed. That number might just be a convenient way to uniquely name leafs.
That was completely wrong.

The_AwaKening 08-11-2006 02:16 AM

Either I'm not understanding the bug, or this one is fixed.


I'm using like this and it works just fine:
Collapse JASS:
function UnitTypeBool takes nothing returns boolean
    return IsUnitType(GetFilterUnit(),UNIT_TYPE_HERO)

function TestUnitType takes nothing returns nothing
 local boolexpr b = Condition(function UnitTypeBool)
 local group g = CreateGroup()
 local unit u
    call GroupEnumUnitsOfPlayer(g,GetTriggerPlayer(),b)
    set u=FirstOfGroup(g)
    call DisplayTextToPlayer(GetTriggerPlayer(),0,0,GetUnitName(u))
    call DestroyGroup(g)
    call DestroyBoolExpr(b)
 set u=null
 set g=null
 set b=null
Displays the name of one of my hero's just fine. I checked as well with multiple heros, and it's not taking any other of my units.

Vexorian 08-11-2006 03:29 AM

It happens with UNIT_TYPE_STRUCTURE or UNIT_TYPE_PEON , don't quite remember. Always worked fine with UNIT_TYPE_HERO

Blade.dk 08-11-2006 06:26 PM

There is a read more link for a reason. Read the thread it links to.

PandaMine 09-01-2006 01:44 AM

There is another JASS bug (which is actually more a data type bug then a jass one) which is subtracting 2 reals that are extremely close to eachother (but not the same) will returns a real that is jibberish rounded to 31 zeroes. Here is the post of the bug

This bug is extremely rare and unlikey to happen in most situations, but if your dealing with co-ordinates, map grid and vectors it can be propable that you will get this error (and in some cases certain) as can be seen in the post

peq 04-26-2007 12:00 AM

Collapse JASS:
    private multiboard board = CreateMultiboard()

This will crash Warcraft before starting the map. Took me 2 hours to find that error :( but i am not quite sure if it´s a bug.

Vexorian 04-26-2007 02:08 PM

yeah, a lot of handles can't be instanciated from globals block, I noticed this when making the optimizer.

Armentia 08-03-2007 03:18 PM

I dunno if it's good enough for your thread, but if you use SetUnitX and/or SetUnitY on a unit that has no movement, the units model stays stationary, while it moves... the selection circle of a unit.

cohadar 08-12-2007 05:35 PM


Originally Posted by Blade.dk
GroupEnumUnitsInRectCounted and GroupEnumUnitsInRangeCounted
Those two natives seems to show irregular behaviour when used on large numbers of units.


None of these functions works,
I ask for 3 units from a region and I always get all of them

Counted function are bugged.

Use normal GetEnumUnit functions + GetRandomSubGroup

darkwulfv 08-12-2007 06:44 PM

I found this. Apparently, using UnitDamagePoint(...) will desync any player using a Mac. It sounds really stupid and random, but I use it in my map, and any time it was used, the same player (who was on a mac) crashed out. Every time. And nobody else did. Maybe it was his computer, but it seems terribly weird and random, and may need to be looked into (probably by Pyro or Tide-Arc, since they're our resident Mac users.)

cohadar 08-25-2007 02:06 PM

This is not really a bug but people might consider it one.


Or any other group order will fail if there is more than 200 (approximately)
units in a group that you are ordering.

It will fail in the sense that it will order only first 200 or so units
and the rest will be ignored.

I believe this happens because it hits operation limit.

Solution would be to use ForGruop with waits every 200 units or something.


and here is the solution, it works flawlesly.
Collapse JASS:
function GroupOrderer takes group g, integer order , real x, real y returns nothing
    local integer i = 0
    local unit u
        exitwhen false
        set u = FirstOfGroup(g)
        if u == null then
            exitwhen true
        call GroupRemoveUnit(g, u)
        call IssuePointOrderById(u, order, x, y)
        set i = i + 1
        if i >=100 then 
            call TriggerSleepAction(0.0)
            set i = 0

you call it like this:
Collapse JASS:
    call GroupOrderer.execute(gw, ATTACK, WestExitX, WestExitY)

Note that we use execute so this will create a new thread so waits in GroupOrderer will not affect main trigger.


I am sorry I posted a solution that is specific to my map,
general solution should not remove units from a group, here it is:

Collapse JASS:
    integer orderEnum
    real xEnum
    real yEnum
    integer iEnum

function GroupOrdererEnum takes nothing returns nothing
    call IssuePointOrderById(GetEnumUnit(), orderEnum, xEnum, yEnum)
    if iEnum > 100 then
        call TriggerSleepAction(0.0)
        set iEnum = 0

function GroupOrderer takes group g, integer order , real x, real y returns nothing
    set orderEnum = order
    set xEnum = x
    set yEnum = y
    set iEnum = 0
    call ForGroup(g, function GroupOrdererEnum)

NOTE: this code has been tested by ordering 2 large groups of units,
one ordered by this code and other ordered by GroupPointOrderById()

GroupPointOrderById() failed miserably.

All times are GMT. The time now is 02:15 PM.

Powered by vBulletin (Copyright ©2000 - 2019, Jelsoft Enterprises Ltd).
Hosted by www.OICcam.com
IT Support and Services provided by Executive IT Services