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

Question about textmacro's

Status
Not open for further replies.
Level 14
Joined
Apr 20, 2009
Messages
1,543
Is it possible to use local or global variables inside textmacro's?

What I try to do is the following:

JASS:
 function myFunction takes nothing returns boolean
        local unit triggeringUnit = GetTriggerUnit()
        local integer i = 1
        local string digits
        loop
            exitwhen i > 60
            if (i < 10) then
                set digits = "000" + I2S(i)
            elseif (i < 100) then
                set digits = "00" + I2S(i)
            endif
            //! runtextmacro SetType(digits)
            //! textmacro SetType takes n
                if (triggeringUnit == gg_unit_h00J_$n$) then 
            //! endtextmacro
                    set tempInteger = i
                    return true
                endif
            set i = i + 1
        endloop
        return true
    endfunction

This doesn't seem to work. Is there any workaround in doing this?
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
Level 14
Joined
Apr 20, 2009
Messages
1,543
You save them somewhere, maybe in a Table / Hashtable / unit array. Up to you.

I know this can be used instead, but I was simply wondering if this was possible. It would save me some time in this case.

You can use locals and globals inside textmacros too. Lua is something different than textmacros.
How would I use locals and globals inside textmacro's?
Isn't Lua only supposed to work for object generation?

For example:
JASS:
//! externalblock extension=lua FileExporter $FILENAME$
    //! runtextmacro LUA_FILE_HEADER()
    //! i writelua("PitchRollDests", [[
    
        //! i dofile("GetVarObject")
    
        //! i function barrelroll(pitch, roll, name)
            //! i local dest = getvarobject("LTbx", "destructables", "DESTRUCTABLES_" .. name, false)
            //! i createobject("LTbx", dest)
            //! i makechange(current, "bnam", name)
            //! i makechange(current, "bmap", pitch)
            //! i makechange(current, "bmar", roll)
        //! i end
        
        //! i function barrelgen(name, count)
            //! i local factor = 6.28/(count-1)
            //! i local angle  = 0
            //! i for i=1, count do
                //! i barrelroll(angle, angle, name .. " [" .. i .. "]")
                //! i angle = angle - factor
            //! i end
        //! i end
    //! i ]])
//! endexternalblock
Wouldn't that script create objects inside the object editor? This should basically only provide functions to create the objects in the object editor right?
I'm trying to refference preplaced units so I don't think Lua will be abled to help me with that would it?

If it's possible to use locals and globals inside textmacro's, then could you give me an example on how to do what I'm trying to do?
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Gui generated variables (gg_...) are only created once you've selected the preplaced thing on the map through the GUI (and then you can delete this dummy GUI action), before that they just don't exist in the map script.
Maybe that's your problem.

But yes you shouldn't use them, just use a vjass global variable, and eventually you can give a gg_.. pointer to this variable, this way your code is more modular.

EDIT :

And textmacros are not dynamic, they need a litteral string, it can't take a variable one because the jass code is generated on compilation, so you can't use them like you did.
I suggest you to read more the jasshelper documentation.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
Gui generated variables (gg_...) are only created once you've selected the preplaced thing on the map through the GUI (and then you can delete this dummy GUI action), before that they just don't exist in the map script.
Maybe that's your problem.

Thanks I totally forgot about this :D!

But yes you shouldn't use them, just use a vjass global variable, and eventually you can give a gg_.. pointer to this variable, this way your code is more modular.

Could you perhaps give an example on pointing the variable towards a gg_ in a loop ^.^? I just can't seem to get this working >.<

EDIT:


EDIT :
And textmacros are not dynamic, they need a litteral string, it can't take a variable one because the jass code is generated on compilation, so you can't use them like you did.
I suggest you to read more the jasshelper documentation.

Yes I just read that in the thread I refferenced in this thread earlier: http://www.thehelper.net/threads/jass-globals-in-textmacros-lua.149069/
And you're right I should probably read the documentation more :p
 
Thanks I totally forgot about this :D!
That's exactly what I said here:
I think your main problem id GUI automatically creates the globals while in JASS you have to create them yourself. You can use locals and globals inside textmacros too. Lua is something different than textmacros.

Could you perhaps give an example on pointing the variable towards a gg_ in a loop ^.^? I just can't seem to get this working >.<
Something like this:

JASS:
//! textmacro SetGlobal takes INT
globals
    unit gg_SOMETHING_$INT$ = null
endglobals
//! endtextmacro

