Warcraft III: MapsModelsSkinsIconsSpellsToolsTutorials
WC3 JASS: Code SnippetsJASS and vJASS Spells and SystemsJass Tutorials
Chat @Discord

Author Topic: Trackables (Mouse detection)  (Read 50 times)

  • Recognized User
  • Newbie - level 1
  • *
  • Posts: 13
  • WC3 Models: 3
  • WC3 Tutorials: 0
  • WC3 Tools: 0
  • WC3 Maps: 0
  • WC3 Skins: 0
  • WC3 Icons: 0
  • WC3 Spells: 0
  • Reputation: 0
  • User
    • View Profile
Trackables (Mouse detection)
« on: July 09, 2017, 01:51:10 AM »
Tutorial originally made by wonderpriest inspired in Kattana original tutorial.


A trackable is just something like a doodad, let's say. But it is different as it can't be selected, it can't be moved, it can't die, and it can't be eliminated. It doesn't even have to be seen if you don't want it to.
The point of a trackable is to harness the mouse detection for usage in triggers. Mouse detection just means the game registers when your mouse pointer moves over an object, or clicks it.

As I get more questions, I will answer them here so you don't have to sift through the posts.
Code: jass  [Select]
  1. Q. Do trackables work in multiplayer maps?
  2. A. Yes, they work fine. As for tracking which player triggered the trackable, you would need a handler system for that.

Although Blizzard gave us these functions to use mouse detection, it doesn't seem they really cared to finsh the code, because you can not retrieve a triggering player from a trackable event. Nor can a trackable be owned by a player.
The usage of trackables is very limited, because you can not manipulate anything about a trackable once you create it, or before. This means you can not move, scale, color, or make any other kind of modification. You just create it, and that's it.
Also, one of the reasons not many people know of trackables, is because they require JASS to fully use. You can create and manipulate trackables through the Custom Script action, but there is no event in GUI that uses trackables.
Fortunately, the functions are not very hard to understand and require little, if any, JASS knowledge.

I wanted to bring these trackables to attention, because even many JASSers seem to not know what they are. Trackables are a powerful tool that can be used to make better interactive systems, and even things like mini-games.

To use trackables, first you must create them. They can not be pre-placed in a map, so you must make them through triggers. They are created somewhat like units are created, only you use a model string to determine the model of the trackable, not an id or name.
This is actually very useful, because you can use any valid model path. This includes units, buildings, doodads...anything with a model path. If you use a unit or buildiing model, the trackable will appear looking like a neutral hostile unit, with no team colors.
Trackables do play animations. If you want a trackable to be invisible, you just insert a void string argument (""). Here is the function to create a trackable:

Code: jass  [Select]
  1. CreateTrackable(string modelpath, real x, real y, real facing)
  3. modelpath is the path of the model you would like to use. Use "" for an invisable trackable. Remember to use \\ instead of \.
  4. real x and real y are the coordinates of the location to create the trackable
  5. facing is the angle that the trackable faces (remember this cannot be changed after creation)

The events for trackables are as follows:

Code: jass  [Select]
  1. TriggerRegisterTrackableHitEvent(trigger whichTrigger, trackable t)
  2. TriggerRegisterTrackableTrackEvent(trigger whichTrigger, trackable t)
  4. trackable is a handle that you use like any other handle (unit, location...).

TriggerRegisterTrackableHitEvent registers when a player clicks on a trackable. TriggerRegisterTrackableTrackEvent registers when a player moves his mouse across a trackable.
You may notice that this same system is in place with normal units in Warcraft III. When you click a unit, you select it. When you pass over a unit with your mouse, a bar shows it's health.
Trackable events work like any other event, but you also need to specify a trackable for the event to register.

A Trigger:
This trigger will create a trackable, and when someone passes over it, a message will be sent.
Code: jass  [Select]
  1. function Massage takes nothing returns nothing
  2.     call DisplayTextToForce(GetPlayersAll(),"Peasant: OOh, that feels nice.") //Displays the pleasure of the peasant when we rub him with our mouse
  3. endfunction
  5. //===========================================================================
  6. function InitTrig_zomg takes nothing returns nothing
  7.  local trigger t=CreateTrigger() //Creates the trigger
  8.  local trackable tr=CreateTrackable("units\\human\\Peasant\\Peasant.mdl",0,0,-90) //Creates our trackable, with the peasant model
  9.     call TriggerRegisterTrackableTrackEvent(t,tr) //Registers when someone passes over tr with their mouse
  10.     call TriggerAddAction(t,function Massage) //Calls our actions function
  11. endfunction

You may notice I display the message to all players. This is because there is no 'GetTriggeringPlayer' for a trackable event, which is probably the biggest limitation of trackables. But, there is a 'GetTriggeringTrackable'. Which opens up possibilites to fix the missing TriggeringPlayer problem. (With 'GetTriggeringTrackable', you may be able to stimulate a Triggering Player, maybe by using the Handle Vars or another system)

The Result:

ADD: Trackable Workarounds (credits to KaTTana)
Using Handle Vars With Trackables
KaTTana wrote this part better than I can, so here it is.
You can find KaTTana's Trackables tutorial here: Link
You can find KaTTana's Handle Var turorial here: Link

