1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. The Melee Mapping Contest #4: 2v2 - Results are out! Step by to congratulate the winners!
    Dismiss Notice
  3. We're hosting the 15th Mini-Mapping Contest with YouTuber Abelhawk! The contestants are to create a custom map that uses the hidden content within Warcraft 3 or is inspired by any of the many secrets within the game.
    Dismiss Notice
  4. The 20th iteration of the Terraining Contest is upon us! Join and create exquisite Water Structures for it.
    Dismiss Notice
  5. Check out the Staff job openings thread.
    Dismiss Notice

Trackables System [GUI Friendly] v1.10

Submitted by Flux
This bundle is marked as approved. It works and satisfies the submission rules.
Preview GIFs
GIF Preview

[​IMG]


Code (vJASS):

//          Trackables System [GUI Friendly] v1.10
//                    by Flux
//     http://www.hiveworkshop.com/forums/members/flux/

//  A trackables system which is easy to use for GUI users.
//  It allows users to detect when a certain player hovers
//  or clicks (using the mouse) on an area within a Region
//  (which is actually a rect in JASS).

//  NOTE:
//   - This system cost 1 hashtable.
//   - TRK_Players (force) is automatically destroyed so it is
//     highly advised to not set TRK_Players to an existing Player
//     group, but instead, create a new one (as shown in the demo).
//   - TRK_Point (location) must not be removed or overwritten.

//  HOW TO IMPORT:
//  1. Copy the Trackables System Variable Creator in your map.
//     Make sure you set the "Automatically create unknown variables
//     while pasting trigger data" in Files -> Preferences.
//     After copying, delete Trackables System Variable Creator
//  2. Copy Trackables System to your map.

//  HOW TO USE:
//  1. Set 'TRK_Players'. The Players in this PlayerGroup are the ones
//     who can interact with the trackables about to be created.
//     The Player Group is automatically destroyed so you don't need
//     to manually destroy 'TRK_Players'
//  2. Set 'TRK_Rect' which refers to the rect where the trackables
//     will be created. Rects are called Regions in GUI.
//  3. Set 'TRK_HoverTrigger' which refers to the trigger that will run when
//     a player in TRK_Players hovers a trackable in the 'TRK_Region'.
//  4. Set 'TRK_ClickTrigger' which refers to the trigger that will run when
//     a player in TRK_Players clicks a trackable in the 'TRK_Region'.
//  5. Set 'TRK_Spacing' which refers to the spacing between trackables.
//  6. Set 'TRK_ModelPath' which determines how the trackables will look
//     in game.
//  7. Run the system using:
//     'Trigger - Run Trackables System <gen> (checking conditions)'
//  8. In your trackables event triggers, TRK_Point refers to the location
//     of the trackables that was clicked/hovered and TRK_TriggeringPlayer
//     is the player that interacted with the trackable. Note that you cannot
//     use TRK_Point and TRK_TriggeringPlayer in the Conditions so you have
//     to create a big IF-THEN-ELSE if your condition involves TRK_Point
//     or TRK_TriggeringPlayer
//  9. Do your actions


function Trig_Trackables_System_InitVariables takes nothing returns boolean
    local integer id = LoadInteger(udg_TRK_Hashtable, GetHandleId(GetTriggeringTrackable()), 0)
    call MoveLocation(udg_TRK_Point, udg_TRK_TrackableX[id], udg_TRK_TrackableY[id])
    set udg_TRK_TriggeringPlayer = udg_TRK_TrackableOwner[id]
    return true
endfunction

function Trig_Trackables_System_PickPlayers takes nothing returns nothing
    local string s = ""
    local trackable t
    set udg_TRK_TrackableOwner[udg_TRK_Index] = GetEnumPlayer()
    if GetPlayerSlotState(udg_TRK_TrackableOwner[udg_TRK_Index]) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(udg_TRK_TrackableOwner[udg_TRK_Index]) == MAP_CONTROL_USER then
        //Trackable Properties
        set udg_TRK_TrackableX[udg_TRK_Index] = udg_TRK_x
        set udg_TRK_TrackableY[udg_TRK_Index] = udg_TRK_y
        if GetLocalPlayer() == udg_TRK_TrackableOwner[udg_TRK_Index] then
            set s = udg_TRK_ModelPath
        endif
        set t = CreateTrackable(s, udg_TRK_x, udg_TRK_y, 0)
        //Save index
        call SaveInteger(udg_TRK_Hashtable, GetHandleId(t), 0, udg_TRK_Index)
        //Register the trackable
        if udg_TRK_HoverTrigger != null then
            call TriggerRegisterTrackableTrackEvent(udg_TRK_HoverTrigger, t)
        endif
        if udg_TRK_ClickTrigger != null then
            call TriggerRegisterTrackableHitEvent(udg_TRK_ClickTrigger, t)
        endif
        set udg_TRK_Index = udg_TRK_Index + 1
    endif
