Snippet EasyKeys

Prozix

New Member
Reaction score
7
This library makes checking for arrow key presses a lot easier. You should definitely check the demo map out to see what you can accomplish with this.

JASS:

library EasyKeys initializer Init
//EasyKeys v1.1 by Prozix

//pros: -  Everything has been done for you
//      -  Easy to use
//      -  You can check for: Newpress, Doublepress, Release, Held and Doubleheld in this version!

//cons: -  Slow (due to warcraft keypress event limitations)
//      -  EasyKeys requires you to call an update function in order to make this system work which would become annoying to do properly if you have multiple triggers using this system at once

//how to use:
//      Lets say I want to know if player 1 (red) is holding the up key:
//      if Pad[0].U.Held() then
//          BJDebugMsg("Up key being pressed by player 1")
//      endif

//      general syntax: Pad[#playerid#].#key#.#state()# with
//          playerid = the players id (0-11)
//          key = U, D, L or R (up down left right)
//          state() = Held(), Doubleheld(), Newpress(), Doublepress() or Released()

//      Maximum amount of ticks to register a double press can be adjusted in the globals section below

globals
    private constant integer KEY_LOOSE = 0
    private constant integer KEY_NEWPRESS = 1
    private constant integer KEY_HELD = 2
    private constant integer KEY_RELEASED = 3
    private constant integer KEY_DOUBLEPRESS = 4
    private constant integer KEY_DOUBLEHELD = 5
    
    private constant integer DOUBLEPRESS_TICKLIMIT = 8
endglobals

private struct KEY 
    integer action
    integer ticks
    static method create takes nothing returns thistype
        local thistype k = thistype.allocate()
        set k.action = KEY_LOOSE
        set k.ticks = 0
        return k
    endmethod
    
    method Newpress takes nothing returns boolean
        if .action == KEY_NEWPRESS then
            return true
        endif
        return false
    endmethod
    method Doublepress takes nothing returns boolean
        if .action == KEY_DOUBLEPRESS then
            return true
        endif
        return false
    endmethod
    method Held takes nothing returns boolean
        if .action == KEY_NEWPRESS or .action == KEY_DOUBLEPRESS or .action == KEY_HELD or .action == KEY_DOUBLEHELD then
            return true
        endif
        return false
    endmethod
    method Doubleheld takes nothing returns boolean
        if .action == KEY_DOUBLEHELD then
            return true
        endif
        return false
    endmethod
    method Released takes nothing returns boolean
        if .action == KEY_RELEASED then
            return true
        endif
        return false
    endmethod
    
    method Update takes nothing returns nothing
        if .action == KEY_NEWPRESS then
            if .ticks == 0 then
                set .ticks = 1
                set .action = KEY_HELD
            elseif .ticks < DOUBLEPRESS_TICKLIMIT then
                set .action = KEY_DOUBLEPRESS
            endif
            
        elseif .action == KEY_DOUBLEPRESS then
            set .ticks = 0
            set .action = KEY_DOUBLEHELD
            
        elseif .action == KEY_RELEASED then
            set .action = KEY_LOOSE
        endif
        
        if .ticks>0 then
            set .ticks = .ticks+1
        endif
        if .ticks>DOUBLEPRESS_TICKLIMIT then
            set .ticks = 0
        endif
    endmethod
endstruct

struct ARROWS
    KEY U
    KEY D
    KEY L
    KEY R
    static method create takes nothing returns thistype
        local thistype a = thistype.allocate()
        set a.U = KEY.create()
        set a.D = KEY.create()
        set a.L = KEY.create()
        set a.R = KEY.create()
        return a
    endmethod
    method Update takes nothing returns nothing
        call .U.Update()
        call .D.Update()
        call .L.Update()
        call .R.Update()
    endmethod
endstruct

globals
    ARROWS array Pad[12]
endglobals

//! textmacro ArrowFunc takes KEY
private function PressArrow$KEY$ takes nothing returns nothing
    set Pad[GetPlayerId(GetEventDetectingPlayer())].$KEY$.action = KEY_NEWPRESS
endfunction
private function ReleaseArrow$KEY$ takes nothing returns nothing
    set Pad[GetPlayerId(GetEventDetectingPlayer())].$KEY$.action = KEY_RELEASED
endfunction
//! endtextmacro
//! runtextmacro ArrowFunc("U")
//! runtextmacro ArrowFunc("D")
//! runtextmacro ArrowFunc("L")
//! runtextmacro ArrowFunc("R")

