Code: def pbSameThread(wnd) return false if wnd==0 processid=[0].pack('l') getCurrentThreadId=Win32API.new('kernel32','GetCurrentThreadId', '%w()','l') getWindowThreadProcessId=Win32API.new('user32','GetWindowThreadProcessId', '%w(l p)','l') threadid=getCurrentThreadId.call wndthreadid=getWindowThreadProcessId.call(wnd,processid) return (wndthreadid==threadid) end module Input DOWN = 2 LEFT = 4 RIGHT = 6 UP = 8 A = 11 B = 12 C = 13 X = 14 Y = 15 Z = 16 L = 17 R = 18 SHIFT = 21 CTRL = 22 ALT = 23 F5 = 25 F6 = 26 F7 = 27 F8 = 28 F9 = 29 LeftMouseKey = 1 RightMouseKey = 2 # GetAsyncKeyState or GetKeyState will work here @GetKeyState=Win32API.new("user32", "GetAsyncKeyState", "i", "i") @GetForegroundWindow=Win32API.new("user32", "GetForegroundWindow", "", "i") # Returns whether a key is being pressed @PadState=Win32API.new("xinput1_3.dll","XInputGetState","ip","l") Buttons=[64,128,32,16,256,512,1024,2048,1,16384,2,32768] Assign=[64,128,32,16,256,512,1024,2048,1,16384,2,32768] @counter=0 @DeadZone=[] def self.getstate(key) return (@GetKeyState.call(key)&0x8000)>0 end def self.PadState(key) #Basicamente, el nucleo de todo esto, all hail this method inputData= "\0" * 16 @PadState.call(0,inputData) arr=inputData.unpack("ssnnssss") if @DeadZone.empty? @DeadZone.push(arr[4],arr[5],arr[6],arr[7]) end if key==Assign[6] && (arr[4]==-32767||arr[6]==-32767) return true end if key==Assign[7] && (arr[6]==32767 || arr[4]==32767) return true end if key==Assign[4] && (arr[5]==32767 || arr[7]==32767) return true end if key==Assign[5] && (arr[5]==-32767 || arr[7]==-32767) return true end if key==Assign[3] && arr[3]>100 return true end if arr[2]==key return true end return false end def self.State2(key) data=self.PadState(key) code=self.GetCode(key) if data==true && @padPState[code]==false @padPState[code]=true @padKeyState[code]+=1 return true end if data==false @padPState[code]=false @padKeyState[code]=0 return false end if data==true && @padPState[code]==true @padKeyState[code]+=1 return false end return false end def self.State(key) data=self.PadState(key) code=self.GetCode(key) if data==true && @padPressState[code]==false @padPressState[code]=true @padKeyState[code]+=1 return true end if data==false @padPressState[code]=false @padKeyState[code]=0 return false end if data==true && @padPressState[code]==true @padKeyState[code]+=1 return false end return false end def self.padVibrate(vibration1,vibration2) @SetState=Win32API.new("xinput1_3.dll","XInputSetState","ip","") @SetState.call(0,"#{vibration1},#{vibration2}") end def self.updateKeyState(i) gfw=pbSameThread(@GetForegroundWindow.call()) if !@stateUpdated[i] newstate=self.getstate(i) && gfw @triggerstate[i]=(newstate&&@keystate[i]==0) @releasestate[i]=(!newstate&&@keystate[i]>0) @keystate[i]=newstate ? @keystate[i]+1 : 0 @stateUpdated[i]=true end end def self.Update(i,identifier=0) gfw = pbSameThread(@GetForegroundWindow.call()) if !@padStateUpdated[i] state=(self.PadState(Assign[i]) && gfw) @padTriggerState[i]=(state && @padKeyState[i]==0) @padKeyState[i]=(state ? @padKeyState[i]+1 : 0) @padReleaseState[i]=(!state && @padKeyState[i]>0) @padStateUpdated[i]=true end end def self.update if @keystate for i in 0...256 # just noting that the state should be updated # instead of thunking to Win32 256 times @stateUpdated[i]=false if @keystate[i] > 0 # If there is a repeat count, update anyway # (will normally apply only to a very few keys) updateKeyState(i) end if @counter>Assign.size @counter=0 end @padStateUpdated[@counter]=false if @padKeyState if @padKeyState[@counter]>0 self.Update(@counter) end end @counter+=1 end else @stateUpdated=[] @keystate=[] @triggerstate=[] @releasestate=[] @padStateUpdated=[] @padKeyState=[] @padTriggerState=[] @padPressState=[] @padPState=[] @padReleaseState=[] for i in 0...256 @stateUpdated[i]=true @keystate[i]=self.getstate(i) ? 1 : 0 @triggerstate[i]=false @releasestate[i]=false if i<=Assign.size @padStateUpdated[i]=true @padKeyState[i]= self.PadState(i) ? 1 : 0 @padTriggerState[i]=false @padPressState[i]=false @padReleaseState[i]=false @padPState[i]=false end end end end def self.buttonToKey(button) case button when Input::DOWN return [0x28] # Down when Input::LEFT return [0x25] # Left when Input::RIGHT return [0x27] # Right when Input::UP return [0x26] # Up when Input::A return [0x5A,0x10] # Z, Shift when Input::B return [0x58,0x1B] # X, ESC when Input::C return [0x43,0x0D,0x20] # C, ENTER, Space when Input::X return [0x41] # A when Input::Y return [0x53] # S when Input::Z return [0x44] # D when Input::L return [0x51,0x21] # Q, Page Up when Input::R return [0x57,0x22] # W, Page Down when Input::SHIFT return [0x10] # Shift when Input::CTRL return [0x11] # Ctrl when Input::ALT return [0x12] # Alt when Input::F5 return [0x74] # F5 when Input::F6 return [0x75] # F6 when Input::F7 return [0x76] # F7 when Input::F8 return [0x77] # F8 when Input::F9 return [0x78] # F9 else return [] end end def self.PadCode(button) #Returns the key value case button when Input::UP; return [Assign[4]] when Input::DOWN; return [Assign[5]] when Input::LEFT; return [Assign[6]] when Input::RIGHT; return [Assign[7]] when Input::B; return [Assign[1]] when Input::C; return [Assign[2]] when Input::A; return [Assign[3]] when Input::L; return [Assign[8]] when Input::R; return [Assign[10]] end return [] end def self.dir4 button=0 repeatcount=0 if self.press?(Input::DOWN) && self.press?(Input::UP) return 0 end if self.press?(Input::LEFT) && self.press?(Input::RIGHT) return 0 end for b in [Input::DOWN,Input::LEFT,Input::RIGHT,Input::UP] rc=self.count(b) if rc>0 if repeatcount==0 || rc<repeatcount button=b repeatcount=rc end end end return button end def self.dir8 buttons=[] for b in [Input::DOWN,Input::LEFT,Input::RIGHT,Input::UP] rc=self.count(b) if rc>0 buttons.push([b,rc]) end end if buttons.length==0 return 0 elsif buttons.length==1 return buttons[0][0] elsif buttons.length==2 # since buttons sorted by button, no need to sort here if (buttons[0][0]==Input::DOWN && buttons[1][0]==Input::UP) return 0 end if (buttons[0][0]==Input::LEFT && buttons[1][0]==Input::RIGHT) return 0 end end buttons.sort!{|a,b| a[1]<=>b[1]} updown=0 leftright=0 for b in buttons if updown==0 && (b[0]==Input::UP || b[0]==Input::DOWN) updown=b[0] end if leftright==0 && (b[0]==Input::LEFT || b[0]==Input::RIGHT) leftright=b[0] end end if updown==Input::DOWN return 1 if leftright==Input::LEFT return 3 if leftright==Input::RIGHT return 2 elsif updown==Input::UP return 7 if leftright==Input::LEFT return 9 if leftright==Input::RIGHT return 8 else return 4 if leftright==Input::LEFT return 6 if leftright==Input::RIGHT return 0 end end def self.count(button) for btn in self.buttonToKey(button) c=self.repeatcount(btn) return c if c>0 end for btn in self.PadCode(button) c=self.padRepeatCount(btn) return c if c>0 end return 0 end def self.release?(button) rc=0 for btn in self.buttonToKey(button) c=self.repeatcount(btn) return false if c>0 rc+=1 if self.releaseex?(btn) end for btn in self.PadCode(button) c=self.padRepeatCount(btn) return false if c>0 rc+=1 if self.padReleaseex?(btn) end return rc>0 end def self.trigger?(button) trigger= self.buttonToKey(button).any? {|item| self.triggerex?(item) } pad = self.PadCode(button).any? {|item| self.padTriggerex?(item)} return trigger || pad end def self.repeat?(button) trigger= self.buttonToKey(button).any? {|item| self.repeatex?(item) } pad= self.PadCode(button).any? {|item| self.padRepeatex?(item)} return trigger || pad end def self.press?(button) return self.count(button)>0 end def self.repeatex?(key) return false if !@keystate updateKeyState(key) return @keystate[key]==1 || (@keystate[key]>20 && (@keystate[key]&1)==0) end def self.padRepeatex?(key) return false if !@padKeyState code=GetCode(key) self.State2(key) return @padKeyState[code]==1 || (@padKeyState[code]>20 && (@padKeyState[code]&1)==0) end def self.releaseex?(key) return false if !@releasestate updateKeyState(key) return @releasestate[key] end def self.padReleasex?(key) return false if !@padReleaseState code=self.GetCode(key) self.Update(code) return @padReleaseState[code] end def self.triggerex?(key) return false if !@triggerstate updateKeyState(key) return @triggerstate[key] end def self.padTriggerex?(key) return false if !@padTriggerState code= self.GetCode(key) result=self.State(key) return result end def self.repeatcount(key) return 0 if !@keystate updateKeyState(key) return @keystate[key] end def self.padRepeatCount(key) return 0 if !@padKeyState code= self.GetCode(key) result=self.Update(code) return @padKeyState[code] end def self.pressex?(key) trigger= self.repeatcount(key)>0 pad= self.repeatcount(key)>0 return trigger || pad end def self.RunToogle Kernel.pbMessage(_INTL("wds")) $PokemonSystem.runstyle=1 $PokemonGlobal.runtoogle=true end def self.GetCode(key) for i in 0..Assign.size if Assign[i]==key return i end end return 100 end end # Requires Win32API module Mouse gsm = Win32API.new('user32', 'GetSystemMetrics', 'i', 'i') @GetCursorPos = Win32API.new('user32', 'GetCursorPos', 'p', 'i') @SetCapture = Win32API.new('user32', 'SetCapture', 'p', 'i') @ReleaseCapture = Win32API.new('user32', 'ReleaseCapture', '', 'i') module_function def getMouseGlobalPos pos = [0, 0].pack('ll') if @GetCursorPos.call(pos) != 0 return pos.unpack('ll') else return nil end end def screen_to_client(x, y) return nil unless x and y screenToClient = Win32API.new('user32', 'ScreenToClient', %w(l p), 'i') pos = [x, y].pack('ll') if screenToClient.call(Win32API.pbFindRgssWindow, pos) != 0 return pos.unpack('ll') else return nil end end def setCapture @SetCapture.call(Win32API.pbFindRgssWindow) end def releaseCapture @ReleaseCapture.call end # Returns the position of the mouse relative to the game window. def getMousePos(catch_anywhere = false) resizeFactor=($ResizeFactor) ? $ResizeFactor : 1 x, y = screen_to_client(*getMouseGlobalPos) width, height = Win32API.client_size if catch_anywhere or (x >= 0 and y >= 0 and x < width and y < height) return (x/resizeFactor).to_i, (y/resizeFactor).to_i else return nil end end def del if @oldcursor == nil return else @SetClassLong.call(Win32API.pbFindRgssWindow,-12, @oldcursor) @oldcursor = nil end end end

CURRENT ERRORS ​

-As this is an XInput based script is possible that some controllers

aren´t compatible with this script, in order to make them work you will need to use external programs as XInputWrapper (for dualshocks) or x360ce (i dind´t test out if this one works, so i can´t ensure it to be compatible with rpg maker)



-Although is very rare that it occurs,for some reasons i still don´t know in some menus as the default essentials pause menu you will need to press the A button several times in order for it to response.

​

CONTROLS(Following an xbox controller structure)

button B= C key

button A=Z key

button Y=X key

DPAD or Joysticks=Directional arrows

R2 or L2=Run

​

​

TO BE DONE ​

- Give functionality to the remaining buttons

-Create a screen to customize the button functionality

-Solve problems as the one of the pause menu



if you have any suggestion or you want to report an error, please leave a comment. ​

I was investigating a bit with ruby and i wanted to see in deep how did win32API worked. For my first try i decided to get on with the XInput dll and... well, this come out.Essentials Gamepad Input is an easy to install script ready to be use directly in essentials with any xinput compatible gamepad and without any need of doing modifications or external programs as xpadder.You can also use Dualshock controllers, but you will need to use Xinput Wrapper in order to make it work.Installing it is as easy as following one simple step:Replace PSystem_Controls with this