Pass a variable by static value

CaptainJack

New Member
Reaction score
2
JASS:
function ItemRecipe_2items_Conditions takes nothing returns boolean
    local integer asdf
    set asdf = udg_ItemRecipe_Counter
    if ( (UnitHasItemOfTypeBJ(GetTriggerUnit(), LoadInteger(udg_ItemRecipe, udg_ItemRecipe_ParentKey[asdf], 1)) == true) and (UnitHasItemOfTypeBJ(GetTriggerUnit(), LoadInteger(udg_ItemRecipe, udg_ItemRecipe_ParentKey[asdf], 2)) == true) ) then
        return true
    endif
    return false
endfunction

function ItemRecipe_2items_Actions takes nothing returns nothing   
    call RemoveItem( GetItemOfTypeFromUnitBJ(GetTriggerUnit(), LoadInteger(udg_ItemRecipe, udg_ItemRecipe_ParentKey[udg_ItemRecipe_Counter], 1)) )
    call RemoveItem( GetItemOfTypeFromUnitBJ(GetTriggerUnit(), LoadInteger(udg_ItemRecipe, udg_ItemRecipe_ParentKey[udg_ItemRecipe_Counter], 2)) )
    call UnitAddItemByIdSwapped(LoadInteger(udg_ItemRecipe, udg_ItemRecipe_ParentKey[udg_ItemRecipe_Counter], 0), GetTriggerUnit()) 
endfunction 

function ItemRecipe_2items takes integer i1, integer i2, integer created returns nothing
    
    local trigger ItemRecipe = CreateTrigger()
    
    set udg_ItemRecipe_Counter = udg_ItemRecipe_Counter + 1
    
    call SaveInteger(udg_ItemRecipe, udg_ItemRecipe_ParentKey[udg_ItemRecipe_Counter], 0, created)
    call SaveInteger(udg_ItemRecipe, udg_ItemRecipe_ParentKey[udg_ItemRecipe_Counter], 1, i1)
    call SaveInteger(udg_ItemRecipe, udg_ItemRecipe_ParentKey[udg_ItemRecipe_Counter], 2, i2)
        
    call TriggerRegisterAnyUnitEventBJ(ItemRecipe, EVENT_PLAYER_UNIT_PICKUP_ITEM)
    call TriggerAddCondition(ItemRecipe, Condition(function ItemRecipe_2items_Conditions))
    call TriggerAddAction(ItemRecipe, function ItemRecipe_2items_Actions)  
endfunction

//===========================================================================
function InitTrig_Item_Recipes takes nothing returns nothing
    set udg_ItemRecipe = InitHashtable()
    
    call ItemRecipe_2items('ratf', 'ckng', 'modt')
    call ItemRecipe_2items('desc', 'rde4', 'ofro')
endfunction


I have tried unsuccessfully to pass a variable by value as opposed to reference. Does anyone have a nice way to do this? For those of you who don't get what I mean here. The local asdf is proof of this, as I was hoping that local value would create a "leaked variable" to hold the static value.





This is what I want to happen.

udg_ItemRecipe_ParentKey[udg_ItemRecipe_Counter]
udg_ItemRecipe_ParentKey[1]

I want a way to pass the udg_ItemRecipe_Counter as a number value as opposed to the variable itself, so that I can create triggers on the fly. I would rather have several triggers created then appending action code to a single trigger. (Though I'm not sure if this would even matter, because there is a decent chance that blizzard merges all things with similar events into a single block of code at compilation.)
 

Bribe

vJass errors are legion
Reaction score
67
there is a decent chance that blizzard merges all things with similar events into a single block of code at compilation.)

No, absolutely not. It is not grouped, it is not similar, it all clashes. Hence the use of Jesus4Lyf's GTrigger.

Not sure at all what you mean by "pass variable by value as opposed to reference".
 

CaptainJack

New Member
Reaction score
2
Well then please explain why that code continues to evaluate dynamically, causing only the final recipe added to work successfully?

EDIT: Let me try destroying the reference for the trigger and see if that makes a difference.
 

Jesus4Lyf