private function Init takes nothing returns nothing
    local integer i = 0
    local trigger PressU = CreateTrigger()
    local trigger PressD = CreateTrigger()
    local trigger PressL = CreateTrigger()
    local trigger PressR = CreateTrigger()
    
    local trigger ReleaseU = CreateTrigger()
    local trigger ReleaseD = CreateTrigger()
    local trigger ReleaseL = CreateTrigger()
    local trigger ReleaseR = CreateTrigger()
    set i = 0
    loop
        call TriggerRegisterPlayerEvent(PressU, Player(i), EVENT_PLAYER_ARROW_UP_DOWN)
        call TriggerRegisterPlayerEvent(PressD, Player(i), EVENT_PLAYER_ARROW_DOWN_DOWN)
        call TriggerRegisterPlayerEvent(PressL, Player(i), EVENT_PLAYER_ARROW_LEFT_DOWN)
        call TriggerRegisterPlayerEvent(PressR, Player(i), EVENT_PLAYER_ARROW_RIGHT_DOWN)
        
        call TriggerRegisterPlayerEvent(ReleaseU, Player(i), EVENT_PLAYER_ARROW_UP_UP)
        call TriggerRegisterPlayerEvent(ReleaseD, Player(i), EVENT_PLAYER_ARROW_DOWN_UP)
        call TriggerRegisterPlayerEvent(ReleaseL, Player(i), EVENT_PLAYER_ARROW_LEFT_UP)
        call TriggerRegisterPlayerEvent(ReleaseR, Player(i), EVENT_PLAYER_ARROW_RIGHT_UP)
        
        set Pad<i> = ARROWS.create()
        
        set i = i+1
        exitwhen i == bj_MAX_PLAYERS or i == Pad.size
    endloop
    call TriggerAddAction(PressU, function PressArrowU)
    call TriggerAddAction(PressD, function PressArrowD)
    call TriggerAddAction(PressL, function PressArrowL)
    call TriggerAddAction(PressR, function PressArrowR)
    
    call TriggerAddAction(ReleaseU, function ReleaseArrowU)
    call TriggerAddAction(ReleaseD, function ReleaseArrowD)
    call TriggerAddAction(ReleaseL, function ReleaseArrowL)
    call TriggerAddAction(ReleaseR, function ReleaseArrowR)
endfunction
endlibrary
</i>


This system is a time saver with an easy way to accomplish things involving keypresses

An extensive example of how you could use it:
JASS:

scope MoveHeroes initializer Init
globals
    private unit array heroes[3]
    private constant string SPECIAL_EFFECT = &quot;Abilities\\Spells\\Human\\Polymorph\\PolyMorphTarget.mdl&quot;
    private constant real MOVESPEED = 8
    private constant real TURNSPEED = 8
endglobals

private function MoveHero takes nothing returns boolean
    local integer i = 0
    local real a
    loop
        if heroes<i>!=null then
            set a = GetUnitFacing(heroes<i>)*bj_DEGTORAD
            //Up key
            if Pad<i>.U.Doublepress() then
                call DestroyEffect(AddSpecialEffect(SPECIAL_EFFECT, GetUnitX(heroes<i>), GetUnitY(heroes<i>)))
                call DisplayTextToPlayer(Player(i), 0, 0, &quot;SPRINTING!&quot;)
            endif
            if Pad<i>.U.Doubleheld() then
                call SetUnitPosition(heroes<i>, GetUnitX(heroes<i>)+Cos(a)*MOVESPEED*3, GetUnitY(heroes<i>)+Sin(a)*MOVESPEED*3)
            elseif Pad<i>.U.Held() then
                call SetUnitPosition(heroes<i>, GetUnitX(heroes<i>)+Cos(a)*MOVESPEED, GetUnitY(heroes<i>)+Sin(a)*MOVESPEED)
            endif
            //Down key
            if Pad<i>.D.Newpress() then
                call DestroyEffect(AddSpecialEffect(SPECIAL_EFFECT, GetUnitX(heroes<i>), GetUnitY(heroes<i>)))
            elseif Pad<i>.D.Held() then
                call SetUnitPosition(heroes<i>, GetUnitX(heroes<i>)-Cos(a)*MOVESPEED, GetUnitY(heroes<i>)-Sin(a)*MOVESPEED)
            elseif Pad<i>.D.Released() then
                call DestroyEffect(AddSpecialEffect(SPECIAL_EFFECT, GetUnitX(heroes<i>), GetUnitY(heroes<i>)))
            endif
            //Left key
            if Pad<i>.L.Doubleheld() then
                call SetUnitFacing(heroes<i>, GetUnitFacing(heroes<i>)+TURNSPEED*3)
            elseif Pad<i>.L.Held() then
                call SetUnitFacing(heroes<i>, GetUnitFacing(heroes<i>)+TURNSPEED)
            endif
            //Right key
            if Pad<i>.R.Doubleheld() then
                call SetUnitFacing(heroes<i>, GetUnitFacing(heroes<i>)-TURNSPEED*3)
            elseif Pad<i>.R.Held() then
                call SetUnitFacing(heroes<i>, GetUnitFacing(heroes<i>)-TURNSPEED)
            endif
            //instant spin
            if Pad<i>.L.Doublepress() or Pad<i>.R.Doublepress() then
                call DisplayTextToPlayer(Player(i), 0, 0, &quot;Superturnspeed!&quot;)
            endif
            //Camera
            if Player(i) == GetLocalPlayer() then
                call SetCameraTargetController(heroes<i>, 0, 0, true)
                call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, 1100, 0)
                call SetCameraField(CAMERA_FIELD_ZOFFSET, 100, 0)
                call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, 325, 0)
                call SetCameraField(CAMERA_FIELD_ROTATION, GetUnitFacing(heroes<i>), 0.0625)
                call SetCameraField(CAMERA_FIELD_FIELD_OF_VIEW, 65, 0)
            endif
        endif
        call Pad<i>.Update()
        set i = i+1
        exitwhen i==heroes.size
    endloop
    return false
