• 🏆 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] [Snippet] GUI Unit Indexer -> vJass Plugin

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
GUI Unit Indexer with vJass syntax has been realized with this groundbreaking tool. The idea for this came from the user, Spellbound.

Note that no changes to the GUI code were needed to make this happen, so the only thing a user would need to do is import this script and make the library a requirement to libraries who call its functions. The implication of this, I suppose, is that GUI Unit Indexer can now be used for vJass resources.

Notably different than Nestharus' API, I have included OnUnitIndex and OnUnitDeindex which are shorter to write and are not ugly. They also take a single code argument instead of a boolexpr and integer argument. The function "OnUnitDeindex" will normally fire at a random time after a unit has left the game, if you want it to fire at the instant before the unit becomes unavailable, you'll want to have the GUI Unit Event resource in your system: http://www.hiveworkshop.com/forums/spells-569/unit-event-v2-0-0-0-a-201641/

JASS:
library UnitIndexerGUI //requires GUI Unit Indexer
    
    globals
        private trigger index = null
        private trigger deindex = null
        private trigger init = null
        private trigger tempTrig
    endglobals

    private function DoTheThings takes trigger t, code c, real r returns trigger
        if t == null then
            set t = CreateTrigger()
            call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, r)
        endif
        call TriggerAddCondition(t, Filter(c))
        set tempTrig = t
        set t = null
        return tempTrig
    endfunction

    //call RegisterUnitIndexEvent(Filter(function Blah), EVENT_UNIT_INDEXED)
    //->
    //call OnUnitIndex(function Blah)
    function OnUnitIndex takes code c returns nothing
        set index = DoTheThings(index, c, 1.)
    endfunction

    //call RegisterUnitIndexEvent(Filter(function Blah), EVENT_UNIT_DEINDEXED)
    //->
    //call OnUnitDeindex(function Blah)
    function OnUnitDeindex takes code c returns nothing
        set deindex = DoTheThings(deindex, c, 2.)
    endfunction

    private function DestroyInit takes nothing returns boolean
        call DestroyTrigger(init) //will still allow consecutive triggerconditions to run.
        set init = null
        return false
    endfunction

    //GUI Unit Indexer will initialize after any vJass stuff, so you need to do your
    //unit-indexer-requiring stuff after this event instead of a module/struct/library
    //initializer.
    function OnUnitIndexerInitialized takes code c returns nothing
        if init == null then
            set init = CreateTrigger()
            call TriggerAddCondition(init, Filter(function DestroyInit))
            call TriggerRegisterVariableEvent(init, "udg_UnitIndexEvent", EQUAL, 3.00)
        endif
        call TriggerAddCondition(init, Filter(c))
    endfunction

    function GetUnitId takes unit u returns integer
        return GetUnitUserData(u)
    endfunction

    function GetUnitById takes integer id returns unit
        return udg_UDexUnits[id]
    endfunction

    function GetIndexedUnit takes nothing returns unit
        return udg_UDexUnits[udg_UDex]
    endfunction

    function GetIndexedUnitId takes nothing returns integer
        return udg_UDex
    endfunction

    function IsUnitIndexed takes unit u returns boolean
        return udg_UDexUnits[GetUnitUserData(u)] == u
    endfunction

endlibrary
 
Last edited:
Day 5516:

I've just gotten back from the battlefield. Until this day, it seemed as though the war between GUI and JASS would never cease. This day... *teardrop lands onto page* GUI has struck a major blow. General Bribe and his harlots revealed a new weapon. It is a weapon so devious that my very comrades are already turning over to his side. One by one, they use his so called "plug-in". Next thing you know, they start prefixing their globals with udg_ and talking about how fast they can click through the menus. I fear that this may be the end of our dynasty. I only wish... *pen falls* *bombs echo in the distance* *Bribe's temptresses wrap their arms around the Colonel* *screen fades to black*


(he ded)

But on a serious note, never thought I'd see a GUI system used for vJASS. Seems fine to me apart from the name of "DoStuff" (as Maker mentioned). Should be approvable.
 
Riiiiiiight, so little problem. I tried importing Bannar's ConstructEvent and for one, I was getting errors from JassHelper. So I imported the RegisterPlayerUnitEvent by Magtheridon96 and it saved without any other errors.

Now when I try to use GetStructureBuilder(), JassHelper says not enough arguments. set udg_TempUnit = GetStructureBuilder() more specifically. A friend tested ConstructEvent on a dummy map and used TriggerHappy's indexer instead, and he was not required to have RegisterPlayerUnitEvent; set udg_TempUnit = GetStructureBuilder() also worked. So I'm assuming there are still some compatibility issues to iron out? I did replace the code in Bannar's library like you told me to in PM, Bribe, so it could be something else.

JASS:
function Trig_Taskmaster_Build_JASS_Func003Func002A takes nothing returns nothing
    call IssueTargetOrderBJ( udg_TempUnit, "smart", GetTriggerUnit() )
endfunction

