Is there a predefined procedure for checking to see if a button is held down, much like with MouseDown()?

If there isn't, how can I improve upon this nonsense I've been starting to work on to create my own button_down proc for things like holding north and east buttons at the same time to have the guy travel north east?

MV = Multikey_Check(NORTH, pushed)
pushed = "north"
world << "[MV]"
step(src, MV)
pushed = null

MV = Multikey_Check(EAST, pushed)
pushed = "east"
world << MV
step(src, MV)
pushed = null

if(direction == previous_direction) return 0
if((direction == NORTH && previous_direction == "east") || (direction == EAST && previous_direction == "north"))
if((direction == NORTH && previous_direction == "west") || (direction == WEST && previous_direction == "north"))
if((direction == SOUTH && previous_direction == "east") || (direction == EAST && previous_direction == "south"))
if((direction == SOUTH && previous_direction == "west") || (direction == WEST && previous_direction == "south"))
Forum_Account's Pixel Movement library includes this functionality, if you're interested in learning more about it, I suggest looking there.
You can define macros for when the key is pressed and released. Those procs modify a var to remember the current state of the key so you can just check that var to know the state of the key.

There are also libraries available to make this easier for you:
You need to define key+up and key+down macros. You can do that in the interface file. Then you set a flag when the key+down is triggered, and clear it when the key+up is triggered.

Here's an example specifically for the directional keys:
var/activeKeys = 0

verb/triggerKey(dir as null|num, trigger=1 as null|num)
activeKeys |= dir // Add the key by setting its bit in the flag
activeKeys &= ~dir // Remove the key by removing its bit in the flag

return (activeKeys & dir) // See if the key's bit is set

icon = 'Person.dmi'
var/speed = 3
while(src && client)
step(src,client.activeKeys) // Hacky, probably shouldn't do it this way, but since activeKeys uses the same bit flags as dir, you could

And here's the macro set:

If you wanted more control over the keyboard in general, you would have to use a list to track which keys were down.

Ah, ninja'd!
In response to DarkCampainger
"Then you set a flag when the key+down "

I've never really understood flags. Is it possible there's somewhere I can read up on them, or something of that nature?

Also I don't understand these operations, maybe because I don't understand flags, or maybe I just don't know them at all:

activeKeys &= ~dirM

activeKeys |= dir

So pretty much the <t>&= , |=,</t>, and the symbol used in front of dirM; <t>~</t>

Any help appreciated on this, and thanks for the help so far!
In response to Speedro
I'd recommend not using bit flags anyway. It'll limit you to 16 keys and you also have to remember which key corresponds to which bit. Use individual vars or a list instead.

I think that Kaiochao's library maintains a list of the names of keys you're holding so you can say if("north" in list) to check if the up key is being held. The keyboard handling in my Pixel Movement library gives you an associative list of keys such that keys["a"] is 1 when the A key is being held and 0 when it's not.

To implement this yourself just make macros that call the same verbs (one for keys being pressed, another for them being released) and pass them the name of the key:

list/keys = list()
KeyDown(k as text)
keys[k] = 1
KeyUp(k as text)
keys[k] = 0
You had made another post about the can_bump() proc but it was deleted (not sure if you deleted it or if someone else did) so I'll post a response here:

This is the original definition that only returns 1 for dense turfs.

> mob
> proc
> can_bump(atom/a)
> // Every turf is dense, they're just different heights. A floor turf
> // that you'd normally consider non-dense is actually dense - you can
> // walk on top of it. If you couldn't bump into them you'd fall right
> // through them.
> if(isturf(a))
> // In 2D mode you can only bump dense turfs, in 3D mode
> // you can bump any turf, it's just a question of how tall
> // the turf is that determines if you do hit it.
> return a.density
> #else
> return 1
> #endif

This overrides it to make it also return 1 for dense mobs.

> mob
> can_bump(atom/a)
> if(ismob(a))
> return a.density
> return ..()
In response to Forum_account
Thanks for your concerns, I appreciate it!

However actually the issue was "overriding procedure definition", and I realized after I posted it that:


if that line of code is before the actual procedure definition


Then I think it gives me the overriding procedure definition error.

However this seems unnecessary since if the compiler recognizes this, then can't it just flip it around anyways?
In response to Speedro
It would make sense. As long as there's only one real definition and the rest just override it you'd think it'd be possible. Though, the order does matter to a certain extent so I'm not surprised it works this way.

For example:

world << "A"

world << "B"

world << "C"

If you call mob.something() it'll output "C" because it runs the last definition. If you call ..() in any of those procs it'll call the previous one - calling ..() in the last proc calls the middle one and calling ..() in the middle one calls the top one.
In response to Speedro
The error you're talking about is "proc definition not allowed inside of another proc", which is caused by trying to define a proc within a proc. Like so:

// Do stuff

It has nothing to do with where things are defined or what order they're defined.