[JASS] How to pass Data from functionA to functionB.

Status
Not open for further replies.
Level 6
Joined
Mar 22, 2009
Messages
276
I tried using the return bug with timers but its not working with 1.24d patch. I tried using the hashtable but I failed on converting the timer handle into integer. Yes H2I problem again. I also tried doing it via structs but I've been confused with it.

Im trying to learn it to make jass spells for my map. I need to learn it for me to be able to make MUI/MPI looping spells.

Are there any way to convert handle to integer?

Or give me a sample. Fix this practice jass.

JASS:
scope Practice initializer PracticeInit
    
    private function PracticeA takes nothing returns nothing
        local unit u = GetTriggerUnit()
        local integer i = GetUnitLevel(u)
        local timer t
        //what shall I call here to store the value of integer i and unit u to be able to pass it to PracticeB?
        call TimerStart( t, 1.00, true, function PracticeB )
    endfunction
    
    private function PracticeB takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local unit u // = to what??
        local integer i2 = 0
        local integer i // = to what??
        if i2 <= i then
            //I'm planning to put some SetUnitPositionLoc here to make unit u move.
            BJDebugMsg(I2S(i))
            set i2 = i2 + 1
        else
            set i2 = 0
            call DestroyTimer(t)
        endif
    endfunction

    private function PracticeInit takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_CAST )
        call TriggerAddAction( t, function PracticeA )
    endfunction
endscope
I dont care if I can declare the variables into PracticeB what I want is to practice the method of passing values for future spell making.

Thanks.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
swipe5-weep said:
Are there any way to convert handle to integer?

This is something that is even available in GUI.

JASS:
native GetHandleId takes handle h returns integer

Here's your fixed code:

JASS:
scope Practice initializer PracticeInit
    
    globals
        // In order to use hashtables you need to declare a global hashtable:
        private hashtable   table       = InitHashtable()
    endglobals
    
    // You also have to declare PracticeB above PracticeA, since PracticeA references it.
    private function PracticeB takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local unit  u = LoadUnitHandle(table, GetHandleId(t), 0)
        local integer i2 = 0                
        local integer i = LoadInteger(table, GetHandleId(t), 1)
        if i2 <= i then
            //I'm planning to put some SetUnitPositionLoc here to make unit u move.
            call BJDebugMsg(I2S(i))
            set i2 = i2 + 1
        else
            set i2 = 0
            // When you no longer need the contents of a child hashtable then you should
            // flush it as you would gamecache.
            call FlushChildHashtable(table, GetHandleId(t))
            call DestroyTimer(t)
        endif
        // You need to null your local variables to eliminate the references.
        set t=null
        set u=null
    endfunction

    
    private function PracticeA takes nothing returns nothing
        local unit u = GetTriggerUnit()
        local integer i = GetUnitLevel(u)
        local timer t
        //what shall I call here to store the value of integer i and unit u to be able to pass it to PracticeB?
        // ----
        call SaveUnitHandle(table, GetHandleId(t), 0, u)        // The '0' represents what key I need to reference
        call SaveInteger(table, GetHandleId(t), 1, i)
        call TimerStart( t, 1.00, true, function PracticeB )    // the unit in the other method/function.
        
        // Null locals:
        set u=null
        set t=null
    endfunction


    private function PracticeInit takes nothing returns nothing
        local trigger t = CreateTrigger()
        // I would use EVENT_PLAYER_UNIT_SPELL_EFFECT rather than SPELL_CAST because
        // SPELL_CAST does not take into consideration the unit's cast backswing.
        call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_CAST )
        call TriggerAddAction( t, function PracticeA )
    endfunction
endscope
 
Level 14
Joined
Nov 18, 2007
Messages
816
Its a relic of the past, if you dont want to support older versions of WC3 (which you really shouldnt as older versions of WC3 suffer from a bug that allows injecting malware into maps, if youre planning a multiplayer map), its best if you ignore it.

If you need to know though, it was a bug in the JASS VM that let you return any type of data from a function and use it in the function returned to as data of the type the returning function was declared to return.

[jass=Example]function H2I takes handle h returns integer
return h // execution of the function is stopped after the first return statement, so this function will always return "h"
return 0 // this line is needed because WC3s syntax checker only checked the last return statement for typesafety. 0 is a valid integer, thus fooling the syntax checker into believing that all values returned from this function are valid integers
endfunction[/code]

If you cast a handle or one of its subtypes to integer, youll get the internal handle ID. Most useful handle types (most of those now being a subtype of agent) share a stack of IDs (probably for synchronization purposes), but some like lightning, image, texttag or ubersplat each use a separate stack of IDs. They also each use a different allocation algorithm.
If you cast a string to integer, youll get the strings position in WC3s internal string table (this value is inconsistent after saving and loading a map, and thus shouldnt be relied upon).
If you cast a code variable to integer, youll get the functions memory address in bits.
Interestingly, if you cast nothing to integer (yes, that really worked), you can fetch whatever was last returned from a function.
 
Level 5
Joined
Nov 22, 2009
Messages
181
cool. although i only partially understood what you meant.
i mean i understood but I don't know much about hashtables and i don't understand about the s2i comment. and wait, if the function returns an integer why does it say return h?
 
It essentially "tricks" wc3. Before, wc3 used to only pay attention to the last return. So say you did something like this:
JASS:
function DoStuff takes real x, real y returns unit
    set bj_lastCreatedUnit = CreateUnit(Player(0),'hfoo',x,y,270)
    if x == 0 or y == 0 then
        return 0
    endif
    return bj_lastCreatedUnit
endfunction

Would compile just fine for the syntax editor. Yeah, it is just an example though, it isn't meant to be of any use in this case. Since the final return would return a unit type, it wouldn't care about the return 0 not returning a unit type variable/value. The last return was commonly used just to return the value it was supposed to according to the function's "return xxx" part, and then the first one was to return the typecasted value. This method was called typecasting (which really isn't that useful anymore with hashtables and GetHandleId(), except for W2U maybe).

Now, why does it return the "h" instead of the "0"? Well, say you were to do this:
JASS:
function Whee takes nothing returns nothing
    call BJDebugMsg("First return")
    return
    call BJDebugMsg("Second return")
    return
endfunction

"Second return" would never show up. return acts as a "Skip Remaining Actions", it basically just exits the function. In functions that return a value, when the first return is executed, it will return that value and skip the rest of the actions. In H2I, it skips return 0.

They fixed this bug though, so we can't use it anymore. It was useful in some cases, but now with structs and more efficient timer systems, you no longer need to worry about going back to local handle vars. However, this knowledge is useful when you want to know how to fix a map for it to work properly in 1.24+. There are still methods for typecasting using fogstates and hashtables:
http://www.thehelper.net/forums/showthread.php?t=135583

But generally, we don't have much of a use for it now. (Except for H2I, but blizz finally made a native GetHandleId() to replace the older slower version)
 
Status
Not open for further replies.
Top