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

[JASS] vJass Structs

Status
Not open for further replies.
Level 4
Joined
Dec 10, 2005
Messages
73
Just need a little help getting this right before I start programming it.

JASS:
struct Staffdata //declaring the struct
integer task
integer Guestnumber
boolean Guestlefted
endstruct

function blah takes nothing returns nothing 
//this function assigns the struct Index to the unit

local Staffdata Hi = Staffdata.create()
local integer i = integer(Hi)

call SetUnitUserData(u,i)
endfunction

function blah2 takes nothing returns nothing
//this function calls the created struct.


local Staffdata Hi = Something?(GetUnitUserData(u)) //what do I do here?

//Do some wicked stuff

call Hi.destroy()
endfunction

Is this right? Am I allowed to do something like this with structs, every if they are local.
 
Level 9
Joined
Apr 5, 2008
Messages
529
Yes, you can attach structs to units this way.

JASS:
local Staffdata Hi = Staffdata(GetUnitUserData(u))

I would recommend not using SetUnitUserData, as I've heard it can get buggy. There's a script over at wc3c which allows you to index units, this way you can store the structs in arrays with the units index.
 
Level 18
Joined
Oct 18, 2007
Messages
930
Here is a simple handle attachment system made for you :D
JASS:
library HandleData

    globals
        private constant integer SIZE = 409550
        
        private integer array HandlerData [SIZE]
    endglobals
    
    private function H2I takes handle h returns integer
        return h
        return 0
    endfunction
    
    function GetHandleData takes handle h returns integer
        return HandlerData[H2I(h) - 0x100000]
    endfunction
    
    function SetHandleData takes handle h, integer value returns nothing
        set HandlerData[H2I(h) - 0x100000] = value
    endfunction
    
    function FlushHandleData takes handle h returns nothing
        set HandlerData[H2I(h) - 0x100000] = 0
    endfunction

endlibrary


Example on how you use it.
JASS:
struct StaffData
    integer Tast
    integer GuestNumber
    boolean GuestLeaved
endstruct

function Test1 takes nothing returns nothing
    local StaffData dat = StaffData.create()
    
    call SetHandleData( YourUnit, dat )
endfunction

function Test2 takes nothing returns nothing
    local StaffData dat = GetHandleData( YourUnit )
    
  //[ACTIONS APPLIES HERE!]
  
    call FlushHandleData( YourUnit ) // Not really needed but it is there to make it safe, in case of dubble free
    call dat.destroy()
endfunction

You can use other stuff than units to :p like locations, effects, etc.
 
Level 11
Joined
Apr 6, 2008
Messages
760
JASS:
struct Staffdata //declaring the struct
integer task
integer Guestnumber
boolean Guestlefted
endstruct

function blah takes nothing returns nothing


local Staffdata Hi = Staffdata.create()

call SetUnitUserData(u,Hi)
endfunction

function blah2 takes nothing returns nothing
//this function calls the created struct.


local Staffdata Hi = GetUnitUserData(u)

//Do some wicked stuff

call Hi.destroy()
endfunction
 