Good Idea™
Reaction score
397
Well then please explain why that code continues to evaluate dynamically, causing only the final recipe added to work successfully?
This is dynamic:
JASS:
function ItemRecipe_2items_Conditions takes nothing returns boolean
    local integer asdf
    set asdf = udg_ItemRecipe_Counter
    if ( (UnitHasItemOfTypeBJ(GetTriggerUnit(), LoadInteger(udg_ItemRecipe, udg_ItemRecipe_ParentKey[asdf], 1)) == true) and (UnitHasItemOfTypeBJ(GetTriggerUnit(), LoadInteger(udg_ItemRecipe, udg_ItemRecipe_ParentKey[asdf], 2)) == true) ) then
        return true
    endif
    return false
endfunction

It loads the value from the global every time the condition is evaluated (not once when the trigger is created). :p
Conditions are not static. They are actually the same as actions, except you cannot use waits in them, and you must return a boolean which says whether or not the "actions" run. :)
 

CaptainJack

New Member
Reaction score
2
That would mean any variable I utilize is passed solely by reference, and not by value. As you see in that global the global will be again like I said


udg_ItemRecipe_ParentKey[udg_ItemRecipe_Counter]

as oppossed to by value

udg_ItemRecipe_ParentKey[1]
 

Bribe

vJass errors are legion
Reaction score
67
I'm not sure what you're trying to do. Do you want to change the value of the global, or are you trying to preserve it?

If you think of integers as objects (which can be treated as false-objects if you use structs), each time you do "local integer asdf = udg_Integer" you're making a copy of "udg_Integer", so that by changing asdf you are not changing udg_Integer, and by changing udg_Integer you are not changing asdf.
 

CaptainJack

New Member
Reaction score
2
Clearly the idea is to save the value of the global by passing it by VALUE to the index of the array in the condition. If you don't understand what I mean by passing something by value as opposed to reference then you probably haven't done any coding outside of JASS and probably will not be able to help with this.

Because the following quote would only have helped me if I have never programmed before.
If you think of integers as objects (which can be treated as false-objects if you use structs), each time you do "local integer asdf = udg_Integer" you're making a copy of "udg_Integer", so that by changing asdf you are not changing udg_Integer, and by changing udg_Integer you are not changing asdf.




Another thing that I have found wrong that no one has corrected was the fact that I never set any values to the array, so even if you had any fix it wouldn't have worked.

JASS:
function ItemRecipe_2items_Conditions takes nothing returns boolean
    local integer asdf
    set asdf = udg_ItemRecipe_Counter
    if ( (UnitHasItemOfTypeBJ(GetTriggerUnit(), LoadInteger(udg_ItemRecipe, udg_ItemRecipe_ParentKey[asdf], 1)) == true) and (UnitHasItemOfTypeBJ(GetTriggerUnit(), LoadInteger(udg_ItemRecipe, udg_ItemRecipe_ParentKey[asdf], 2)) == true) ) then
        return true
    endif
    return false
endfunction

function ItemRecipe_2items_Actions takes nothing returns nothing   
    call RemoveItem( GetItemOfTypeFromUnitBJ(GetTriggerUnit(), LoadInteger(udg_ItemRecipe, udg_ItemRecipe_ParentKey[udg_ItemRecipe_Counter], 1)) )
    call RemoveItem( GetItemOfTypeFromUnitBJ(GetTriggerUnit(), LoadInteger(udg_ItemRecipe, udg_ItemRecipe_ParentKey[udg_ItemRecipe_Counter], 2)) )
    call UnitAddItemByIdSwapped(LoadInteger(udg_ItemRecipe, udg_ItemRecipe_ParentKey[udg_ItemRecipe_Counter], 0), GetTriggerUnit())
endfunction 