endfunction

private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterTimerEvent(t, 0.03125, true)
    call TriggerAddCondition(t, Condition(function MoveHero))
    
    set heroes[0] = gg_unit_Hpal_0001
    set heroes[1] = gg_unit_Hpal_0002
    set heroes[2] = gg_unit_Hpal_0003
    
    call PauseUnit(heroes[0], true)
    call PauseUnit(heroes[1], true)
    call PauseUnit(heroes[2], true)
endfunction
endscope
</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>


This example is included in the demo map :)

Have fun!
 

Attachments

  • EasyKeysv1.1.w3x
    34 KB · Views: 303

Jesus4Lyf

Good Idea™
Reaction score
397
This system doesn't make any sense as far as I can see, except to see whether or not a player is holding down a key, which would tend to be done in periodic effects and hence this is total overkill. As for checking if a key was pressed or released, the natives do that and this doesn't really seem to simplify anything.
I think it is highly probable that you, yes you, will find this quite useless.
And on that note, I will graveyard this until it is apparently useful.
 

Prozix

New Member
Reaction score
7
As long as people using the search function are able to find this I'm okay with whatever you do.

The extra thing this library does is that you can check for a newpress. Also I think it's easier to use than with the events:

this:
JASS:

scope MoveHeroesBad initializer Init
globals
    unit array heroes[12]
    integer array Up[12]
    integer array Down[12]
    integer array Left[12]
    integer array Right[12]
endglobals

private function MoveHeroNewpressUp takes nothing returns nothing
    local unit u = heroes[GetPlayerId(GetEventDetectingPlayer())]
    set Up[GetPlayerId(GetEventDetectingPlayer())] = 1
    if not(u == null) then
        call DestroyEffect(AddSpecialEffect(SPECIAL_EFFECT, GetUnitX(u), GetUnitY(u)))
    endif
endfunction
private function MoveHeroNewpressDown takes nothing returns nothing
    local unit u = heroes[GetPlayerId(GetEventDetectingPlayer())]
    set Down[GetPlayerId(GetEventDetectingPlayer())] = 1
    if not(u == null) then
        call DestroyEffect(AddSpecialEffect(SPECIAL_EFFECT, GetUnitX(u), GetUnitY(u)))
    endif
endfunction
private function MoveHeroNewpressLeft takes nothing returns nothing
    local unit u = heroes[GetPlayerId(GetEventDetectingPlayer())]
    set Left[GetPlayerId(GetEventDetectingPlayer())] = 1
    if not(u == null) then
        call DestroyEffect(AddSpecialEffect(SPECIAL_EFFECT, GetUnitX(u), GetUnitY(u)))
    endif
endfunction
private function MoveHeroNewpressRight takes nothing returns nothing
    local unit u = heroes[GetPlayerId(GetEventDetectingPlayer())]
    set Right[GetPlayerId(GetEventDetectingPlayer())] = 1
    if not(u == null) then
        call DestroyEffect(AddSpecialEffect(SPECIAL_EFFECT, GetUnitX(u), GetUnitY(u)))
    endif
endfunction


