- Pokémon Essentials Version
- v16.2 ➖
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
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
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.
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
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.
-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.
- Credits
- Kyu