function ItemRecipe_2items takes integer i1, integer i2, integer created returns nothing
    
    local trigger ItemRecipe = CreateTrigger()
    local integer asdf
    
    set udg_ItemRecipe_Counter = udg_ItemRecipe_Counter + 1
    set udg_ItemRecipe_ParentKey[udg_ItemRecipe_Counter] = udg_ItemRecipe_Counter
    set asdf = udg_ItemRecipe_Counter
    
    call SaveInteger(udg_ItemRecipe, udg_ItemRecipe_ParentKey[asdf], 0, created)
    call SaveInteger(udg_ItemRecipe, udg_ItemRecipe_ParentKey[asdf], 1, i1)
    call SaveInteger(udg_ItemRecipe, udg_ItemRecipe_ParentKey[asdf], 2, i2)
        
    call TriggerRegisterAnyUnitEventBJ(ItemRecipe, EVENT_PLAYER_UNIT_PICKUP_ITEM)
    call TriggerAddCondition(ItemRecipe, Condition(function ItemRecipe_2items_Conditions))
    call TriggerAddAction(ItemRecipe, function ItemRecipe_2items_Actions)
  
endfunction

//===========================================================================
function InitTrig_Item_Recipes takes nothing returns nothing
    set udg_ItemRecipe = InitHashtable()

    call ItemRecipe_2items('ratf', 'ckng', 'modt')
    call ItemRecipe_2items('desc', 'rde4', 'ofro')
endfunction


With my understanding of JASS the local shouldn't be recycled until it has been set to null, so I don't see why this doesn't evaluate statically.
 

Jesus4Lyf

Good Idea™
Reaction score
397
Clearly the idea
Nothing is clear. Tell us what you would like to achieve. :)
If you don't understand what I mean by passing something by value as opposed to reference then you probably haven't done any coding outside of JASS and probably will not be able to help with this.
If you don't understand that it is impossible to pass an integer by reference in JASS, perhaps you don't know what passing by reference means.
This is what I want to happen.

udg_ItemRecipe_ParentKey[udg_ItemRecipe_Counter]
udg_ItemRecipe_ParentKey[1]
That is not something that can "happen". That is two expressions.
With my understanding of JASS the local shouldn't be recycled until it has been set to null, so I don't see why this doesn't evaluate statically.
Locals don't get recycled. Ever. Only agents' handle ids get recycled, as well as strings. If a local variable is of an agent type, therefore, its value can be destroyed, and when all references to its previous value are removed, the id (reference) will be recycled. This can only happen to an agent type local, and is generally irrelevant unless you're discussing cleaning leaks.

It seems to me that you're mixing up notions of compile-time and run-time, and not realising that [LJASS]set asdf = udg_ItemRecipe_Counter[/LJASS] is run every time the condition is evaluated, which is not statically done when the map starts up. Like I said before, conditions are much the same as actions. If the trigger is being fired by an event, putting a condition on a trigger as well as actions is the same as putting:
JASS:
if not (my condition) then
    return
endif

at the start of the trigger's actions, and not including the condition.

Would you like to tell us from a broader perspective (one that is not tied to any implementation) what it is which you are trying to achieve? It seems to be something to do with item recipes...
 

CaptainJack

New Member
Reaction score
2
1. I'm trying to achieve the way to pass an integer by value. I can't be any more clear, and this is the topic of the thread.

2. I'm perfectly aware there isn't a simple built in way to do this in JASS, which is why I am posing on here.

3. I am 100% aware that these are two expressions, I was using it to illustrate what passing by reference versus value would be. Maybe I need to draw a picture so that everyone can get what I mean. Otherwise:

REFERENCE: udg_ItemRecipe_ParentKey[udg_ItemRecipe_Counter]
VALUE: udg_ItemRecipe_ParentKey[1]

4. I am 100% aware that set asdf = udg_ItemRecipe_Counter is run EVERY TIME. And that is the point, because if you read the code you would see that I am creating a trigger for every single item.

Extra: So this would logically mean that if the local integer asdf isn't destroyed after run time, then it should retain the value of udg_ItemRecipe_Counter for that particular trigger.

The only thing I can see that might need to be done is null the ItemRecipe trigger reference, so that it can be reused with each execution of the code.
 

Bribe

vJass errors are legion
Reaction score
67
OK, I see where you are thinking now.

Locals are magic little creatures, they are simply amazing and horrific all at once. First time a function is run - asdf is intialized, then the function ends and ... asdf is lost forever. It's as if the integer never existed. Second time a function is run, asdf is initialized, then ceases to exist at the [ljass]endfunction[/ljass] line.

