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

[vJASS] struct question

Status
Not open for further replies.
Level 6
Joined
Mar 7, 2011
Messages
124
Hi,
I just started learning how to use the editor today so I might have a few really stupid questions. Don't simplify the explanations though, I should be able to keep up.

I already read the nifty oop struct tutorial, so thank you azn for that.

Anyways here's my problem in condensed form:

JASS:
struct Wheel

    //my first question is should it be:
    private hashtable myunits
    //or
    private hashtable myunits = InitHashtable()            
    
    .
    . //lots of irrelevant methods (all in the Wheel struct)
    .

    method createwheel takes nothing returns hashtable
        //stuff that works
        return units //IS of type hashtable
    endmethod    

        static method create takes nothing returns Wheel
        local Wheel newwheel = Wheel.allocate()
        set newwheel.myunits = newwheel.createwheel //<==== my big question
        return newwheel
    endmethod
endstruct

OK so the jasshelper compiler says that I've got an undeclared variable Wheel at the line that ive marked with my big question. Here's what it looks like in jasshelper

Code:
set s__Wheel_myunits[newwheel]=Wheel.getMethod(createwheel,newwheel)

I don't think I should be running into any problems with a static method calling a non static, since its really a instance variable calling the nonstatic method (.createwheel)

From the sound of the error it almost seems like I'd need to wait to call any methods in my struct until after the constructor has been fully finished, but that seems like such a huge flaw I can't even imagine blizzard would have made JASS that way.



My other question has to do with running a different method periodically
I found this in the functions list
JASS:
call TriggerRegisterTimerEventPeriodic(new.rotatewheel, .03)
but periodic stuff is usually dangerous and I don't know how wc3 handles its trigger evaluations. so basically my question is, is that function ok? rotatewheel can be a pretty heavy operation, if that makes a difference.
 
Level 6
Joined
Mar 7, 2011
Messages
124
i can't tell if what you said is a suggestion to make it more usable, a suggestion to prevent errors down the road or a solution to my problem. it doesn't sound like a solution to the immediate problem though.

but anyways

tell me if I've got the right idea
so i'd basically have one hash that every structure uses and which struct is which is identified in the hash by some key thats unique to each struct.

mmmn
if thats the case then it wont work without sacrificing a huge amount of what makes what im doing interesting
each hash already uses both keys (and obviously the data)
if there was a type of hash that had 1 more key available then I could make it work like you think it should.

either way, this struct isn't intended to be used more than 3 or 4 times, what is the maximum amount of hashes?


also i had another thought
if they cant be destroyed, then what if I store pointers to the ones that are no longer in use in an array
and then whenever I create a hash in this struct I check to see if there are any unused ones in the array before making a new one.
idk if that'll work though.
 
JASS:
struct Wheel

    //my first question is should it be:
    private hashtable myunits
    //or
    private hashtable myunits = InitHashtable()            
    
    .
    . //lots of irrelevant methods (all in the Wheel struct)
    .

    method createwheel takes nothing returns hashtable
        //stuff that works
        return units //IS of type hashtable
    endmethod    

        static method create takes nothing returns Wheel
        local Wheel newwheel = Wheel.allocate()
        set newwheel.myunits = newwheel.createwheel //<==== my big question
        return newwheel
    endmethod
endstruct

OK so the jasshelper compiler says that I've got an undeclared variable Wheel at the line that ive marked with my big question. Here's what it looks like in jasshelper

Code:
set s__Wheel_myunits[newwheel]=Wheel.getMethod(createwheel,newwheel)

I don't think I should be running into any problems with a static method calling a non static, since its really a instance variable calling the nonstatic method (.createwheel)

It says that you have an undeclared variable because:
newwheel.createwheel

!=

newwheel.createwheel()

You have to use the latter method, since you are calling a function rather than referencing a variable.

The initialization question depends on a few factors. In reality, you should be using a static variable (same as a non-array global) instead of assigning it to a member, and that variable can just be declared as:
static hashtable myunits = InitHashtable()

As DSG said. EDIT: If you are only using it should be fine, but it may end up being more efficient to just use 1 and use different parent indexes when saving. (idk, it depends on what you are doing)

To answer the question, however, it depends on whether or not you want the variable to have a hashtable created and assigned to it upon allocation. If you supply an initial value to a struct member (it does not apply to static/globals), then it will set that member to the initial value upon allocation. Usually you can just do this yourself in the .create() method, but you can choose either one.

My other question has to do with running a different method periodically
I found this in the functions list
JASS:
call TriggerRegisterTimerEventPeriodic(new.rotatewheel, .03)
but periodic stuff is usually dangerous and I don't know how wc3 handles its trigger evaluations. so basically my question is, is that function ok? rotatewheel can be a pretty heavy operation, if that makes a difference.

That function is fine. It is pretty much same as using a timer, but allows a trigger to be evaluated/executed instead. To be honest, you shouldn't worry about periodics unless you are doing something wrong (eg: leaking) or if the period is too low (eg: anything 0.01 or below [100 exec/s or more]).

EDIT:
either way, this struct isn't intended to be used more than 3 or 4 times, what is the maximum amount of hashes?

256 is the maximum amount of hashtables, so in that case it would be fine. ;)
 
Level 6
Joined
Mar 7, 2011
Messages
124
lol
I can't even play that off as a "thats one of those wacky JASS things"
thats pretty much a every language thing
well herp derp, go me.

Well anyways thank you very much purge (and dr) thats exactly what I was looking for
 
Level 20
Joined
Jul 6, 2009
Messages
1,885
I'm sorry to post in this thread, but now that you mentioned static variables...
Just wanted to ask how are static variables different from normal ones? Purge&Fire said they're same as non-array globals, but i doubt they can be used outside of struct as other globals >_>
 