endfunction

function Trig_Trackables_System_Main takes nothing returns boolean
    local real xmax = GetRectMaxX(udg_TRK_Rect)
    local real xmin = GetRectMinX(udg_TRK_Rect)
    local real ymax = GetRectMaxY(udg_TRK_Rect)
    set udg_TRK_y = GetRectMinY(udg_TRK_Rect)
    if udg_TRK_HoverTrigger != null then
        call TriggerAddCondition(udg_TRK_HoverTrigger , Condition(function Trig_Trackables_System_InitVariables))
    endif
    if udg_TRK_ClickTrigger != null then
        call TriggerAddCondition(udg_TRK_ClickTrigger , Condition(function Trig_Trackables_System_InitVariables))
    endif
    loop
        exitwhen udg_TRK_y >= ymax
        set udg_TRK_x = xmin
        loop
            exitwhen udg_TRK_x >= xmax
            //Create Trackable for each player
            call ForForce(udg_TRK_Players, function Trig_Trackables_System_PickPlayers)
            set udg_TRK_x = udg_TRK_x + udg_TRK_Spacing
        endloop
        set udg_TRK_y = udg_TRK_y + udg_TRK_Spacing
    endloop
    if udg_TRK_Players != bj_FORCE_ALL_PLAYERS then
        call DestroyForce(udg_TRK_Players)
    endif
    set udg_TRK_HoverTrigger = null
    set udg_TRK_ClickTrigger = null
    return false
endfunction

//===========================================================================
function InitTrig_Trackables_System takes nothing returns nothing
    set gg_trg_Trackables_System = CreateTrigger()
    set udg_TRK_Hashtable = InitHashtable()
    set udg_TRK_Point = Location(0, 0)
    set udg_TRK_Index = 0
    call TriggerAddCondition(gg_trg_Trackables_System, Condition(function Trig_Trackables_System_Main))
endfunction


 


Using the System
Create

  • Create Trackables Demo 1
    • Events
      • Player - Player 1 (Red) types a chat message containing 1 as An exact match
    • Conditions
    • Actions
      • Game - Display to (All players) the text: Demo 1 enabled!
      • -------- ----------------------------------------------------------------- --------
      • -------- ---------- Set the configurations --------------- --------
      • -------- ----------------------------------------------------------------- --------
      • -------- Player Group that can interact with the Trackable --------
      • Set TRK_Players = (Player group(Player 1 (Red)))
      • -------- Select the Region where Trackables will be created --------
      • Set TRK_Rect = Region 000 <gen>
      • -------- Select the trigger that will run when the mouse hovers the trackables --------
      • Set TRK_HoverTrigger = Demo 1 on Hover <gen>
      • -------- Select the trigger that will run when the mouse clicks the trackables --------
      • Set TRK_ClickTrigger = Demo 1 on Click <gen>
      • -------- Set the spacing between trackables --------
      • Set TRK_Spacing = 128.00
      • -------- Set the model path of trackables --------
      • Set TRK_ModelPath = Doodads\Terrain\InvisiblePlatform\InvisiblePlatform.mdl
      • -------- Run the System --------
      • Trigger - Run Trackables System <gen> (checking conditions)



OnMouseHover

  • Demo 1 on Hover
    • Events
    • Conditions
    • Actions
      • -------- Your Actions Here --------
      • Unit - Make Tinker 0000 <gen> face TRK_Point over 0.00 seconds



OnMouseClick

  • Demo 1 on Click
    • Events
    • Conditions
    • Actions
      • -------- Your Actions Here --------
      • Unit - Order Tinker 0000 <gen> to Move To TRK_Point