For some stupid, lame reason, handle-pointers need to be nulled while boolean/integer/real/string/code are treated as you would expect from them. Aside from that weirdness, you can consider locals to be privatized to within the scope of the function's single run-time and lost forever afterward.

If you have a TriggerSleepAction in the middle of the function, the local retains its value, so during that waiting period you can have that function be called many times - each instanciating a new version of asdf and remembering their designated value through the wait period (the perfect MUI example). That might be the coolest use of locals there is.

If you want to narrow a "local" to be synched to a trigger, you could try hashing the integer to the handle id of the trigger, using global variables (either hashtable or other indexing means).
 

CaptainJack

New Member
Reaction score
2
Alright it is good to know that basic types will exist properly in their scope. Though it doesn't help me in trying to pass something by value. Hopefully someone who hasn't read this will have a nice little juke to make it work.

Sgqvur, you also shouldn't post just to pad your post count.
 

saw792

Is known to say things. That is all.
Reaction score
280
We've told you repeatedly that basic types are passed by value. We don't have access to the "value" of any handle types.

What it seems you are actually looking for is a value that can be stored locally for a function, and retain it's value every time that function is called from a particular trigger. Which would then lead me to suggest trigger attachment, using a hashtable and GetHandleId(GetTriggeringTrigger()) as a parent key.

Might I also add that you have contradicted yourself a number of times in this thread and responded quite rudely to people asking for clarification. If a few of us veterans don't understand what you mean it's probably not our fault. You aren't the only one that codes in other programming languages.

EDIT: Also, this is most certainly not the best way to write a recipe system. If you will excuse my vJASS:
JASS:
library Recipes

  struct Recipe
      integer i1
      integer i2
      integer i3
      integer i4
      integer i5
      integer i6
      integer result
      
      static trigger t = CreateTrigger()
      static integer rcount = 0

      static method create takes integer item1, integer item2, integer item3, integer item4, integer item5, integer item6, integer newitem returns Recipe
        local Recipe r = Recipe.allocate()
        set r.i1 = item1
        set r.i2 = item2
        set r.i3 = item3
        set r.i4 = item4
        set r.i5 = item5
        set r.i6 = item6
        set r.result = newitem
        set rcount = rcount + 1
        return r
      endmethod

     
      static method completeCheck takes nothing returns boolean
        // Some lame overcomplicated loop through all items for all recipes
        return false
      endmethod

      static method onInit takes nothing returns nothing
         set t = CreateTrigger()
         call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_PICKUP_ITEM)
         call TriggerAddCondition(t, Condition(function Recipe.completeCheck))
      endmethod

  endstruct

endlibrary


I would probably just use unit attachment in the end anyway, or at least an array in the Recipe struct. Whichever way you approach it, recipes end up being lame.
 

CaptainJack

New Member
Reaction score
2
Looks like saw792 didn't actually read through the post, the idea of the thread was a nice workaround to pass an integer by value. Unfortunately you must have never tested a trigger before, because you can't actually pass an integer by value in JASS with this situation. The TriggerAddCondition() doesn't accept functions with parameters, nor does the TriggerAddAction() for that matter. Also if you couldn't tell, I have no desire to use vJASS. As far as your claiming I spend time contradicting myself, you must not have read anything because the variables are still being dynamically generated via the reference.

I already have my own solution utilizing hashtables plus H2I (GetHandleId), but I would still love to see a clever way of passing by value. (Even if it is in vJASS)
 

saw792

Is known to say things. That is all.
Reaction score
280
*Sigh*

I did read the thread. You don't need a workaround to pass an integer by value, since you can't pass it any other way. There is no clever workaround, because the entire concept is entirely retarded within the confines of JASS. Learn how to code properly in JASS before you start trying to throw your weight around and accusing me of not understanding.
 

CaptainJack

New Member
Reaction score
2
If you pulled your head out of the sand, you would have seen that I already have my own solution for a problem that would require this. Secondly, you must not understand the concept of passing something by value, because the only thing you can use in a condition is a statically typed value or a reference. So don't say that you understand, when you clearly aren't getting what is being asked. Obviously a scripting language is going to be extremely limited, but that doesn't mean clever solutions shouldn't be sought. And passing something by value isn't retarded within any programming language, even if it is a simple scripting language like JASS.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top