• 🏆 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!

[Lua][vJass] New Table

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
From what I understood, problem occurs when there are multiple item tables declares, meaby even to the same unit type.

Problem may lie within: set unitTypeTable[ this.unitTypeId] = this since you are reassigning table index to be used on death event each time item table is declared for type T, meaning: with your currect create method, I can not have multiple tables for given unit type, like 'hpea'. Instead of allocating new instance you should have checked if such unitType table is already found and allocated. If so, just use recovered index instead.

Provide demo code with which you are testing your bugs, would help a lot.

B) there are many flaws within your code, like:
// where 'r' is random int from 1 to weight if r > weights[L1 - 1] and r < weights[L1] then what happens if we roll exactly 'border' number? (lets say 20 in your test map). There is no "=" operator within if statement, thus such item will never be found.
Searching and indexing could be improved a lot, however, this is not the case now.
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
From what I understood, problem occurs when there are multiple item tables declares, meaby even to the same unit type.

Problem may lie within: set unitTypeTable[ this.unitTypeId] = this since you are reassigning table index to be used on death event each time item table is declared for type T, meaning: with your currect create method, I can not have multiple tables for given unit type, like 'hpea'. Instead of allocating new instance you should have checked if such unitType table is already found and allocated. If so, just use recovered index instead.

Provide demo code with which you are testing your bugs, would help a lot.

There are no duplicates for unit type.

This is what I am using.
JASS:
function addToTable takes nothing returns nothing
    local ItemDropSystem data = ItemDropSystem.createForType( 'hpea')
    call data.addItem( 'afac', 20)
    call data.addItem( 'ratc', 20)
    call data.addItem( 'rat6', 20)
    call data.addItem( 'rat9', 20)
    call data.addItem( 'rst1', 100)
    
    set data = ItemDropSystem.createForType( 'hfoo')
    call data.addItem( 'rag1', 100)
endfunction

JASS:
        method addItem takes integer itemId, integer weight returns nothing
            set this.index = this.index + 1
            set this.ttlWeight = this.ttlWeight + weight
            set itemIdTable[this][index] = itemId
            call BJDebugMsg( " Struct instance = " + I2S( this) + " Item Id = " + I2S( itemIdTable[this][index]) + " = " + I2S( itemId))
            set itemDropTable[this][itemId] = this.ttlWeight
            call BJDebugMsg( " Struct instance = " + I2S( this) + " Item weight " + I2S( itemDropTable[this][itemId]) + " = " + I2S( this.ttlWeight))
        endmethod
        
        private method dropItem takes real x, real y returns boolean
            local integer r
            local integer L = 1
            local integer L1 = 1
            local integer end = 0
            local integer array weights
            set weights[0] = 0
            if this != 0 then
                loop
                    exitwhen L > this.index
                    set weights[L] = itemDropTable[this][itemIdTable[this][L]]
                    call BJDebugMsg( " Struct Instance = " + I2S( this) + " Item # = " + I2S( L) + " Unit type id = " + I2S( this.unitTypeId) + " Item Id = " + I2S( itemIdTable[this][L]) + " Weight = " + I2S( itemDropTable[this][itemIdTable[this][L]]))
                    set end = end + 1
                    set L = L + 1
                endloop
                set L = 1
                loop
                    exitwhen L > this.multiDrop
                        set r = GetRandomInt( 1, this.ttlWeight)
                        loop
                            exitwhen L1 > end
                            if r > weights[L1 - 1] and r <= weights[L1] then
                                call CreateItem( itemIdTable[this][L1], x, y)
                            endif
                            set L1 = L1 + 1
                        endloop
                    set L = L + 1
                endloop
            endif
            return this.dropTypeTableAlso
        endmethod
Below are some pics of what I get with those messages.

B) there are many flaws within your code, like:
// where 'r' is random int from 1 to weight if r > weights[L1 - 1] and r < weights[L1] then what happens if we roll exactly 'border' number? (lets say 20 in your test map). There is no "=" operator within if statement, thus such item will never be found.
Searching and indexing could be improved a lot, however, this is not the case now.

Yes I did miss that = in the weights check. Thanks.
It now looks like this.
// where 'r' is random int from 1 to weight if r > weights[L1 - 1] and r <= weights[L1] then
 

Attachments

  • Startup..PNG
    Startup..PNG
    208.4 KB · Views: 83
  • LoadingData.PNG
    LoadingData.PNG
    317.1 KB · Views: 65

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
Because of your rep I'm representing 666 haxs :p

Honestly, when I entered your test map, I've immidiately replaced Table with TableArray where is was needed thus as of now, I still could not see the problem.