//! textmacro UseGlobal takes INT
    set gg_SOMETHING_$INT$ = CreateUnit(Player(0), 'hpea', 0., 0., 0.)
//! endtextmacro

// inside a library / scope
//! runtextmacro SetGlobal("1")

// somewhere in a function
//! runtextmacro UseGlobal("1")
However, I don't suggest you to do it ...

Edit:
You can even do this:
JASS:
globals
    integer COUNTER = 5
endglobals

//! textmacro SetGlobal takes INT
globals
    unit gg_SOMETHING_$INT$ = null
endglobals
//! endtextmacro

//! textmacro UseGlobal takes INT
    set gg_SOMETHING_$INT$ = CreateUnit(Player(0), 'hpea', 0., 0., 0.)
//! endtextmacro

// inside a library / scope
//! runtextmacro SetGlobal("1")
//! runtextmacro SetGlobal("2")
//! runtextmacro SetGlobal("3")
//! runtextmacro SetGlobal("4")
//! runtextmacro SetGlobal("5")

function CreateGlobalsInLoop takes nothing returns nothing
    loop
        exitwhen COUNTER == 0
        
        //! runtextmacro UseGlobal(COUNTER)
        set COUNTER = COUNTER -1
    endloop
endfunction
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Excepted that gg_ variables are not created automatically but requires a selection of the "thing" by the mapmaker ?
I mean preplaced "things" have not automatically their gg_ variable.

EDIT :

Your last example is wrong, as said textmacros requires a litteral string, not a variable one.
COUNTER is a variable.

And anyway using the same naming global convention than the GUI is a big no.

Basically textmacros are just a copy/paste with static arguments
 
Okay Troll-Brain, since you like to be specific, here is how it works:
The GUI has a selector engine which will write a global variable whenever you use the selector and the unit is not yet registered.
This engine of course can only be triggered when using the Gui "Select Unit / Select XXX" option of the target handle.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
I just like the accucary, you were not enough clear, that was hardly exactly what you said before, that's all.
In fact it could be interpreted like gg_ variables were always automatically created, or at least that's what i've understood (but i can fail ofc)

Also see my edit.
 
Troll-Brain,
since I don't use " in my call I can pass variables too.
I did it in my CustomInventory too.
Yes, it works, just try it yourself.