A Part of KaTTana's Tutorial:
"We don't have any natives for getting the (x,y) coordinates of a trackable, but we can handle that ourselves with the Local Handle Variables.
Here is a custom API for extended use of trackables.

Code: jass  [Select]
  1. // ===========================
  2. //   Trackable API
  4. function GetTrackableX takes trackable tc returns real
  5.     return GetHandleReal(tc, "x")
  6. endfunction
  7. function GetTrackableY takes trackable tc returns real
  8.     return GetHandleReal(tc, "y")
  9. endfunction
  10. function GetTrackableFacing takes trackable tc returns real
  11.     return GetHandleReal(tc, "facing")
  12. endfunction
  13. function GetTrackablePath takes trackable tc returns string
  14.     return GetHandleString(tc, "path")
  15. endfunction
  17. function NewTrackable takes string path, real x, real y, real facing returns trackable
  18.     local trackable tc = CreateTrackable(path, x, y, facing)
  19.     call SetHandleReal(tc, "x", x)
  20.     call SetHandleReal(tc, "y", y)
  21.     call SetHandleReal(tc, "facing", facing)
  22.     call SetHandleString(tc, "path", path)
  23.     return tc
  24. endfunction

Trackables in Multiplayer
Previously, the tutorial stated that trackables didn't work in multiplayer, but that was wrong. They work fine, and they don't desynchronize the game.
However, there is no way to determine which player triggered the event on a trackable. We can work around this by creating a trackable for each player - each can only be triggered by one player.

Code: jass  [Select]
  1.     // t1 and t2 are visually the same trackable, but in fact they only work for one player each
  2.     local trackable t1 // Player 1's trackable
  3.     local trackable t2 // Player 2's trackable
  4.     local string peasant = "units\\human\\Peasant\\Peasant.mdl"
  5.     local string invisible = ""
  6.     local string path = invisible
  8.     if ( GetLocalPlayer() == Player(0) ) then
  9.         set path = peasant
  10.     endif
  11.     set t1 = CreateTrackable(path, -500, 0, 0)
  13.     set path = invisible
  14.     if ( GetLocalPlayer() == Player(1) ) then
  15.         set path = peasant
  16.     endif
  17.     set t2 = CreateTrackable(path, -500, 0, 0)
  19.     call SetHandleInt(t1, "player", 0) // Store which player "owns" this trackable
  20.     call SetHandleInt(t2, "player", 1) // Same for player 2
  22.     // Add events to register track/hit on t1 and t2...

After this, you can determine the player triggering a trackable by reading the local integer named "player" on the triggering trackable.

We can extend to NewTrackable if you like:
Code: jass  [Select]
  1. function GetTrackableOwner takes trackable t returns player
  2.     return Player(GetHandleInt(t, "player"))
  3. endfunction
  5. function NewTrackable takes string path, real x, real y, real facing, player owner returns trackable
  6.     local trackable tc
  7.     local string invisible = ""
  8.     if GetLocalPlayer() != owner then
  9.         set path = invisible
  10.     endif
  11.     set tc = CreateTrackable(path, x, y, facing)
  12.     call SetHandleReal(tc, "x", x)
  13.     call SetHandleReal(tc, "y", y)
  14.     call SetHandleReal(tc, "facing", facing)
  15.     call SetHandleString(tc, "path", path)
  16.     call SetHandleInt(tc, "player", GetPlayerId(owner))
  17.     return tc
  18. endfunction

Giving height to Trackables
Although the natives do not allow it, a simple workaround enables us to create trackables at a given height above ground.
Code: jass  [Select]
  1. function CreateTrackableZ takes string path, real x, real y, real z, real face returns trackable
  2.     local destructable d = CreateDestructableZ( 'OTip', x, y, z, 0.00, 1, 0 )
  3.     local trackable tr = CreateTrackable( path, x, y, face )
  4.     call RemoveDestructable( d )
  5.     set d = null
  6.     return tr
  7. endfunction
It works by creating an Invisible Platform at the given height, and then creating the trackable on top of that. After removing the platform, the trackable stays in place."

Once again, that was part of KaTTana's trackable tutorial, which you can find here: Link

That's it for the Trackables tutorial, thanks for reading, and hope you have fun using these in your map!

Questions, comments, and suggestions are welcome, and appreciated!

ADD: If anyone finds this confusing, or wants a demo map to look at, just say iit and I will make a demo map using all of the Trackable functions.


[System] Unit Recycler & Simple Damage Detection System

Started by moyackBoard Codes & Snippets

Replies: 6
Views: 12810
Last post June 25, 2013, 08:50:33 PM
by moyack
Mouse X and Y Position?

Started by SwordmanBoard JetScript

Replies: 3
Views: 7861
Last post August 04, 2013, 06:18:50 AM
by Sourc[e]x
Blizzard Modding Information Center Starcraft II Modding Information Center Wacraft III Modding Information Center WC3JASS.com - The JASS Vault Chronicles of Darkness - A Warcraft III mod Jetcraft - A Starcraft II mod Troll Smash - A Warcraft III Arena
  Mod DB - Change the Game Power of Corruption - A Warcraft III altered melee map Chaos Realm - The world of Game modders and wc3 addicts Follow us on Facebook!!