ID:111799
 
Keywords: hdk, keys, mouse
HDK Mouse And Keys by Hiro the Dragon King
Real-time mouse updates as well as left and right macros for the Shift, Ctrl, and Alt keys.
6 fans · Created Feb 13 2011
Now that my long labored (i.e., procrastinated) gimmick finally has it's own neat little package, I can write up a decent article on how it works and how you can use it. I'll even throw in a few tips and tricks.

How It Came To Be
A few years ago, I wanted to create a library out of a HUD system I was working on. I thought that I should spruce it up with something exciting, something that nobody's done before. I decided on being able to drag objects around on the screen was the way to go, so I did soe research. After looking around, I saw that dragging objects around was only once done, and the creator's method no longer worked.

After a few iterations, I decided that the system needed improvement and pixel precision was the way to go. It was a month or so before I found the method by which to do this. As I was reading through release notes of BYOND updates, I came across version 441.1099 and the very last bit caught my eye. Knowing that JavaScript had access to mouse coordinates, I knew that back and forth banter between BYOND and JavaScript was the solution I was looking for. After all, Meebo handled the effect in a similar fashion.

It took a while for me to realize that this mouse function needed to be isolated and even longer before realizing that it should have it's own library. But, eventually, I did and through months and months of procrastination and distraction, I've finally made it here.


How It Works

Mouse Tracking
Basically, I start by effectively cloning map elements except making it a browser element instead; same size, pos, parent, anchors, borders, everything. This way, the browser has all of the information it will ever need. The only thing that ever needs to be updated is a change in the client's view.

Now I can send a script to that browser element and have it constantly check and calculate the coordinates of the mouse, relative to the actual map element. Using the information provided, the script can calculate and compensate for ANY obstacle thrown at it. Changes in position, size, even icon-size are automatically dealt with by the script. Every tick, as defined by tick_lag, the script will update the server of the mouse's position, if the position has changed since the last tick.

Modifier Macros
For the modifier macros, I simply browse()'d a script that runs click() event on a one millisecond loop and checks the position of the modifier keys on each iteration. If they've changed, the script will update the server. The reason that the loop is so quick is to make sure that all key-ups and key-downs are caught. The server seems to queue them in the same manner as actual macros.


How It's Used

Basic Mouse Coordinates

Let's get these out of the way first. Upon start-up, world.icon_size is automatically decoded into two rather convenient global variables, shown below. These are great for icon calculations.
var/icon_sizex
var/icon_sizey


Now on to the good stuff. Everything else is defined under client. There are only three that you need to play with to make this work.
client/var
list/maps
list/screen_viewx
list/screen_viewy

If you would like to use a map, you must add the map's name to the list of maps and you must define the size of the screen in screen_viewx and screen_viewy. client.view will be calculated from the first value in each list. If no view sizes are specified, then the screen_view variables will default to client.view. A single pixel will be added to the to make sure that the map stays at the right size, even in the absence of any HUD elements. Example:
client
maps = list("map1","map2")
maps = list(10,5)
maps = list(7,5)

In this example, map1's screen, as well as client.view, will be "10x7" and map2's screen will be "5x5". The coordinates are then outputted to these variables:
client/var
list/mousex
list/mousey

The coordinates are stored and indexed in the order of the maps they belong to. If would like to output the coordinates from map1, you would simply write:
world << mousex[1]
world << mousey[1]

Now all that you have to do is call StartMaps() and specify the map you want to use as an argument. For instance, if we wanted to use map1, we would use:
StartMaps(1)



Map Update Management

There are four things that you will have to do to maintain that this library continually provides the correct information. If map.icon-size ever changes, client.UpdateMaps(map_number) needs to be called, where map_number is the index of the map in client.maps and null will update all of the maps. If world.tick_lag ever changes, client.UpdateTickLag() needs to be called. If you would like to change the size of the map's views or the client's view, edit the client's screen_view variables and call client.UpdateScreenSize(map_number). And finally, if you add to or remove maps from the client's maps list, call client.UpdateLists(), followed by StartMaps(map_number), if you're adding.