Edit:
I was wrong, I mean this works:
JASS:
/* ----------------------------------- *//*
    Version: 0.1
    Author: Anachron
    Date: 04th Jan 2010
    
    Release information:
    Do not use this library without 
    copyright information.
    
    Copyright 2009
    
    This is the general container.
*/
/* ----------------------------------- */
library CIAll requires Table, AdvancedTable, CIWindow, CustomWindow, CIContent,
    
    //! textmacro CIAll_NewButton takes DEST_ID, X, Y, DESTSAFE, TRACKSAFE, WINDOW, PLAYER, SIZE
    set $TRACKSAFE$ = $WINDOW$.createTrack($PLAYER$, "CustomWindow\\Track75.mdx", CI_UI_BASE_X +$X$, CI_UI_BASE_Y +$Y$, 0., 0.)
    set $DESTSAFE$  = $WINDOW$.createDestructable($PLAYER$, $DEST_ID$, $SIZE$ +.01, CI_UI_BASE_X +$X$, CI_UI_BASE_Y +$Y$, 0., 270)
    //! endtextmacro

    struct CIAll
        public IntegerTable    Buttons      = 0
        public IntegerTable    Tracks       = 0
        public BooleanTable    HasItem      = 0
        public ItemTable       Items        = 0
        
        public CustomWindow    window       = 0
        public CustomInventory inventory    = 0
        public CIContent       content      = 0
        
        public Table            ItemToSlot  = 0
        public Table            SlotToItem  = 0
        
        public integer         maximum      = 0
        
        public stub method init takes nothing returns nothing
        endmethod
        public stub method refresh takes nothing returns nothing
        endmethod
        public stub method pick takes CustomItem ci returns nothing
        endmethod
        public stub method pickCond takes CustomItem ci, integer slot returns boolean
            return true
        endmethod
        public stub method drop takes CustomItem ci returns nothing
        endmethod
        public stub method dropCond takes CustomItem ci, integer slot returns boolean
            return true
        endmethod
        public stub method getSlotIcon takes integer slot returns integer
            return -1
        endmethod
        
        public static method create takes integer m, CustomWindow w, CustomInventory i, CIContent c returns thistype
            local thistype this = thistype.allocate()
            
            set .maximum = m
            set .window = w
            set .inventory = i
            set .content = c
            
            set Buttons     = IntegerTable.create()
            set Tracks      = IntegerTable.create()
            set HasItem     = BooleanTable.create()
            set Items       = ItemTable.create()
            
            set ItemToSlot  = Table.create()
            set SlotToItem  = Table.create()
            
            return this
        endmethod
        
        public method refreshSlot takes integer slot returns nothing
            local real x = CWTrackAble(.Tracks[slot]).getX()
            local real y = CWTrackAble(.Tracks[slot]).getY()
            local player slotPlayer = GetOwningPlayer(.inventory.getOwner())
            local integer slotDest = .getSlotIcon(slot)
            
            call CWDestructable(.Buttons[slot]).destroy()
            set .Buttons[slot] = .window.createDestructable(slotPlayer, slotDest, .76, x, y, .1, 270)
        endmethod
        
        public method addItemToSlot takes CustomItem ci, integer slot returns boolean
            local integer ID = GetHandleId(ci.getHandle())
            
            if not .HasItem[slot] then
                if .pickCond(ci, slot) then
                    set .ItemToSlot[ID] = slot
                    set .SlotToItem[slot] = ID
                    set .Items[slot] = ci.getHandle()
                    set .HasItem[slot] = true
                    
                    call .refreshSlot(slot)
                    call .pick(ci)
                    return true
                else
                    static if LIBRARY_CIError then
                        call CIError.create(4, 1, GetOwningPlayer(.inventory.getOwner()), "You can't equip this item.")
                    else
                        debug call BJDebugMsg("|cffffcc00" + SCOPE_PREFIX + "Error|r: " + "Can't equip item!")
                    endif
                endif
            else
                static if LIBRARY_CIError then
                    call CIError.create(4, 1, GetOwningPlayer(.inventory.getOwner()), "This slot is already in use.")
                else
                    debug call BJDebugMsg("|cffffcc00" + SCOPE_PREFIX + "Error|r: " + "This slot is already in use!")
                endif
            endif
            
            
            return false
        endmethod
        
        public method addItem takes CustomItem ci returns boolean
            local integer i = 0
            
            loop
                exitwhen i >= .maximum
                
                if not .HasItem[i] then
                    return .addItemToSlot(ci, i)
                endif
                
                set i = i +1
            endloop
            
            return false
        endmethod
        
        public method moveItemToSlot takes CustomItem ci, integer targ returns boolean
            local integer id = GetHandleId(ci.getHandle())
            local integer slot = .ItemToSlot[id]
            
            if .HasItem[targ] then
                return false
            endif
            
            call .removeItemFromSlot(slot)
            call .addItemToSlot(ci, targ)
            return true
        endmethod
        
        public method switchItems takes CustomItem left, CustomItem right returns boolean
            local integer slotOne   = getItemSlot(left)
            local integer idOne     = GetHandleId(left.getHandle())
            local integer slotTwo   = getItemSlot(right)
            local integer idTwo     = GetHandleId(right.getHandle())
            
            if slotOne != -1 and slotTwo != -1 then
                set .ItemToSlot[idOne]     = slotTwo
                set .SlotToItem[slotOne]   = idTwo
                set .Items[slotOne]        = right.getHandle()
                set .HasItem[slotOne]      = true
                
                set .ItemToSlot[idTwo]     = slotOne
                set .SlotToItem[slotTwo]   = idOne
                set .Items[slotTwo]        = left.getHandle()
                set .HasItem[slotTwo]      = true
                
                call .refreshSlot(slotOne)
                call .refreshSlot(slotTwo)
                
                return true
            endif
            
            return false
        endmethod
        
        public method removeItemFromSlot takes integer slot returns boolean
            local CustomItem slotItem = CustomItem.load(.SlotToItem[slot])
            if not .HasItem[slot] then
                return false
            endif
            
            if not .dropCond(slotItem, slot) then
                static if LIBRARY_CIError then
                    call CIError.create(4, 1, GetOwningPlayer(.inventory.getOwner()), "You can't drop this item.")
                else
                    debug call BJDebugMsg("|cffffcc00" + SCOPE_PREFIX + "Error|r: " + "You can't drop this item.")
                endif
                return false
            endif
            
            call .ItemToSlot.flush(GetHandleId(.Items[slot]))
            call .SlotToItem.flush(slot)
            set .HasItem[slot] = false
            set .Items[slot] = null
            call .refreshSlot(slot)
            
            call .drop(slotItem)
            return true
        endmethod
        
        public method removeItem takes CustomItem ci returns boolean
            return .removeItemFromSlot(.getItemSlot(ci))
        endmethod
        
        public method getItemSlot takes CustomItem ci returns integer
            local integer id = GetHandleId(ci.getHandle()) 
            
            if not .ItemToSlot.exists(id) then
                return -1
            endif
            
            return .ItemToSlot[id]
        endmethod
        
        public method getSlotItem takes integer slot returns CustomItem
            return CustomItem.load(.SlotToItem[slot])
        endmethod
        
        public method hasItem takes CustomItem ci returns boolean
            return .getItemSlot(ci) != -1
        endmethod
        
        public method hasSlotItem takes integer slot returns boolean
            return .SlotToItem[slot] != 0
        endmethod
        
        public method check takes CustomItem ci returns boolean
            return not .hasItem(ci)
        endmethod
        
        public method compareTracks takes CWTrackAble eventTrack, integer slot returns boolean
            return .Tracks[slot] == eventTrack
        endmethod
    endstruct

