Game client codebase including: - CharacterActionControl: Character and creature management - GlobalScript: Network, items, skills, quests, utilities - RYLClient: Main client application with GUI and event handlers - Engine: 3D rendering engine (RYLGL) - MemoryManager: Custom memory allocation - Library: Third-party dependencies (DirectX, boost, etc.) - Tools: Development utilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
398 lines
14 KiB
OpenEdge ABL
398 lines
14 KiB
OpenEdge ABL
VERSION 1.0 CLASS
|
|
BEGIN
|
|
MultiUse = -1 'True
|
|
Persistable = 0 'NotPersistable
|
|
DataBindingBehavior = 0 'vbNone
|
|
DataSourceBehavior = 0 'vbNone
|
|
MTSTransactionMode = 0 'NotAnMTSObject
|
|
END
|
|
Attribute VB_Name = "cInput"
|
|
Attribute VB_GlobalNameSpace = False
|
|
Attribute VB_Creatable = True
|
|
Attribute VB_PredeclaredId = False
|
|
Attribute VB_Exposed = False
|
|
Option Explicit
|
|
|
|
'Here we will control all of the input, from any source
|
|
'List of camera views (same enum listed in the camera class)
|
|
Private Enum DefaultCameraViews
|
|
DefaultView
|
|
OverHeadView
|
|
SideOverheadView1
|
|
SideOverheadView2
|
|
OpponentView
|
|
CustomView
|
|
End Enum
|
|
|
|
'*NOTE*
|
|
'
|
|
'I may want to add Force Feedback support, if i do, I would do so here.
|
|
|
|
'Mouse constants
|
|
Private Const mlJoystickRange As Long = 35
|
|
Private Const mnMaxZThresh As Single = 35
|
|
Private Const mnMaxYThresh As Single = 50
|
|
Private Const mnMaxXThresh As Single = 35
|
|
|
|
'DirectInput variables, etc
|
|
Private Const glBufferSize As Long = 10
|
|
'DInput objects
|
|
Private di As DirectInput8
|
|
Private diMouse As DirectInputDevice8
|
|
Private diKeyboard As DirectInputDevice8
|
|
Private diJoystick As DirectInputDevice8
|
|
'Is the camera moving?
|
|
Private mfMovingCamera As Boolean
|
|
|
|
'Local properties to determine what controls should be used
|
|
Public UseMouse As Boolean
|
|
Public UseKeyboard As Boolean
|
|
Public UseJoystick As Boolean
|
|
Public JoystickGuid As String
|
|
Public JoystickSensitivity As Single
|
|
Public MouseSensitivity As Single
|
|
Public KeyboardSensitivity As Single
|
|
|
|
Public Property Get InputObject() As DirectInput8
|
|
Set InputObject = di
|
|
End Property
|
|
|
|
Public Function InitDirectInput(oForm As Form) As Boolean
|
|
|
|
Dim diProp As DIPROPLONG
|
|
Dim diProp_Dead As DIPROPLONG
|
|
Dim diProp_Range As DIPROPRANGE
|
|
Dim diProp_Saturation As DIPROPLONG
|
|
|
|
On Error GoTo FailedInput
|
|
|
|
InitDirectInput = True
|
|
'Create the DirectInput object, and all of the devices we need.
|
|
If UseMouse Then
|
|
Set diMouse = di.CreateDevice("guid_SysMouse")
|
|
diMouse.SetCommonDataFormat DIFORMAT_MOUSE
|
|
diMouse.SetCooperativeLevel oForm.hwnd, DISCL_FOREGROUND Or DISCL_EXCLUSIVE
|
|
|
|
' Set the buffer size
|
|
diProp.lHow = DIPH_DEVICE
|
|
diProp.lObj = 0
|
|
diProp.lData = glBufferSize
|
|
Call diMouse.SetProperty("DIPROP_BUFFERSIZE", diProp)
|
|
'Acquire the mouse
|
|
diMouse.Acquire
|
|
End If
|
|
|
|
If UseKeyboard Then
|
|
Set diKeyboard = di.CreateDevice("GUID_SysKeyboard")
|
|
|
|
diKeyboard.SetCommonDataFormat DIFORMAT_KEYBOARD
|
|
diKeyboard.SetCooperativeLevel oForm.hwnd, DISCL_FOREGROUND Or DISCL_NONEXCLUSIVE
|
|
'Acquire the keyboard
|
|
diKeyboard.Acquire
|
|
End If
|
|
|
|
If UseJoystick Then
|
|
On Error Resume Next
|
|
Set diJoystick = di.CreateDevice(JoystickGuid)
|
|
If Err Then 'This joystick doesn't exist anymore
|
|
UseJoystick = False
|
|
Exit Function
|
|
End If
|
|
On Error GoTo FailedInput
|
|
diJoystick.SetCommonDataFormat DIFORMAT_JOYSTICK
|
|
diJoystick.SetCooperativeLevel oForm.hwnd, DISCL_FOREGROUND Or DISCL_EXCLUSIVE
|
|
|
|
'Set deadzone to 10 percent
|
|
With diProp_Dead
|
|
.lData = mlJoystickRange \ 20
|
|
.lHow = DIPH_BYOFFSET
|
|
.lObj = DIJOFS_X
|
|
diJoystick.SetProperty "DIPROP_DEADZONE", diProp_Dead
|
|
.lObj = DIJOFS_Y
|
|
diJoystick.SetProperty "DIPROP_DEADZONE", diProp_Dead
|
|
End With
|
|
|
|
'Set saturation zones to 5 percent
|
|
With diProp_Saturation
|
|
.lData = mlJoystickRange \ 40
|
|
.lHow = DIPH_BYOFFSET
|
|
.lObj = DIJOFS_X
|
|
diJoystick.SetProperty "DIPROP_SATURATION", diProp_Saturation
|
|
.lObj = DIJOFS_Y
|
|
diJoystick.SetProperty "DIPROP_SATURATION", diProp_Saturation
|
|
End With
|
|
|
|
'Just in case this device doesn't let us set the range
|
|
On Error Resume Next
|
|
'Set range for all axes
|
|
With diProp_Range
|
|
.lHow = DIPH_DEVICE
|
|
.lMin = -mlJoystickRange
|
|
.lMax = mlJoystickRange
|
|
End With
|
|
diJoystick.SetProperty "DIPROP_RANGE", diProp_Range
|
|
On Error GoTo FailedInput
|
|
|
|
diJoystick.Acquire
|
|
End If
|
|
|
|
Exit Function
|
|
|
|
FailedInput:
|
|
InitDirectInput = False
|
|
|
|
End Function
|
|
|
|
Private Sub ProcessMouseData(oPaddle As cPaddle, oPuck As cPuck)
|
|
'This is where we respond to any change in mouse state. Usually this will be an axis movement
|
|
'or button press or release
|
|
|
|
Dim diDeviceData(1 To glBufferSize) As DIDEVICEOBJECTDATA
|
|
Dim lNumItems As Long
|
|
Dim lCount As Integer
|
|
Dim lTempX As Single, lTempZ As Single
|
|
|
|
On Error GoTo INPUTLOST 'In case we lost the mouse
|
|
diMouse.Acquire 'Just in case
|
|
lNumItems = diMouse.GetDeviceData(diDeviceData, 0)
|
|
On Error GoTo 0 'Reset our error
|
|
|
|
' Process data
|
|
For lCount = 1 To lNumItems
|
|
Select Case diDeviceData(lCount).lOfs
|
|
Case DIMOFS_X 'We moved the X axis
|
|
If mfMovingCamera Then
|
|
With goCamera.Position
|
|
If lTempZ = 0 Then lTempZ = .z
|
|
lTempX = .X + (diDeviceData(lCount).lData * MouseSensitivity)
|
|
goCamera.SetCameraPosition CustomView, oPaddle.PaddleID
|
|
If Abs(lTempX) > mnMaxXThresh Then
|
|
'Whoops too much
|
|
lTempX = mnMaxXThresh * (lTempX / Abs(lTempX))
|
|
End If
|
|
End With
|
|
Else
|
|
With oPaddle.Position
|
|
If lTempZ = 0 Then lTempZ = .z
|
|
lTempX = .X + (diDeviceData(lCount).lData * MouseSensitivity)
|
|
End With
|
|
End If
|
|
Case DIMOFS_Y 'We moved the Y axis
|
|
If mfMovingCamera Then
|
|
With goCamera.Position
|
|
If lTempX = 0 Then lTempX = .X
|
|
lTempZ = .z - (diDeviceData(lCount).lData * MouseSensitivity)
|
|
goCamera.SetCameraPosition CustomView, oPaddle.PaddleID
|
|
If Abs(lTempZ) > mnMaxZThresh Then
|
|
'Whoops too much
|
|
lTempZ = mnMaxZThresh * (lTempZ / Abs(lTempZ))
|
|
End If
|
|
End With
|
|
Else
|
|
With oPaddle.Position
|
|
If lTempX = 0 Then lTempX = .X
|
|
lTempZ = .z - (diDeviceData(lCount).lData * MouseSensitivity)
|
|
End With
|
|
End If
|
|
Case DIMOFS_BUTTON1
|
|
mfMovingCamera = (diDeviceData(lCount).lData And &H80 = &H80)
|
|
End Select
|
|
Next lCount
|
|
'Ok, this sequence is done, process the info, and move on
|
|
If lTempX <> 0 And lTempZ <> 0 Then
|
|
If mfMovingCamera Then
|
|
goCamera.Position = vec3(lTempX, goCamera.Position.Y, lTempZ)
|
|
Else
|
|
oPaddle.LastPosition = oPaddle.Position
|
|
oPaddle.Position = vec3(lTempX, oPaddle.Position.Y, lTempZ)
|
|
oPaddle.Velocity = vec3(oPaddle.Position.X - oPaddle.LastPosition.X, oPaddle.Velocity.Y, oPaddle.Position.z - oPaddle.LastPosition.z)
|
|
oPaddle.LastVelocityTick = timeGetTime
|
|
End If
|
|
End If
|
|
MakeSurePaddleIsOnBoard oPaddle
|
|
Exit Sub
|
|
|
|
INPUTLOST:
|
|
If (Err.Number = DIERR_INPUTLOST) Or (Err.Number = DIERR_NOTACQUIRED) Then
|
|
'We no longer have the mouse..
|
|
End If
|
|
End Sub
|
|
|
|
Private Sub ProcessKeyBoardData(oPaddle As cPaddle, oPuck As cPuck)
|
|
|
|
'This is where we respond to any change in keyboard state. Usually this will be an axis movement
|
|
'or button press or release
|
|
|
|
Dim diKeys As DIKEYBOARDSTATE
|
|
Dim lTempX As Single, lTempZ As Single
|
|
|
|
On Error GoTo INPUTLOST 'In case we lost focus
|
|
diKeyboard.Acquire 'Just in case
|
|
diKeyboard.GetDeviceStateKeyboard diKeys
|
|
|
|
If KeyPressed(diKeys, DIK_LEFTARROW) Or KeyPressed(diKeys, DIK_NUMPAD4) Then
|
|
oPaddle.LastPosition = oPaddle.Position
|
|
With oPaddle.Position
|
|
lTempX = .X - KeyboardSensitivity
|
|
oPaddle.Position = vec3(lTempX, .Y, .z)
|
|
End With
|
|
oPaddle.Velocity = vec3(oPaddle.Position.X - oPaddle.LastPosition.X, oPaddle.Velocity.Y, oPaddle.Velocity.z)
|
|
oPaddle.LastVelocityTick = timeGetTime
|
|
End If
|
|
If KeyPressed(diKeys, DIK_RIGHTARROW) Or KeyPressed(diKeys, DIK_NUMPAD6) Then
|
|
oPaddle.LastPosition = oPaddle.Position
|
|
With oPaddle.Position
|
|
lTempX = .X + KeyboardSensitivity
|
|
oPaddle.Position = vec3(lTempX, .Y, .z)
|
|
End With
|
|
oPaddle.Velocity = vec3(oPaddle.Position.X - oPaddle.LastPosition.X, oPaddle.Velocity.Y, oPaddle.Velocity.z)
|
|
oPaddle.LastVelocityTick = timeGetTime
|
|
End If
|
|
If KeyPressed(diKeys, DIK_UPARROW) Or KeyPressed(diKeys, DIK_NUMPAD8) Then
|
|
oPaddle.LastPosition = oPaddle.Position
|
|
With oPaddle.Position
|
|
lTempZ = .z + KeyboardSensitivity
|
|
oPaddle.Position = vec3(.X, .Y, lTempZ)
|
|
End With
|
|
oPaddle.Velocity = vec3(oPaddle.Velocity.X, oPaddle.Velocity.Y, oPaddle.Position.z - oPaddle.LastPosition.z)
|
|
oPaddle.LastVelocityTick = timeGetTime
|
|
End If
|
|
If KeyPressed(diKeys, DIK_DOWNARROW) Or KeyPressed(diKeys, DIK_NUMPAD2) Then
|
|
oPaddle.LastPosition = oPaddle.Position
|
|
With oPaddle.Position
|
|
lTempZ = .z - KeyboardSensitivity
|
|
oPaddle.Position = vec3(.X, .Y, lTempZ)
|
|
End With
|
|
oPaddle.Velocity = vec3(oPaddle.Velocity.X, oPaddle.Velocity.Y, oPaddle.Position.z - oPaddle.LastPosition.z)
|
|
oPaddle.LastVelocityTick = timeGetTime
|
|
End If
|
|
|
|
MakeSurePaddleIsOnBoard oPaddle
|
|
Exit Sub
|
|
|
|
INPUTLOST:
|
|
If (Err.Number = DIERR_INPUTLOST) Or (Err.Number = DIERR_NOTACQUIRED) Then
|
|
'We no longer have the mouse..
|
|
End If
|
|
End Sub
|
|
|
|
Private Sub ProcessJoystickData(oPaddle As cPaddle, oPuck As cPuck)
|
|
|
|
'This is where we respond to any change in keyboard state. Usually this will be an axis movement
|
|
'or button press or release
|
|
|
|
Dim diJoy As DIJOYSTATE
|
|
Dim lTempX As Single, lTempZ As Single
|
|
|
|
On Error GoTo INPUTLOST 'In case we lost focus
|
|
diJoystick.Acquire 'Just in case
|
|
diJoystick.Poll
|
|
diJoystick.GetDeviceStateJoystick diJoy
|
|
|
|
If diJoy.X <> 0 Then
|
|
oPaddle.LastPosition = oPaddle.Position
|
|
With oPaddle.Position
|
|
lTempX = .X + (diJoy.X * JoystickSensitivity)
|
|
oPaddle.Position = vec3(lTempX, .Y, .z)
|
|
End With
|
|
oPaddle.Velocity = vec3(oPaddle.Position.X - oPaddle.LastPosition.X, oPaddle.Velocity.Y, oPaddle.Velocity.z)
|
|
oPaddle.LastVelocityTick = timeGetTime
|
|
End If
|
|
If diJoy.Y <> 0 Then
|
|
oPaddle.LastPosition = oPaddle.Position
|
|
With oPaddle.Position
|
|
lTempZ = .z - (diJoy.Y * JoystickSensitivity)
|
|
oPaddle.Position = vec3(.X, .Y, lTempZ)
|
|
End With
|
|
oPaddle.Velocity = vec3(oPaddle.Velocity.X, oPaddle.Velocity.Y, oPaddle.Position.z - oPaddle.LastPosition.z)
|
|
oPaddle.LastVelocityTick = timeGetTime
|
|
End If
|
|
|
|
MakeSurePaddleIsOnBoard oPaddle
|
|
Exit Sub
|
|
|
|
INPUTLOST:
|
|
If (Err.Number = DIERR_INPUTLOST) Or (Err.Number = DIERR_NOTACQUIRED) Then
|
|
'We no longer have the joystick..
|
|
End If
|
|
End Sub
|
|
|
|
Public Sub GetAndHandleInput(oPaddle As cPaddle, oPuck As cPuck)
|
|
|
|
Dim vOldPaddle As D3DVECTOR
|
|
|
|
oPaddle.Velocity = vec3(0, 0, 0)
|
|
vOldPaddle = oPaddle.Position
|
|
If UseMouse Then
|
|
'First let's handle the mouse
|
|
ProcessMouseData oPaddle, oPuck
|
|
End If
|
|
|
|
If UseKeyboard Then
|
|
'Now we can worry about keyboard
|
|
ProcessKeyBoardData oPaddle, oPuck
|
|
End If
|
|
|
|
If UseJoystick Then
|
|
'If we have a joystick selected check that too
|
|
ProcessJoystickData oPaddle, oPuck
|
|
End If
|
|
oPaddle.EnsureReality vOldPaddle, oPuck
|
|
End Sub
|
|
|
|
'Helper function to determine if a key is pressed
|
|
Private Function KeyPressed(diKeys As DIKEYBOARDSTATE, Key As Byte)
|
|
KeyPressed = (diKeys.Key(Key) And &H80 = &H80)
|
|
End Function
|
|
|
|
Private Function MakeSurePaddleIsOnBoard(oPaddle As cPaddle)
|
|
Dim lTempZ As Single, lTempX As Single
|
|
lTempX = oPaddle.Position.X
|
|
lTempZ = oPaddle.Position.z
|
|
|
|
'Don't let the paddle leave the left or right sides of the table
|
|
If lTempX > (gnSideLeftWallEdge - (gnPaddleRadius)) Then
|
|
lTempX = (gnSideLeftWallEdge - (gnPaddleRadius))
|
|
ElseIf lTempX < (gnSideRightWallEdge + (gnPaddleRadius)) Then
|
|
lTempX = (gnSideRightWallEdge + (gnPaddleRadius))
|
|
End If
|
|
'Depending on which end of the table we are *supposed* to be on,
|
|
'restrict our movement.
|
|
If oPaddle.PaddleID = 0 Then
|
|
If lTempZ > -(gnPaddleRadius * 1.5) Then
|
|
lTempZ = -(gnPaddleRadius * 1.5)
|
|
ElseIf lTempZ < (gnFarWallEdge + (gnPaddleRadius)) Then
|
|
lTempZ = (gnFarWallEdge + (gnPaddleRadius))
|
|
End If
|
|
Else
|
|
If lTempZ > (gnNearWallEdge - (gnPaddleRadius)) Then
|
|
lTempZ = (gnNearWallEdge - (gnPaddleRadius))
|
|
ElseIf lTempZ < (gnPaddleRadius * 1.5) Then
|
|
lTempZ = (gnPaddleRadius * 1.5)
|
|
End If
|
|
End If
|
|
|
|
oPaddle.Position = vec3(lTempX, oPaddle.Position.Y, lTempZ)
|
|
End Function
|
|
|
|
Private Sub Class_Initialize()
|
|
Set diMouse = Nothing
|
|
Set diKeyboard = Nothing
|
|
Set diJoystick = Nothing
|
|
Set di = Nothing
|
|
Set di = dx.DirectInputCreate
|
|
End Sub
|
|
|
|
Private Sub Class_Terminate()
|
|
On Error Resume Next 'Ignore any errors, we're cleaning everything up
|
|
'Unacquire the mouse
|
|
If Not (diMouse Is Nothing) Then diMouse.Unacquire
|
|
If Not (diKeyboard Is Nothing) Then diKeyboard.Unacquire
|
|
If Not (diJoystick Is Nothing) Then diJoystick.Unacquire
|
|
'Destroy our objects
|
|
Set diMouse = Nothing
|
|
Set diKeyboard = Nothing
|
|
Set diJoystick = Nothing
|
|
Set di = Nothing
|
|
End Sub
|