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

[System] OnDoubleClick {Trackable2}

Level 11
Joined
Sep 12, 2008
Messages
657
i've made a struct that allows you to bind a trigger to a double click on a trackable,
basicly, it uses trackable2, allthought it probably shouldn't,
but i guess it is better for now, since it also allows me to use the event registry, and get the activating player, any how, heres the code and a example code:
JASS:
library OnDoubleClick requires Trackable2
    globals
        constant integer Max_Instances = 10
        //--------------------------------------------------------------
        //Max_Instances
        //
        // This value will indicate how many trackables are allowed to be followed per struct.
        // When you reach limit, it will not allow you to create any more.
    endglobals
    
    struct onDoubleClick
        private static hashtable TimerHash = InitHashtable()
        public static integer InstanceCount = 0
        public integer c
        public Trackable2 array tra[Max_Instances]
        public Event array ev[Max_Instances]
        public trigger array tri[Max_Instances]
        public timer array tim[Max_Instances]
        public real array timeout[Max_Instances]
        public boolean array two[Max_Instances]
        public player array last[Max_Instances]
        
        public Trackable2 lastTrack
        public player lastPlayer
        
        public static method create takes nothing returns thistype
            local integer this = thistype.allocate()
            set InstanceCount = InstanceCount + 1
            return this
        endmethod
        
        public method register takes trigger callback, Trackable2 listened, real timeDiffrence returns EventReg
            local trigger t = CreateTrigger()
            local EventReg r
            set c=c+1
            if c <= Max_Instances - 1 then
                set .ev[c] = Event.create()
                set r = ev[c].register(callback)
                set r.data = this
                set .tri[c] = callback
                set .tra[c] = listened
                set .tim[c] = CreateTimer()
                set .timeout[c] = timeDiffrence
                call TriggerAddCondition(t, Filter(function thistype.onClick))
                call listened.registerClick(t)
            else
                debug call BJDebugMsg("|c00FF0000[ERROR]|r |c000000FFonDoubleClick: |r|c0000FF00Trying to register more then " + I2S(Max_Instances) + " trackables into a single struct.|r")
                return null
            endif
            return r
        endmethod
        
        private static method resetData takes nothing returns nothing
            local timer t = GetExpiredTimer()
            local thistype id = LoadInteger(TimerHash, GetHandleId(t), 0)
            local integer c = LoadInteger(TimerHash, GetHandleId(t), 1)
            
            set id.two[c] = false
            set id.last[c] = null
        endmethod
        
        private static method onClick takes nothing returns boolean
            local Trackable2 tracked = GetTriggeringTrackable2()
            local thistype t = 1
            local integer c = 1
            local integer co = 1
            
            loop
            exitwhen c>=InstanceCount + 1
            set t=thistype(c)
            loop
            exitwhen co>=t.c + 1
            if t.tra[co] == tracked then
                set t.last[co]=GetTrackedPlayer()
                set t.lastTrack=tracked
                set t.lastPlayer=t.last[co]
                if t.two[co] then
                    call t.ev[co].fire()
                    set t.two[co]=false
                    return false
                endif
                set t.two[co]=true
                call TimerStart(t.tim[co], t.timeout[co], false, function thistype.resetData)
                call SaveInteger(TimerHash, GetHandleId(t.tim[co]), 0, integer(t))
                call SaveInteger(TimerHash, GetHandleId(t.tim[co]), 1, co)
            endif
            set co=co+1
            endloop
            set c=c+1
            endloop
            
            
            return false
        endmethod
    endstruct
endlibrary

The commands from onDoubleClick struct:

JASS:
public static method create takes nothing returns thistype
public method register takes trigger callback, Trackable2 listened, real timeDiffrence returns EventReg

in register, the returned EventReg contains the struct index, so you can use it aswell, heres an example on how to use it:
JASS:
library CreateHero initializer onInit uses OnDoubleClick

    private function OnDoubleClick takes nothing returns boolean
        local Trackable2 tr
        local player tp
        local integer id
        local EventReg ev
        local onDoubleClick odc
        
        //2 ways to create the unit
        
        //Option #1                                     // Okay, basicly, the 2 options
        set tr = GetTriggeringTrackable2()              // are same, its better to use first option,
        set tp = GetTrackedPlayer()                     // but if you want to use solely the 
        set id = tr.userData                            // OnDoubleClick library, i'd sugguest
        call CreateUnit(tp, id, tr.X, tr.Y, tr.Facing)  // using the second option, but you must remember
        set tp = null                                   // the second option uses exactly what the first option
        //Option #2                                     // uses, its just that the second option automaticly sets
        set ev = Event.getTriggeringEventReg()          // it as variables, with Trackable2 call
        set odc = ev.data                               // while the first option is using Trackable2 callbacks directly.
        set tr = odc.lastTrack                          // I have no clue what is better to use, but thats up to you i guess..
        set tp = odc.lastPlayer                         //
        set id = tr.userData                            // Happy coding =]
        call CreateUnit(tp, id, tr.X, tr.Y, tr.Facing)  //
        set tp = null
        
        return false
    endfunction
    private function onInit takes nothing returns nothing
        local trigger t = CreateTrigger()
        local Trackable2 tr = Trackable2.create("units\\human\\HeroPaladin\\HeroPaladin.mdl",0,  0,  0,  180)
        //                                            Paladin From Human Race Model Path    x=0,y=0,z=0 facing = 180 = downwards,
        //                                                                                              downards makes it look better.
        local onDoubleClick c = onDoubleClick.create()
        set tr.userData = 'Hpal'
        call TriggerAddCondition(t, Filter(function OnDoubleClick))
        call c.register(t, tr, 0.5)
    endfunction
endlibrary

I have no clue if this actually worths behing submitted here, but atleast i'd like to get feedbacks/etc, thanks =]
 
Last edited by a moderator:
Level 8
Joined
Oct 3, 2008
Messages
367
I find the way you did this to be rather strange. Can't quite figure out what's going on.

You should make it basically a clone of DoubleClick, but for trackables. I feel that DoubleClick's method is ideal, allowing a global event with an extremely simple interface and efficient method of data attachment using TriggerExecCount. I wouldn't mind if you just copypasted the code and altered it from there.

Use Trackable2's feature that lets you detect when any trackable is clicked anywhere. This will let you do a global event, letting the user check for specific trackables if he desires.

You should also use Event, whether it be Jesus4Lyf's original version or the one Nestharus made. Should probably use the Jesus4Lyf version considering Trackable2 requires it anyway.

And lastly, include a link to Trackable2 (and Event if you choose to utilize it) in the first post.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
The code looks short enough for what it does but it also seems to add
an unnecessary layer of complexity. If it's a double-click detection, that
only deals with trackables, you should check your naming convention a
little better. "onDoubleClick", for example, does not imply in its name
that it's "On Double Click a Trackable".
 
Top