private function MoveHeroHeld takes nothing returns nothing
    //every...
    local integer i = 0
    loop
        if Up<i> == 1 and not(heroes<i> == null) then
            call SetUnitPosition(GetUnitX(heroes<i>), GetUnitY(heroes<i>)+12)
        endif
        //Down, Left and Right
        i = i+1
        exitwhen i==heroes.size
    endloop
endfunction

private function MoveHeroReleased takes nothing returns nothing
    set UP[GetPlayerId(GetEventDetectingPlayer())] = 0
    //do stuff
endfunction

private function Init takes nothing returns nothing
    local trigger upNewpress = CreateTrigger()
    local trigger upReleased = CreateTrigger()
    local trigger upHeld = CreateTrigger()
    // oh jesus...
    
    //blabla
endfunction
endscope
</i></i></i></i>


would become this:

JASS:

scope MoveHeroes initializer Init
globals
    unit array heroes[12]
endglobals

private function MoveHero takes nothing returns boolean
    local integer i = 0
    loop
        if not(heroes<i>==null) then
            if Pad<i>.U.Newpress() then
                call DestroyEffect(AddSpecialEffect(SPECIAL_EFFECT, GetUnitX(heroes<i>), GetUnitY(heroes<i>)))
            elseif Pad<i>.U.Held() then
                call SetUnitPosition(GetUnitX(heroes<i>), GetUnitY(heroes<i>)+12)
            elseif Pad<i>.U.Released() then
                //do stuff
            endif
        endif
        set i = i+1
        exitwhen i==heroes.size
    endloop
    Pad<i>.Update()
    return false
endfunction

private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterTimerEvent(t, 0.03, true)
    call TriggerAddCondition(t, Condition(function MoveHero))
    
    //init heroes
endfunction
endscope
</i></i></i></i></i></i></i></i></i>


Which is in my opinion a lot neater, don't you agree?
 

Romek

Super Moderator
Reaction score
964
Read this.

We want Quality, not Quantity. Thus, submit only what you think is good! If your post contains something like "check out my crappy spell" it will hit graveyard right away.
:p
 

Prozix

New Member
Reaction score
7
I think you misunderstood what I was trying to say. At first glance this might seem useless but it isn't. It works and it's easy to use. What more do you want?
 

Romek

Super Moderator
Reaction score
964
I think J4L's point was simply that you shouldn't submit something and say it's useless. A better description, example and such would be nice.

Anyway, this does indeed seem quite useful, so I'll move it back to the T&R forum for comments and such. :)
 

tooltiperror

Super Moderator
Reaction score
231
JASS:
//pros: -  everything has been done for you
//      -  easy to use

//cons: -  slow (due to warcraft keypress event limitations)
//      -  you have to call an update function in order to make this system work which would become annoying to do properly if you have multiple triggers using this system at once


You should put Pro's before Cons.
 

Prozix

New Member
Reaction score
7
I think J4L's point was simply that you shouldn't submit something and say it's useless. A better description, example and such would be nice.

Anyway, this does indeed seem quite useful, so I'll move it back to the T&R forum for comments and such. :)
Yeah that's true, but I though no matter how I would put it, this might seem useless to some people anyway. I'll just follow the forums rules next time..

There is a little example in the map itself, I suppose I should copy it to the main post. Thanx anyway


> You should put Pro's before Cons.

:p did that on purpose, changed it
 

Jesus4Lyf

Good Idea™
Reaction score
397
JASS:
EasyKeys requires you to call an update function in order to make this system work which would become annoying to do properly if you have multiple triggers using this system at once

My point was really that without this being automated, this is just a wrapper for native functionality.

If you threw this up on T32, and maybe provided some Events for on double press... this might be a lot more helpful (you don't have to use the linked stuff, these are just suggestions).

It is poor encapsulation and design to use an update method which the user must call.
 

tooltiperror

Super Moderator
Reaction score
231
If this is updated, I may use it for a racing/boating game.
 

Prozix

New Member
Reaction score
7
The Event system you've written can be very usefull. I think I'm thinking to much in a "game loop" way without events.

Your suggestions are really good. I'm going to rewrite it now ^^

Owkay......... Darn Event doesn't compile. I redownloaded Jassnewgenpack 5d but it says: "destroy, member redeclared".

I made a lot of changes (almost none->inefficient/ugly code) to make it work(I hope) but now Event doens't work. I think I have done something terribly stupid but I don't know what...
 

Attachments

  • EasyKeysv1.1.w3x
    40.1 KB · Views: 276
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    New recipe is another summer dessert Berry and Peach Cheesecake - https://www.thehelper.net/threads/recipe-berry-and-peach-cheesecake.194169/

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top