function Trig_Taskmaster_Build_JASS_Func003C takes nothing returns boolean
    if ( not ( GetUnitTypeId(udg_TempUnit) == 'uaco' ) ) then
        return false
    endif
    if ( not ( IsUnitInGroup(udg_TempUnit, udg_Boss_group) == true ) ) then
        return false
    endif
    return true
endfunction

function Trig_Taskmaster_Build_JASS_Actions takes nothing returns nothing
    set udg_TempUnit = GetEventBuilder()
    call AddSpecialEffectLocBJ( GetUnitLoc(udg_TempUnit), "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl" )
    if ( Trig_Taskmaster_Build_JASS_Func003C() ) then
        set udg_ID = GetUnitUserData(udg_TempUnit)
        call ForGroupBJ( udg_Minion_group[udg_ID], function Trig_Taskmaster_Build_JASS_Func003Func002A )
    else
    endif
endfunction

//===========================================================================
function InitTrig_Taskmaster_Build_JASS takes nothing returns nothing
    set gg_trg_Taskmaster_Build_JASS = CreateTrigger(  )
    call TriggerRegisterConstructEvent(gg_trg_Taskmaster_Build_JASS, ConstructEvent.START)
    call TriggerAddAction( gg_trg_Taskmaster_Build_JASS, function Trig_Taskmaster_Build_JASS_Actions )
endfunction
The special effect is just to know if it worked. I'll be removing it afterwards.


PS: as a habitual GUI user, commenting in the JASS section feels like... a filthy human tracking mud in pristine elven halls :D
 
Last edited:
I have tried that already, but nothing happens. The code in my post was from the demo map and it worked. When I use it in my own map, I get missing arguments (as expected), and using GetEventBuilder() doesn't do anything. I tried with vanilla GUI events (unit begins construction) as well as call TriggerRegisterConstructEvent(gg_trg_Taskmaster_Build_JASS, ConstructEvent.START) for the JASS version and neither seems to work. I'm not sure what I'm doing wrong.
 

Zwiebelchen

Hosted Project GR
Level 35
Joined
Sep 17, 2009
Messages
7,236
tumblr_mwzmy7UNKq1rss05ao1_250.gif
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
The irony here is that this API is almost identical to Nestharus' first iteration of UnitIndexer, a project I was really interested in due to the fact that it was the most minimalistic approach possible. UnitIndexer now has over 9,000 requirements and lines of code (if you include static ifs and the libraries it requires, it's probably almost 9000 to be slightly less sarcastic).
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
why did you split the resource to two libraries? the only function inside RealEvent could just as much be private function at the top of the UnitIndexerGUI lib. which would also reduce library name pollution(library_once is very deadly, because if I make one myself with the same name, I may be wondering why Im getting syntax errors, because only your version is parsed)
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
I love the On(De)IndexUnit event, its not eye sore and doesnt require a tutorial to use unlike the other one.

I wonder tho, is the lazy initialization needed? because right now you have to evaluate both conditions every time you call the DoThings function, which could be potentially dropped down to one if you were to pre-initialize the triggers inside module or struct or whatnot + then you wouldnt need to return the trigger. I also dont really see why you reassign the trigger to itself(since the param t is returned effectively).

If you didnt return it, you probably wouldnt need the tempTrig shenanigans either + you would save yourself an assignment inside the API calls.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Thank you for bringing that to my attention. I've gone ahead and fixed a bug when you made me ponder my script for a bit. The function was previously going to bug in most circumstances. With that change, the event only gets created once. I suppose I could attach a boolean "IsTriggerWaitOnSleeps" instead of creating them like that, but I think this is fine.

Edit: I've also made it so that the OnUnitIndexerInitialized trigger is destroyed the first time it's run, since it only needs to be used once.
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
There is not much that can go wrong in here, since it is a thin wrapper around already proof-tested and approved GUI resource, and it has somewhat compatible API to other resources + I like the onUnitIndex/Deindex more than RegisterUnit...Event(u, UNIT_INDEXED, function) so yeah, I vote for approval(since I am of lower rank in the hierarchy, I would rather someone else also say if its approved)
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
I came. I saw.

JASS:
   function GetUnitById takes integer id returns unit
       return udg_UDexUnits[id]
   endfunction

   function GetIndexedUnit takes nothing returns unit
       return udg_UDexUnits[udg_UDex]
   endfunction

   function GetIndexedUnitId takes nothing returns integer
       return udg_UDex
   endfunction

   function IsUnitIndexed takes unit u returns boolean
       return udg_UDexUnits[GetUnitUserData(u)] == u
   endfunction

I came again. Thank you for this plugin!
 
Level 15
Joined
Nov 30, 2007
Messages
1,202
I honestly think you should just recreate the GUI-Unit Indexer within a vJass library structure and use the same GUI-variables rather than this. The wrappers are good but there is no point in separating the two resources except for that you can of course. Though I understand that some people still use older versions of wc3 that don't support vjass directly?
 
Last edited:
Top