Meaby I'm just dumb but your example is more complex one, since its system implementation. Usually, the best way is to post smallest code possible, without anything (and no, add & drop Item methods solely wont work, meaning pasting just those 2 is incomplete ^)^ ) unrelated to the problem with statement what you'd exect from the code and whats the actuall output of the code is. Fine, you have added messages, but I dont know whats those should or should not shown.


However, you can not neclect this:
JASS:
        static method createForType takes integer unitTypeId returns thistype
            local thistype this = thistype.allocate()
            set this.unitTypeId = unitTypeId
            set unitTypeTable[ this.unitTypeId] = this
            set this.specificUnit = false
            set this.dropTypeTableAlso = false
            call this.setValues()
            return this
        endmethod
       
        static method createForUnit takes unit u, boolean dropTypeTableAlso returns thistype
            local thistype this = thistype.allocate()
            set this.unitTypeId = GetHandleId( u)
            set unitIdTable[ this.unitTypeId] = this
            set this.specificUnit = true
            set this.dropTypeTableAlso = dropTypeTableAlso
            call this.setValues()
            return this
        endmethod
Lets assume user is tricky and/or mad and suddenly he adjust 2 tables for signle unit type?
Fix is quite simple:
JASS:
        static method createForType takes integer unitTypeId returns thistype
            local thistype this
            if unitTypeTable[ this.unitTypeId] == 0 then // is allocated?
                set this = thistype.allocate()
                set this.unitTypeId = unitTypeId
                set unitTypeTable[ this.unitTypeId] = this
                set this.specificUnit = false
                set this.dropTypeTableAlso = false
                call this.setValues()
            else
                set this = unitTypeTable[ this.unitTypeId]
            endif
            return this
        endmethod
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
deathismyfriend, the main point is that you have the variables declared wrong. You can't set a Table to a TableArray index, and then not typecast that Table back to TableArray each time you use it. Just declare it as a TableArray.

Thanks Bribe. That was my problem this whole time. What a stupid mistake.

@Bannar
Thanks for your help as always. I will fix it to protect the creation.

Thanks to both of you +rep

Edit: I can't rep either of you atm sorry.

Edit 2: Fixed Bannars name lol.
 
Last edited:

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
This is what Ralle told me. I was an admin on few forums, and yes changing users nickname is easy - but it can also bring burden into forum with everyone getting confused who is he writing with.
Its good that Ralle set some rules, one of them being nickname limitation change.

Anyways, lets not go with offtopic any further.
 
Level 11
Joined
Oct 11, 2012
Messages
711
Can anyone explain what are the top two lines used for? How are they useful?
Thank you.
JASS:
set a[654321] = 'A'   //<-------
set a[54321] = 'B'  //<-------
set a.unit[12345] = GetTriggerUnit()
set a.unit[GetHandleId(a.unit[12345])] = GetSpellTargetUnit()
set a.real['ABCD'] = 3.14159
set a.integer[133] = 21
 
It is just assigning the integer 'A' and integer 'B' to particular keys in the table instance "a".

a -> key 654321 -> 'A'
a -> key 54321 -> 'B'

'A' and 'B' are integers. The apostrophe 'XXXX' notation is normally used for rawcodes. Rawcodes are just formed from ASCII characters, e.g. 'a' corresponds to 97. When you have a code such as 'abcd', it'll use an algorithm to generate an integer representation.

We use raw codes all the time for unit types, abilities, etc. But as for the individual 'a' or 'b', you won't find too many uses except in specific cases. For example, dialogs provide an option for a hotkey, and you can input 'a' or 'b', etc. to determine the hotkey (since it takes an integer, not a string). You can also use it for some weird array mechanic, if you want to be fancy:
JASS:
local integer array i
set i['a'] = 24
set i['b'] = 25
set i['c'] = 26
// equivalent to
set i[97] = 24
set i[98] = 25
set i[99] = 26
 
Level 11
Joined
Oct 11, 2012
Messages
711
It is just assigning the integer 'A' and integer 'B' to particular keys in the table instance "a".

a -> key 654321 -> 'A'
a -> key 54321 -> 'B'

'A' and 'B' are integers. The apostrophe 'XXXX' notation is normally used for rawcodes. Rawcodes are just formed from ASCII characters, e.g. 'a' corresponds to 97. When you have a code such as 'abcd', it'll use an algorithm to generate an integer representation.

We use raw codes all the time for unit types, abilities, etc. But as for the individual 'a' or 'b', you won't find too many uses except in specific cases. For example, dialogs provide an option for a hotkey, and you can input 'a' or 'b', etc. to determine the hotkey (since it takes an integer, not a string). You can also use it for some weird array mechanic, if you want to be fancy:
JASS:
local integer array i
set i['a'] = 24
set i['b'] = 25
set i['c'] = 26
// equivalent to
set i[97] = 24
set i[98] = 25
set i[99] = 26