Using TRK_TriggeringPlayer

  • Demo 2 on Hover
    • Events
    • Conditions
    • Actions
      • -------- Your Actions Here --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • TRK_TriggeringPlayer Equal to Player 1 (Red)
        • Then - Actions
          • Unit - Move Wisp 0004 <gen> instantly to TRK_Point
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TRK_TriggeringPlayer Equal to Player 2 (Blue)
            • Then - Actions
              • Unit - Move Wisp 0005 <gen> instantly to TRK_Point
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • TRK_TriggeringPlayer Equal to Player 3 (Teal)
                • Then - Actions
                  • Unit - Move Wisp 0006 <gen> instantly to TRK_Point
                • Else - Actions


Changelog

Changelog:
v1.00 - [17 December 2015]
- Initial Release

v1.01 - [18 December 2015]
- Fixed a minor mistake in TriggerAddCondition. It now fully works without needing Jass New Gen Pack.

v1.02 - [8 January 2016]
- Custom scripts no longer needed!
- System will check first if the player is a user before creating the trackable for that player.
- Trackables' center will no longer exceed the specified rect boundary.
- Changed the variable name to 'TRK_Rect' since it is actually a rect but called Region in GUI.

v1.03 - [3 April 2016 ]
- TRK_Point no longer needs to be removed through Custom script.
- Fixed some typo.

v1.10 - [1 January 2017]
- Fixed a possible bug when too many trackables are used.
- Fixed unintentional resetting of TRK_Index resulting to a bug.


Keywords:
trackable, track, GUI friendly, mouse, click, hover, mouse move, mouse interact
Contents

Trackable System [GUI Friendly] v1.1 (Map)