Level 4
Joined
Dec 10, 2005
Messages
73
Thanks for the info and extra thanks for the handle Dynasti. Looks like I have to start recoding the entire game since I used GetUnituserdata. :(.I will look more into this.

I have another question. Lets say I have 5 structs already attached to 5 units. I then need to destroy unit 3, but would first call the struct and destroy that first.

First 1 2 3 4 5
becomes 1 2 - 4 5

Now there's a hole. I believe it coded to solve this by just moving the last element into that slot.

then becomes 1 2 5 4.

Question is, would the value assigned by the attachment system be affected in anyway by this, since all the data in struct 5 has moved into position 3? Another way: Does struct 5 take the index number of struct 3? How does vJass know what Index numbers are free?
 
Level 18
Joined
Oct 18, 2007
Messages
930
Thanks for the info and extra thanks for the handle Dynasti. Looks like I have to start recoding the entire game since I used GetUnituserdata. :(.I will look more into this.

I have another question. Lets say I have 5 structs already attached to 5 units. I then need to destroy unit 3, but would first call the struct and destroy that first.

First 1 2 3 4 5
becomes 1 2 - 4 5

Now there's a hole. I believe it coded to solve this by just moving the last element into that slot.

then becomes 1 2 5 4.

Question is, would the value assigned by the attachment system be affected in anyway by this, since all the data in struct 5 has moved into position 3? Another way: Does struct 5 take the index number of struct 3? How does vJass know what Index numbers are free?

Always remember to not make staffdata for more than one unit at the time, if you want to do it you need to use the end function first


Simple solution


add this to your struct
JASS:
unit Staff

integer Position
static integer array Index
static integer Total = 0

then here is an example on how to recycle them:


Start

JASS:
function StartStaffData takes unit u returns nothing
    local StaffData dat = StaffData.create()

    set dat.Staff = u
    set dat.Position = StaffData.Total

    set StaffData.Index[StaffData.Total] = dat
    set StaffData.Total = StaffData.Total + 1

    call SetHandleData( u, dat )

  //More Actions here
endfunction

End

JASS:
function EndStaff takes unit u returns nothing
    local StaffData dat = GetHandleData( u )
    local integer i = dat.Position

    set StaffData.Total = StaffData.Total - 1
    set StaffData.Index[i] = StaffData.Index[StaffData.Total]

    call FlushHandleData( u )

    set u = null // Always remember to null struct members

    call dat.destroy()

    set dat = StaffData.Index[i]

    set dat.Position = i
endfunction



I think this should work
 
Level 4
Joined
Dec 10, 2005
Messages
73
Yea, I was wondering if I needed to do that. I didn't know if it was coded to automatically to recycled. But I guess it's better to be sure.

hmm, I find this interesting yet confusing. You destroyed the entire struct but replaced it via an integer, which is hard to believe. Do I need to do anything to the last struct? ( clean it since it still has data)

Can I do this then?

JASS:
local Staffdata dat
set dat = 2

//Do stuff to struct 2

P.S look at my post count :D
 
Level 18
Joined
Oct 18, 2007
Messages
930
Yea, I was wondering if I needed to do that. I didn't know if it was coded to automatically to recycled. But I guess it's better to be sure.

hmm, I find this interesting yet confusing. You destroyed the entire struct but replaced it via an integer, which is hard to believe. Do I need to do anything to the last struct? ( clean it since it still has data)

Can I do this then?

JASS:
local Staffdata dat
set dat = 2

//Do stuff to struct 2

P.S look at my post count :D

Well you should not do that
JASS:
    set dat = StaffData.Index[i]
    set dat.Position = i
What this does is that it gives the recycled struct info about where it is in the recycler. If you dont do it excactly things can get pretty ugly

The recycler works like this

Lets say we have 5 structs running
1 - 2 - 3 - 4 - 5

then struct number 3 is removed
1 - 2 - _ - 4 - 5

Now we got a hole, but we fix that by moving the last end of the stack to the current position of the removed struct
1 - 2 - 5 - 4

We also give information to the struct that struct number 5 is in stack line 3.
JASS:
    set dat = StaffData.Index[i]
    set dat.Position = i

Here i = 3

and the Index is 5 in line 3 or Index[Line] == struct or Index[3] = 5
 
Level 4
Joined
Dec 10, 2005
Messages
73
I think you missed the point of my question. I asked if the recycling of struct will affect the attachment system. Since struct 5 is attached to unit 5 with the number 5, would filling in the hole created by the destruction struct 3 by using struct 5 destroy the link between struct 5 and unit 5.

How does vJass struct system handle this? Does it recycle as well? Would I still be able to call the attached struct using the integer 5?

I not sure how structs works internally so I'm just going to set the last struct ( 5 in this case) to fill the hole( struct 3) by copy all the member data manually and reattach the handle integer to the unit.

eg:
JASS:
function Transfer takes integer i, integer L returns nothing
local Staffdata A = i // i represents the hole
local Staffdata B = L// L represent the last struct created

set A.task = B.task
set A.Guestnumber = B.Guestnumber 
...
set A.unit = B.unit  // know which unit is attached to this struct

call B.destroy() // will free Index and null everything
set L = L - 1

set SetHandleData( A.unit, i)

endfunction

Thanks for the help.
 
Level 14
Joined
Nov 18, 2007
Messages
816
This isnt exaclty hard to do.

JASS:
library Staff uses PUI // PUI uses UnitUserData

    struct Staff
        unit staff
        
        static Staff array Structs
    endstruct
    
    function StartStaffData takes unit u returns nothing
    local integer i=GetUnitIndex(u) // PUI // returns a unique index, currently not in use by any other unit // default range: 0-4096
        set Staff.Structs[i]=Staff.create()
        set Staff.Structs[i].staff=u
    endfunction
    
    function EndStaff takes unit u returns nothing
    local integer i=GetUnitIndex(u) // PUI
        set Staff.Structs[i].staff=null
        call Staff.Structs[i].destroy()
    endfunction
    
endlibrary
 
Level 18
Joined
Oct 18, 2007
Messages
930
I think you missed the point of my question. I asked if the recycling of struct will affect the attachment system. Since struct 5 is attached to unit 5 with the number 5, would filling in the hole created by the destruction struct 3 by using struct 5 destroy the link between struct 5 and unit 5.

How does vJass struct system handle this? Does it recycle as well? Would I still be able to call the attached struct using the integer 5?

I not sure how structs works internally so I'm just going to set the last struct ( 5 in this case) to fill the hole( struct 3) by copy all the member data manually and reattach the handle integer to the unit.

eg:
JASS:
function Transfer takes integer i, integer L returns nothing
local Staffdata A = i // i represents the hole
local Staffdata B = L// L represent the last struct created

set A.task = B.task
set A.Guestnumber = B.Guestnumber 
...
set A.unit = B.unit  // know which unit is attached to this struct

call B.destroy() // will free Index and null everything
set L = L - 1

set SetHandleData( A.unit, i)

endfunction

Thanks for the help.

Wrong.

You should not recycle it in that way, it is unefficient and bad.

If you change the structs position in the recycling system it does not change any values, we just set the .Position to its new position. Doing this with the .Position is important if you want to destroy a struct in the middle of structs that are in use.

But why do you need to recycle it? Do you use a check loop? Because you dont really need to recycle positions of structs if you are not using any loop for your structs
 
Level 8
Joined
Aug 6, 2008
Messages
451
You should use UnitUserData to index your units, and then use UserData as an array index:

Data1[ GetUnitUserData( u ) ]
Data2[ GetUnitUserData( u ) ]
Data3[ GetUnitUserData( u ) ]
...
DataN[ GetUnitUserData( u ) ]


Every unit just must have different UnitUserData.
( I think PUI does something like this, but you can also just do it yourself in the way that works best for your map )

edit. Just like RolePlaynGamer said.
 
Status
Not open for further replies.
Top