Notes:
client/proc
/*Updates the speed at which all maps send updates, corresponding
to world.tick_lag.Note that this will automatically update all
other maps and JavaScript extras too.*/

UpdateTickLag()


/*Sends the corresponding map.icon-size to the map_number indexed
or every map listed.*/

UpdateMaps(map_number)

/*Updates the size of the corresponding map, or all maps, and sends
the pertinent infromation to the map, or all maps.*/

UpdateScreenSize(map_number)

/*Updates the size of each of the lists to allow for the correct
amount of information.*/

UpdateLists(map_number)

If you allow your users to play with those settings through the interface, you will need to write a verb that the interface can access to make the appropriate call.


Advanced Mouse Coordinates

You can also generate more advanced coordinates, those that directly correspond to the mouse parameter's screen-loc. In order to do so, you must turn on the setting;
client/var/GenerateScreenLoc
... and it will automatically convert mousex and mousey to the four variables;
client/var
list/screen_tx
list/screen_px
list/screen_ty
list/screen_py
... for use as screen_loc coordinates. Here is how you'd use them in the screen_loc format.
screen_loc = "[screen_tx[1]]:[screen_px[1]],[screen_ty[1]]:[screen_py[1]]"
//OR
screen_loc = "[maps[2]]:[screen_tx[2]]:[screen_px[2]],[screen_ty[2]]:[screen_py[2]]"



Map Coordinates

There are two more settings that will allow you to automatically generate more advanced coordinates. When working with this setting, you have to remember that the first map listed in client.maps is assumed to be the default map. Program accordingly. The
first setting is;
client/var/GenerateMapCoordinates
If you turn this on, the coordinates of your mouse over the actual in-game map will be generated, in pixels, to the variables;
client/var
mapx
mapy
These would be useful if you employed a pixel-based coordinate system into your game.

The second setting;
client/var/GenerateMapLoc
... will automatically generate true map coordinates (as in x, y, pixel_x, pixel_y) to
the four variables;
client/var
map_tx
map_px
map_ty
map_py



Start, Stop, Pause, Resume

Each system now has four functions, shown below:
client/proc
StartMaps(map_number)
/*Creates a window(s) that keeps track of and updates the server
of mouse coordinates.*/


StopMaps(map_number)
/*Deletes the window(s).*/

PauseMaps(map_number)
/*Disables the window(s).*/

ResumeMaps(map_number)
/*Re-enables the window(s).*/


There are also commands that correspond to the JavaScript extras (explained below). They are:

client/proc
StartJavaScript[Keys/Mouse/Variables]()
Stop "
Pause "
Resume "



JavaScript Extras

The last setting that you can turn on will allow you to have real-time information about settings on the client's end. Below is a list of all the information that it allows you access to.
client/var
/*The absolute position of the mouse on the client's screen.*/
screenX
screenY

/*The dimensions of usable space on the client's screen.*/
availWidth
availHeight
/*The actual dimensions of the client's screen.*/
width
height
/*The bit depth of colors on the client's screen.*/
colorDepth

/*The the positions of the client's Shift, Ctrl, and Alt keys.*/
shiftKey
ctrlKey
altKey



Hooks

Last but not least, we have a list of the hooks that you can use to play with all of these wonderful features.
client/proc
/*These are hooks should be painfully obvious...*/
shiftKeyDown()
shiftKeyUp()

ctrlKeyDown()
ctrlKeyUp()

altKeyDown()
altKeyUp()

/*These are all called once per tick to update the server, where
num is the index of the map being updated and x and y are the new
coordinates.*/

UpdateMouse(num,x,y)
..()

UpdateJavaScriptMouse(screenX,screenY)
..()

UpdateJavaScriptVariables(availWidth,availHeight,width,height,colorDepth)
..()




Please be sure to report any bugs or errors to me.
Lmao awesome.
Very useful library. Keep it up!