Reviews
Moderator
08:51, 18th Dec 2015 Bribe: Well-made with no issues which I can identify. 3.7/5. Please see the Track resource, http://www.hiveworkshop.com/forums/jass-resources-412/system-track-205760/ for perhaps adding a check when it's FORCE_ALL_PLAYERS that...
  1. 08:51, 18th Dec 2015
    Bribe: Well-made with no issues which I can identify. 3.7/5. Please see the Track resource, http://www.hiveworkshop.com/forums/jass-resources-412/system-track-205760/ for perhaps adding a check when it's FORCE_ALL_PLAYERS that the player is actually playing.
     
  2. Flux

    Flux

    Joined:
    Feb 6, 2014
    Messages:
    2,334
    Resources:
    28
    Maps:
    1
    Spells:
    19
    Tutorials:
    2
    JASS:
    6
    Resources:
    28
    GIF Preview Coming soon
     

    Attached Files:

    Last edited: Dec 18, 2015
  3. ILH

    ILH

    Joined:
    May 8, 2012
    Messages:
    608
    Resources:
    16
    Models:
    14
    Icons:
    1
    Tutorials:
    1
    Resources:
    16
    Great, this is what I need for my map :wthumbsup:
    +Rep
     
  4. Flux

    Flux

    Joined:
    Feb 6, 2014
    Messages:
    2,334
    Resources:
    28
    Maps:
    1
    Spells:
    19
    Tutorials:
    2
    JASS:
    6
    Resources:
    28
    Damn, forgot to add the Condition() in the TriggerAddCondition again. I'll update this as soon as possible.

    @Bribe, sure I'll include that in the update.

    EDIT:
    @ILH, tested it myself, it works in vanilla World Editor.
     
    Last edited: Jan 8, 2016
  5. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    6,099
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    Cool. A system written in plain JASS is useful.

    Imo "region" should be replaced by "rect", in description and in code.
    Vanilla JASS user might also use it, and it's anways fairly simple to
    learn for GUI users that "Regions" in GUI is actually a rect.
    It should be not exclusivly for GUI.

    udg_TRK_y > ymax

    ->
    udg_TRK_y >= ymax


    exitwhen udg_TRK_x > xmax

    ->
    exitwhen udg_TRK_x >= xmax


    And no destroy is supported.
     
  6. Flux

    Flux

    Joined:
    Feb 6, 2014
    Messages:
    2,334
    Resources:
    28
    Maps:
    1
    Spells:
    19
    Tutorials:
    2
    JASS:
    6
    Resources:
    28
    Okay I understand, I will just put "regions" in GUI are actually "rect" somewhere in the documentation.

    Why? it won't create a trackable at the edge if I did this since it will exit the loop immediately if it the x and y happens to be at the edge of the rect.

    Trackables can't be destroyed ;). If the user ever want to, they can disable the onHover and onClick triggers.
     
  7. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    6,099
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    Yes, you're right. But indices can be recycled so they can be used again.

    And for the ">=", from my point of view, I would not want to have
    trackables (partialy) outside my rect, but prefer to have a little "buffer" instead.
    I myself would even use the size of trackable in the "exitwhen" condition.
    But you can let it imo if you like it.
     
  8. Flux

    Flux

    Joined:
    Feb 6, 2014
    Messages:
    2,334
    Resources:
    28
    Maps:
    1
    Spells:
    19
    Tutorials:
    2
    JASS:
    6
    Resources:
    28
    You're right, but I don't think anyone will reach the limit because if they do, they also have 8190 trackables in the map.

    Good point, I would consider the trackable size if it can be detected.
    But yeah, "I would not want to have trackables (partialy) outside my rect" make sense. I will change it.
     
  9. Flux

    Flux

    Joined:
    Feb 6, 2014
    Messages:
    2,334
    Resources:
    28
    Maps:
    1
    Spells:
    19
    Tutorials:
    2
    JASS:
    6
    Resources:
    28
    Totally forgot to update this, but I remember when I saw the GUITrack from another user.

    So, updated to v1.02.
    Changes:
    - Custom scripts no longer needed!
    - System will check first if the player is a user before creating the trackable for that player.
    - Trackables' center will no longer touch the edge of the specified rect.
    - Changed the variable name to 'TRK_Rect' since it is actually a rect but called Region in GUI.
     
    Last edited: Jan 8, 2016
  10. sentrywiz

    sentrywiz

    Joined:
    Feb 10, 2009
    Messages:
    1,875
    Resources:
    16
    Maps:
    10
    Tutorials:
    6
    Resources:
    16
    Just curious, would this system lag in let's say: 128x64 map for multiple players?
     
  11. Flux

    Flux

    Joined:
    Feb 6, 2014
    Messages:
    2,334
    Resources:
    28
    Maps:
    1
    Spells:
    19
    Tutorials:
    2
    JASS:
    6
    Resources:
    28
    I don't know. Go try it for yourself.
     
  12. Legal_Ease

    Legal_Ease

    Joined:
    Feb 8, 2013
    Messages:
    1,456
    Resources:
    28
    Icons:
    11
    Packs:
    1
    Skins:
    2
    Maps:
    10
    Template:
    1
    Tutorials:
    3
    Resources:
    28
    This is amazing. It has great documentation and is easy enough to understand that even I can use it. Great work!!! I have a few questions though. Can you detect left-click from right-click? Smart already works for right, but I want a different action on left.

    Also, it's great for moving a unit or activating a spell targeting a point, but how do I make it select a unit. Say, I hoover over a unit and I want it to have a floating text that says "Hi." How would that work? I could pick units within 50 of TRK_Point but that seems a bit sloppy. Could you write a quick example of how that might work? How can I enable the smart order again? Seems this system overwrites it. Which makes sense for something but not for others.

    Sorry for being so naive. This system is really cool and I think that with such easy use many people will be able to use it even if they don't understand how it works. The more demos the better. 5/5 +rep
     
    Last edited: Apr 26, 2016
  13. Flux

    Flux

    Joined:
    Feb 6, 2014
    Messages:
    2,334
    Resources:
    28
    Maps:
    1
    Spells:
    19
    Tutorials:
    2
    JASS:
    6
    Resources:
    28
    Is the unit that would say "Hi" moving?

    I think you can't detect right-click but I haven't tested it.

    This system does not overwrite the smart order, it is just a demo. The main functionality is creating trackables in a rect and defining the hover and onClick triggers.
     
  14. Legal_Ease

    Legal_Ease

    Joined:
    Feb 8, 2013
    Messages:
    1,456
    Resources:
    28
    Icons:
    11
    Packs:
    1
    Skins:
    2
    Maps:
    10
    Template:
    1
    Tutorials:
    3
    Resources:
    28
    It might be. I made it work with pick all unit within 127 of TRK_Point, but it seemed slow and not super responsive. It would get the units though and could probably be optimized with the right range.

    Well, if you can detect left-click (smart), then can't you get right-click by process of elimination? I guess that doesn't work when you have no unit selected since there is no order issued, but for my purposes and for many other's, having it only do an action when a unit is selected is most likely what we want anyway. What I'm looking for is a duel attack functionality like Diablo II that fires one attack with right click and a different one with left. It seems like this system can do that, but I'm short on know how.

    Can you add a demo that does something else then so the smart order is not interrupted? For example, the trackable click creates a special effect. I disabled the onClick demo trigger and I was still unable to move any units. It would just be nice to see more demos.

    Either way, I meant what I said. This is a very advanced system and you have made it very accessible to those of us with less than advanced triggering skills. Sadly, I can't get Bribe's KB2D to work for warstomp. So seeing a system that is way more advanced be presented in such an easy to use fashion, is really amazing! Thank you. I will have fun with this!
     
  15. Flux

    Flux

    Joined:
    Feb 6, 2014
    Messages:
    2,334
    Resources:
    28
    Maps:
    1
    Spells:
    19
    Tutorials:
    2
    JASS:
    6
    Resources:
    28
    Unfortunately, I don't know how to apply it for moving units efficiently because trackables can't be moved. But for non-moving let's say NPCs, you can create a small rect (region) where the NPC is located and create an onHover trigger there.

    The reason you still can't order Tinker (in demo) is probably because of the onHover trigger. It forces Tinker to face where the mouse cursor is, stopping current orders.
     
  16. Legal_Ease

    Legal_Ease

    Joined:
    Feb 8, 2013
    Messages:
    1,456
    Resources:
    28
    Icons:
    11
    Packs:
    1
    Skins:
    2
    Maps:
    10
    Template:
    1
    Tutorials:
    3
    Resources:
    28
    I see. Well, it's really cool anyway. I probably can't use it in my current project but it makes me want to use it for something. I'm just do impressed with how easy it is to use.
     
  17. Kakarotto

    Kakarotto

    Joined:
    Oct 6, 2015
    Messages:
    7
    Resources:
    0
    Resources:
    0
    this system cant be used on multiplayer since i cant detect the point for specific player like TRK_Point[( GetConvertedPlayerId(udg_TRK_TriggeringPlayer())] ..... each time i try to make it an array , it doesnt work on multiplayer.... I have tested it with my friend me and my friend if we keep clicking fast me and him walk to the same point... is there anyway to fix this?
    Thank you for Taking Time Reading this.
     
  18. Flux

    Flux

    Joined:
    Feb 6, 2014
    Messages:
    2,334
    Resources:
    28
    Maps:
    1
    Spells:
    19
    Tutorials:
    2
    JASS:
    6
    Resources:
    28
    Uhm TRK_Point isn't an array. You could try doing something like this for specific player clicks
    • Demo 2 on Hover
      • Events
      • Conditions
      • Actions
        • -------- Your Actions Here --------
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • TRK_TriggeringPlayer Equal to Player 1 (Red)
          • Then - Actions
            • Unit - Move Wisp 0004 <gen> instantly to TRK_Point
          • Else - Actions
            • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • TRK_TriggeringPlayer Equal to Player 2 (Blue)
              • Then - Actions
                • Unit - Move Wisp 0005 <gen> instantly to TRK_Point
              • Else - Actions
                • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  • If - Conditions
                    • TRK_TriggeringPlayer Equal to Player 3 (Teal)
                  • Then - Actions
                    • Unit - Move Wisp 0006 <gen> instantly to TRK_Point
                  • Else - Actions
     
  19. Kakarotto

    Kakarotto

    Joined:
    Oct 6, 2015
    Messages:
    7
    Resources:
    0
    Resources:
    0
    yea i did try this before you say , but this method also did not work :(, it works great and perfectly with single but with multiplayer the point is the same for everybody cant make it specifically.
    and , it's like when someone clicks it's good , but when 2 or more clicks in the same time the point will be displayed for both player in the same point .
     
    Last edited: Dec 31, 2016