• 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.

Struct instances

Status
Not open for further replies.
Level 20
Joined
Jul 6, 2009
Messages
1,885
I recently learned structs and i was wondering how would i loop through struct instances.
In JASS spells, i always just attach data to units in a hashtable, loop through units and load data from hashtable. But how do i do it with structs?

Do i need to somehow attach struct instances to units, loop through units and load data from instances? (If so, how would i attach 'em?)

Or do i loop through instances and load corresponding units saved in instances? (If so, how would i loop through instances?)

Or is there some way i didn't think of?
 
This is by far the easiest method.

http://www.hiveworkshop.com/forums/jass-functions-413/system-unit-indexer-172090/

An example of adding to a list on index.
JASS:
struct List extends array
    readonly thistype next
    private thistype previous

    private method index takes nothing returns nothing
        set thistype(0).previous.next = this
        set previous = thistype(0).previous
        set next = 0
        set thistype(0).previous = 0
    endmethod

    private method deindex takes nothing returns nothing
        set previous.next = next
        set next.previous = previous
    endmethod

    private static method filter takes unit u returns boolean
        return true
    endmethod

    implement UnitIndexStruct
endstruct

You could take the same idea and apply it to a spell or w/e. This adds indexed units to a list, the spell might added targeted units to a list. It removes deindexed units from the list, the spell might remove resolved, dead, and removed units from the list. UnitEvent could also be useful (check JASS section).


You could also implement your own instantiation (like a list in the spell) and store the unit into the list or store the unit id (if using a unit indexer) into the list (but if you store unit id, you should either be prepared to clean it on deindex or lock it).
 
Level 26
Joined
Aug 18, 2009
Messages
4,099
You can surely do both but iterating through is the more indirect way and somewhat ineffective on many instances. If you want to do so, you would set up an array holding the instances and adjust on allocation/deallocation. The normal allocation method fetches ids from 1 upwards (1, 2, 3, 4, ...) but when looping from instances amount to 1 you would also get the destroyed ones, so there needs to be an indicator at least when not implementing an own tracking list.

So, I like the direct approaches better myself. You can use a hashtable and save the struct (it is an integer) under the handle id of the unit (GetHandleId) or there are also other unit indexing systems out there that might return smaller ids that you can put into arrays as indizes. These systems might as well use other inhouse unit values like custom value or things that can be changed without affecting gameplay.
 
Level 20
Joined
Jul 6, 2009
Messages
1,885
One more question - is it more efficient to load same value from struct multiple times or to save it in a local variable?
Example
JASS:
struct A
    real x
endstruct

function
    local A a = A.create()
    local real x = a.x
    call SetUnitX(SomeUnit,x)
    call SetUnitFacing(SomeUnit,x)
    set SomeLocation = Location(x,x)
endfunction
//or...
function
    local A a = A.create()
    call SetUnitX(SomeUnit,a.x)
    call SetUnitFacing(SomeUnit,a.x)
    set SomeLocation = Location(a.x,a.x)
endfunction
Even though it would be logical that first function is more efficient, i'm not sure since i think it's same to load a value from a struct and a variable. (Just guessing, that's why i ask)
 
Level 26
Joined
Aug 18, 2009
Messages
4,099
Locals are read faster than globals and a.x would be x[a], loading a each time and an array lookup. Since you declared a as local here, this would be a difference of reading one array. I actually put it in a local when I need the value more than one time, not only because of the speed but hate it to load data multiple times in a function from more global and indirect expressions.
 
Status
Not open for further replies.
Top