Thanks for the explanation. But why not just use this if 'A' and 'B' are considered integers:
JASS:
set a.integer[654321] = 'A' 
set a.integer[54321] = 'B'
 
Thanks for the explanation. But why not just use this if 'A' and 'B' are considered integers:
JASS:
set a.integer[654321] = 'A' 
set a.integer[54321] = 'B'

That option wasn't added until later requested by Spinnaker. Before, you had to save integers without the ".integer". It might've been for backwards compatibility/similarity with Vexorian's Table.
 

Deleted member 219079

D

Deleted member 219079

This is really nice, only one hashtable makes it perfect :D

Here, local TableArray da = TableArray[0x2000] on your example, why do you have an x in integer?
 

Deleted member 219079

D

Deleted member 219079

Okay, hex value, cool :D (I've no idea what it is)
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
you have decimal, octal, binary and hexadecimal values(there are more obscure like duodecimal).

Hexadecimal allows you to have 1 character per 16 values, so valid hexadecimal literals are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f(and upper case equivalents), where a is equal to 10, b to 11, ..., f to 15 and finally 10 in hexadecimal is 16. This is the same as the rawcode system, but rawcode uses 256-base numeric system
 

Deleted member 219079

D

Deleted member 219079

I'd be a total liar if I said I can do nxnnnn numbers now :/ But thanks for explaining anyway! Maybe some day..

What's the difference of flush and destroy? I wanted to destroy so I made flush then destroy but it nags at me, does destroy also flush? The api section only says destroy destroys it.. I'm so confused of this.
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
Flush merely reemoves everything within the table instance, whereas destroy flushes the table and recycles its instance so that when you call create next time it will give you that instance back

Call flush when you want to continue using the instance. If you no longer need it(such as inside your struct's destroy method), then you should call destroy
 

Deleted member 219079

D

Deleted member 219079

Okay thanks dude, got it fixed now
 
Level 15
Joined
Aug 7, 2013
Messages
1,337
Correct me if I'm wrong, but I believe Table is missing weathereffect.

Would appreciate if that could be added in, or I might do it myself if it's just a text macro that builds each .type syntax.

Edit: apologies. appears that Blizzard did not make LoadWeatherEffectHandle .
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
I don't think Bribe would mind if you edit the code to your needs, as long as you don't redistribute it as your own work (no offense intended).
 
Level 15
Joined
Aug 7, 2013
Messages
1,337
Well I'd rather not get messy.

But it would be nice (well nice for me) if Table supported weathereffect and possibly terraindeformation.
 

Deleted member 219079

D

Deleted member 219079

Is there a way to make array - based version? I mean in speed comparison cache < hashtable < variable arrays, so it could be blazing fast

I don't case if it'd only support 8190 instances, it'd still be super cool
 
Last edited by a moderator:
Level 22
Joined
Sep 24, 2005
Messages
4,821
Why not just use normal arrays then? Or what you want is a jass hash function? I don't think it would be faster than the native hashtable though.
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
It shouldnt, since TableArray[xx] will create 5 Tables and return them to you, so they are completly different.

Try printing A[1] and B[1] and you will see it will not overrite it(it shouldnt at least), because they are different instances(they should be)
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
It shouldnt, since TableArray[xx] will create 5 Tables and return them to you, so they are completly different.

Try printing A[1] and B[1] and you will see it will not overrite it(it shouldnt at least), because they are different instances(they should be)

I tested it: it does replace. :(
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
JASS:
scope s initializer i
    private function i takes nothing returns nothing
        local TableArray a = TableArray[5]
        local TableArray b = TableArray[5]
        
        call BJDebugMsg(I2S(integer(a[2])))
        call BJDebugMsg(I2S(integer(b[2])))
        
        set a[2].integer[4] = 8
        set b[2].integer[4] = 11
        
        call BJDebugMsg(I2S(a[2].integer[4]))
    endfunction
endscope

prints correctly 8 for me, and the indexes are -3 and -8(apparently TableArray will allocate Tables with negative indexes growing from 0 to -inf).

You have some problem on your end most likely
 
Level 9
Joined
Jun 21, 2012
Messages
432
Lately I can't stop using Table, so it is my duty to say:

Some thinks of Table:

TableArray has many disadvantages:

- You have to know the index/size set ta=TableArray[size/index] when it is created :vw_wtf:.

- The point of using "TableArray" is that just not have limits... when set some value: set ta[myMissIndex].integer[this]=someValue

- TableArray if I am not mistaken does not work with arrays variables Table array ta because of static method operator []

It is tedious create a TableArray with a certain size... why not just use "TableArray" in Table struct as follows:

set ta.integer[parentKey][childKey]=someValue.

For me and I think for many, it would also be excellent if there was a new update of your Table fixing these disadvantages.
 
Top