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!
I have a problem with the number of current Structs instance at the same moment
I create 511 instance (with allocate) and after all that if I want to create an other one (with allocate) it seems that it gives me every time the 511th
n°510 => new
n°511 => new
n°512 => n°511 given
n°513 => n°511 given
n°514 => n°511 given
...
Its a default struct not the one that extends array
that struct has 39 attributes. each (2 arrays, 1 nested object)
is there a way to change that, or is there a number max of instance per stucts fixed by the game
By default, the max number of active instances for a single struct is 8190 (due to the old warcraft 3 array limit being 8192).
However, that max limit gets reduced when you use array attributes. Take this as an example:
JASS:
struct Example
real array x[100]
endstruct
Depending on the highest array size you put (e.g. 100), the limit gets reduced by that factor. If the highest array size you have is x, then you can calculate the max number of instances you can have with: floor((8190 - x) / x). So in this case, you would have a maximum of (8190 - 100) / 100 = 80 instances. This has to do with the fact that normal struct attributes are ultimately just array variables under the hood (the "instance" is the integer index), so to support array struct attributes, they have to divide the array into chunks.
Here are some other examples:
real array x[1] => 8189 instance limit
real array x[2] => 4094 instance limit
real array x[16] => 510 instance limit
I'm guessing one of your attributes has an array size of 15 or 16, so you're probably running into that limitation.
struct Example[10000] // the limit now becomes 99
real array x[100]
endstruct
But I don't really recommend this in your case given how complex your struct is. If you use that feature, then under the hood, it'll basically generate a copy of the struct and all its variables for each additional 8190 members you need. So if you chose to have a limit of say, 80000, then it would have to generate at least 10*39 = 390 variables to support your struct.
It's also not particularly ideal since you still have to deal with a fixed limit. Instead, I recommend using a library like Table:
Lua's tables make both Vexorian and my vJass Table libraries obsolete. However, for ease of converting vJass scripts to Lua, I've provided the below. Table = {} HandleTable = Table StringTable = Table --One map, no hashtables. Welcome to Lua Table version 1.1.1.0 --Made by Bribe, special...
www.hiveworkshop.com
Here is a sample of how you could tweak the example above to instead use a "Table" instance, and you can essentially get the same functionality:
JASS:
struct Example
Table x
static method create takes nothing returns thistype
local thistype this = thistype.allocate()
set x = Table.create()
return this
endmethod
endstruct
private function Init takes nothing returns nothing
local Example example = Example.create()
set example.x.real[0] = 3.14
set example.x.real[1] = 6
set example.x.real[2] = 9
call BJDebugMsg(R2S(example.x.real[0])) // prints 3.140
call BJDebugMsg(R2S(example.x.real[1])) // prints 6.000
call BJDebugMsg(R2S(example.x.real[2])) // prints 9.000
endfunction
That way, you can slap as many values as you want and you don't have to really worry about the code that gets generated under the hood (and you get to keep the limit at 8190 ).
Why use this over other Alloc? - This module generates the least code possible in comparison to both the default vJass allocator and all the other Alloc, and uses only one variable for the whole map - The default vJass allocator is not updated to the new JASS_MAX_ARRAY_SIZE Alloc.jlibrary...
yep! Structs references are actually just integers under-the-hood, so you can store them as you would a regular integer. Here is an example:
JASS:
globals
hashtable ht = InitHashtable()
endglobals
struct MyStruct
string name
endstruct
private function Init takes nothing returns nothing
local MyStruct a
local MyStruct b
set a = MyStruct.create()
set a.name = "Bob"
// Save the struct the same way you would an integer
call SaveInteger(ht, 0, 0, a)
// Load it the same way too
set b = LoadInteger(ht, 0, 0)
call BJDebugMsg(b.name) // prints Bob
endfunction
Or with Table:
JASS:
globals
Table t
endglobals
struct MyStruct
string name
endstruct
private function Init takes nothing returns nothing
local MyStruct a
local MyStruct b
set t = Table.create()
set a = MyStruct.create()
set a.name = "Bob"
// Store it in the table
set t.integer[0] = a
// Load it from the table
set b = t.integer[0]
call BJDebugMsg(b.name) // prints Bob
endfunction
Why use this over other Alloc? - This module generates the least code possible in comparison to both the default vJass allocator and all the other Alloc, and uses only one variable for the whole map - The default vJass allocator is not updated to the new JASS_MAX_ARRAY_SIZE Alloc.jlibrary...
good point--but just note that in order to use those custom allocators, you need to make your struct extends array, which prevents you from having array attributes (which he seems to have in this case).
I used that " local thistype po = thistype(num)" to create some struct, it works at some points allow me to create the good amount of struct but causes random bugs
what is the difference with a " local thistype po = thistype.allocate()"
I used that " local thistype po = thistype(num)" to create some struct, it works at some points allow me to create the good amount of struct but causes random bugs
what is the difference with a " local thistype po = thistype.allocate()"
Whenever you want to make a new instance of a struct, you should typically use thistype.allocate() or .create(). That way, vJASS will be able to keep track of which indices are "available" vs. which ones are currently being used. Then when you call thistype.deallocate() or .destroy(), it'll correctly mark those indices as available again.
Keep in mind that structs are just arrays:
JASS:
struct Example
real x
real y
endstruct
// under-the-hood, this is:
globals
// used for .allocate() and .deallocate() to keep track of which indices are free/used
constant integer si__Example=1
integer si__Example_F=0
integer si__Example_I=0
integer array si__Example_V
// the actual attributes
real array s__Example_x
real array s__Example_y
endglobals
And the struct "instance" is just an integer that serves as the index for that array.
So technically, using thistype(num) can "work" since you're just choosing a specific integer index to use for those arrays, but vJASS won't actually be aware that you're using that index. This can cause all sorts of bugs:
You need to make sure "num" is unique, otherwise you may end up overwriting data that is meant for a different struct instance.
If you call .create() or .allocate() for that struct elsewhere, it might end up choosing a number you already used--again, causing data to be unexpectedly overwritten.
So in your case, I recommend sticking with the usual allocators/deallocators!
That being said, there's still a place for using integers directly when you want to override the allocation/deallocation. For those cases, you'll typically mark the struct as extends array to disable the default allocator/deallocator. Then you can either add your own functions to generate and track indices used, or you can use indices directly. A common example is when you use a unit indexer (which just assigns every unit on the map a unique integer from 0 to 8191)--for those cases you might just end up using the IDs directly:
JASS:
struct Example extends array
real x
real y
endstruct
function TrackUnit takes unit u returns nothing
local Example e = GetUnitUserData(u)
set e.x = GetUnitX(u)
set e.y = GetUnitY(u)
endfunction
But in general, those are usually for more niche purposes.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.