endlibrary

JASS:
/* ----------------------------------- *//*
    Version: 0.1
    Author: Anachron
    Date: 04th Jan 2010
    
    Release information:
    Do not use this library without 
    copyright information.
    
    Copyright 2009
    
    This is the container for slots.
*/
/* ----------------------------------- */
library CISlots requires CIAll

    globals
        private real tmpX = 0.
        private real tmpY = 0.
    endglobals

    struct CISlots extends CIAll
    
        public method init takes nothing returns nothing
            local integer rows = 4
            local integer columns = 5
            local integer max = rows * columns
            local integer r = 0
            local integer c = 0
            local integer nr = 0
            
            loop
                exitwhen r >= rows
                    set c = columns -1
                    loop
                        exitwhen c < 0
                    
                        //! runtextmacro CIAll_NewButton("'cwit'", "(c - columns/2) * 64.", " -32. + (r - rows/2) * 64.", ".Buttons[(max -1) -nr]", ".Tracks[(max -1) -nr]", ".window", "GetOwningPlayer(.inventory.getOwner())","0.75")
                        set .HasItem[nr] = false
                        set .Items[nr] = null
                        
                        set nr = nr +1
                        set c = c -1
                    endloop
                set r = r +1
            endloop
        endmethod
        
        public method refresh takes nothing returns nothing
            local CustomInventory   inv         = .inventory
            local CIEquips          equip       = .content.getEquipment()
            local CIPotions         potions     = .content.getPotions()
            local CustomItem        ci          = 0
            local integer           i           = 0
            
            loop
                exitwhen i >= .maximum
                
                set ci = .getSlotItem(i)
                if not inv.hasItem(ci) or ci == 0 then 
                    call .removeItemFromSlot(i)
                endif
                set i = i +1
            endloop
            
            set i = 0
            set ci = 0
            loop
                exitwhen i >= inv.getIndex() or i >= .maximum
                
                set ci = inv.getItem(i)
                if ci != 0 and not .hasItem(ci) then
                    if not equip.hasItem(ci) and not potions.hasItem(ci) then
                        call .addItem(ci)
                    endif
                endif
                
                set i = i +1
            endloop
        endmethod
        
        private method getSlotIcon takes integer slot returns integer
            local integer destID = -1
            static if LIBRARY_CIItemDest then
                if .getSlotItem(slot) != 0 then
                    set destID = .getSlotItem(slot).dest
                endif
            endif
            
            if destID != -1 then
                return destID
            endif
            return 'cwit'
        endmethod
        
        public method pick takes CustomItem ci returns nothing
            return
        endmethod
        
        public method pickCond takes CustomItem ci, integer slot returns boolean
            return GetUnitState(.inventory.getOwner(), UNIT_STATE_LIFE) >= 1.
        endmethod
        
        public method drop takes CustomItem ci returns nothing
            return
        endmethod
        
        public method dropCond takes CustomItem ci, integer slot returns boolean
            return GetUnitState(.inventory.getOwner(), UNIT_STATE_LIFE) >= 1.
        endmethod
        
    endstruct

endlibrary
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Troll-Brain,
since I don't use " in my call I can pass variables too.
I did it in my CustomInventory too.
Yes, it works, just try it yourself.