Level 6
Joined
Mar 7, 2011
Messages
124
a static variable is something that is the same for wherever it exists.
not to be confused with a final variable which is constant.

for example if you have a struct with a static local variable then while that variable won't exist in a global sense, every struct will share that variable. if its changed in one instance of the struct, its immediately changed for all instances. thats the basic description of it, if you know what pointers are then you can think of static variables all having a pointer to one single data value.

thats why you can't use this when you're operating with a static method, it simply doesn't have any meaning since the static method applies across the struct.

like purge said a non array static variable is very similar to a non array global, because of how its shared. it might have additional properties like it being local, but essentially purge's definition hits the mark
 
Level 20
Joined
Jul 6, 2009
Messages
1,885
a static variable is something that is the same for wherever it exists.
not to be confused with a final variable which is constant.

for example if you have a struct with a static local variable then while that variable won't exist in a global sense, every struct will share that variable. if its changed in one instance of the struct, its immediately changed for all instances. thats the basic description of it, if you know what pointers are then you can think of static variables all having a pointer to one single data value.

thats why you can't use this when you're operating with a static method, it simply doesn't have any meaning since the static method applies across the struct.

like purge said a non array static variable is very similar to a non array global, because of how its shared. it might have additional properties like it being local, but essentially purge's definition hits the mark

Good explanation. Thanks.
 
Level 6
Joined
Mar 7, 2011
Messages
124
Youre welcome

I've got a new question though.

here's my problem in condensed form

JASS:
struct Thing

    private method something takes nothing returns nothing
        ...
    endmethod

    private method startWheel takes Thing newthing returns nothing
        local trigger triggerthing = CreateTrigger()
        call TriggerRegisterTimerEventPeriodic(triggerthing, .03)
        call TriggerAddAction(triggerthing, newthing.something())
    endmethod
endstruct

this doesn't work because newthing.something() is evaluated (which returns nothing)

so my question is, how do I pass a pointer to the method something?

a side question is, are there lambda functions in vJASS?
 
Level 11
Joined
Sep 30, 2009
Messages
697
JASS:
struct Thing

    private method something takes nothing returns nothing
        ...
    endmethod

    private method startWheel takes Thing newthing returns nothing
        local trigger triggerthing = CreateTrigger()
        call TriggerRegisterTimerEventPeriodic(triggerthing, .03)
        call TriggerAddAction(triggerthing, newthing.something())
    endmethod
endstruct

Should be:

JASS:
struct Thing
    // has to be static :/
    private static method something takes nothing returns nothing
        ...
    endmethod

    private method startWheel takes Thing newthing returns nothing
        local trigger triggerthing = CreateTrigger()
        call TriggerRegisterTimerEventPeriodic(triggerthing, .03)
        call TriggerAddAction(triggerthing, function Thing.something)
    endmethod
endstruct

Only static members may be passed to triggers. Also you have to use "function <yourfunction>" or with struct members "function <yourstruct>.<yourstaticmethod>"

In this case I would use a timer and attach your structs data to it since creating too many triggers isn't that good. Basically triggers should be created at map initialization only in most cases anyway.

A good way to attach data to timers would be TimerUtils: http://www.wc3c.net/showthread.php?t=101322

a side question is, are there lambda functions in vJASS?

vJass doesn't have such, but Zinc an extension of vJass has anonymous functions.
 
Level 6
Joined
Mar 7, 2011
Messages
124
ok well if I make that method static then it loses all this. references
it relies on some sort of reference to an instance struct but it would be fine if I could do function Thing.something(newthing).
which apparently I cant do because it has to be parameterless as well as static :(

but I guess you saw that coming with the bit about timer.utils

can i have a basic summary of how its used?
 
Last edited:
ok well if I make that method static then it loses all this. references
it relies on some sort of reference to an instance struct but it would be fine if I could do function Thing.something(newthing).

but I guess you saw that coming with the bit about timer.utils

can i have a basic summary of how its used?

Yes, data can't be passed when inputting code arguments. this.func is the same as having an argument, because jasshelper just ends up turning it into func(this).

TimerUtils can allow you to assign and retrieve those instances across functions. This is your current problem:
JASS:
struct Test
    real x
    
    static method callback takes nothing returns nothing
        // how do you get the instance?
    endmethod
    
    static method test takes nothing returns nothing
        local thistype this = thistype.allocate()
        local timer T = CreateTimer()
        set this.x = 25
        call TimerStart(T,5,false,function thistype.callback)
        set T = null
    endmethod
endstruct

However, using the TimerUtils library will allow you to attach data to the timer, and retrieve it in the callback function.
JASS:
struct Test
    real x
    
    static method callback takes nothing returns nothing
        local timer T = GetExpiredTimer() // blizz allows us to retrieve the timer that was started
        local thistype this = GetTimerData(T) // we retrieve the data from that timer
        call BJDebugMsg(R2S(this.x)) //do whatever you need with the data
        call ReleaseTimer(T) // recycles the timer for later use, and detaches the data from it
        call this.destroy() // destroys the instance
        set T = null //not really necessary since the timer will never be destroyed (only recycled)
    endmethod
    
    static method test takes nothing returns nothing
        local thistype this = thistype.allocate()
        local timer T = NewTimer() // use this function instead
        // if there are free timers, then it will return one
        // else, it will create a new timer
        set this.x = 25
        
        call SetTimerData(T,this) //attaches the data to the timer
        call TimerStart(T,5,false,function thistype.callback)
        set T = null // not really necessary since the timer will never be destroyed (only recycled)
    endmethod
endstruct

TimerUtils is just one of the several systems for data attachment. Timers are also not the only handles you can attach data to.
 
Status
Not open for further replies.
Top