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 || rc0 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