What ?!
It can't be, since textmacros are "compiled" on script save.
So it can't guess what's the value of COUNTER, maybe it doesn't pop up an error, but that can't work.
Check the outputwar3map.j
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
Thanks for all the help and explanations guys, I decided to do it this way though:

JASS:
library IncreaseTalent initializer Init
    globals
        integer tempInteger = 0
    endglobals

    private function checkIfCanSpend takes nothing returns boolean
       local unit triggeringUnit = GetTriggerUnit()
       local integer i = 1
       local string digits
       loop
          exitwhen i > 60
           //! textmacro SetType takes n
               if (triggeringUnit == gg_unit_h00J_$n$) then 
                   set tempInteger = i
                   return true
               endif
            //! endtextmacro
            //! runtextmacro SetType("0001")
            //! runtextmacro SetType("0002")
            //! runtextmacro SetType("0003")
            //! runtextmacro SetType("0004")
            //! runtextmacro SetType("0005")
            //! runtextmacro SetType("0006")
            //! runtextmacro SetType("0007")
            //! runtextmacro SetType("0008")
            //! runtextmacro SetType("0009")
            //! runtextmacro SetType("0010")
            //! runtextmacro SetType("0011")
            //! runtextmacro SetType("0012")
            //! runtextmacro SetType("0013")
            //! runtextmacro SetType("0014")
            //! runtextmacro SetType("0015")
            //! runtextmacro SetType("0016")
            //! runtextmacro SetType("0017")
            //! runtextmacro SetType("0018")
            //! runtextmacro SetType("0019")
            //! runtextmacro SetType("0020")
            //! runtextmacro SetType("0021")
            //! runtextmacro SetType("0022")
            //! runtextmacro SetType("0023")
            //! runtextmacro SetType("0024")
            //! runtextmacro SetType("0025")
            //! runtextmacro SetType("0026")
            //! runtextmacro SetType("0027")
            //! runtextmacro SetType("0028")
            //! runtextmacro SetType("0029")
            //! runtextmacro SetType("0030")
            //! runtextmacro SetType("0031")
            //! runtextmacro SetType("0032")
            //! runtextmacro SetType("0033")
            //! runtextmacro SetType("0034")
            //! runtextmacro SetType("0035")
            //! runtextmacro SetType("0036")
            //! runtextmacro SetType("0037")
            //! runtextmacro SetType("0038")
            //! runtextmacro SetType("0039")
            //! runtextmacro SetType("0040")
            //! runtextmacro SetType("0041")
            //! runtextmacro SetType("0042")
            //! runtextmacro SetType("0043")
            //! runtextmacro SetType("0044")
            //! runtextmacro SetType("0045")
            //! runtextmacro SetType("0046")
            //! runtextmacro SetType("0047")
            //! runtextmacro SetType("0048")
            //! runtextmacro SetType("0049")
            //! runtextmacro SetType("0050")
            //! runtextmacro SetType("0051")
            //! runtextmacro SetType("0052")
            //! runtextmacro SetType("0053")
            //! runtextmacro SetType("0054")
            //! runtextmacro SetType("0055")
            //! runtextmacro SetType("0056")
            //! runtextmacro SetType("0057")
            //! runtextmacro SetType("0058")
            //! runtextmacro SetType("0059")
            //! runtextmacro SetType("0060")
           set i = i + 1
       endloop
       return false
   endfunction
    
    private function Increase takes nothing returns nothing
        
    endfunction

    private function Init takes nothing returns nothing
        local integer i
        local trigger t = CreateTrigger()
        loop
            exitwhen i > bj_MAX_PLAYERS
                call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SELECTED, null)
            set i = i + 1
        endloop
        call TriggerAddCondition(t, Condition(function checkIfCanSpend))
        call TriggerAddAction(t, function Increase )
    endfunction
endlibrary

Seems to work so far. +rep to the both of you.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
I suppose you guys are right :/
I'm gonna do a unit user data refference instead.

Plus not too mention that I can't nest more then 50 ifs ^.^

I need to find a way to make bribes unit indexer index a specific type of unit first though :/
I think I can manage.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
there are some other GUI systems that rely on the GUI unit indexer >.>

I preferr using your Unit Indexer instead but since I'm working with GUI'ers I'll have to do it this way...
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
I totally forgot about static ifs, that might actually be quite a good idea :D

Thanks Nestharus!
 
Status
Not open for further replies.
Top