VbGORE1.0.14ClientSource
From VbGORE Visual Basic Online RPG Engine
This will contain the complete source of vbGORE for quick access usage.
Contents |
[edit] vbGORE Version 1.0.14
This is the complete source of vbGORE Version 1.0.14. For quick access and code viewing.
[edit] GameClient Source
[edit] Forms
[edit] frmConnect
Option Explicit Private Sub Form_KeyPress(KeyAscii As Integer) '***************************************************************** 'Call for the click button to be pressed if return is pressed 'More info: http://www.vbgore.com/GameClient.frmConnect.Form_KeyPress '***************************************************************** If KeyAscii = Asc(vbNewLine) Then ClickConnect End Sub Private Sub Form_Load() '***************************************************************** 'Load the values / graphics for the connect form 'More info: http://www.vbgore.com/GameClient.frmConnect.Form_Load '***************************************************************** 'Set the text boxes to transparent SetPictureTextboxes Me.hwnd 'Get the username/password NameTxt.Text = Var_Get(DataPath & "Game.ini", "INIT", "Name") PasswordTxt.Text = Var_Get(DataPath & "Game.ini", "INIT", "Password") SavePass = CBool(Val(Var_Get(DataPath & "Game.ini", "INIT", "SavePass")) * -1) 'Set the SavePass image SavePass = Not SavePass 'Since the routine reverses, we reverse to reverse the reverse... trust me, it just works ;) SavePassImg_Click 'Get the background Me.Picture = LoadPicture(App.Path & "\Grh\Connect.bmp") End Sub Private Sub ClickNew() '***************************************************************** 'Click the New Account button 'More info: http://www.vbgore.com/GameClient.frmConnect.ClickNew '***************************************************************** 'Show frmNew and hide frmConnect frmNew.Visible = True frmNew.Show Me.Visible = False End Sub Private Sub ClickConnect() '***************************************************************** 'Click the Connect button 'More info: http://www.vbgore.com/GameClient.frmConnect.ClickConnect '***************************************************************** 'Store the user name and password UserName = NameTxt.Text UserPassword = PasswordTxt.Text 'Validate the user data, then start the connecting sequence If Game_CheckUserData Then SendNewChar = False InitSocket End If End Sub Private Sub ClickExit() '***************************************************************** 'Click the Exit button 'More info: http://www.vbgore.com/GameClient.frmConnect.ClickExit '***************************************************************** 'Save the game ini (name and password) Var_Write DataPath & "Game.ini", "INIT", "Name", NameTxt.Text Var_Write DataPath & "Game.ini", "INIT", "SavePass", -CInt(SavePass) If Not SavePass Then Var_Write DataPath & "Game.ini", "INIT", "Password", "" Else Var_Write DataPath & "Game.ini", "INIT", "Password", PasswordTxt.Text End If 'End program IsUnloading = 1 End Sub Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) '***************************************************************** 'Process clicking events 'More info: http://www.vbgore.com/GameClient.frmConnect.Form_MouseDown '***************************************************************** 'New If Engine_Collision_Rect(X, Y, 1, 1, 217, 149, 96, 18) Then ClickNew 'Connect If Engine_Collision_Rect(X, Y, 1, 1, 217, 127, 96, 18) Then ClickConnect 'Exit If Engine_Collision_Rect(X, Y, 1, 1, 217, 171, 96, 18) Then ClickExit End Sub Private Sub Form_Unload(Cancel As Integer) '***************************************************************** 'Disable the picture textboxes 'More info: http://www.vbgore.com/GameClient.frmConnect.Form_Unload '***************************************************************** FreePictureTextboxes Me.hwnd End Sub Private Sub NameTxt_Change() '***************************************************************** 'Validates the name textbox upon changing 'More info: http://www.vbgore.com/GameClient.frmConnect.NameTxt_Change '***************************************************************** 'Make sure the string is legal If Len(NameTxt.Text) > 0 Then If Game_LegalString(NameTxt.Text) = False Then NameTxt.Text = Left$(NameTxt.Text, Len(NameTxt.Text) - 1) NameTxt.SelStart = Len(NameTxt.Text) End If End If End Sub Private Sub NameTxt_KeyPress(KeyAscii As Integer) '***************************************************************** 'Connect when return is pressed 'More info: http://www.vbgore.com/GameClient.frmConnect.NameTxt_KeyPress '***************************************************************** If KeyAscii = Asc(vbNewLine) Then KeyAscii = 0 ClickConnect End If End Sub Private Sub PasswordTxt_Change() '***************************************************************** 'Validates the password textbox upon changing 'More info: http://www.vbgore.com/GameClient.frmConnect.PasswordTxt_Change '***************************************************************** If Len(PasswordTxt.Text) > 0 Then If Game_LegalString(PasswordTxt.Text) = False Then PasswordTxt.Text = Left$(PasswordTxt.Text, Len(PasswordTxt.Text) - 1) PasswordTxt.SelStart = Len(PasswordTxt.Text) End If End If End Sub Private Sub PasswordTxt_KeyPress(KeyAscii As Integer) '***************************************************************** 'Connect when return is pressed 'More info: http://www.vbgore.com/GameClient.frmConnect.PasswordTxt_KeyPress '***************************************************************** If KeyAscii = Asc(vbNewLine) Then KeyAscii = 0 ClickConnect End If End Sub Private Sub SavePassImg_Click() '***************************************************************** 'Hide or show the Save Password image and store the value 'More info: http://www.vbgore.com/GameClient.frmConnect.SavePassImg_Click '***************************************************************** 'Change the value SavePass = Not SavePass 'Display the image or remove it If SavePass Then SavePassImg.Picture = LoadPicture(GrhPath & "Check.gif") Else Set SavePassImg.Picture = Nothing End If End Sub
[edit] frmMain
Option Explicit Implements DirectXEvent8 Private Declare Function GetCursorPos Lib "user32.dll" (ByRef lpPoint As POINTAPI) As Long Private Sub DirectXEvent8_DXCallback(ByVal EventID As Long) '***************************************************************** 'Handles mouse device events (movement, clicking, mouse wheel scrolling, etc) 'More info: http://www.vbgore.com/GameClient.frmMain.DirectXEvent8_DXCallback '***************************************************************** Dim DevData(1 To 50) As DIDEVICEOBJECTDATA Dim NumEvents As Long Dim LoopC As Long Dim Moved As Byte Dim OldMousePos As POINTAPI On Error GoTo ErrOut 'Check if message is for us If EventID <> MouseEvent Then Exit Sub If GetActiveWindow = 0 Then Exit Sub 'Retrieve data NumEvents = DIDevice.GetDeviceData(DevData, DIGDD_DEFAULT) 'Loop through data For LoopC = 1 To NumEvents Select Case DevData(LoopC).lOfs 'Move on X axis Case DIMOFS_X If Windowed Then OldMousePos = MousePos GetCursorPos MousePos MousePos.X = MousePos.X - (Me.Left \ Screen.TwipsPerPixelX) MousePos.Y = MousePos.Y - (Me.Top \ Screen.TwipsPerPixelY) MousePosAdd.X = -(OldMousePos.X - MousePos.X) MousePosAdd.Y = -(OldMousePos.Y - MousePos.Y) Else MousePosAdd.X = (DevData(LoopC).lData * MouseSpeed) MousePos.X = MousePos.X + MousePosAdd.X If MousePos.X < 0 Then MousePos.X = 0 If MousePos.X > frmMain.ScaleWidth Then MousePos.X = frmMain.ScaleWidth End If Moved = 1 'Move on Y axis Case DIMOFS_Y If Windowed Then OldMousePos = MousePos GetCursorPos MousePos MousePos.X = MousePos.X - (Me.Left \ Screen.TwipsPerPixelX) MousePos.Y = MousePos.Y - (Me.Top \ Screen.TwipsPerPixelY) MousePosAdd.X = -(OldMousePos.X - MousePos.X) MousePosAdd.Y = -(OldMousePos.Y - MousePos.Y) Else MousePosAdd.Y = (DevData(LoopC).lData * MouseSpeed) MousePos.Y = MousePos.Y + MousePosAdd.Y If MousePos.Y < 0 Then MousePos.Y = 0 If MousePos.Y > ScreenHeight Then MousePos.Y = ScreenHeight End If Moved = 1 'Mouse wheel is scrolled Case DIMOFS_Z 'Scroll the chat buffer if the cursor is over the chat buffer window If ShowGameWindow(ChatWindow) Then If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, GameWindow.ChatWindow.Screen.X, GameWindow.ChatWindow.Screen.Y, GameWindow.ChatWindow.Screen.Width, GameWindow.ChatWindow.Screen.Height) Then If DevData(LoopC).lData > 0 Then ChatBufferChunk = ChatBufferChunk + 0.25 ElseIf DevData(LoopC).lData < 0 Then ChatBufferChunk = ChatBufferChunk - 0.25 End If Engine_UpdateChatArray GoTo NextLoopC End If End If 'Scroll the zoom if the buffer didn't scroll If DevData(LoopC).lData > 0 Then ZoomLevel = ZoomLevel + (ElapsedTime * 0.001) If ZoomLevel > MaxZoomLevel Then ZoomLevel = MaxZoomLevel ElseIf DevData(LoopC).lData < 0 Then ZoomLevel = ZoomLevel - (ElapsedTime * 0.001) If ZoomLevel < 0 Then ZoomLevel = 0 End If 'Left button pressed Case DIMOFS_BUTTON0 If DevData(LoopC).lData = 0 Then MouseLeftDown = 0 SelGameWindow = 0 Else If MouseLeftDown = 0 Then 'Clicked down MouseLeftDown = 1 Input_Mouse_LeftClick End If End If 'Right button pressed Case DIMOFS_BUTTON1 If DevData(LoopC).lData = 0 Then MouseRightDown = 0 Input_Mouse_RightRelease Else If MouseRightDown = 0 Then 'Clicked down MouseRightDown = 1 Input_Mouse_RightClick End If End If End Select 'Update movement If Moved Then Input_Mouse_Move 'Reset move variables Moved = 0 MousePosAdd.X = 0 MousePosAdd.Y = 0 End If NextLoopC: Next LoopC ErrOut: End Sub Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) '***************************************************************** 'Forwards KeyDown events to the Input_Keys_Down sub 'More info: http://www.vbgore.com/GameClient.frmMain.Form_KeyDown '***************************************************************** Input_Keys_Down KeyCode KeyCode = 0 Shift = 0 End Sub Private Sub Form_KeyPress(KeyAscii As Integer) '***************************************************************** 'Forwards KeyPress events to the Input_Keys_Press sub 'More info: http://www.vbgore.com/GameClient.frmMain.Form_KeyPress '***************************************************************** Input_Keys_Press KeyAscii KeyAscii = 0 End Sub Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer) '***************************************************************** 'Clears the KeyUp keycode and shift values 'More info: http://www.vbgore.com/GameClient.frmMain.Form_KeyUp '***************************************************************** KeyCode = 0 Shift = 0 End Sub Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) '***************************************************************** 'Regain focus to Direct Input mouse in case the device is lost 'More info: http://www.vbgore.com/GameClient.frmMain.Form_MouseDown '***************************************************************** On Error Resume Next DIDevice.Acquire MousePos.X = X MousePos.Y = Y On Error GoTo 0 End Sub Private Sub Form_Resize() '***************************************************************** 'Regain focus to Direct Input mouse in case the device is lost 'Form_Resize is called when the form returns from a minimized state, which 'is why we have this here 'More info: http://www.vbgore.com/GameClient.frmMain.Form_Resize '***************************************************************** On Error Resume Next If Not DIDevice Is Nothing Then If Not Windowed Then DIDevice.Acquire End If On Error GoTo 0 End Sub Private Sub ShutdownTimer_Timer() '***************************************************************** 'Loops through the shutdown sequence to close up the program. A loop 'is made because it can sometimes take multiple tries to successfully 'close down GOREsock. 'More info: http://www.vbgore.com/GameClient.frmMain.ShutdownTimer_Timer '***************************************************************** Static FailedUnloads As Long On Error Resume Next 'Who cares about an error if we are closing down 'Quit the client - we must user a timer since DoEvents wont work (since we're not multithreaded) 'Close down the socket If FailedUnloads > 5 Or frmMain.GOREsock.ShutDown <> soxERROR Then frmMain.GOREsock.UnHook 'Unload the engine Engine_Init_UnloadTileEngine 'Unload the forms Engine_UnloadAllForms 'Unload everything else End Else 'If the socket is making an error on the shutdown sequence for more than a second, just unload anyways FailedUnloads = FailedUnloads + 1 End If End Sub Private Sub GOREsock_OnDataArrival(inSox As Long, inData() As Byte) '********************************************* 'Retrieve the CommandIDs and send to corresponding data handler 'More info: http://www.vbgore.com/GameClient.frmMain.GOREsock_OnDataArrival '********************************************* Dim rBuf As DataBuffer Dim CommandID As Byte Dim BufUBound As Long 'Set up the data buffer Set rBuf = New DataBuffer rBuf.Set_Buffer inData BufUBound = UBound(inData) 'Packet arrived! LastServerPacketTime = timeGetTime 'Uncomment this to see packets going into the client 'Dim i As Long 'Dim s As String 'For i = LBound(inData) To UBound(inData) ' If inData(i) >= 100 Then ' s = s & inData(i) & " " ' ElseIf inData(i) >= 10 Then ' s = s & "0" & inData(i) & " " ' Else ' s = s & "00" & inData(i) & " " ' End If 'Next i 'Debug.Print s Do 'Get the Command ID CommandID = rBuf.Get_Byte 'Make the appropriate call based on the Command ID With DataCode Select Case CommandID Case 0 'This often means there was an offset problem in the packet, adding too many empty values Case .Comm_Talk: Data_Comm_Talk rBuf Case .Map_LoadMap: Data_Map_LoadMap rBuf Case .Map_SendName: Data_Map_SendName rBuf Case .Server_ChangeChar: Data_Server_ChangeChar rBuf Case .Server_ChangeCharType: Data_Server_ChangeCharType rBuf Case .Server_CharHP: Data_Server_CharHP rBuf Case .Server_CharMP: Data_Server_CharMP rBuf Case .Server_Connect: Data_Server_Connect Case .Server_Disconnect: Data_Server_Disconnect Case .Server_EraseChar: Data_Server_EraseChar rBuf Case .Server_EraseObject: Data_Server_EraseObject rBuf Case .Server_IconBlessed: Data_Server_IconBlessed rBuf Case .Server_IconCursed: Data_Server_IconCursed rBuf Case .Server_IconIronSkin: Data_Server_IconIronSkin rBuf Case .Server_IconProtected: Data_Server_IconProtected rBuf Case .Server_IconStrengthened: Data_Server_IconStrengthened rBuf Case .Server_IconWarCursed: Data_Server_IconWarCursed rBuf Case .Server_IconSpellExhaustion: Data_Server_IconSpellExhaustion rBuf 'Case .Server_KeepAlive: Data_Server_KeepAlive - Not needed since it only confirms the connection is alive Case .Server_MailBox: Data_Server_Mailbox rBuf Case .Server_MailItemRemove: Data_Server_MailItemRemove rBuf Case .Server_MailMessage: Data_Server_MailMessage rBuf Case .Server_MailObjUpdate: Data_Server_MailObjUpdate rBuf Case .Server_MakeChar: Data_Server_MakeChar rBuf Case .Server_MakeCharCached: Data_Server_MakeCharCached rBuf Case .Server_MakeEffect: Data_Server_MakeEffect rBuf Case .Server_MakeSlash: Data_Server_MakeSlash rBuf Case .Server_MakeObject: Data_Server_MakeObject rBuf Case .Server_MakeProjectile: Data_Server_MakeProjectile rBuf Case .Server_Message: Data_Server_Message rBuf Case .Server_MoveChar: Data_Server_MoveChar rBuf Case .Server_PlaySound: Data_Server_PlaySound rBuf Case .Server_PlaySound3D: Data_Server_PlaySound3D rBuf Case .Server_SendQuestInfo: Data_Server_SendQuestInfo rBuf Case .Server_SetCharDamage: Data_Server_SetCharDamage rBuf Case .Server_SetCharSpeed: Data_Server_SetCharSpeed rBuf Case .Server_SetUserPosition: Data_Server_SetUserPosition rBuf Case .Server_UserCharIndex: Data_Server_UserCharIndex rBuf Case .User_Attack: Data_User_Attack rBuf Case .User_Bank_Open: Data_User_Bank_Open rBuf Case .User_Bank_UpdateSlot: Data_User_Bank_UpdateSlot rBuf Case .User_BaseStat: Data_User_BaseStat rBuf Case .User_Blink: Data_User_Blink rBuf Case .User_CastSkill: Data_User_CastSkill rBuf Case .User_ChangeServer: Data_User_ChangeServer rBuf Case .User_Emote: Data_User_Emote rBuf Case .User_KnownSkills: Data_User_KnownSkills rBuf Case .User_LookLeft: Data_User_LookLeft rBuf Case .User_LookRight: Data_User_LookLeft rBuf Case .User_ModStat: Data_User_ModStat rBuf Case .User_Rotate: Data_User_Rotate rBuf Case .User_SetInventorySlot: Data_User_SetInventorySlot rBuf Case .User_SetWeaponRange: Data_User_SetWeaponRange rBuf Case .User_Target: Data_User_Target rBuf Case .User_Trade_Accept: Data_User_Trade_Accept rBuf Case .User_Trade_Cancel: Data_User_Trade_Cancel Case .User_Trade_StartNPCTrade: Data_User_Trade_StartNPCTrade rBuf Case .User_Trade_Trade: Data_User_Trade_Trade rBuf Case .User_Trade_UpdateTrade: Data_User_Trade_UpdateTrade rBuf Case .Combo_ProjectileSoundRotateDamage: Data_Combo_ProjectileSoundRotateDamage rBuf Case .Combo_SlashSoundRotateDamage: Data_Combo_SlashSoundRotateDamage rBuf Case .Combo_SoundRotateDamage: Data_Combo_SoundRotateDamage rBuf Case Else rBuf.Overflow 'Something went wrong or we hit the end, either way, RUN!!!! End Select End With 'Exit when the buffer runs out If rBuf.Get_ReadPos > BufUBound Then Exit Do Loop Set rBuf = Nothing End Sub Private Sub GOREsock_OnConnecting(inSox As Long) '********************************************* 'When the connection is made to the server, this will send 'the login packet if the user has not already logged in 'More info: http://www.vbgore.com/GameClient.frmMain.GOREsock_OnConnecting '********************************************* If SocketOpen = 0 Then Sleep 50 DoEvents 'Pre-saved character If SendNewChar = False Then sndBuf.Put_Byte DataCode.User_Login sndBuf.Put_String UserName sndBuf.Put_String UserPassword Else 'New character sndBuf.Put_Byte DataCode.User_NewLogin sndBuf.Put_String UserName sndBuf.Put_String UserPassword sndBuf.Put_Integer UserHead sndBuf.Put_Integer UserBody sndBuf.Put_Byte UserClass End If 'Save Game.ini If Not SavePass Then UserPassword = vbNullString Var_Write DataPath & "Game.ini", "INIT", "Name", UserName Var_Write DataPath & "Game.ini", "INIT", "Password", UserPassword 'Send the data Data_Send DoEvents End If End Sub
[edit] frmNew
Option Explicit Private Sub ClickCancel() '***************************************************************** 'Hides frmNew and displays frmConnect 'More info: http://www.vbgore.com/GameClient.frmNew.ClickCancel '***************************************************************** 'Show the connect screen frmConnect.Visible = True 'Hide this screen Me.Visible = False End Sub Private Sub ClickCreate() '***************************************************************** 'Sends the packet to the server requesting to create a new user 'More info: http://www.vbgore.com/GameClient.frmNew.ClickCancel '***************************************************************** 'Set the variables UserName = NameTxt.Text UserPassword = PasswordTxt.Text UserBody = BodyCmb.ListIndex UserHead = HeadCmb.ListIndex UserClass = ClassCmb.ListIndex 'Convert the body by listbox index to the body number Select Case UserBody Case 0: UserBody = 1 Case Else: UserBody = 1 End Select 'Convert the head by listbox index to the head number Select Case UserHead Case 0: UserHead = 1 Case Else: UserHead = 1 End Select 'Convert the class by listbox index to the class number Select Case UserClass Case 0: UserClass = ClassID.Warrior Case 1: UserClass = ClassID.Mage Case 2: UserClass = ClassID.Rogue Case Else: UserClass = ClassID.Warrior End Select 'Connect If Game_CheckUserData Then SendNewChar = True InitSocket End If End Sub Private Sub Form_Unload(Cancel As Integer) '***************************************************************** 'Unloads the picture textboxes 'More info: http://www.vbgore.com/GameClient.frmNew.Form_Unload '***************************************************************** FreePictureTextboxes Me.hwnd End Sub Private Sub NameTxt_KeyPress(KeyAscii As Integer) '***************************************************************** 'Create new character when return is pressed 'More info: http://www.vbgore.com/GameClient.frmNew.NameTxt_KeyPress '***************************************************************** If KeyAscii = Asc(vbNewLine) Then KeyAscii = 0 ClickCreate End If End Sub Private Sub PasswordTxt_KeyPress(KeyAscii As Integer) '***************************************************************** 'Create new character when return is pressed 'More info: http://www.vbgore.com/GameClient.frmNew.PasswordTxt_KeyPress '***************************************************************** If KeyAscii = Asc(vbNewLine) Then KeyAscii = 0 ClickCreate End If End Sub Private Sub Form_KeyPress(KeyAscii As Integer) '***************************************************************** 'Create new character when return is pressed 'More info: http://www.vbgore.com/GameClient.frmNew.Form_KeyPress '***************************************************************** If KeyAscii = Asc(vbNewLine) Then ClickCreate End Sub Private Sub Form_Load() '***************************************************************** 'Loads up the values for frmNew and creates the listbox values and pictures 'More info: http://www.vbgore.com/GameClient.frmNew.Form_Load '***************************************************************** 'Set the background picture Me.Picture = LoadPicture(GrhPath & "New.bmp") 'Set the text boxes to transparent SetPictureTextboxes Me.hwnd 'Load up the head, body and class values you can select 'For the head and body, to add more, you have to edit it accordingly in the server ' under User_ConnectNew on this line: ' ' 'Check for a valid body and head ' If Head <> 1 Then Exit Sub ' If Body <> 1 Then Exit Sub ' 'Or something similar. It will appear at the top of the routine, and is pretty much the ' only thing that makes reference to the body or head in that sub, so it is easy to find. 'Failure to do this will make the server reject the character. This is to prevent people from ' editing the packets to make their body or head whatever they want it to be. 'Create the heads With HeadCmb .Clear .AddItem "Head 1", 0 .ListIndex = 0 End With 'Create the bodies With BodyCmb .Clear .AddItem "Body 1", 0 .ListIndex = 0 End With 'Create the classes With ClassCmb .Clear .AddItem "Warrior", 0 .AddItem "Mage", 1 .AddItem "Rogue", 2 .ListIndex = 0 End With End Sub Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) '***************************************************************** 'Check if the buttons on the form were clicked 'More info: http://www.vbgore.com/GameClient.frmNew.Form_MouseDown '***************************************************************** 'Click on "Create" If Engine_Collision_Rect(X, Y, 1, 1, 5, 189, 66, 15) Then ClickCreate 'Click on "Cancel" If Engine_Collision_Rect(X, Y, 1, 1, 118, 190, 66, 15) Then ClickCancel End Sub
[edit] Modules
[edit] AllFilesInFolder
Option Explicit Private Sub AddItem2Array1D(ByRef VarArray As Variant, ByVal VarValue As Variant) Dim i As Long Dim iVarType As Integer iVarType = VarType(VarArray) - 8192 i = UBound(VarArray) Select Case iVarType Case vbInteger, vbLong, vbSingle, vbDouble, vbCurrency, vbDecimal, vbByte If VarArray(0) = 0 Then i = 0 Else i = i + 1 End If Case vbDate If VarArray(0) = "00:00:00" Then i = 0 Else i = i + 1 End If Case vbString If VarArray(0) = vbNullString Then i = 0 Else i = i + 1 End If Case vbBoolean If VarArray(0) = False Then i = 0 Else i = i + 1 End If Case Else End Select ReDim Preserve VarArray(i) VarArray(i) = VarValue End Sub Public Function AllFilesInFolders(ByVal sFolderPath As String, Optional bWithSubFolders As Boolean = False) As String() Dim sTemp As String Dim sDirIn As String Dim i As Integer, j As Integer ReDim sFilelist(0) As String, sSubFolderList(0) As String, sToProcessFolderList(0) As String sDirIn = sFolderPath If Not (Right$(sDirIn, 1) = "\") Then sDirIn = sDirIn & "\" On Error Resume Next sTemp = Dir$(sDirIn & "*.*") Do While LenB(sTemp) <> 0 AddItem2Array1D sFilelist(), sDirIn & sTemp sTemp = Dir Loop If bWithSubFolders Then sTemp = Dir$(sDirIn & "*.*", vbDirectory) Do While LenB(sTemp) <> 0 If sTemp <> "." Then If sTemp <> ".." Then If (GetAttr(sDirIn & sTemp) And vbDirectory) = vbDirectory Then AddItem2Array1D sToProcessFolderList, sDirIn & sTemp End If End If sTemp = Dir Loop If UBound(sToProcessFolderList) > 0 Or UBound(sToProcessFolderList) = 0 And LenB(sToProcessFolderList(0)) <> 0 Then For i = 0 To UBound(sToProcessFolderList) sSubFolderList = AllFilesInFolders(sToProcessFolderList(i), bWithSubFolders) If UBound(sSubFolderList) > 0 Or UBound(sSubFolderList) = 0 And LenB(sSubFolderList(0)) <> 0 Then For j = 0 To UBound(sSubFolderList) AddItem2Array1D sFilelist(), sSubFolderList(j) Next End If Next End If End If AllFilesInFolders = sFilelist On Error GoTo 0 End Function
[edit] Compressions
Option Explicit Public Enum CompressMethods RLE = 1 RLE_Loop = 2 LZMA = 3 PAQ8l = 4 Deflate64 = 5 MonkeyAudio = 6 '*.wav only End Enum #If False Then Private RLE, RLE_Loop, LZMA, PAQ8l, Deflate64, MonkeyAudio #End If 'Value between 0 and 9, higher requiring more RAM/CPU but better compression 'Keep in mind decompressing requires a lot of RAM, too, so don't go higher than 7 Private Const PAQ8l_Level As Byte = 6 Private CompressArray() As Byte Private OutStream() As Byte Private OutPos As Long Private CntPos As Long Private Type STARTUPINFO cb As Long lpReserved As String lpDesktop As String lpTitle As String dwX As Long dwY As Long dwXSize As Long dwYSize As Long dwXCountChars As Long dwYCountChars As Long dwFillAttribute As Long dwFlags As Long wShowWindow As Integer cbReserved2 As Integer lpReserved2 As Long hStdInput As Long hStdOutput As Long hStdError As Long End Type Private Type PROCESS_INFORMATION hProcess As Long hThread As Long dwProcessID As Long dwThreadID As Long End Type Private Const QUOTE As String * 1 = """" Private Declare Function CreateProcessA Lib "kernel32" (ByVal lpApplicationname As Long, ByVal lpCommandLine As String, ByVal lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As Long, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Private Declare Sub CopyMem Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long) Private Function GetRandomFileName() As String '***************************************************************** 'Generates a random file name 'More info: http://www.vbgore.com/CommonCode.Compressions.GetRandomFileName '***************************************************************** Dim i As Long For i = 1 To (3 + Int(Rnd * 10)) GetRandomFileName = GetRandomFileName & GetRandomChar Next i End Function Private Function GetRandomChar() As String '***************************************************************** 'Generates a random character of either 0-9, a-z or A-Z 'More info: http://www.vbgore.com/CommonCode.Compressions.GetRandomChar '***************************************************************** Dim i As Long i = Int(Rnd * 3) Select Case i '0 to 9 Case 0 GetRandomChar = Str$(Int(Rnd * 9)) 'A to Z Case 1 GetRandomChar = Chr$(65 + Int(Rnd * 26)) 'a to z Case 2 GetRandomChar = Chr$(97 + Int(Rnd * 26)) End Select End Function Private Sub CommandLine(ByVal CommandLineString As String) '***************************************************************** 'Runs a command line string and waits for the process to finish 'More info: http://www.vbgore.com/CommonCode.Compressions.CommandLine '***************************************************************** Dim Start As STARTUPINFO Dim Proc As PROCESS_INFORMATION Start.dwFlags = &H1 Start.wShowWindow = 0 CreateProcessA 0&, CommandLineString, 0&, 0&, 1&, &H20&, 0&, 0&, Start, Proc Do While WaitForSingleObject(Proc.hProcess, 0) = 258 DoEvents Sleep 1 Loop End Sub Private Sub SaveBytes(ByRef Bytes() As Byte, ByVal File As String) '***************************************************************** 'Saves a byte array to a file 'More info: http://www.vbgore.com/CommonCode.Compressions.SaveBytes '***************************************************************** Dim FileNum As Byte 'Delete the file if it already exists If Dir$(File, vbNormal) <> vbNullString Then Kill File 'Find a free file number FileNum = FreeFile 'Write the bytes to the file Open File For Binary Access Write As #FileNum Put #FileNum, , Bytes() Close #FileNum End Sub Private Sub LoadBytes(ByRef Bytes() As Byte, ByVal File As String) '***************************************************************** 'Loads a byte array from a file 'More info: http://www.vbgore.com/CommonCode.Compressions.LoadBytes '***************************************************************** Dim FileNum As Byte 'Find a free file number FileNum = FreeFile Open File For Binary Access Read As #FileNum 'Make sure there is data in the file If LOF(FileNum) > 0 Then 'Resize the Bytes array to fit all of the bytes in the file 'then grab them ReDim Bytes(0 To LOF(FileNum) - 1) Get #FileNum, , Bytes() End If Close #FileNum End Sub Public Sub Compression_Compress_PAQ8l(ByteArray() As Byte) '***************************************************************** 'Compresses a byte array with PAQ8l compression 'More info: http://www.vbgore.com/CommonCode.Compressions.Compression_Compress_PAQ8l '***************************************************************** Dim FileName As String FileName = GetRandomFileName SaveBytes ByteArray(), App.Path & "\" & FileName & ".bin" CommandLine DataPath & "paq8l.exe -" & PAQ8l_Level & " " & QUOTE & App.Path & "\" & FileName & ".bin" & QUOTE If Dir$(App.Path & "\" & FileName & ".bin.paq8l") <> vbNullString Then LoadBytes ByteArray(), App.Path & "\" & FileName & ".bin.paq8l" Kill App.Path & "\" & FileName & ".bin.paq8l" End If Kill App.Path & "\" & FileName & ".bin" End Sub Public Sub Compression_DeCompress_PAQ8l(ByteArray() As Byte) '***************************************************************** 'Decompresses a byte array with PAQ8l compression 'More info: http://www.vbgore.com/CommonCode.Compressions.Compression_DeCompress_PAQ8l '***************************************************************** Dim FileName As String FileName = GetRandomFileName SaveBytes ByteArray(), App.Path & "\" & FileName & ".bin.paq8l" CommandLine DataPath & "paq8l.exe -d " & QUOTE & App.Path & "\" & FileName & ".bin.paq8l" & QUOTE If Dir$(App.Path & "\" & FileName & ".bin") <> vbNullString Then LoadBytes ByteArray(), App.Path & "\" & FileName & ".bin" Kill App.Path & "\" & FileName & ".bin" End If Kill App.Path & "\" & FileName & ".bin.paq8l" End Sub Private Sub Compression_Add_CharToArray(ToArray() As Byte, ToPos As Long, ByVal Char As Byte) '***************************************************************** 'Adds a char (byte) to an array at a specific location (used for RLE compression) 'More info: http://www.vbgore.com/CommonCode.Compressions.Compression_Add_CharToArray '***************************************************************** If ToPos > UBound(ToArray) Then ReDim Preserve ToArray(ToPos + 500) End If ToArray(ToPos) = Char ToPos = ToPos + 1 End Sub Public Sub Compression_Compress(SrcFile As String, DestFile As String, Compression As CompressMethods) '***************************************************************** 'A wrapper for easy file-based compression 'More info: http://www.vbgore.com/CommonCode.Compressions.Compression_Compress '***************************************************************** Dim Dummy As Boolean If Compression_File_Load(SrcFile) = 0 Then Exit Sub Select Case Compression Case RLE Compression_Compress_RLE CompressArray(), Dummy Case RLE_Loop Compression_Compress_RLELoop CompressArray() Case LZMA Compression_Compress_LZMA CompressArray() Case PAQ8l Compression_Compress_PAQ8l CompressArray() Case Deflate64 Compression_Compress_Deflate64 CompressArray() End Select Compression_File_Save DestFile Erase CompressArray End Sub Public Sub Compression_Compress_LZMA(ByteArray() As Byte) '***************************************************************** 'Compresses a byte array with LZMA compression 'More info: http://www.vbgore.com/CommonCode.Compressions.Compression_Compress_LZMA '***************************************************************** Dim FileName As String FileName = GetRandomFileName SaveBytes ByteArray(), App.Path & "\" & FileName & ".bin" CommandLine DataPath & "7za.exe a -t7z " & QUOTE & App.Path & "\" & FileName & ".bin.7z" & QUOTE & " -aoa " & QUOTE & App.Path & "\" & FileName & ".bin" & QUOTE & " -mx9 -m0=LZMA:d80m:fb273:lc5:pb1:mc10000" If Dir$(App.Path & "\" & FileName & ".bin.7z") <> vbNullString Then LoadBytes ByteArray(), App.Path & "\" & FileName & ".bin.7z" Kill App.Path & "\" & FileName & ".bin.7z" End If Kill App.Path & "\" & FileName & ".bin" End Sub Public Sub Compression_Compress_MonkeyAudio(ByteArray() As Byte) '***************************************************************** 'Compresses a byte array with MonkeyAudio (.wav files only) compression 'More info: http://www.vbgore.com/CommonCode.Compressions.Compression_Compress_MonkeyAudio '***************************************************************** Dim FileName As String '*.wav only FileName = GetRandomFileName SaveBytes ByteArray(), App.Path & "\" & FileName & ".wav" CommandLine DataPath & "mac.exe " & QUOTE & App.Path & "\" & FileName & ".wav" & QUOTE & " " & QUOTE & App.Path & "\" & FileName & ".wav.ape" & QUOTE & " -c5000" If Dir$(App.Path & "\" & FileName & ".wav.ape") <> vbNullString Then LoadBytes ByteArray(), App.Path & "\" & FileName & ".wav.ape" Kill App.Path & "\" & FileName & ".wav.ape" End If Kill App.Path & "\" & FileName & ".wav" End Sub Public Sub Compression_DeCompress_MonkeyAudio(ByteArray() As Byte) '***************************************************************** 'Decompresses a byte array with MonkeyAudio (.wav files only) compression 'More info: http://www.vbgore.com/CommonCode.Compressions.Compression_DeCompress_MonkeyAudio '***************************************************************** Dim FileName As String '*.wav only FileName = GetRandomFileName SaveBytes ByteArray(), App.Path & "\" & FileName & ".wav.ape" CommandLine DataPath & "mac.exe " & QUOTE & App.Path & "\" & FileName & ".wav.ape" & QUOTE & " " & QUOTE & App.Path & "\" & FileName & ".wav" & QUOTE & " -d" If Dir$(App.Path & "\" & FileName & ".wav") <> vbNullString Then LoadBytes ByteArray(), App.Path & "\" & FileName & ".wav" Kill App.Path & "\" & FileName & ".wav" End If Kill App.Path & "\" & FileName & ".wav.ape" End Sub Public Sub Compression_Compress_Deflate64(ByteArray() As Byte) '***************************************************************** 'Compresses a byte array with Deflate64 compression 'More info: http://www.vbgore.com/CommonCode.Compressions.Compression_Compress_Deflate64 '***************************************************************** Dim FileName As String FileName = GetRandomFileName SaveBytes ByteArray(), App.Path & "\" & FileName & ".bin" CommandLine DataPath & "7za.exe a -tzip " & QUOTE & App.Path & "\" & FileName & ".bin.7z" & QUOTE & " -aoa " & QUOTE & App.Path & "\" & FileName & ".bin" & QUOTE & " -mx9 -mm=Deflate64 -mfb=257 -mpass=15 -mmc=1000" If Dir$(App.Path & "\" & FileName & ".bin.7z") <> vbNullString Then LoadBytes ByteArray(), App.Path & "\" & FileName & ".bin.7z" Kill App.Path & "\" & FileName & ".bin.7z" End If Kill App.Path & "\" & FileName & ".bin" End Sub Public Sub Compression_DeCompress_Deflate64(ByteArray() As Byte) '***************************************************************** 'Decompresses a byte array with Deflate64 compression 'More info: http://www.vbgore.com/CommonCode.Compressions.Compression_DeCompress_Deflate64 '***************************************************************** Dim FileName As String FileName = GetRandomFileName SaveBytes ByteArray(), App.Path & "\" & FileName & ".bin.7z" CommandLine DataPath & "7za.exe e " & QUOTE & App.Path & "\" & FileName & ".bin.7z" & QUOTE If Dir$(App.Path & "\" & FileName & ".bin") <> vbNullString Then LoadBytes ByteArray(), App.Path & "\" & FileName & ".bin" Kill App.Path & "\" & FileName & ".bin" End If Kill App.Path & "\" & FileName & ".bin.7z" End Sub Public Sub Compression_Compress_RLE(ByteArray() As Byte, IsCompressed As Boolean) '***************************************************************** 'Compresses a byte array with RLE (Run-Length Encryption) compression 'More info: http://www.vbgore.com/CommonCode.Compressions.Compression_Compress_RLE '***************************************************************** Dim X As Long Dim Y As Long Dim ByteCount As Long Dim LastAsc As Integer Dim TelSame As Long Dim IsRun As Boolean Dim ZeroCount As Integer Dim LengthPos As Long Dim NoLength As Boolean Dim ContStream() As Byte Dim LengthStream() As Byte If UBound(ByteArray) = 0 Then Exit Sub ReDim ContStream(200) ReDim LengthStream(200) ReDim OutStream(500) IsCompressed = False CntPos = 1 OutPos = 0 For X = 0 To UBound(ByteArray) IsRun = LastAsc = ByteArray(X) And X <> 0 If Not IsRun Then If TelSame = 1 Then TelSame = 0 Compression_Add_CharToArray OutStream, OutPos, CByte(LastAsc) ByteCount = ByteCount + 1 ElseIf TelSame > 1 Then For Y = 1 To Int(ByteCount / 255) Compression_Add_CharToArray ContStream, CntPos, 255 Next Y ByteCount = ByteCount Mod 255 If ByteCount = 0 Then ZeroCount = ZeroCount + 1 Compression_Add_CharToArray ContStream, CntPos, CByte(ByteCount) ByteCount = 0 For Y = 1 To Int(TelSame / 255) Compression_Add_CharToArray LengthStream, LengthPos, 255 Next Y TelSame = TelSame Mod 255 Compression_Add_CharToArray LengthStream, LengthPos, CByte(TelSame) TelSame = 0 End If Compression_Add_CharToArray OutStream, OutPos, ByteArray(X) ByteCount = ByteCount + 1 Else TelSame = TelSame + 1 End If LastAsc = ByteArray(X) Next X If IsRun Then If TelSame < 2 Then Compression_Add_CharToArray OutStream, OutPos, CByte(LastAsc) Else For Y = 1 To Int(ByteCount / 255) Compression_Add_CharToArray ContStream, CntPos, 255 Next Y ByteCount = ByteCount Mod 255 Compression_Add_CharToArray ContStream, CntPos, CByte(ByteCount) For Y = 1 To Int(TelSame / 255) Compression_Add_CharToArray LengthStream, LengthPos, 255 Next Y TelSame = TelSame Mod 255 Compression_Add_CharToArray LengthStream, LengthPos, CByte(TelSame) End If End If ContStream(0) = CByte(ZeroCount) If CntPos > 1 Then IsCompressed = True Call Compression_Add_CharToArray(ContStream, CntPos, 0) 'No Run Till EOF ReDim Preserve ContStream(CntPos - 1) As Byte If LengthPos > 0 Then ReDim Preserve LengthStream(LengthPos - 1) Else NoLength = True End If ReDim Preserve OutStream(OutPos - 1) As Byte CntPos = UBound(ContStream) + 1 LengthPos = 0 If Not NoLength Then LengthPos = UBound(LengthStream) + 1 OutPos = UBound(OutStream) + 1 ReDim ByteArray(CntPos + LengthPos + OutPos - 1) CopyMem ByteArray(0), ContStream(0), CntPos If LengthPos > 0 Then CopyMem ByteArray(CntPos), LengthStream(0), LengthPos CopyMem ByteArray(CntPos + LengthPos), OutStream(0), OutPos End Sub Public Sub Compression_Compress_RLELoop(ByteArray() As Byte) '***************************************************************** 'Compresses a byte array with RLE (Run-Length Encryption) compression 'This will loop it until no more compression can be made 'More info: http://www.vbgore.com/CommonCode.Compressions.Compression_Compress_RLELoop '***************************************************************** Dim TimesRLE As Integer Dim IsCompressed As Boolean Do Compression_Compress_RLE ByteArray, IsCompressed TimesRLE = TimesRLE + 1 Loop While IsCompressed ReDim Preserve ByteArray(UBound(ByteArray) + 1) ByteArray(UBound(ByteArray)) = TimesRLE End Sub Public Sub Compression_DeCompress(SrcFile As String, DestFile As String, Compression As CompressMethods) '***************************************************************** 'A wrapper for easy file-based decompression 'More info: http://www.vbgore.com/CommonCode.Compressions.Compression_DeCompress '***************************************************************** If Compression_File_Load(SrcFile) = 0 Then Exit Sub Select Case Compression Case RLE Compression_DeCompress_RLE CompressArray() Case RLE_Loop Compression_DeCompress_RLELoop CompressArray() Case LZMA Compression_DeCompress_LZMA CompressArray() Case PAQ8l Compression_DeCompress_PAQ8l CompressArray() Case Deflate64 Compression_DeCompress_Deflate64 CompressArray() End Select Compression_File_Save DestFile Erase CompressArray End Sub Public Sub Compression_DeCompress_LZMA(ByteArray() As Byte) '***************************************************************** 'Decompresses a byte array using LZMA compression 'More info: http://www.vbgore.com/CommonCode.Compressions.Compression_DeCompress_LZMA '***************************************************************** Dim FileName As String FileName = GetRandomFileName SaveBytes ByteArray(), App.Path & "\" & FileName & ".bin.7z" CommandLine DataPath & "7za.exe e " & QUOTE & App.Path & "\" & FileName & ".bin.7z" & QUOTE If Dir$(App.Path & "\" & FileName & ".bin") <> vbNullString Then LoadBytes ByteArray(), App.Path & "\" & FileName & ".bin" Kill App.Path & "\" & FileName & ".bin" End If Kill App.Path & "\" & FileName & ".bin.7z" End Sub Public Sub Compression_DeCompress_RLE(ByteArray() As Byte) '***************************************************************** 'Decompresses a byte array using RLE (Run-Length Encryption) compression 'More info: http://www.vbgore.com/CommonCode.Compressions.Compression_DeCompress_RLE '***************************************************************** Dim X As Long Dim CntCount As Long Dim bytLastChar As Byte Dim ByteCount As Long Dim InpPos As Long Dim ZeroCount As Integer Dim LengthPos As Long ZeroCount = 0 For X = 1 To UBound(ByteArray) If ByteArray(X) = 0 Then If ZeroCount = ByteArray(0) Then Exit For ZeroCount = ZeroCount + 1 End If If ByteArray(X) <> 255 Then CntCount = CntCount + 1 End If Next X OutPos = 0 CntPos = 1 LengthPos = X + 1 InpPos = LengthPos Do While CntCount > 0 If ByteArray(InpPos) <> 255 Then CntCount = CntCount - 1 End If InpPos = InpPos + 1 Loop ReDim OutStream(UBound(ByteArray) - InpPos + 1) ByteCount = Compression_ReadFromArray_Char(ByteArray, CntPos) CntCount = Compression_ReadFromArray_Char(ByteArray, LengthPos) Do If ByteCount = 0 Then For X = 1 To UBound(ByteArray) - InpPos + 1 bytLastChar = Compression_ReadFromArray_Char(ByteArray, InpPos) Compression_Add_CharToArray OutStream, OutPos, bytLastChar Next X Else For X = 1 To ByteCount bytLastChar = Compression_ReadFromArray_Char(ByteArray, InpPos) Compression_Add_CharToArray OutStream, OutPos, bytLastChar Next X If ByteCount = 255 Then Do ByteCount = Compression_ReadFromArray_Char(ByteArray, CntPos) For X = 1 To ByteCount bytLastChar = Compression_ReadFromArray_Char(ByteArray, InpPos) Compression_Add_CharToArray OutStream, OutPos, bytLastChar Next X Loop While ByteCount = 255 ByteCount = Compression_ReadFromArray_Char(ByteArray, CntPos) Else ByteCount = Compression_ReadFromArray_Char(ByteArray, CntPos) End If For X = 1 To CntCount Compression_Add_CharToArray OutStream, OutPos, bytLastChar Next X If CntCount = 255 Then Do CntCount = Compression_ReadFromArray_Char(ByteArray, LengthPos) For X = 1 To CntCount Compression_Add_CharToArray OutStream, OutPos, bytLastChar Next X Loop While CntCount = 255 CntCount = Compression_ReadFromArray_Char(ByteArray, LengthPos) Else CntCount = Compression_ReadFromArray_Char(ByteArray, LengthPos) End If End If Loop While InpPos <= UBound(ByteArray) ReDim ByteArray(OutPos - 1) As Byte CopyMem ByteArray(0), OutStream(0), OutPos End Sub Public Sub Compression_DeCompress_RLELoop(ByteArray() As Byte) '***************************************************************** 'Decompresses a byte array using a looped RLE (Run-Length Encryption) compression 'More info: http://www.vbgore.com/CommonCode.Compressions.Compression_DeCompress_RLELoop '***************************************************************** Dim X As Integer Dim TimesRLE As Integer TimesRLE = ByteArray(UBound(ByteArray)) ReDim Preserve ByteArray(UBound(ByteArray) - 1) For X = 1 To TimesRLE Compression_DeCompress_RLE ByteArray Next X End Sub Private Function Compression_File_Load(FilePath As String) As Byte '***************************************************************** 'Loads a file into the CompressArray() byte array 'More info: http://www.vbgore.com/CommonCode.Compressions.Compression_File_Load '***************************************************************** Dim FreeNum As Integer If Not Len(FilePath) = 0 Then FreeNum = FreeFile Open FilePath For Binary As #FreeNum If LOF(FreeNum) = 0 Then Close #FreeNum Compression_File_Load = 0 Exit Function End If ReDim CompressArray(0 To LOF(FreeNum) - 1) Get #FreeNum, , CompressArray() Close #FreeNum End If Compression_File_Load = 1 End Function Private Sub Compression_File_Save(FilePath As String) '***************************************************************** 'Saves a file from the CompressArray() byte array 'More info: http://www.vbgore.com/CommonCode.Compressions.Compression_File_Save '***************************************************************** Dim FreeNum As Integer If LenB(FilePath) <> 0 Then If LenB(Dir$(FilePath, vbNormal)) <> 0 Then Kill FilePath FreeNum = FreeFile Open FilePath For Binary As #FreeNum Put #FreeNum, , CompressArray() Close #FreeNum End If End Sub Private Function Compression_ReadFromArray_Char(FromArray() As Byte, FromPos As Long) As Byte '***************************************************************** 'Reads a char (byte) from a specific location in an array 'More info: http://www.vbgore.com/CommonCode.Compressions.Compression_ReadFromArray_Char '***************************************************************** Compression_ReadFromArray_Char = FromArray(FromPos) FromPos = FromPos + 1 End Function
[edit] DataIDs
Option Explicit '********** Emoticons ************ Public Const NumEmotes As Byte = 10 Public Type EmoID Dots As Byte Exclimation As Byte Question As Byte Surprised As Byte Heart As Byte Hearts As Byte HeartBroken As Byte Utensils As Byte Meat As Byte ExcliQuestion As Byte End Type Public EmoID As EmoID '********** Classes ************ 'Classes work by using bitwise operations, so each class ID must be a power of 2 (1, 2, 4, 8, 16, 32, 64, or 128) 'If you want more clases, change the classes to "Integer" 'To set class requirements, OR the values together 'EX: 'ClassReq = Warrior OR Rogue 'This means the class must be a Warrior or Rogue 'To check the values, use AND 'EX: 'If ClassReq AND UserClass Then ' User meets requirements 'Else ' User doesn't meet requirements 'End If Public Type ClassID Warrior As Integer Mage As Integer Rogue As Integer NoReq As Integer End Type Public ClassID As ClassID '********** Packets ************ 'Data String Codenames (Reduces all data transfers to 1 byte tags) Public Type DataCode Comm_Talk As Byte Comm_Shout As Byte Comm_Emote As Byte Comm_Whisper As Byte Comm_GroupTalk As Byte Comm_FontType_Talk As Byte Comm_FontType_Fight As Byte Comm_FontType_Info As Byte Comm_FontType_Quest As Byte Comm_FontType_Group As Byte Comm_UseBubble As Byte 'Do not use this alone - OR it onto Comm_Talk! Server_MailMessage As Byte Server_MailBox As Byte Server_MailItemTake As Byte Server_MailItemRemove As Byte Server_MailDelete As Byte Server_MailCompose As Byte Server_UserCharIndex As Byte Server_SetUserPosition As Byte Server_MakeChar As Byte Server_MakeCharCached As Byte Server_EraseChar As Byte Server_MoveChar As Byte Server_ChangeChar As Byte Server_MakeObject As Byte Server_EraseObject As Byte Server_PlaySound As Byte Server_PlaySound3D As Byte Server_Who As Byte Server_CharHP As Byte Server_CharMP As Byte Server_IconCursed As Byte Server_IconWarCursed As Byte Server_IconBlessed As Byte Server_IconStrengthened As Byte Server_IconProtected As Byte Server_IconIronSkin As Byte Server_IconSpellExhaustion As Byte Server_SetCharDamage As Byte Server_Help As Byte Server_Disconnect As Byte Server_Connect As Byte Server_Message As Byte Server_SetCharSpeed As Byte Server_MakeProjectile As Byte Server_MakeSlash As Byte Server_MailObjUpdate As Byte Server_MakeEffect As Byte Server_SendQuestInfo As Byte Server_ChangeCharType As Byte Server_KeepAlive As Byte Map_LoadMap As Byte Map_DoneLoadingMap As Byte Map_SendName As Byte User_Target As Byte User_KnownSkills As Byte User_Attack As Byte User_SetInventorySlot As Byte User_Desc As Byte User_Login As Byte User_NewLogin As Byte User_Get As Byte User_Drop As Byte User_Use As Byte User_Move As Byte User_Rotate As Byte User_LeftClick As Byte User_RightClick As Byte User_LookLeft As Byte User_LookRight As Byte User_Blink As Byte User_Trade_StartNPCTrade As Byte User_Trade_BuyFromNPC As Byte User_Trade_SellToNPC As Byte User_Trade_Trade As Byte User_Trade_UpdateTrade As Byte User_Trade_Accept As Byte User_Trade_Finish As Byte User_Trade_RemoveItem As Byte User_Trade_Cancel As Byte User_Bank_Open As Byte User_Bank_PutItem As Byte User_Bank_TakeItem As Byte User_Bank_UpdateSlot As Byte User_Bank_Balance As Byte User_Bank_Deposit As Byte User_Bank_Withdraw As Byte User_BaseStat As Byte User_ModStat As Byte User_CastSkill As Byte User_ChangeInvSlot As Byte User_Emote As Byte User_StartQuest As Byte User_CancelQuest As Byte User_SetWeaponRange As Byte User_RequestMakeChar As Byte User_RequestUserCharIndex As Byte User_ChangeServer As Byte User_ConfirmPosition As Byte User_Group_Make As Byte User_Group_Join As Byte User_Group_Leave As Byte User_Group_Invite As Byte User_Group_Info As Byte GM_Approach As Byte GM_Summon As Byte GM_Kick As Byte GM_Raise As Byte GM_SetGMLevel As Byte GM_Thrall As Byte GM_DeThrall As Byte GM_BanIP As Byte GM_UnBanIP As Byte GM_Warp As Byte GM_FindItem As Byte GM_SQL As Byte GM_GiveSkill As Byte GM_GiveGold As Byte GM_GiveObject As Byte GM_KillMap As Byte GM_Kill As Byte GM_WarpToMap As Byte GM_IPInfo As Byte GM_BanList As Byte Combo_ProjectileSoundRotateDamage As Byte Combo_SoundRotateDamage As Byte Combo_SlashSoundRotateDamage As Byte End Type Public DataCode As DataCode '********** Character Stats/Skills ************ 'Keep in mind vbGORE does a really bad job at actually making use of these stats by default, especially for the NPCs. If you're going 'to make a game, you will definitely want to add your own stats and change how they work. Public Type StatOrder 'These can NOT be modded (theres no ModStat()) MinMAN As Byte MinHP As Byte MinSTA As Byte Gold As Byte Points As Byte EXP As Byte ELU As Byte ELV As Byte 'These CAN be modded (ModStat() is used along with BaseStat()) MaxHIT As Byte MinHIT As Byte DEF As Byte MaxHP As Byte MaxSTA As Byte MaxMAN As Byte Str As Byte Agi As Byte 'For NPCs, this is the hit rate Mag As Byte Speed As Byte 'Speed works as + (Speed / 2) on the client since just + Speed would be too drastic (8 would double the normal speed) End Type Public SID As StatOrder 'Stat ID Public Const NumStats As Byte = 18 Public Const FirstModStat As Byte = 9 'The lowest number of the first stat that can be modded Public Type SkillID Bless As Byte Protection As Byte Strengthen As Byte Warcry As Byte Heal As Byte IronSkin As Byte SpikeField As Byte SummonBandit As Byte End Type Public SkID As SkillID 'Skill IDs Public Const NumSkills As Byte = 8 Public Sub InitDataCommands() '***************************************************************** 'Sets the values of IDs for emoticons, skills, packets, etc 'Every value in here must be identical on the client and server, which is why 'the same module is used for both the client and server! 'More info: http://www.vbgore.com/CommonCode.DataIDs.InitDataCommands '***************************************************************** 'Emoticon IDs With EmoID .Dots = 1 .Exclimation = 2 .Question = 3 .Surprised = 4 .Heart = 5 .Hearts = 6 .HeartBroken = 7 .Utensils = 8 .Meat = 9 .ExcliQuestion = 10 End With 'Skill IDs With SkID .Bless = 1 .Heal = 2 .IronSkin = 3 .Protection = 4 .Strengthen = 5 .Warcry = 6 .SpikeField = 7 .SummonBandit = 8 End With 'Class IDs With ClassID 'These values must be based off of powers of 2! (Note: The 16th bit is not 2 ^ 16, its -(2 ^ 15) because its signed) 'If you do not set the values in powers of 2, it will screw up the classes big time. .Warrior = 1 '2 ^ 0 .Mage = 2 '2 ^ 1 .Rogue = 4 '2 ^ 2 ... etc 'This sets every bit to 1, which means that it will work with every class .NoReq = -1 'Read up on how signed binary works if you want to figure out why this is -1 End With 'Stat IDs With SID 'These can NOT be modded - they only have and need one value BaseStat() .MinHP = 1 .MinMAN = 2 .MinSTA = 3 .Gold = 4 .Points = 5 .EXP = 6 .ELU = 7 .ELV = 8 'These CAN be modded, whether it is by spells, items, etc - the mod value is held in ModStat() .MaxHIT = 9 .MaxHP = 10 .MaxMAN = 11 .MaxSTA = 12 .MinHIT = 13 .DEF = 14 .Agi = 15 .Mag = 16 .Str = 17 .Speed = 18 End With 'Packet IDs With DataCode .User_RequestMakeChar = 1 .GM_Thrall = 2 .Server_IconSpellExhaustion = 3 .Comm_Shout = 4 .Server_UserCharIndex = 5 .Comm_Emote = 6 .Server_SetUserPosition = 7 .Map_LoadMap = 8 .Map_DoneLoadingMap = 9 .GM_Raise = 10 .GM_Kick = 11 .Server_CharHP = 12 .GM_Summon = 13 .User_ChangeServer = 14 .Map_SendName = 15 .User_Attack = 16 .Server_MakeChar = 17 .Server_EraseChar = 18 .Server_MoveChar = 19 .Server_ChangeChar = 20 .Server_MakeObject = 21 .Server_EraseObject = 22 .User_KnownSkills = 23 .User_SetInventorySlot = 24 .User_StartQuest = 25 .Server_Connect = 26 .Server_PlaySound = 27 .User_Login = 28 .User_NewLogin = 29 .Comm_Whisper = 30 .Server_Who = 31 .User_Move = 32 .User_Rotate = 33 .User_LeftClick = 34 .User_RightClick = 35 .User_Group_Info = 36 .User_Get = 37 .User_Drop = 38 .User_Use = 39 .GM_Approach = 40 .Comm_Talk = 41 .Server_SetCharDamage = 42 .User_ChangeInvSlot = 43 .User_Emote = 44 .Server_CharMP = 45 .Server_Disconnect = 46 .User_LookLeft = 47 .User_LookRight = 48 .User_Blink = 49 .User_Trade_RemoveItem = 50 .User_Trade_BuyFromNPC = 51 .User_BaseStat = 52 .User_ModStat = 53 .GM_BanIP = 54 .GM_UnBanIP = 55 .Server_SendQuestInfo = 56 .User_ConfirmPosition = 57 .Server_Help = 58 .User_Desc = 59 .User_Trade_Cancel = 60 .User_Target = 61 .User_Trade_StartNPCTrade = 62 .User_Trade_SellToNPC = 63 .User_CastSkill = 64 .Server_IconCursed = 65 .Server_IconWarCursed = 66 .Server_IconBlessed = 67 .Server_IconStrengthened = 68 .Server_IconProtected = 69 .Server_IconIronSkin = 70 .Server_MailBox = 71 .Server_MailMessage = 72 .User_RequestUserCharIndex = 73 .Server_MailItemTake = 74 .Server_MailObjUpdate = 75 .Server_MailDelete = 76 .Server_MailCompose = 77 .GM_SetGMLevel = 78 .Server_Message = 79 .GM_DeThrall = 80 .Server_PlaySound3D = 81 .Server_SetCharSpeed = 82 .User_SetWeaponRange = 83 .Server_MakeProjectile = 84 .Server_MakeSlash = 85 .Server_MakeEffect = 86 .User_Bank_Open = 87 .User_Bank_PutItem = 88 .User_Bank_TakeItem = 89 .User_Bank_UpdateSlot = 90 .User_Group_Join = 91 .User_Group_Invite = 92 .User_Group_Leave = 93 .User_Group_Make = 94 .Comm_GroupTalk = 95 .User_Bank_Deposit = 96 .User_Bank_Withdraw = 97 .User_Bank_Balance = 98 .GM_Warp = 99 .Server_ChangeCharType = 100 .User_Trade_Trade = 101 .User_Trade_UpdateTrade = 102 .User_Trade_Accept = 104 .User_Trade_Finish = 105 .User_CancelQuest = 106 .Combo_ProjectileSoundRotateDamage = 107 .Combo_SoundRotateDamage = 108 .Combo_SlashSoundRotateDamage = 109 .Server_MakeCharCached = 110 .GM_FindItem = 111 .GM_SQL = 112 .GM_GiveSkill = 113 .GM_GiveGold = 114 .GM_GiveObject = 115 .GM_KillMap = 116 .GM_Kill = 117 .GM_WarpToMap = 118 .GM_IPInfo = 119 .GM_BanList = 120 .Server_KeepAlive = 121 'This values can be used over again since they aren't used in their own packet header .Comm_FontType_Fight = 1 .Comm_FontType_Info = 2 .Comm_FontType_Quest = 3 .Comm_FontType_Talk = 4 .Comm_FontType_Group = 5 'Value 128 can be used over again since this does not count as an ID in itself - just ignore this variable! ;) .Comm_UseBubble = 128 End With End Sub
[edit] Declares
'** ____ _________ ______ ______ ______ _______ ** '** \ \ / / \ / ____\ / \| \ | ____| ** '** \ \ / /| | / | | || |____ ** '*** \ \ / / | /| | ___ | | / | ____| *** '**** \ \/ / | \| | \ \| | _ \ | |____ **** '****** \ / | | \__| | | | \ \| | ****** '******** \____/ |_____/ \______/ \______/|__| \__\_______| ******** '******************************************************************************* '******************************************************************************* '************ vbGORE - Visual Basic 6.0 Graphical Online RPG Engine ************ '************ Official Release: Version 1.0.13 ************ '************ http://www.vbgore.com ************ '******************************************************************************* '******************************************************************************* '***** License Information For General Users: ********************************** '******************************************************************************* '** vbGORE comes completely free. You may charge for people to play your game ** '** along with you may accept donations for your game. The only rules you ** '** must follow when using vbGORE are: ** '** - You may not claim the engine as your own creation. ** '** - You may not sell the code to vbGORE in any way or form, whether it is ** '** the original vbGORE code or a modified version of it. Selling your game** '** may be an exception - if you wish to do this, you must first acquire ** '** permission from Spodi directly. ** '** - If you are distributing vbGORE or modified code of it, read the ** '** section "Source Distrubution Information" below. ** '** This license is subject to change at any time. Only the most current ** '** version of the license applies, not the copy of the license that came with** '** your copy of vbGORE. This means if rules are added for version 1.0, you ** '** can not avoid them by using a previous version such as 0.3. ** '******************************************************************************* '***** Source Distribution Information: **************************************** '******************************************************************************* '** If you wish to distribute this source code, you must distribute as-is ** '** from the vbGORE website unless permission is given to do otherwise. This ** '** comment block must remain in-tact in the distribution. If you wish to ** '** distribute modified versions of vbGORE, please contact Spodi (info below) ** '** before distributing the source code. You may never label the source code ** '** as the "Official Release" or similar unless the code and content remains ** '** unmodified from the version downloaded from the official website. ** '** You may also never sale the source code without permission first. If you ** '** want to sell the code, please contact Spodi (below). This is to prevent ** '** people from ripping off other people by selling an insignificantly ** '** modified version of open-source code just to make a few quick bucks. ** '******************************************************************************* '***** Creating Engines With vbGORE: ******************************************* '******************************************************************************* '** If you plan to create an engine with vbGORE that, please contact Spodi ** '** before doing so. You may not sell the engine unless told elsewise (the ** '** engine must has substantial modifications), and you may not claim it as ** '** all your own work - credit must be given to vbGORE, along with a link to ** '** the vbGORE homepage. Failure to gain approval from Spodi directly to ** '** make a new engine with vbGORE will result in first a friendly reminder, ** '** followed by much more drastic measures. ** '******************************************************************************* '***** Helping Out vbGORE: ***************************************************** '******************************************************************************* '** If you want to help out with vbGORE's progress, theres a few things you ** '** can do: ** '** *Donate - Great way to keep a free project going. :) Info and benifits ** '** for donating can be found at: ** '** http://www.vbgore.com/index.php?title=Donate ** '** *Contribute - Check out our forums, contribute ideas, report bugs, or ** '** help expend the wiki pages! ** '** *Link To Us - Creating a link to vbGORE, whether it is on your own web ** '** page or a link to vbGORE in a forum you visit, every link helps ** '** spread the word of vbGORE's existance! Buttons and banners for ** '** linking to vbGORE can be found on the following page: ** '** http://www.vbgore.com/index.php?title=Buttons_and_Banners ** '** *Spread The Word - The more people who know about vbGORE, the more people** '** there is to report bugs and suggestions to improve the engine! ** '******************************************************************************* '***** Conact Information: ***************************************************** '******************************************************************************* '** Please contact the creator of vbGORE (Spodi) directly with any questions: ** '** AIM: Spodii Yahoo: Spodii ** '** MSN: Spodii@hotmail.com Email: spodi@vbgore.com ** '** 2nd Email: spodii@hotmail.com Website: http://www.vbgore.com ** '******************************************************************************* '***** Credits: **************************************************************** '******************************************************************************* '** Below are credits to those who have helped with the project or who have ** '** distributed source code which has help this project's creation. The below ** '** is listed in no particular order of significance: ** '** ** '** Chase: Help with programming, bug reports, and adding the trading system ** '** Nex666: Help with mapping, graphics, bug reports, hosting, etc ** '** Graphics (Avatar): Supplied the character sprite graphics, + a few more ** '** http://www.zidev.com/ ** '** Map tiles: ** '** http://lostgarden.com/2006/07/more-free-game-graphics.html ** '** ORE (Aaron Perkins): Used as base engine and for learning experience ** '** http://www.baronsoft.com/ ** '** SOX (Trevor Herselman): Used for all the networking ** '** http://pscode.com/vb/scripts/ShowCode.asp?txtCodeId=35239&lngWId=1 ** '** Compression Methods (Marco v/d Berg): Provided compression algorithms ** '** http://pscode.com/vb/scripts/ShowCode.asp?txtCodeId=37867&lngWId=1 ** '** All Files In Folder (Jorge Colaccini): Algorithm implimented into engine ** '** http://pscode.com/vb/scripts/ShowCode.asp?txtCodeId=51435&lngWId=1 ** '** ** '** Also, all the members of the vbGORE community who have submitted ** '** tutorials, bugs, suggestions, criticism and have just stuck around!! ** '** ** '** If you feel you belong in these credits, please contact Spodi (above). ** '******************************************************************************* '******************************************************************************* Option Explicit '********** Debug/Display Settings ************ 'These are your key constants - reccomended you turn off ALL debug constants before ' compiling your code for public usage just speed reasons 'Set this to true to force updater check Public Const ForceUpdateCheck As Boolean = False 'Running speed - make sure you have the same value on the server! Public Const RunningSpeed As Byte = 5 Public Const RunningCost As Long = 1 'How much stamina it cost to run 'Max chat bubble width Public Const BubbleMaxWidth As Long = 140 'Word filter - use by "word-filterto,nextword-nextfilterto"... etc Public Const FilterString As String = "fuck-****,shit-****,ass-***,bitch-*****" Public FilterFind() As String Public FilterReplace() As String '********** NPC chat info ************ Public Type NPCChatLineCondition Condition As Byte 'The condition used (see NPCCHAT_COND_) Value As Long 'Used to hold a numeric condition value ValueStr As String 'Used to hold a value for SAY conditions End Type Public Type NPCChatLine NumConditions As Byte 'Total number of conditions Conditions() As NPCChatLineCondition Text As String 'The text that will be said Style As Byte 'The style used for the text (see NPCCHAT_STYLE_) Delay As Integer 'The delay time applied after saying this line End Type Public Type NPCChatAskAnswer 'The individual chat input answers Text As String 'The answer string GotoID As Byte 'ID the answer will move to End Type Public Type NPCChatAskLine 'Individual chat input lines Question As String 'The question text NumAnswers As Byte 'Number of answers that can be used Answer() As NPCChatAskAnswer End Type Public Type NPCChatAsk 'Chat input information (ASK parameters) StartAsk As Byte 'ID to start the asking on Ask() As NPCChatAskLine 'Holds all the ASK questions/responses End Type Public Type NPCChat Format As Byte 'Format of the chat (see NPCCHAT_FORMAT_) ChatLine() As NPCChatLine 'The information on the chat line NumLines As Byte 'The number of chat lines Distance As Long 'The distance the user must be from the NPC to activate the chat Ask As NPCChatAsk 'All the ASK information End Type Public NPCChat() As NPCChat 'Conditions (this are used as bit-flags, so only use powers of 2!) Public Const NPCCHAT_COND_LEVELLESSTHAN As Long = 2 ^ 0 Public Const NPCCHAT_COND_LEVELMORETHAN As Long = 2 ^ 1 Public Const NPCCHAT_COND_HPLESSTHAN As Long = 2 ^ 2 Public Const NPCCHAT_COND_HPMORETHAN As Long = 2 ^ 3 Public Const NPCCHAT_COND_KNOWSKILL As Long = 2 ^ 4 Public Const NPCCHAT_COND_DONTKNOWSKILL As Long = 2 ^ 5 Public Const NPCCHAT_COND_SAY As Long = 2 ^ 6 'Chat formats Public Const NPCCHAT_FORMAT_RANDOM As Byte = 0 Public Const NPCCHAT_FORMAT_LINEAR As Byte = 1 'Chat sytles Public Const NPCCHAT_STYLE_BOTH As Byte = 0 Public Const NPCCHAT_STYLE_BOX As Byte = 1 Public Const NPCCHAT_STYLE_BUBBLE As Byte = 2 'Client character types Public Const ClientCharType_PC As Byte = 1 Public Const ClientCharType_NPC As Byte = 2 Public Const ClientCharType_Grouped As Byte = 3 Public Const ClientCharType_Slave As Byte = 4 '********** Trade table ************ Public Type TradeObj Name As String Grh As Long Amount As Integer Value As Long End Type Public Type TradeTable User1Name As String 'The name of the table User2Name As String User1Accepted As Byte User2Accepted As Byte Trade1(1 To 9) As TradeObj 'The objects both indexes have entered Trade2(1 To 9) As TradeObj Gold1 As Long 'The gold both indexes have entered Gold2 As Long MyIndex As Byte 'States whether this client is index 1 or 2 End Type Public TradeTable As TradeTable '********** Other stuff ************ Public BaseStats(1 To NumStats) As Long Public ModStats(FirstModStat To NumStats) As Long 'Delay timers for packet-related actions (so to not spam the server) Public Const AttackDelay As Long = 200 'These constants are client-side only Public Const LootDelay As Long = 500 ' - changing these lower wont make it faster server-side! Public LastAttackTime As Long Public LastLootTime As Long 'Cached packets Type Cache_Server_MakeChar Body As Integer Head As Integer Heading As Byte X As Byte Y As Byte Speed As Byte Name As String Weapon As Integer Hair As Integer Wings As Integer HP As Byte MP As Byte ChatID As Byte CharType As Byte End Type Type PacketCache Server_MakeChar As Cache_Server_MakeChar End Type Public PacketCache As PacketCache 'Item description variables Public ItemDescWidth As Long Public ItemDescLine(1 To 10) As String 'Allow 10 lines maximum Public ItemDescLines As Byte 'Object constants Public Const MAX_INVENTORY_SLOTS As Byte = 49 'Active ASK information Public Type ActiveAsk AskName As String AskIndex As Byte ChatIndex As Byte QuestionTxt As String End Type Public ActiveAsk As ActiveAsk 'User's inventory Type Inventory ObjIndex As Long Name As String GrhIndex As Long Amount As Integer Equipped As Boolean Value As Long End Type 'Quest information Type QuestInfo Name As String Desc As String End Type Public QuestInfo() As QuestInfo Public QuestInfoUBound As Byte 'Messages Public NumMessages As Byte Public Message() As String 'Signs Public Signs() As String 'Known user skills/spells Public UserKnowSkill(1 To NumSkills) As Byte 'Attack range Public UserAttackRange As Byte 'User status vars Public UserInventory(1 To MAX_INVENTORY_SLOTS) As Inventory Public UserBank(1 To MAX_INVENTORY_SLOTS) As Inventory 'The time the last packet from the server arrived Public LastServerPacketTime As Long 'If there is a clear path to the target (if any) Public ClearPathToTarget As Byte 'Used during login Public SendNewChar As Boolean Public sndBuf As DataBuffer Public ChatBufferChunk As Single Public SoxID As Long Public SocketMoveToIP As String Public SocketMoveToPort As Integer Public SocketOpen As Byte Public TargetCharIndex As Integer Public Const DegreeToRadian As Single = 0.01745329251994 'Pi / 180 Public Const RadianToDegree As Single = 57.2958279087977 '180 / Pi 'Mail sending spam prevention Public LastMailSendTime As Long 'Holds the skin the user is using at the time Public CurrentSkin As String 'Blocked directions - take the blocked byte and OR these values (If Blocked OR <Direction> Then...) Public Const BlockedNorth As Byte = 1 Public Const BlockedEast As Byte = 2 Public Const BlockedSouth As Byte = 4 Public Const BlockedWest As Byte = 8 Public Const BlockedAll As Byte = 15 Public UseSfx As Byte Public UseMusic As Byte 'States if the project is unloading (has to give Sox time to unload) Public IsUnloading As Byte 'User login information Public UserPassword As String Public UserName As String Public UserClass As Byte Public UserBody As Byte Public UserHead As Byte 'Holds the name of the last person to whisper to the client Public LastWhisperName As String 'Zoom level - 0 = No Zoom, > 0 = Zoomed Public ZoomLevel As Single Public Const MaxZoomLevel As Single = 0.3 'Cursor flash rate Public Const CursorFlashRate As Long = 450 'If click-warping is on or not (can only be used by GMs) Public UseClickWarp As Byte 'Emoticon delay Public EmoticonDelay As Long 'How long char remains aggressive-faced after being attacked Public Const AGGRESSIVEFACETIME = 4000 'Save password check Public SavePass As Boolean 'Maximum variable sizes Public Const MAXLONG As Long = (2 ^ 31) - 1 Public Const MAXINT As Integer = (2 ^ 15) - 1 Public Const MAXBYTE As Byte = (2 ^ 8) - 1 '********** DLL CALLS *********** Public Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer Public Declare Function writeprivateprofilestring Lib "kernel32" Alias "WritePrivateProfileStringA" (ByVal lpApplicationname As String, ByVal lpKeyname As Any, ByVal lpString As String, ByVal lpfilename As String) As Long Public Declare Function getprivateprofilestring Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationname As String, ByVal lpKeyname As Any, ByVal lpdefault As String, ByVal lpreturnedstring As String, ByVal nsize As Long, ByVal lpfilename As String) As Long Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long) Public Declare Sub ZeroMemory Lib "kernel32.dll" Alias "RtlZeroMemory" (ByRef Destination As Any, ByVal Length As Long) Public Declare Function GetActiveWindow Lib "user32" () As Long Public Declare Function timeGetTime Lib "winmm.dll" () As Long Public Declare Function timeBeginPeriod Lib "winmm.dll" (ByVal uPeriod As Long) As Long
[edit] Encryptions
Option Explicit 'Credits goes to Fredrik Qvarfort for writing the algorithms in Visual Basic! '***** Packet encryption options ***** Public Const PacketEncTypeNone As Byte = 0 'Use no encryption Public Const PacketEncTypeRC4 As Byte = 1 'Use RC4 encryption Public Const PacketEncTypeXOR As Byte = 2 'Use XOR encryption Public Const PacketEncTypeServerIn As Byte = PacketEncTypeNone 'Encryption for server in (or client out) packets Public Const PacketEncTypeServerOut As Byte = PacketEncTypeNone 'Encryption for server out (or client in) packets 'These are only used if the PacketEncType is not PacketEncTypeNone Private Const PacketEncKey1 As String = "al123vcAM !$@(2!@_#;241234vzxv!@$(*_DSZVc2123" 'First encryption key (any string works) Private Const PacketEncKey2 As String = "t123409-nsad DS:!$N$MN!U_AKLJ!1240naga!@$)ZZV" 'Second encryption key (any string works) Public Const PacketEncSeed As Long = 214 'The number to start from (any random value works) Public Const PacketEncKeys As Byte = 40 'Number of packet encryption keys '***** RC4 ***** Private m_sBoxRC4(0 To 255) As Integer '***** SIMPLE XOR ***** Private m_XORKey() As Byte Private m_XORKeyLen As Long Private m_XORKeyValue As String '***** MISC ***** 'Key-dependant Private m_KeyS As String Private Declare Sub CopyMem Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long) Sub GenerateEncryptionKeys(ByRef PacketKeys() As String) '***************************************************************** 'Generates a series of unique keys based off the parameters 'It is recommended you change this routine a bit for better safety for public games 'Do NOT use random (Rnd) values since the server and client must make identical keys 'More info: http://www.vbgore.com/CommonCode.Encryptions.GenerateEncryptionKeys '***************************************************************** Dim Seed As Long Dim Key1 As String Dim Key2 As String Dim B2() As Byte Dim b() As Byte Dim i As Long Dim j As Long 'Set the start values Seed = PacketEncSeed Key1 = PacketEncKey1 Key2 = PacketEncKey2 'Set the number of keys ReDim PacketKeys(0 To PacketEncKeys - 1) 'Crop down the keys if needed If Len(Key2) > 32 Then Key2 = Left$(Key2, 32) If Len(Key1) > 32 Then Key1 = Left$(Key1, 32) 'Loop through the needed keys For i = 0 To PacketEncKeys - 1 'Generate a new seed Seed = (i * Seed) - 1 'Jumble up the keys through XOR randomization b = StrConv(Key1, vbFromUnicode) 'Convert to a byte array B2 = StrConv(Key2, vbFromUnicode) For j = 0 To Len(Key1) - 1 Seed = Seed + j + 1 'Modify the seed based on the placement of the character Do While Seed > 255 'Keep it in the byte range Seed = Seed - 255 Loop b(j) = b(j) Xor Seed 'XOR the character by the seed B2(j) = B2(j) Xor CByte(Seed \ 2) Next j Key1 = StrConv(b, vbUnicode) 'Convert back to a string Key2 = StrConv(B2, vbUnicode) 'Jumble up the keys through encryption Key2 = Encryption_RC4_EncryptString(Key2, Key1) Key1 = Encryption_RC4_EncryptString(Key1, Key2) 'Store the key PacketKeys(i) = Key1 Next i End Sub Private Function Encryption_Misc_FileExist(FileName As String) As Boolean '***************************************************************** 'Checks if a file exists 'More info: http://www.vbgore.com/CommonCode.Encryptions.Encryption_Misc_FileExist '***************************************************************** On Error GoTo NotExist Call FileLen(FileName) Encryption_Misc_FileExist = True On Error GoTo 0 NotExist: End Function Public Sub Encryption_RC4_DecryptByte(ByteArray() As Byte, Optional Key As String) '***************************************************************** 'Decryptes a byte array with RC4 encryption 'More info: http://www.vbgore.com/CommonCode.Encryptions.Encryption_RC4_DecryptByte '***************************************************************** Call Encryption_RC4_EncryptByte(ByteArray(), Key) End Sub Public Sub Encryption_RC4_DecryptFile(SourceFile As String, DestFile As String, Optional Key As String) '***************************************************************** 'Decrypts a file with RC4 encryption 'More info: http://www.vbgore.com/CommonCode.Encryptions.Encryption_RC4_DecryptFile '***************************************************************** Dim Filenr As Integer Dim ByteArray() As Byte 'Make sure the source file do exist If (Not Encryption_Misc_FileExist(SourceFile)) Then Call Err.Raise(vbObjectError, , "Error in Skipjack Encryption_RC4_EncryptFile procedure (Source file does not exist).") Exit Sub End If 'Open the source file and read the content 'into a bytearray to decrypt Filenr = FreeFile Open SourceFile For Binary Access Read As #Filenr ReDim ByteArray(0 To LOF(Filenr) - 1) Get #Filenr, , ByteArray() Close #Filenr 'Decrypt the bytearray Call Encryption_RC4_DecryptByte(ByteArray(), Key) 'If the destination file already exist we need 'to delete it since opening it for binary use 'will preserve it if it already exist If (Encryption_Misc_FileExist(DestFile)) Then Kill DestFile 'Store the decrypted data in the destination file Filenr = FreeFile Open DestFile For Binary Access Write As #Filenr Put #Filenr, , ByteArray() Close #Filenr End Sub Public Function Encryption_RC4_DecryptString(Text As String, Optional Key As String) As String '***************************************************************** 'Decrypts a string array with RC4 encryption 'More info: http://www.vbgore.com/CommonCode.Encryptions.Encryption_RC4_DecryptString '***************************************************************** Dim ByteArray() As Byte 'Convert the data into a byte array ByteArray() = StrConv(Text, vbFromUnicode) 'Decrypt the byte array Call Encryption_RC4_DecryptByte(ByteArray(), Key) 'Convert the byte array back into a string Encryption_RC4_DecryptString = StrConv(ByteArray(), vbUnicode) End Function Public Sub Encryption_RC4_EncryptByte(ByteArray() As Byte, Optional Key As String) '***************************************************************** 'Encrypts a byte array with RC4 encryption 'More info: http://www.vbgore.com/CommonCode.Encryptions.Encryption_RC4_EncryptByte '***************************************************************** Dim i As Long Dim j As Long Dim Temp As Byte Dim Offset As Long Dim OrigLen As Long Dim sBox(0 To 255) As Integer 'Set the new key (optional) If (Len(Key) > 0) Then Encryption_RC4_SetKey Key 'Create a local copy of the sboxes, this 'is much more elegant than recreating 'before encrypting/decrypting anything Call CopyMem(sBox(0), m_sBoxRC4(0), 512) 'Get the size of the source array OrigLen = UBound(ByteArray) + 1 'Encrypt the data For Offset = 0 To (OrigLen - 1) i = (i + 1) Mod 256 j = (j + sBox(i)) Mod 256 Temp = sBox(i) sBox(i) = sBox(j) sBox(j) = Temp ByteArray(Offset) = ByteArray(Offset) Xor (sBox((sBox(i) + sBox(j)) Mod 256)) Next End Sub Public Sub Encryption_RC4_EncryptFile(SourceFile As String, DestFile As String, Optional Key As String) '***************************************************************** 'Encrypts a file with RC4 encryption 'More info: http://www.vbgore.com/CommonCode.Encryptions.Encryption_RC4_EncryptFile '***************************************************************** Dim Filenr As Integer Dim ByteArray() As Byte 'Make sure the source file do exist If (Not Encryption_Misc_FileExist(SourceFile)) Then Call Err.Raise(vbObjectError, , "Error in Skipjack Encryption_RC4_EncryptFile procedure (Source file does not exist).") Exit Sub End If 'Open the source file and read the content 'into a bytearray to pass onto encryption Filenr = FreeFile Open SourceFile For Binary Access Read As #Filenr ReDim ByteArray(0 To LOF(Filenr) - 1) Get #Filenr, , ByteArray() Close #Filenr 'Encrypt the bytearray Call Encryption_RC4_EncryptByte(ByteArray(), Key) 'If the destination file already exist we need 'to delete it since opening it for binary use 'will preserve it if it already exist If (Encryption_Misc_FileExist(DestFile)) Then Kill DestFile 'Store the encrypted data in the destination file Filenr = FreeFile Open DestFile For Binary Access Write As #Filenr Put #Filenr, , ByteArray() Close #Filenr End Sub Public Function Encryption_RC4_EncryptString(Text As String, Optional Key As String) As String '***************************************************************** 'Encrypts a string with RC4 encryption 'More info: http://www.vbgore.com/CommonCode.Encryptions.Encryption_RC4_EncryptString '***************************************************************** Dim ByteArray() As Byte 'Convert the data into a byte array ByteArray() = StrConv(Text, vbFromUnicode) 'Encrypt the byte array Call Encryption_RC4_EncryptByte(ByteArray(), Key) 'Convert the byte array back into a string Encryption_RC4_EncryptString = StrConv(ByteArray(), vbUnicode) End Function Public Sub Encryption_RC4_SetKey(New_Value As String) '***************************************************************** 'Sets the encryption key for RC4 encryption 'More info: http://www.vbgore.com/CommonCode.Encryptions.Encryption_RC4_SetKey '***************************************************************** Dim a As Long Dim b As Long Dim Temp As Byte Dim Key() As Byte Dim KeyLen As Long 'Do nothing if the key is buffered If (m_KeyS = New_Value) Then Exit Sub 'Set the new key m_KeyS = New_Value 'Save the password in a byte array Key() = StrConv(m_KeyS, vbFromUnicode) KeyLen = Len(m_KeyS) 'Initialize s-boxes For a = 0 To 255 m_sBoxRC4(a) = a Next a For a = 0 To 255 b = (b + m_sBoxRC4(a) + Key(a Mod KeyLen)) Mod 256 Temp = m_sBoxRC4(a) m_sBoxRC4(a) = m_sBoxRC4(b) m_sBoxRC4(b) = Temp Next End Sub Public Sub Encryption_XOR_DecryptByte(ByteArray() As Byte, Optional Key As String) '***************************************************************** 'Decrypts a byte array with XOR encryption 'More info: http://www.vbgore.com/CommonCode.Encryptions.Encryption_XOR_DecryptByte '***************************************************************** Call Encryption_XOR_EncryptByte(ByteArray(), Key) End Sub Public Sub Encryption_XOR_DecryptFile(SourceFile As String, DestFile As String, Optional Key As String) '***************************************************************** 'Decrypts a file with XOR encryption 'More info: http://www.vbgore.com/CommonCode.Encryptions.Encryption_XOR_DecryptFile '***************************************************************** Dim Filenr As Integer Dim ByteArray() As Byte 'Make sure the source file do exist If (Not Encryption_Misc_FileExist(SourceFile)) Then Call Err.Raise(vbObjectError, , "Error in Skipjack Encryption_XOR_EncryptFile procedure (Source file does not exist).") Exit Sub End If 'Open the source file and read the content 'into a bytearray to decrypt Filenr = FreeFile Open SourceFile For Binary Access Read As #Filenr ReDim ByteArray(0 To LOF(Filenr) - 1) Get #Filenr, , ByteArray() Close #Filenr 'Decrypt the bytearray Call Encryption_XOR_DecryptByte(ByteArray(), Key) 'If the destination file already exist we need 'to delete it since opening it for binary use 'will preserve it if it already exist If (Encryption_Misc_FileExist(DestFile)) Then Kill DestFile 'Store the decrypted data in the destination file Filenr = FreeFile Open DestFile For Binary Access Write As #Filenr Put #Filenr, , ByteArray() Close #Filenr End Sub Public Function Encryption_XOR_DecryptString(Text As String, Optional Key As String) As String '***************************************************************** 'Decrypts a string with XOR encryption 'More info: http://www.vbgore.com/CommonCode.Encryptions.Encryption_XOR_DecryptString '***************************************************************** Dim ByteArray() As Byte 'Convert the source string into a byte array ByteArray() = StrConv(Text, vbFromUnicode) 'Encrypt the byte array Call Encryption_XOR_DecryptByte(ByteArray(), Key) 'Return the encrypted data as a string Encryption_XOR_DecryptString = StrConv(ByteArray(), vbUnicode) End Function Public Sub Encryption_XOR_EncryptByte(ByteArray() As Byte, Optional Key As String) '***************************************************************** 'Encrypts a byte array with XOR encryption 'More info: http://www.vbgore.com/CommonCode.Encryptions.Encryption_XOR_EncryptByte '***************************************************************** Dim Offset As Long Dim ByteLen As Long 'Set the new key if one was provided If (Len(Key) > 0) Then Encryption_XOR_SetKey Key 'Get the size of the source array ByteLen = UBound(ByteArray) + 1 'Loop thru the data encrypting it with simply XOR´ing with the key For Offset = 0 To (ByteLen - 1) ByteArray(Offset) = ByteArray(Offset) Xor m_XORKey(Offset Mod m_XORKeyLen) Next End Sub Public Sub Encryption_XOR_EncryptFile(SourceFile As String, DestFile As String, Optional Key As String) '***************************************************************** 'Encrypts a file with XOR encryption 'More info: http://www.vbgore.com/CommonCode.Encryptions.Encryption_XOR_EncryptFile '***************************************************************** Dim Filenr As Integer Dim ByteArray() As Byte 'Make sure the source file do exist If (Not Encryption_Misc_FileExist(SourceFile)) Then Call Err.Raise(vbObjectError, , "Error in Skipjack Encryption_XOR_EncryptFile procedure (Source file does not exist).") Exit Sub End If 'Open the source file and read the content 'into a bytearray to pass onto encryption Filenr = FreeFile Open SourceFile For Binary Access Read As #Filenr ReDim ByteArray(0 To LOF(Filenr) - 1) Get #Filenr, , ByteArray() Close #Filenr 'Encrypt the bytearray Call Encryption_XOR_EncryptByte(ByteArray(), Key) 'If the destination file already exist we need 'to delete it since opening it for binary use 'will preserve it if it already exist If (Encryption_Misc_FileExist(DestFile)) Then Kill DestFile 'Store the encrypted data in the destination file Filenr = FreeFile Open DestFile For Binary Access Write As #Filenr Put #Filenr, , ByteArray() Close #Filenr End Sub Public Function Encryption_XOR_EncryptString(Text As String, Optional Key As String) As String '***************************************************************** 'Encrypts a string with XOR encryption 'More info: http://www.vbgore.com/CommonCode.Encryptions.Encryption_XOR_EncryptString '***************************************************************** Dim ByteArray() As Byte 'Convert the source string into a byte array ByteArray() = StrConv(Text, vbFromUnicode) 'Encrypt the byte array Call Encryption_XOR_EncryptByte(ByteArray(), Key) 'Return the encrypted data as a string Encryption_XOR_EncryptString = StrConv(ByteArray(), vbUnicode) End Function Public Sub Encryption_XOR_SetKey(New_Value As String) '***************************************************************** 'Sets the encryption key for XOR encryption 'More info: http://www.vbgore.com/CommonCode.Encryptions.Encryption_XOR_SetKey '***************************************************************** 'Do nothing if the key is buffered If (m_XORKeyValue = New_Value) Then Exit Sub 'Set the new key and convert it to a 'byte array for faster accessing later m_XORKeyValue = New_Value m_XORKeyLen = Len(New_Value) m_XORKey() = StrConv(m_XORKeyValue, vbFromUnicode) End Sub
[edit] FilePaths
Option Explicit Public DataPath As String Public Data2Path As String Public GrhPath As String Public GrhMapPath As String Public MapPath As String Public MapEXPath As String Public MusicPath As String Public ServerDataPath As String Public SfxPath As String Public MessagePath As String Public LogPath As String Public ServerTempPath As String Public SignsPath As String Public Sub InitFilePaths() '***************************************************************** 'Set the common file paths 'More info: http://www.vbgore.com/CommonCode.FilePaths.InitFilePaths '***************************************************************** DataPath = App.Path & "\Data\" Data2Path = App.Path & "\Data2\" GrhPath = App.Path & "\Grh\" GrhMapPath = App.Path & "\GrhMapEditor\" MapPath = App.Path & "\Maps\" MapEXPath = App.Path & "\MapsEX\" MusicPath = App.Path & "\Music\" ServerDataPath = App.Path & "\ServerData\" SfxPath = App.Path & "\Sfx\" MessagePath = DataPath & "Messages\" SignsPath = DataPath & "Signs\" LogPath = App.Path & "\Logs\" ServerTempPath = ServerDataPath & "_temp\" End Sub
[edit] General
Option Explicit Public Enum LogType General = 0 CodeTracker = 1 PacketIn = 2 PacketOut = 3 CriticalError = 4 InvalidPacketData = 5 End Enum Public Type NPCTradeItems Name As String Value As Long GrhIndex As Long End Type Public NumBytesForSkills As Long Public NPCTradeItems() As NPCTradeItems Public NPCTradeItemArraySize As Byte Public FPSCap As Long 'The FPS cap the user defined to use (in milliseconds, not FPS) 'Used for the 64-bit timer Private GetSystemTimeOffset As Currency Private Declare Sub GetSystemTime Lib "kernel32.dll" Alias "GetSystemTimeAsFileTime" (ByRef lpSystemTimeAsFileTime As Currency) 'Sleep API - used to put a process into "idle" for X milliseconds Public Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long) 'Like the Shell function, but more powerful - used to call another application to load it Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long Public Sub Log(ByVal DummyT As String, ByVal DummyB As LogType) '*************************************************** 'Dummy routine for logs from the server since some files are shared between multiple projects '*************************************************** End Sub Public Function Engine_ValidChar(ByVal CharIndex As Integer) As Boolean '*************************************************** 'Checks for a valid character index - if no valid index 'is found a packet will be sent to the server requesting information 'on the character CharIndex in case they were not made for whatever reason 'More info: http://www.vbgore.com/GameClient.General.Engine_ValidChar '*************************************************** If CharIndex <= 0 Then GoTo InvalidChar If CharIndex > LastChar Then GoTo InvalidChar If CharList(CharIndex).Active = 0 Then GoTo InvalidChar Engine_ValidChar = True Exit Function InvalidChar: sndBuf.Allocate 3 sndBuf.Put_Byte DataCode.User_RequestMakeChar sndBuf.Put_Integer CharIndex Engine_ValidChar = False End Function Public Function Engine_BuildSkinsList() As String '*************************************************** 'Returns the list of all the skins in a format for the chatbox 'More info: http://www.vbgore.com/GameClient.General.Engine_BuildSkinsList '*************************************************** Dim TempSplit() As String Dim Files() As String Dim i As Long 'Get the list of files Files() = AllFilesInFolders(DataPath & "Skins\", False) 'Show the header message Engine_AddToChatTextBuffer "The following skins are available:", FontColor_Info 'Look for files ending with ".ini" only For i = LBound(Files) To UBound(Files) If Right$(Files(i), 4) = ".ini" Then 'Crop out the skin name and add it to the function TempSplit() = Split(Files(i), "\") If LenB(Engine_BuildSkinsList) <> 0 Then Engine_BuildSkinsList = Engine_BuildSkinsList & vbCrLf Engine_BuildSkinsList = Engine_BuildSkinsList & " * |" & Left$(TempSplit(UBound(TempSplit)), Len(TempSplit(UBound(TempSplit))) - 4) & "|" End If Next i End Function Sub Game_BuildFilter() '***************************************************************** 'Creates the filtering strings from the const FilterString 'More info: http://www.vbgore.com/GameClient.General.Game_BuildFilter '***************************************************************** Dim sGroup() As String Dim sSplit() As String Dim i As Long 'Check if we even have filtered words If LenB(FilterString) = 0 Then Exit Sub 'Split up the word groups sGroup() = Split(FilterString, ",") ReDim FilterFind(0 To UBound(sGroup())) ReDim FilterReplace(0 To UBound(sGroup())) For i = 0 To UBound(sGroup()) 'Split up the group to get the word to search for, and the word to replace it with sSplit() = Split(sGroup(i), "-") 'Store the values FilterFind(i) = Trim$(sSplit(0)) FilterReplace(i) = Trim$(sSplit(1)) Next i End Sub Function Game_FilterString(ByVal s As String) As String '***************************************************************** 'Filters a string from all illegal characters and words specified in 'the const FilterString 'More info: http://www.vbgore.com/GameClient.General.Game_FilterString '***************************************************************** Dim i As Long Dim a As Integer Dim t As String 'Check for a legal string If LenB(s) = 0 Then Game_FilterString = s Exit Function End If 'Filter illegal character For i = 1 To Len(s) - 1 a = Asc(Mid$(s, i, 1)) If Not Game_ValidCharacter(a) Then t = vbNullString If i > 1 Then t = t & Left$(s, i - 1) t = t & "X" If i < Len(s) - 1 Then t = t & Right$(s, Len(s) - i) s = t End If Next i 'Call the swear filter s = Game_SwearFilterString(s) 'Return the string Game_FilterString = s End Function Function Game_ClosestTargetNPC() As Integer '***************************************************************** 'Find the closest NPC to target based on the user's heading and NPC's location 'More info: http://www.vbgore.com/GameClient.General.Game_ClosestTargetNPC '***************************************************************** Dim CharValue() As Long Dim LowestValue As Long Dim LowestValueChar As Long Dim UserAngleMod As Long Dim TempAngle As Long Dim TempValue As Long Dim j As Long 'Check for characters If LastChar <= 1 Then Exit Function 'If theres only one character, its probably the user 'Get the initial size of the chars array ReDim CharValue(1 To LastChar) 'Calculate the modifier of the user's heading Select Case CharList(UserCharIndex).Heading Case NORTH: UserAngleMod = 0 * 45 Case NORTHEAST: UserAngleMod = 1 * 45 Case EAST: UserAngleMod = 2 * 45 Case SOUTHEAST: UserAngleMod = 3 * 45 Case SOUTH: UserAngleMod = 4 * 45 Case SOUTHWEST: UserAngleMod = 5 * 45 Case WEST: UserAngleMod = 6 * 45 Case NORTHWEST: UserAngleMod = 7 * 45 End Select 'Loop through all the characters For j = 1 To LastChar 'Make sure the character is used If CharList(j).Active Then If j <> UserCharIndex Then If j <> TargetCharIndex Then If CharList(j).CharType = ClientCharType_NPC Then 'Check that the character is in the screen If CharList(j).Pos.X > ScreenMinX Then If CharList(j).Pos.X < ScreenMaxX Then If CharList(j).Pos.Y > ScreenMinY Then If CharList(j).Pos.Y < ScreenMaxY Then 'Get the angle between the user and the NPC TempAngle = -UserAngleMod + Engine_GetAngle(CharList(UserCharIndex).Pos.X, CharList(UserCharIndex).Pos.Y, CharList(j).Pos.X, CharList(j).Pos.Y) 'Make sure the angle is between 0 and 360 Do While TempAngle >= 360 TempAngle = TempAngle - 360 Loop Do While TempAngle < 0 TempAngle = TempAngle + 360 Loop 'Check that the angle is less between -95 and 95 (not behind them) If TempAngle < 95 Or TempAngle > 265 Then 'Convert the angle to the distance from 0 degrees If TempAngle > 180 Then TempAngle = Abs(360 - TempAngle) If TempAngle = 360 Then TempAngle = 0 'Calculate the value of the character 'Value = Angle * 2 + Distance TempValue = (TempAngle * 0.5) + Engine_Distance(CharList(UserCharIndex).Pos.X, CharList(UserCharIndex).Pos.Y, CharList(j).Pos.X, CharList(j).Pos.Y) 'Check if this value is lower then the first value If LowestValue = 0 Then LowestValue = TempValue LowestValueChar = j Else If LowestValue > TempValue Then LowestValue = TempValue LowestValueChar = j End If End If End If End If End If End If End If End If End If End If End If Next j 'Return the index of the character with the lowest value (best target) Game_ClosestTargetNPC = LowestValueChar End Function Function Game_SwearFilterString(ByVal s As String) As String '***************************************************************** 'Checks the passed string for any swear words to filter out 'More info: http://www.vbgore.com/GameClient.General.Game_SwearFilterString '***************************************************************** Dim i As Long 'Check if we even have filtered words If LenB(FilterString) = 0 Then Game_SwearFilterString = s Exit Function End If 'Loop through all the filters For i = 0 To UBound(FilterFind()) s = Replace$(s, FilterFind(i), FilterReplace(i)) Next i 'Return the string Game_SwearFilterString = s End Function Function Game_CheckUserData() As Boolean '***************************************************************** 'Checks all user data for mistakes and reports any errors 'More info: http://www.vbgore.com/GameClient.General.Game_CheckUserData '***************************************************************** 'Password If Len(UserPassword) < 3 Then MsgBox ("Password box is empty.") Exit Function End If If Len(UserPassword) > 10 Then MsgBox ("Password must be 10 characters or less.") Exit Function End If If Game_LegalString(UserPassword) = False Then MsgBox ("Invalid Password.") Exit Function End If 'Name If Len(UserName) < 3 Then MsgBox ("Name box is empty.") Exit Function End If If Len(UserName) > 10 Then MsgBox ("Name must be 10 characters or less.") Exit Function End If If Game_LegalString(UserName) = False Then MsgBox ("Invalid Name.") Exit Function End If 'If all good send true Game_CheckUserData = True End Function Function Game_ClickItem(ByVal ItemIndex As Byte, Optional ByVal InventoryType As Long = 1) As Long '*************************************************** 'Selects the item clicked if it's valid and return's its index 'More info: http://www.vbgore.com/GameClient.General.Game_ClickItem '*************************************************** 'Make sure item index is within limits If ItemIndex <= 0 Then Exit Function If ItemIndex > MAX_INVENTORY_SLOTS Then Exit Function 'Check by the appropriate window Select Case InventoryType 'User inventory Case 1 If UserInventory(ItemIndex).GrhIndex > 0 Then Game_ClickItem = 1 'Shop inventory Case 2 If NPCTradeItems(ItemIndex).GrhIndex > 0 Then Game_ClickItem = 1 'Bank depot Case 3 If UserBank(ItemIndex).GrhIndex > 0 Then Game_ClickItem = 1 End Select End Function Function Game_ValidCharacter(ByVal KeyAscii As Byte) As Boolean '***************************************************************** 'Only allow certain specified characters (this is used for chat/etc) 'Make sure you update the server's Server_ValidCharacter, too! 'More info: http://www.vbgore.com/GameClient.General.Game_ValidCharacter '***************************************************************** Log "Call Game_ValidCharacter(" & KeyAscii & ")", CodeTracker '//\\LOGLINE//\\ 'Remove bad characters If KeyAscii >= 32 Then Game_ValidCharacter = True End Function Function Game_LegalCharacter(ByVal KeyAscii As Byte) As Boolean '***************************************************************** 'Only allow certain specified characters (this is for username/pass) 'Make sure you update the server's Server_LegalCharacter, too! 'More info: http://www.vbgore.com/GameClient.General.Game_LegalCharacter '***************************************************************** On Error GoTo ErrOut 'Allow numbers between 0 and 9 If KeyAscii >= 48 Then If KeyAscii <= 57 Then Game_LegalCharacter = True Exit Function End If End If 'Allow characters A to Z If KeyAscii >= 65 Then If KeyAscii <= 90 Then Game_LegalCharacter = True Exit Function End If End If 'Allow characters a to z If KeyAscii >= 97 Then If KeyAscii <= 122 Then Game_LegalCharacter = True Exit Function End If End If 'Allow foreign characters If KeyAscii >= 128 Then If KeyAscii <= 168 Then Game_LegalCharacter = True Exit Function End If End If Exit Function ErrOut: 'Something bad happened, so the character must be invalid Game_LegalCharacter = False End Function Function Game_ValidString(ByVal CheckString As String) As Boolean '***************************************************************** 'Check for illegal characters in the string (wrapper for Game_ValidCharacter) 'More info: http://www.vbgore.com/GameClient.General.Game_ValidString '***************************************************************** Dim i As Long On Error GoTo ErrOut 'Check for invalid string If CheckString = vbNullChar Then Exit Function If LenB(CheckString) < 1 Then Exit Function 'Loop through the string For i = 1 To Len(CheckString) 'Check the values If Game_ValidCharacter(AscB(Mid$(CheckString, i, 1))) = False Then Exit Function Next i 'If we have made it this far, then all is good Game_ValidString = True Exit Function ErrOut: 'Something bad happened, so the string must be invalid Game_ValidString = False End Function Function Game_LegalString(ByVal CheckString As String) As Boolean '***************************************************************** 'Check for illegal characters in the string (wrapper for Server_LegalCharacter) 'More info: http://www.vbgore.com/GameClient.General.Game_LegalString '***************************************************************** Dim i As Long On Error GoTo ErrOut 'Check for invalid string If CheckString = vbNullChar Then Exit Function If LenB(CheckString) < 1 Then Exit Function 'Loop through the string For i = 1 To Len(CheckString) 'Check the values If Game_LegalCharacter(AscB(Mid$(CheckString, i, 1))) = False Then Exit Function Next i 'If we have made it this far, then all is good Game_LegalString = True Exit Function ErrOut: 'Something bad happened, so the string must be invalid Game_LegalString = False End Function Public Sub Game_Config_Load() '*************************************************** 'Load the user configuration (used skin and quickbar values) 'More info: http://www.vbgore.com/GameClient.General.Game_Config_Load '*************************************************** Dim i As Byte 'Quickbar For i = 1 To 12 QuickBarID(i).ID = Val(Var_Get(DataPath & "Game.ini", "QUICKBARVALUES", "Slot" & i & "ID")) QuickBarID(i).Type = Val(Var_Get(DataPath & "Game.ini", "QUICKBARVALUES", "Slot" & i & "Type")) Next i 'Skin CurrentSkin = Var_Get(DataPath & "Game.ini", "INIT", "CurrentSkin") End Sub Sub Game_Map_Switch(Map As Integer) '***************************************************************** 'Loads a new map and switches to it 'More info: http://www.vbgore.com/GameClient.General.Game_Map_Switch '***************************************************************** Dim LargestTileSize As Long Dim MapBuf As DataBuffer Dim GetParticleCount As Integer Dim GetEffectNum As Byte Dim GetDirection As Integer Dim GetGfx As Byte Dim GetX As Integer Dim GetY As Integer Dim ByFlags As Long Dim MapNum As Byte Dim i As Integer Dim Y As Byte Dim X As Byte Dim b() As Byte Dim TempInt As Integer 'Check if there was a map before this one - if so, clear it up If MapInfo.Width > 0 Then 'Clear the offset values for the particle engine ParticleOffsetX = 0 ParticleOffsetY = 0 LastOffsetX = 0 LastOffsetY = 0 'Reset the user's position (it won't be drawn at 0,0 since it is an invalid position anyways) UserPos.X = 0 UserPos.Y = 0 'Erase characters LastChar = 0 Erase CharList 'Erase damage LastDamage = 0 Erase DamageList 'Erase objects LastObj = 0 Erase OBJList 'Erase particle effects LastEffect = 0 ReDim Effect(1 To NumEffects) End If 'Open map file MapNum = FreeFile Open MapPath & Map & ".map" For Binary As #MapNum Seek #MapNum, 1 'Store the data in the buffer ReDim b(0 To LOF(MapNum) - 1) Get #MapNum, , b() 'Close the map file Close #MapNum 'Assign the buffer data Set MapBuf = New DataBuffer MapBuf.Set_Buffer b() 'Clear the data array (since its now in the buffer) Erase b() 'Map Header TempInt = MapBuf.Get_Integer 'Not stored in memory MapInfo.Width = MapBuf.Get_Byte MapInfo.Height = MapBuf.Get_Byte 'Resize mapdata array ReDim MapData(1 To MapInfo.Width, 1 To MapInfo.Height) As MapBlock 'Resize the save light buffer ReDim SaveLightBuffer(1 To MapInfo.Width, 1 To MapInfo.Height) 'Load arrays For Y = 1 To MapInfo.Height For X = 1 To MapInfo.Width 'Clear the graphic layers For i = 1 To 6 MapData(X, Y).Graphic(i).GrhIndex = 0 Next i 'Get flag's byte ByFlags = MapBuf.Get_Long 'Blocked If ByFlags And 1 Then MapData(X, Y).Blocked = MapBuf.Get_Byte Else MapData(X, Y).Blocked = 0 'Graphic layers If ByFlags And 2 Then MapData(X, Y).Graphic(1).GrhIndex = MapBuf.Get_Long Engine_Init_Grh MapData(X, Y).Graphic(1), MapData(X, Y).Graphic(1).GrhIndex 'Find the size of the largest tile used If LargestTileSize < GrhData(MapData(X, Y).Graphic(1).GrhIndex).pixelWidth Then LargestTileSize = GrhData(MapData(X, Y).Graphic(1).GrhIndex).pixelWidth End If If LargestTileSize < GrhData(MapData(X, Y).Graphic(1).GrhIndex).pixelHeight Then LargestTileSize = GrhData(MapData(X, Y).Graphic(1).GrhIndex).pixelHeight End If End If If ByFlags And 4 Then MapData(X, Y).Graphic(2).GrhIndex = MapBuf.Get_Long Engine_Init_Grh MapData(X, Y).Graphic(2), MapData(X, Y).Graphic(2).GrhIndex If LargestTileSize < GrhData(MapData(X, Y).Graphic(2).GrhIndex).pixelWidth Then LargestTileSize = GrhData(MapData(X, Y).Graphic(2).GrhIndex).pixelWidth End If If LargestTileSize < GrhData(MapData(X, Y).Graphic(2).GrhIndex).pixelHeight Then LargestTileSize = GrhData(MapData(X, Y).Graphic(2).GrhIndex).pixelHeight End If End If If ByFlags And 8 Then MapData(X, Y).Graphic(3).GrhIndex = MapBuf.Get_Long Engine_Init_Grh MapData(X, Y).Graphic(3), MapData(X, Y).Graphic(3).GrhIndex If LargestTileSize < GrhData(MapData(X, Y).Graphic(3).GrhIndex).pixelWidth Then LargestTileSize = GrhData(MapData(X, Y).Graphic(3).GrhIndex).pixelWidth End If If LargestTileSize < GrhData(MapData(X, Y).Graphic(3).GrhIndex).pixelHeight Then LargestTileSize = GrhData(MapData(X, Y).Graphic(3).GrhIndex).pixelHeight End If End If If ByFlags And 16 Then MapData(X, Y).Graphic(4).GrhIndex = MapBuf.Get_Long Engine_Init_Grh MapData(X, Y).Graphic(4), MapData(X, Y).Graphic(4).GrhIndex If LargestTileSize < GrhData(MapData(X, Y).Graphic(4).GrhIndex).pixelWidth Then LargestTileSize = GrhData(MapData(X, Y).Graphic(4).GrhIndex).pixelWidth End If If LargestTileSize < GrhData(MapData(X, Y).Graphic(4).GrhIndex).pixelHeight Then LargestTileSize = GrhData(MapData(X, Y).Graphic(4).GrhIndex).pixelHeight End If End If If ByFlags And 32 Then MapData(X, Y).Graphic(5).GrhIndex = MapBuf.Get_Long Engine_Init_Grh MapData(X, Y).Graphic(5), MapData(X, Y).Graphic(5).GrhIndex If LargestTileSize < GrhData(MapData(X, Y).Graphic(5).GrhIndex).pixelWidth Then LargestTileSize = GrhData(MapData(X, Y).Graphic(5).GrhIndex).pixelWidth End If If LargestTileSize < GrhData(MapData(X, Y).Graphic(5).GrhIndex).pixelHeight Then LargestTileSize = GrhData(MapData(X, Y).Graphic(5).GrhIndex).pixelHeight End If End If If ByFlags And 64 Then MapData(X, Y).Graphic(6).GrhIndex = MapBuf.Get_Long Engine_Init_Grh MapData(X, Y).Graphic(6), MapData(X, Y).Graphic(6).GrhIndex If LargestTileSize < GrhData(MapData(X, Y).Graphic(6).GrhIndex).pixelWidth Then LargestTileSize = GrhData(MapData(X, Y).Graphic(6).GrhIndex).pixelWidth End If If LargestTileSize < GrhData(MapData(X, Y).Graphic(6).GrhIndex).pixelHeight Then LargestTileSize = GrhData(MapData(X, Y).Graphic(6).GrhIndex).pixelHeight End If End If 'Set light to default (-1) - it will be set again if it is not -1 from the code below For i = 1 To 24 MapData(X, Y).Light(i) = -1 Next i 'Get lighting values If ByFlags And 128 Then For i = 1 To 4 MapData(X, Y).Light(i) = MapBuf.Get_Long Next i End If If ByFlags And 256 Then For i = 5 To 8 MapData(X, Y).Light(i) = MapBuf.Get_Long Next i End If If ByFlags And 512 Then For i = 9 To 12 MapData(X, Y).Light(i) = MapBuf.Get_Long Next i End If If ByFlags And 1024 Then For i = 13 To 16 MapData(X, Y).Light(i) = MapBuf.Get_Long Next i End If If ByFlags And 2048 Then For i = 17 To 20 MapData(X, Y).Light(i) = MapBuf.Get_Long Next i End If If ByFlags And 4096 Then For i = 21 To 24 MapData(X, Y).Light(i) = MapBuf.Get_Long Next i End If 'Store the lighting in the SaveLightBuffer For i = 1 To 24 SaveLightBuffer(X, Y).Light(i) = MapData(X, Y).Light(i) Next i 'Mailbox - Not used by the client 'If ByFlags And 8192 Then MapData(X, Y).Mailbox = 1 Else MapData(X, Y).Mailbox = 0 'Shadows If ByFlags And 16384 Then MapData(X, Y).Shadow(1) = 1 Else MapData(X, Y).Shadow(1) = 0 If ByFlags And 32768 Then MapData(X, Y).Shadow(2) = 1 Else MapData(X, Y).Shadow(2) = 0 If ByFlags And 65536 Then MapData(X, Y).Shadow(3) = 1 Else MapData(X, Y).Shadow(3) = 0 If ByFlags And 131072 Then MapData(X, Y).Shadow(4) = 1 Else MapData(X, Y).Shadow(4) = 0 If ByFlags And 262144 Then MapData(X, Y).Shadow(5) = 1 Else MapData(X, Y).Shadow(5) = 0 If ByFlags And 524288 Then MapData(X, Y).Shadow(6) = 1 Else MapData(X, Y).Shadow(6) = 0 'Clear any old sfx If Not MapData(X, Y).Sfx Is Nothing Then MapData(X, Y).Sfx.Stop Set MapData(X, Y).Sfx = Nothing End If 'Set the sfx If ByFlags And 1048576 Then i = MapBuf.Get_Integer Sound_SetToMap i, X, Y End If 'Blocked attack If ByFlags And 2097152 Then MapData(X, Y).BlockedAttack = 1 Else MapData(X, Y).BlockedAttack = 0 'Sign If ByFlags And 4194304 Then MapData(X, Y).Sign = MapBuf.Get_Integer Else MapData(X, Y).Sign = 0 'If there is a warp If ByFlags And 8388608 Then MapData(X, Y).Warp = 1 Else MapData(X, Y).Warp = 0 Next X Next Y 'Get the number of effects Y = MapBuf.Get_Byte 'Store the individual particle effect types If Y > 0 Then For X = 1 To Y GetEffectNum = MapBuf.Get_Byte GetX = MapBuf.Get_Integer GetY = MapBuf.Get_Integer GetParticleCount = MapBuf.Get_Integer GetGfx = MapBuf.Get_Byte GetDirection = MapBuf.Get_Integer Effect_Begin GetEffectNum, GetX, GetY, GetGfx, GetParticleCount, GetDirection Next X End If 'Clear the map data Set MapBuf = Nothing 'Create the minimap Engine_BuildMiniMap 'Clear out old mapinfo variables MapInfo.Name = vbNullString 'Set current map CurMap = Map 'Auto-calculate the maximum size to set the tile buffer LargestTileSize = LargestTileSize + (32 - (LargestTileSize Mod 32)) 'Round to the next highest factor of 32 TileBufferSize = (LargestTileSize \ 32) 'Divide into tiles 'Force to 2 to draw characters since they are 2 tiles tall 'If you have characters or paperdoll parts > 64 pixels in width or high, you need to increase this If TileBufferSize < 2 Then TileBufferSize = 2 'Cache the TileBufferOffset value to prevent always having to calculate it on the fly TileBufferOffset = ((10 - TileBufferSize) * 32) End Sub Public Sub Game_Config_Save() '*************************************************** 'Saves the user configuration (quickbar, skin and skin position) 'More info: http://www.vbgore.com/GameClient.General.Game_Config_Save '*************************************************** Dim t As String Dim i As Byte 'Quickbar For i = 1 To 12 Var_Write DataPath & "Game.ini", "QUICKBARVALUES", "Slot" & i & "ID", Str$(QuickBarID(i).ID) Var_Write DataPath & "Game.ini", "QUICKBARVALUES", "Slot" & i & "Type", Str$(QuickBarID(i).Type) Next i 'Skin Var_Write DataPath & "Game.ini", "INIT", "CurrentSkin", CurrentSkin 'Skin positions t = DataPath & "Skins\" & CurrentSkin & ".dat" 'Set the custom positions file for the skin With GameWindow Var_Write t, "QUICKBAR", "ScreenX", Str$(.QuickBar.Screen.X) Var_Write t, "QUICKBAR", "ScreenY", Str$(.QuickBar.Screen.Y) Var_Write t, "CHATWINDOW", "ScreenX", Str$(.ChatWindow.Screen.X) Var_Write t, "CHATWINDOW", "ScreenY", Str$(.ChatWindow.Screen.Y) Var_Write t, "INVENTORY", "ScreenX", Str$(.Inventory.Screen.X) Var_Write t, "INVENTORY", "ScreenY", Str$(.Inventory.Screen.Y) Var_Write t, "SHOP", "ScreenX", Str$(.Shop.Screen.X) Var_Write t, "SHOP", "ScreenY", Str$(.Shop.Screen.Y) Var_Write t, "MAILBOX", "ScreenX", Str$(.Mailbox.Screen.X) Var_Write t, "MAILBOX", "ScreenY", Str$(.Mailbox.Screen.Y) Var_Write t, "VIEWMESSAGE", "ScreenX", Str$(.ViewMessage.Screen.X) Var_Write t, "VIEWMESSAGE", "ScreenY", Str$(.ViewMessage.Screen.Y) Var_Write t, "WRITEMESSAGE", "ScreenX", Str$(.WriteMessage.Screen.X) Var_Write t, "WRITEMESSAGE", "ScreenY", Str$(.WriteMessage.Screen.Y) Var_Write t, "AMOUNT", "ScreenX", Str$(.Amount.Screen.X) Var_Write t, "AMOUNT", "ScreenY", Str$(.Amount.Screen.Y) Var_Write t, "MENU", "ScreenX", Str$(.Menu.Screen.X) Var_Write t, "MENU", "ScreenY", Str$(.Menu.Screen.Y) Var_Write t, "BANK", "ScreenX", Str$(.Bank.Screen.X) Var_Write t, "BANK", "ScreenY", Str$(.Bank.Screen.Y) Var_Write t, "NPCCHAT", "ScreenX", Str$(.NPCChat.Screen.X) Var_Write t, "NPCCHAT", "ScreenY", Str$(.NPCChat.Screen.Y) End With End Sub Sub UpdateShownTextBuffer() '***************************************************************** 'Updates the ShownTextBuffer (the text displayed written into the text input box) 'More info: http://www.vbgore.com/GameClient.General.UpdateShownTextBuffer '***************************************************************** Dim X As Long Dim j As Long 'Check if the width is larger then the screen If EnterTextBufferWidth > GameWindow.ChatWindow.Text.Width - 24 Then 'Loop through the characters backwards For X = Len(EnterTextBuffer) To 1 Step -1 'Add up the size j = j + Font_Default.HeaderInfo.CharWidth(Asc(Mid$(EnterTextBuffer, X, 1))) 'Check if the size has become too large If j > GameWindow.ChatWindow.Text.Width - 24 Then 'If the size has become too large, the character before (since we are looping backwards, it is + 1) is the limit ShownText = Right$(EnterTextBuffer, Len(EnterTextBuffer) - X + 1) Exit For End If Next X Else 'Set the shown text buffer to the full buffer ShownText = EnterTextBuffer End If End Sub Sub Main() '***************************************************************** 'The entry-point for the client - gets the client ready and handles 'the main game loop that runs the whole time the client is running 'More info: http://www.vbgore.com/GameClient.General.Main '***************************************************************** Dim KeyClearTime As Long Dim PacketKeys() As String Dim LastUnloadTime As Long Dim StartTime As Long Dim i As Integer 'Set the high-resolution timer timeBeginPeriod 1 'Init file paths InitFilePaths 'Load frmMain Load frmMain frmMain.Hide DoEvents 'Check if we need to run the updater If ForceUpdateCheck Then 'Check for the right parameter If Command$ <> "-sdf@041jkdf0)21`~" Then 'Force the creation of frmConnect, thus forcing the creation of its hWnd Load frmConnect frmConnect.Show frmConnect.Hide 'Load the updater ShellExecute frmConnect.hwnd, vbNullString, App.Path & "\UpdateClient.exe", vbNullString, vbNullString, 1 'The 1 means "show normal" 'Unload the client Engine_UnloadAllForms End End If End If 'Generate the packet keys GenerateEncryptionKeys PacketKeys frmMain.GOREsock.ClearPicture frmMain.GOREsock.SetEncryption PacketEncTypeServerIn, PacketEncTypeServerOut, PacketKeys() Erase PacketKeys 'Number of bytes required to fill the skills NumBytesForSkills = Int((NumSkills - 1) / 8) + 1 'Load the font information Engine_Init_FontSettings 'Load the messages Engine_Init_Messages LCase$(Var_Get(DataPath & "Game.ini", "INIT", "Language")) Engine_Init_Signs LCase$(Var_Get(DataPath & "Game.ini", "INIT", "Language")) 'Fill startup variables for the tile engine EnterTextBufferWidth = 1 ReDim SkillListIDs(1 To NumSkills) 'Set intial user position UserPos.X = 1 UserPos.Y = 1 'Set scroll pixels per frame ShowGameWindow(QuickBarWindow) = 1 ShowGameWindow(ChatWindow) = 1 'Set the array sizes by the number of graphic files NumGrhFiles = CLng(Var_Get(DataPath & "Grh.ini", "INIT", "NumGrhFiles")) ReDim SurfaceDB(1 To NumGrhFiles) ReDim SurfaceSize(1 To NumGrhFiles) ReDim SurfaceTimer(1 To NumGrhFiles) 'Load graphic data into memory Engine_Init_GrhData Engine_Init_BodyData Engine_Init_WeaponData Engine_Init_WingData Engine_Init_HeadData Engine_Init_HairData 'Load the config Game_Config_Load Engine_Init_GUI 'Create the buffer Set sndBuf = New DataBuffer sndBuf.Clear 'Set the form starting positions DoEvents 'Load the data commands InitDataCommands 'Build the word filters Game_BuildFilter 'Display connect window frmConnect.Visible = True 'Main Loop Do 'Calculate the starttime - this is the absolute time it takes from start to finish, disincluding DoEvents ' The idea is that it works just like the ElapsedTime, but in slightly different placing StartTime = timeGetTime 'Check if unloading If IsUnloading = 1 Then Exit Do 'Clear the key cache If KeyClearTime < timeGetTime Then Input_Keys_ClearQueue KeyClearTime = timeGetTime + 200 End If 'Don't draw frame is window is minimized or there is no map loaded If frmMain.WindowState <> 1 Then If CurMap > 0 Then 'Show the next frame Engine_ShowNextFrame 'Check for key inputs Input_Keys_General 'Keep the music looping If MapInfo.Music > 0 Then Music_Loop 1 End If End If 'Perform the following only if the connection to the server is open If SocketOpen Then 'Send the data buffer Data_Send 'Check the time since the last packet arrived If timeGetTime - LastServerPacketTime > 6000 Then 'No response from the server in 5 seconds, must be disconnected :( IsUnloading = 1 End If End If 'Check to unload stuff from memory (only check every 5 seconds) If LastUnloadTime < timeGetTime Then For i = 1 To NumGrhFiles 'Check to unload surfaces If SurfaceTimer(i) > 0 Then 'Only update surfaces in use If SurfaceTimer(i) < timeGetTime Then 'Unload the surface Set SurfaceDB(i) = Nothing SurfaceTimer(i) = 0 End If End If Next i For i = 1 To NumSfx 'Check to unload sound buffers If SoundBufferTimer(i) > 0 Then 'Only update sound buffers in use If SoundBufferTimer(i) < timeGetTime Then 'Unload the sound buffer Set DSBuffer(i) = Nothing SoundBufferTimer(i) = 0 End If End If Next i LastUnloadTime = timeGetTime + 10000 'States we will check the unload routine again in 10 seconds End If 'Check to change servers If SocketMoveToPort > 0 Then If frmMain.GOREsock.ShutDown <> soxERROR Then 'Set up the socket 'Leave the GetIPFromHost() wrapper there, this will convert a host name to IP if needed, or leave it as an IP if you pass an IP SoxID = frmMain.GOREsock.Connect(GetIPFromHost(SocketMoveToIP), SocketMoveToPort) SocketOpen = 1 'If the SoxID = -1, then the connection failed, elsewise, we're good to go! W00t! ^_^ If SoxID = -1 Then MsgBox "Unable to connect to the game server!" & vbCrLf & "Either the server is down or you are not connected to the internet.", vbOKOnly Or vbCritical IsUnloading = 1 Else frmMain.GOREsock.SetOption SoxID, soxSO_TCP_NODELAY, True End If 'Clear the temp values SocketMoveToPort = 0 SocketMoveToIP = vbNullString End If End If 'Do other events DoEvents 'Do sleep event - force FPS at the FPS cap If Not frmMain.Visible Then Sleep 100 'Don't hog resources at connect screen Else If FPSCap > 0 Then If (timeGetTime - StartTime) < FPSCap Then 'If Elapsed Time < Time required for requested highest fps Sleep FPSCap - (timeGetTime - StartTime) End If End If End If Loop 'Save the config Game_Config_Save 'Close down frmMain.ShutdownTimer.Enabled = True End Sub Function Var_Get(ByVal File As String, ByVal Main As String, ByVal Var As String) As String '***************************************************************** 'Gets a string from a text file 'More info: http://www.vbgore.com/GameClient.General.Var_Get '***************************************************************** Var_Get = Space$(1000) getprivateprofilestring Main, Var, vbNullString, Var_Get, 1000, File Var_Get = RTrim$(Var_Get) If LenB(Var_Get) <> 0 Then Var_Get = Left$(Var_Get, Len(Var_Get) - 1) End Function Sub Var_Write(ByVal File As String, ByVal Main As String, ByVal Var As String, ByVal Value As String) '***************************************************************** 'Writes a string to a text file 'More info: http://www.vbgore.com/GameClient.General.Var_Write '***************************************************************** writeprivateprofilestring Main, Var, Value, File End Sub Public Function Engine_WordWrap(ByVal Text As String, ByVal MaxLineLen As Integer) As String '************************************************************ 'Wrap a long string to multiple lines by vbNewLine 'More info: http://www.vbgore.com/GameClient.General.Engine_WordWrap '************************************************************ Dim TempSplit() As String Dim TSLoop As Long Dim LastSpace As Long Dim Size As Long Dim i As Long Dim b As Long 'Too small of text If Len(Text) < 2 Then Engine_WordWrap = Text Exit Function End If 'Check if there are any line breaks - if so, we will support them TempSplit = Split(Text, vbNewLine) For TSLoop = 0 To UBound(TempSplit) 'Clear the values for the new line Size = 0 b = 1 LastSpace = 1 'Add back in the vbNewLines If TSLoop < UBound(TempSplit()) Then TempSplit(TSLoop) = TempSplit(TSLoop) & vbNewLine 'Only check lines with a space If InStr(1, TempSplit(TSLoop), " ") Or InStr(1, TempSplit(TSLoop), "-") Or InStr(1, TempSplit(TSLoop), "_") Then 'Loop through all the characters For i = 1 To Len(TempSplit(TSLoop)) 'If it is a space, store it so we can easily break at it Select Case Mid$(TempSplit(TSLoop), i, 1) Case " ": LastSpace = i Case "_": LastSpace = i Case "-": LastSpace = i End Select 'Add up the size - Do not count the "|" character (high-lighter)! If Not Mid$(TempSplit(TSLoop), i, 1) = "|" Then Size = Size + Font_Default.HeaderInfo.CharWidth(Asc(Mid$(TempSplit(TSLoop), i, 1))) End If 'Check for too large of a size If Size > MaxLineLen Then 'Check if the last space was too far back If i - LastSpace > 4 Then 'Too far away to the last space, so break at the last character Engine_WordWrap = Engine_WordWrap & Trim$(Mid$(TempSplit(TSLoop), b, (i - 1) - b)) & vbNewLine b = i - 1 Size = 0 Else 'Break at the last space to preserve the word Engine_WordWrap = Engine_WordWrap & Trim$(Mid$(TempSplit(TSLoop), b, LastSpace - b)) & vbNewLine b = LastSpace + 1 'Count all the words we ignored (the ones that weren't printed, but are before "i") Size = Engine_GetTextWidth(Font_Default, Mid$(TempSplit(TSLoop), LastSpace, i - LastSpace)) End If End If 'This handles the remainder If i = Len(TempSplit(TSLoop)) Then If b <> i Then Engine_WordWrap = Engine_WordWrap & Mid$(TempSplit(TSLoop), b, i) End If End If Next i Else Engine_WordWrap = Engine_WordWrap & TempSplit(TSLoop) End If Next TSLoop End Function
[edit] Input
Option Explicit Public DI As DirectInput8 Public DIDevice As DirectInputDevice8 Public MousePos As POINTAPI Public MousePosAdd As POINTAPI Public MouseEvent As Long Public MouseLeftDown As Byte Public MouseRightDown As Byte Private Const KeyPress_Shift As Integer = 2 ^ 12 Private Const KeyPress_Control As Integer = 2 ^ 13 Private Const KeyPress_Alt As Integer = 2 ^ 14 Private Type KeyDefinitions MiniMap As Integer PickUpObj As Integer QuickBar(1 To 12) As Integer Attack As Integer ChatBufferUp As Integer ChatBufferDown As Integer InventoryWindow As Integer QuickBarWindow As Integer ChatWindow As Integer StatWindow As Integer MenuWindow As Integer ZoomIn As Integer ZoomOut As Integer MoveNorth As Integer MoveEast As Integer MoveSouth As Integer MoveWest As Integer ResetGUI As Integer QuickTarget As Integer QuickReply As Integer End Type Private KeyDefinitions As KeyDefinitions Private IgnoreNextChatKey As Boolean 'Used to ignore the next keystroke going into the chat buffer (for pressing the quick-reply button) Private Function Input_Keys_IsPressed(ByVal DefinitionValue As Integer, ByVal KeyCode As Integer) As Boolean '***************************************************************** 'Checks if the definition requirements are met - used to check if a defineable 'key or series of keys (such as Shift + A) have been pressed 'More info: http://www.vbgore.com/GameClient.Input.Input_Keys_IsPressed '***************************************************************** Dim CheckForInput As Boolean CheckForInput = True 'Check for shift, alt and control requirements If DefinitionValue And KeyPress_Shift Then If GetAsyncKeyState(16) = 0 Then Exit Function End If If DefinitionValue And KeyPress_Control Then If GetAsyncKeyState(17) = 0 Then Exit Function CheckForInput = False 'No need to check for input if control is pressed End If If DefinitionValue And KeyPress_Alt Then If GetAsyncKeyState(18) = 0 Then Exit Function CheckForInput = False 'No need to check for input if alt is pressed End If 'Remove the shift, alt and control bits, then check for the keycode requirements If (DefinitionValue And 2047) <> KeyCode Then Exit Function 'Check for input boxes being active so we don't run commands when typing If CheckForInput Then 'Typing in the chat buffer If EnterText Then Exit Function 'Writing a message in the mail window If LastClickedWindow = WriteMessageWindow Then If ShowGameWindow(WriteMessageWindow) <> 0 Then Exit Function End If 'Numeric only If Input_Keys_IsNumeric(KeyCode) Then 'Entering a value in the amount window If LastClickedWindow = AmountWindow Then If ShowGameWindow(AmountWindow) <> 0 Then Exit Function End If 'Entering a number on the NPC chat window If LastClickedWindow = NPCChatWindow Then If ShowGameWindow(NPCChatWindow) <> 0 Then Exit Function End If End If End If 'Every test has been passed Input_Keys_IsPressed = True End Function Public Sub Input_Keys_LoadDefinitions() '***************************************************************** 'Load the key definitions for defineable keys made by GameConfig.exe 'More info: http://www.vbgore.com/GameClient.Input.Input_Keys_LoadDefinitions '***************************************************************** Dim i As Long KeyDefinitions.Attack = Val(Var_Get(DataPath & "Game.ini", "INPUT", "Attack")) KeyDefinitions.ChatBufferDown = Val(Var_Get(DataPath & "Game.ini", "INPUT", "ChatBufferDown")) KeyDefinitions.ChatBufferUp = Val(Var_Get(DataPath & "Game.ini", "INPUT", "ChatBufferUp")) KeyDefinitions.ChatWindow = Val(Var_Get(DataPath & "Game.ini", "INPUT", "ChatWindow")) KeyDefinitions.InventoryWindow = Val(Var_Get(DataPath & "Game.ini", "INPUT", "InventoryWindow")) KeyDefinitions.MenuWindow = Val(Var_Get(DataPath & "Game.ini", "INPUT", "MenuWindow")) KeyDefinitions.MiniMap = Val(Var_Get(DataPath & "Game.ini", "INPUT", "MiniMap")) KeyDefinitions.MoveEast = Val(Var_Get(DataPath & "Game.ini", "INPUT", "MoveEast")) KeyDefinitions.MoveNorth = Val(Var_Get(DataPath & "Game.ini", "INPUT", "MoveNorth")) KeyDefinitions.MoveSouth = Val(Var_Get(DataPath & "Game.ini", "INPUT", "MoveSouth")) KeyDefinitions.MoveWest = Val(Var_Get(DataPath & "Game.ini", "INPUT", "MoveWest")) KeyDefinitions.PickUpObj = Val(Var_Get(DataPath & "Game.ini", "INPUT", "PickUpObj")) KeyDefinitions.QuickBarWindow = Val(Var_Get(DataPath & "Game.ini", "INPUT", "QuickBarWindow")) KeyDefinitions.StatWindow = Val(Var_Get(DataPath & "Game.ini", "INPUT", "StatWindow")) KeyDefinitions.ZoomIn = Val(Var_Get(DataPath & "Game.ini", "INPUT", "ZoomIn")) KeyDefinitions.ZoomOut = Val(Var_Get(DataPath & "Game.ini", "INPUT", "ZoomOut")) KeyDefinitions.ResetGUI = Val(Var_Get(DataPath & "Game.ini", "INPUT", "ResetGUI")) KeyDefinitions.QuickTarget = Val(Var_Get(DataPath & "Game.ini", "INPUT", "QuickTarget")) KeyDefinitions.QuickReply = Val(Var_Get(DataPath & "Game.ini", "INPUT", "QuickReply")) For i = 1 To 12 KeyDefinitions.QuickBar(i) = Val(Var_Get(DataPath & "Game.ini", "INPUT", "QuickBar" & i)) Next i End Sub Public Sub Input_Keys_ClearQueue() '***************************************************************** 'Clears the GetAsyncKeyState queue to prevent key presses from a long time ' ago falling into "have been pressed" 'More info: http://www.vbgore.com/GameClient.Input.Input_Keys_ClearQueue '***************************************************************** Dim i As Long For i = 1 To 145 GetAsyncKeyState i Next i End Sub Private Function Input_GetCommand(ByVal CommandString As String) As Boolean '***************************************************************** 'Checks if "CommandString" is the command entered in the buffer 'Partial matches return true, too, such as for example: 'Entered: /quit CommandString: /qui 'More info: http://www.vbgore.com/GameClient.Input.Input_GetCommand '***************************************************************** 'Check for the command passed If UCase$(Left$(EnterTextBuffer, Len(CommandString))) = UCase$(CommandString) Then Input_GetCommand = True Else Input_GetCommand = False End Function Private Function Input_GetBufferArgs() As String '***************************************************************** 'Returns the arguments for a command entered into the chat buffer ' (basically cuts off the command and the space after it) 'More info: http://www.vbgore.com/GameClient.Input.Input_GetBufferArgs '***************************************************************** Dim s() As String 'Split between the first space only s = Split(EnterTextBuffer, " ", 2) 'Return the parameters if they exist If UBound(s) > 0 Then Input_GetBufferArgs = Trim$(s(1)) End Function Public Sub Input_Init() '***************************************************************** 'Init the input devices (keyboard and mouse) 'More info: http://www.vbgore.com/GameClient.Input.Input_Init '***************************************************************** Dim diProp As DIPROPLONG 'Create the device Set DI = DX.DirectInputCreate Set DIDevice = DI.CreateDevice("guid_SysMouse") Call DIDevice.SetCommonDataFormat(DIFORMAT_MOUSE) 'If in windowed mode, free the mouse from the screen If Windowed Then Call DIDevice.SetCooperativeLevel(frmMain.hwnd, DISCL_BACKGROUND Or DISCL_NONEXCLUSIVE) Else Call DIDevice.SetCooperativeLevel(frmMain.hwnd, DISCL_FOREGROUND Or DISCL_EXCLUSIVE) End If diProp.lHow = DIPH_DEVICE diProp.lObj = 0 diProp.lData = 50 Call DIDevice.SetProperty("DIPROP_BUFFERSIZE", diProp) MouseEvent = DX.CreateEvent(frmMain) DIDevice.SetEventNotification MouseEvent End Sub Sub Input_Keys_Press(ByVal KeyAscii As Integer) '***************************************************************** 'Handles input entering to windows (mostly just alphanumeric) 'More info: http://www.vbgore.com/GameClient.Input.Input_Keys_Press '***************************************************************** Dim StartGold As Long Dim b As Boolean '************************* '***** Amount window ***** '************************* If LastClickedWindow = AmountWindow Then 'Backspace If KeyAscii = 8 Then If Len(AmountWindowValue) > 0 Then AmountWindowValue = Left$(AmountWindowValue, Len(AmountWindowValue) - 1) End If End If 'Number If IsNumeric(Chr$(KeyAscii)) Then AmountWindowValue = AmountWindowValue & Chr$(KeyAscii) If Val(AmountWindowValue) > MAXINT Then AmountWindowValue = Str(MAXINT) End If '************************* '***** Trade window ****** '************************* ElseIf LastClickedWindow = TradeWindow Then StartGold = TradeTable.Gold1 'Backspace If KeyAscii = 8 Then If Len(Str$(TradeTable.Gold1)) > 0 Then If Len(Str$(TradeTable.Gold1)) - 1 <= 1 Then TradeTable.Gold1 = 0 Else TradeTable.Gold1 = Left$(Str$(TradeTable.Gold1), Len(Str$(TradeTable.Gold1)) - 1) End If End If End If 'Number If IsNumeric(Chr$(KeyAscii)) Then If Len(Str$(TradeTable.Gold1) & Chr$(KeyAscii)) < Len(Str$(MAXLONG)) Then TradeTable.Gold1 = Val(Str$(TradeTable.Gold1) & Chr$(KeyAscii)) If TradeTable.Gold1 > MAXLONG Then TradeTable.Gold1 = MAXLONG Else TradeTable.Gold1 = MAXLONG End If If TradeTable.Gold1 > BaseStats(SID.Gold) Then TradeTable.Gold1 = BaseStats(SID.Gold) End If 'Check if the gold has changed, if so update it on the server If TradeTable.Gold1 <> StartGold Then sndBuf.Put_Byte DataCode.User_Trade_UpdateTrade sndBuf.Put_Byte 0 sndBuf.Put_Long TradeTable.Gold1 End If '***************************** '***** Write mail window ***** '***************************** ElseIf LastClickedWindow = WriteMessageWindow Then If WMSelCon Then Select Case WMSelCon Case wmFrom If KeyAscii = 8 Then If Len(WriteMailData.RecieverName) > 0 Then WriteMailData.RecieverName = Left$(WriteMailData.RecieverName, Len(WriteMailData.RecieverName) - 1) End If Else If Len(WriteMailData.RecieverName) < 10 Then If Game_ValidCharacter(KeyAscii) Then WriteMailData.RecieverName = WriteMailData.RecieverName & Chr$(KeyAscii) End If End If Case wmSubject If KeyAscii = 8 Then If Len(WriteMailData.Subject) > 0 Then WriteMailData.Subject = Left$(WriteMailData.Subject, Len(WriteMailData.Subject) - 1) End If Else If Len(WriteMailData.Subject) < 30 Then If Game_ValidCharacter(KeyAscii) Then WriteMailData.Subject = WriteMailData.Subject & Chr$(KeyAscii) End If End If Case wmMessage If KeyAscii = 8 Then If Len(WriteMailData.Message) > 0 Then WriteMailData.Message = Left$(WriteMailData.Message, Len(WriteMailData.Message) - 1) End If Else If Len(WriteMailData.Message) < 500 Then If Game_ValidCharacter(KeyAscii) Then WriteMailData.Message = WriteMailData.Message & Chr$(KeyAscii) End If End If End Select End If '***************************** '***** Text input buffer ***** '***************************** Else If EnterText Then 'Check if to ignore this keystroke If IgnoreNextChatKey Then IgnoreNextChatKey = False Else 'Backspace If KeyAscii = 8 Then If Len(EnterTextBuffer) > 0 Then EnterTextBuffer = Left$(EnterTextBuffer, Len(EnterTextBuffer) - 1) b = True End If 'Add to text buffer If Game_ValidCharacter(KeyAscii) Then If Len(EnterTextBuffer) < 85 Then If Game_ValidCharacter(KeyAscii) Then EnterTextBuffer = EnterTextBuffer & Chr$(KeyAscii) b = True End If End If End If 'Update size If b Then EnterTextBufferWidth = Engine_GetTextWidth(Font_Default, EnterTextBuffer) UpdateShownTextBuffer LastClickedWindow = 0 End If End If End If End If End Sub Private Sub Input_Keys_Down_Return() '***************************************************************** 'Return was pressed down 'More info: http://www.vbgore.com/GameClient.Input.Input_Keys_Down_Return '***************************************************************** Dim j As Long Dim i As Long '************************* '***** Amount window ***** '************************* If LastClickedWindow = AmountWindow Then If AmountWindowItemIndex Then If AmountWindowValue <> vbNullString Then If IsNumeric(AmountWindowValue) Then 'Drop into mail If AmountWindowUsage = AW_InvToMail Then 'Check for duplicate entries For j = 1 To MaxMailObjs If WriteMailData.ObjIndex(j) = AmountWindowItemIndex Then ShowGameWindow(AmountWindow) = 0 AmountWindowUsage = 0 If LastClickedWindow = AmountWindow Then LastClickedWindow = 0 Exit Sub End If Next j 'Find the next free slot j = 0 Do j = j + 1 If j > MaxMailObjs Then ShowGameWindow(AmountWindow) = 0 AmountWindowUsage = 0 If LastClickedWindow = AmountWindow Then LastClickedWindow = 0 Exit Sub End If Loop While WriteMailData.ObjIndex(j) > 0 WriteMailData.ObjIndex(j) = AmountWindowItemIndex WriteMailData.ObjAmount(j) = CInt(AmountWindowValue) 'Buy from NPC ElseIf AmountWindowUsage = AW_ShopToInv Then sndBuf.Allocate 4 sndBuf.Put_Byte DataCode.User_Trade_BuyFromNPC sndBuf.Put_Byte AmountWindowItemIndex sndBuf.Put_Integer CInt(AmountWindowValue) 'Sell to NPC ElseIf AmountWindowUsage = AW_InvToShop Then sndBuf.Allocate 4 sndBuf.Put_Byte DataCode.User_Trade_SellToNPC sndBuf.Put_Byte AmountWindowItemIndex sndBuf.Put_Integer CInt(AmountWindowValue) 'Take from bank ElseIf AmountWindowUsage = AW_BankToInv Then sndBuf.Allocate 4 sndBuf.Put_Byte DataCode.User_Bank_TakeItem sndBuf.Put_Byte AmountWindowItemIndex sndBuf.Put_Integer CInt(AmountWindowValue) 'Put in bank ElseIf AmountWindowUsage = AW_InvToBank Then sndBuf.Allocate 4 sndBuf.Put_Byte DataCode.User_Bank_PutItem sndBuf.Put_Byte AmountWindowItemIndex sndBuf.Put_Integer CInt(AmountWindowValue) 'Put in trade ElseIf AmountWindowUsage = AW_InvToTrade Then sndBuf.Put_Byte DataCode.User_Trade_UpdateTrade sndBuf.Put_Byte AmountWindowItemIndex sndBuf.Put_Long CInt(AmountWindowValue) 'Drop on ground Else sndBuf.Allocate 4 sndBuf.Put_Byte DataCode.User_Drop sndBuf.Put_Byte AmountWindowItemIndex sndBuf.Put_Integer CInt(AmountWindowValue) End If Else AmountWindowValue = vbNullString End If ShowGameWindow(AmountWindow) = 0 AmountWindowUsage = 0 If LastClickedWindow = AmountWindow Then LastClickedWindow = 0 End If End If '***************************** '***** Write mail window ***** '***************************** ElseIf LastClickedWindow = WriteMessageWindow Then 'Send message If LastMailSendTime + 4000 < timeGetTime Then 'DelayTimeMail (+1000ms for packet delay) If Len(WriteMailData.Subject) > 0 Then If Len(WriteMailData.Message) > 0 Then If Len(WriteMailData.RecieverName) > 0 Then For i = 1 To MaxMailObjs If WriteMailData.ObjIndex(i) = 0 Then i = i - 1 Exit For End If Next i sndBuf.Allocate 6 + Len(WriteMailData.RecieverName) + Len(WriteMailData.Subject) + Len(WriteMailData.Message) sndBuf.Put_Byte DataCode.Server_MailCompose sndBuf.Put_String WriteMailData.RecieverName sndBuf.Put_String WriteMailData.Subject sndBuf.Put_StringEX WriteMailData.Message sndBuf.Put_Byte i 'Number of objects If i > 0 Then For j = 1 To i sndBuf.Allocate 3 sndBuf.Put_Byte WriteMailData.ObjIndex(j) sndBuf.Put_Integer WriteMailData.ObjAmount(j) Next j End If WriteMailData.Message = vbNullString WriteMailData.RecieverName = vbNullString WriteMailData.Subject = vbNullString ShowGameWindow(WriteMessageWindow) = 0 If LastClickedWindow = WriteMessageWindow Then LastClickedWindow = 0 LastMailSendTime = timeGetTime End If End If End If End If End If '*********************** '***** Chat screen ***** '*********************** If LastClickedWindow <> WriteMessageWindow Then If LastClickedWindow <> ViewMessageWindow Then If LastClickedWindow <> AmountWindow Then If EnterText = True Then If EnterTextBuffer <> vbNullString Then Input_HandleCommands EnterText = False Else EnterText = True End If End If End If End If End Sub Private Function Input_Keys_IsNumeric(ByVal KeyCode As Integer) As Boolean '***************************************************************** 'Check if a numeric key (0 to 9) was pressed 'More info: http://www.vbgore.com/GameClient.Input.Input_Keys_IsNumeric '***************************************************************** '0 = 48 '9 = 57 If KeyCode > 47 Then If KeyCode < 58 Then Input_Keys_IsNumeric = True End If End If End Function Private Function Input_Keys_IsAlpha(ByVal KeyCode As Integer) As Boolean '***************************************************************** 'Check if an alphabet key (A to Z) was pressed 'More info: http://www.vbgore.com/GameClient.Input.Input_Keys_IsAlpha '***************************************************************** 'a = 65 'z = 90 If KeyCode > 64 Then If KeyCode < 91 Then Input_Keys_IsAlpha = True End If End If End Function Private Function Input_Keys_IsAlphaNumeric(ByVal KeyCode As Integer) As Boolean '***************************************************************** 'Check if an alphanumeric key (A to Z, 0 to 9) was pressed 'More info: http://www.vbgore.com/GameClient.Input.Input_Keys_IsAlphaNumeric '***************************************************************** Input_Keys_IsAlphaNumeric = (Input_Keys_IsNumeric(KeyCode) And Input_Keys_IsAlpha(KeyCode)) End Function Sub Input_Keys_Down(ByVal KeyCode As Integer) '***************************************************************** 'Checks keys and respond 'More info: http://www.vbgore.com/GameClient.Input.Input_Keys_Down '***************************************************************** Dim i As Long 'Return was pressed If KeyCode = vbKeyReturn Then Input_Keys_Down_Return Exit Sub End If 'Escape was pressed If KeyCode = vbKeyEscape Then If LastClickedWindow = 0 Then If ShowGameWindow(MenuWindow) = 0 Then If EnterText Then EnterTextBuffer = vbNullString EnterTextBufferWidth = 10 UpdateShownTextBuffer EnterText = False End If End If Else ShowGameWindow(LastClickedWindow) = 0 LastClickedWindow = 0 Exit Sub End If End If 'Hide/show the mini-map If Input_Keys_IsPressed(KeyDefinitions.MiniMap, KeyCode) Then If ShowMiniMap = 0 Then ShowMiniMap = 1 Else ShowMiniMap = 0 End If 'Get object off ground (alt) If Input_Keys_IsPressed(KeyDefinitions.PickUpObj, KeyCode) Then If Engine_OBJ_AtTile(CharList(UserCharIndex).Pos.X, CharList(UserCharIndex).Pos.Y) Then If LastLootTime < timeGetTime Then LastLootTime = timeGetTime + LootDelay sndBuf.Put_Byte DataCode.User_Get End If End If End If 'Use the quick bar For i = 1 To 12 If Input_Keys_IsPressed(KeyDefinitions.QuickBar(i), KeyCode) Then Engine_UseQuickBar KeyCode - vbKeyF1 + 1 End If Next i 'Attack key If Input_Keys_IsPressed(KeyDefinitions.Attack, KeyCode) Then If UserCharIndex > 0 Then If LastAttackTime < timeGetTime Then LastAttackTime = timeGetTime + AttackDelay 'Check for a valid attacking distance If UserAttackRange > 1 Then If TargetCharIndex > 0 Then If TargetCharIndex <> UserCharIndex Then If Engine_Distance(CharList(UserCharIndex).Pos.X, CharList(UserCharIndex).Pos.Y, CharList(TargetCharIndex).Pos.X, CharList(TargetCharIndex).Pos.Y) <= UserAttackRange Then LastAttackTime = timeGetTime sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_Attack sndBuf.Put_Byte CharList(UserCharIndex).Heading Else Engine_AddToChatTextBuffer Message(91), FontColor_Fight End If End If End If Else If Engine_UserIsFacingChar Then LastAttackTime = timeGetTime sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_Attack sndBuf.Put_Byte CharList(UserCharIndex).Heading End If End If End If End If End If 'Chat buffer scrolling If Input_Keys_IsPressed(KeyDefinitions.ChatBufferUp, KeyCode) Then If ShowGameWindow(ChatWindow) Then ChatBufferChunk = ChatBufferChunk + 0.5 Engine_UpdateChatArray End If End If If Input_Keys_IsPressed(KeyDefinitions.ChatBufferDown, KeyCode) Then If ShowGameWindow(ChatWindow) Then If ChatBufferChunk > 1 Then ChatBufferChunk = ChatBufferChunk - 0.5 Engine_UpdateChatArray End If End If End If 'Hide/show windows If Input_Keys_IsPressed(KeyDefinitions.InventoryWindow, KeyCode) Then If ShowGameWindow(InventoryWindow) Then ShowGameWindow(InventoryWindow) = 0 If LastClickedWindow = InventoryWindow Then LastClickedWindow = 0 Else ShowGameWindow(InventoryWindow) = 1 LastClickedWindow = InventoryWindow End If End If If Input_Keys_IsPressed(KeyDefinitions.QuickBarWindow, KeyCode) Then If ShowGameWindow(QuickBarWindow) Then ShowGameWindow(QuickBarWindow) = 0 If LastClickedWindow = QuickBarWindow Then LastClickedWindow = 0 Else ShowGameWindow(QuickBarWindow) = 1 LastClickedWindow = QuickBarWindow End If End If If Input_Keys_IsPressed(KeyDefinitions.ChatWindow, KeyCode) Then If ShowGameWindow(ChatWindow) Then ShowGameWindow(ChatWindow) = 0 If LastClickedWindow = ChatWindow Then LastClickedWindow = 0 Else ShowGameWindow(ChatWindow) = 1 LastClickedWindow = ChatWindow End If End If If Input_Keys_IsPressed(KeyDefinitions.StatWindow, KeyCode) Then If ShowGameWindow(StatWindow) Then ShowGameWindow(StatWindow) = 0 If LastClickedWindow = StatWindow Then LastClickedWindow = 0 Else ShowGameWindow(StatWindow) = 1 LastClickedWindow = StatWindow End If End If If Input_Keys_IsPressed(KeyDefinitions.MenuWindow, KeyCode) Then If ShowGameWindow(MenuWindow) Then ShowGameWindow(MenuWindow) = 0 If LastClickedWindow = MenuWindow Then LastClickedWindow = 0 Else ShowGameWindow(MenuWindow) = 1 LastClickedWindow = MenuWindow End If End If 'Reset skin positions If Input_Keys_IsPressed(KeyDefinitions.ResetGUI, KeyCode) Then Engine_Init_GUI 0 Game_Config_Save End If 'Delete mail (Delete) If KeyCode = vbKeyDelete Then If LastClickedWindow = MailboxWindow Then If ShowGameWindow(MailboxWindow) Then If SelMessage > 0 Then sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.Server_MailDelete sndBuf.Put_Byte SelMessage End If End If End If End If 'Auto-write a reply to the last person to whisper to us If Input_Keys_IsPressed(KeyDefinitions.QuickReply, KeyCode) Then If LenB(LastWhisperName) <> 0 Then EnterText = True EnterTextBuffer = "/tell " & LastWhisperName & " " EnterTextBufferWidth = Engine_GetTextWidth(Font_Default, EnterTextBuffer) IgnoreNextChatKey = True UpdateShownTextBuffer LastClickedWindow = 0 End If End If 'Target the closest character If Input_Keys_IsPressed(KeyDefinitions.QuickTarget, KeyCode) Then i = Game_ClosestTargetNPC If i > 0 Then sndBuf.Allocate 3 sndBuf.Put_Byte DataCode.User_Target sndBuf.Put_Integer i End If End If 'Send an emoticon - but make sure we're not typing or entering in a mail message If EnterText = False Then If Not LastClickedWindow = WriteMessageWindow Then If Not LastClickedWindow = AmountWindow Then If ShowGameWindow(WriteMessageWindow) = 0 Then If ShowGameWindow(NPCChatWindow) = 0 Then If EmoticonDelay < timeGetTime Then EmoticonDelay = timeGetTime + 2000 'Wait 2000ms (two seconds) between emoticon usages Select Case KeyCode Case vbKey1 sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_Emote sndBuf.Put_Byte EmoID.Dots Case vbKey2 sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_Emote sndBuf.Put_Byte EmoID.Exclimation Case vbKey3 sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_Emote sndBuf.Put_Byte EmoID.Question Case vbKey4 sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_Emote sndBuf.Put_Byte EmoID.Surprised Case vbKey5 sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_Emote sndBuf.Put_Byte EmoID.Heart Case vbKey6 sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_Emote sndBuf.Put_Byte EmoID.Hearts Case vbKey7 sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_Emote sndBuf.Put_Byte EmoID.HeartBroken Case vbKey8 sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_Emote sndBuf.Put_Byte EmoID.Utensils Case vbKey9 sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_Emote sndBuf.Put_Byte EmoID.Meat Case vbKey0 sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_Emote sndBuf.Put_Byte EmoID.ExcliQuestion End Select End If Else If KeyCode >= 49 Then If KeyCode - 48 <= GameWindow.NPCChat.NumAnswers Then i = NPCChat(ActiveAsk.ChatIndex).Ask.Ask(ActiveAsk.AskIndex).Answer(KeyCode - 48).GotoID If i > 0 Then Engine_ShowNPCChatWindow ActiveAsk.AskName, ActiveAsk.ChatIndex, i Else ShowGameWindow(NPCChatWindow) = 0 If LastClickedWindow = NPCChatWindow Then LastClickedWindow = 0 End If End If End If End If End If End If End If End If End Sub Private Sub Input_HandleCommands() '***************************************************************** 'Handles all the chat commands - when aborting, use either GoTo CleanUp ' to ignore the keystroke (buffer is not cleared) or GoTo CleanUp to ' clear the buffer, too (its all just about preference) 'More info: http://www.vbgore.com/GameClient.Input.Input_HandleCommands '***************************************************************** Dim TempS() As String Dim s As String Dim s2 As String Dim i As Long Dim j As Long '***** Check for commands ***** If Input_GetCommand("/BLI") Then sndBuf.Put_Byte DataCode.User_Blink ElseIf Input_GetCommand("/LOOKL") Then sndBuf.Put_Byte DataCode.User_LookLeft ElseIf Input_GetCommand("/LOOKR") Then sndBuf.Put_Byte DataCode.User_LookRight ElseIf Input_GetCommand("/WHO") Then sndBuf.Put_Byte DataCode.Server_Who ElseIf Input_GetCommand("/SH") Then s = Input_GetBufferArgs If s = vbNullString Then GoTo CleanUp sndBuf.Put_Byte DataCode.Comm_Shout sndBuf.Put_String s ElseIf Input_GetCommand("/GINFO") Or Input_GetCommand("/GROUPI") Then sndBuf.Put_Byte DataCode.User_Group_Info ElseIf Input_GetCommand("/TELL") Then s = Input_GetBufferArgs If s = vbNullString Then GoTo CleanUp TempS() = Split(s, " ", 2) If UBound(TempS) < 1 Then GoTo CleanUp If LenB(Trim$(TempS(0))) = 0 Then GoTo CleanUp sndBuf.Put_Byte DataCode.Comm_Whisper sndBuf.Put_String Trim$(TempS(0)) sndBuf.Put_String Trim$(TempS(1)) ElseIf Input_GetCommand("/DEP") Then j = Val(Input_GetBufferArgs) If j <= 0 Then GoTo CleanUp sndBuf.Put_Byte DataCode.User_Bank_Deposit sndBuf.Put_Long j 'We will assume that the deposit was successful Engine_AddToChatTextBuffer Replace$(Message(118), "<amount>", Str(j)), FontColor_Info ElseIf Input_GetCommand("/WITH") Then j = Val(Input_GetBufferArgs) If j <= 0 Then GoTo CleanUp sndBuf.Put_Byte DataCode.User_Bank_Withdraw sndBuf.Put_Long j ElseIf Input_GetCommand("/TRADE") Then s = Input_GetBufferArgs If s = vbNullString Then Engine_AddToChatTextBuffer Message(136), FontColor_Info GoTo CleanUp End If If UCase$(s) = UCase$(CharList(UserCharIndex).Name) Then Engine_AddToChatTextBuffer Message(133), FontColor_Info GoTo CleanUp End If sndBuf.Put_Byte DataCode.User_Trade_Trade sndBuf.Put_String s ElseIf Input_GetCommand("/BALAN") Then sndBuf.Put_Byte DataCode.User_Bank_Balance ElseIf Input_GetCommand("/G ") Then s = Input_GetBufferArgs If s = vbNullString Then GoTo CleanUp sndBuf.Put_Byte DataCode.Comm_GroupTalk sndBuf.Put_String s ElseIf Input_GetCommand("/CREATEG") Or Input_GetCommand("/MAKEG") Or Input_GetCommand("/NEWG") Then sndBuf.Put_Byte DataCode.User_Group_Make ElseIf Input_GetCommand("/INVITE") Then s = Input_GetBufferArgs If s = vbNullString Then GoTo CleanUp sndBuf.Put_Byte DataCode.User_Group_Invite sndBuf.Put_String s ElseIf Input_GetCommand("/LEAVEG") Or Input_GetCommand("/EXITG") Then sndBuf.Put_Byte DataCode.User_Group_Leave ElseIf Input_GetCommand("/JOING") Then sndBuf.Put_Byte DataCode.User_Group_Join ElseIf Input_GetCommand("/ME") Then s = Input_GetBufferArgs If s = vbNullString Then GoTo CleanUp sndBuf.Put_Byte DataCode.Comm_Emote sndBuf.Put_String s ElseIf Input_GetCommand("/EM") Then s = Input_GetBufferArgs If s = vbNullString Then GoTo CleanUp sndBuf.Put_Byte DataCode.Comm_Emote sndBuf.Put_String s ElseIf Input_GetCommand("/LANG") Then s = LCase$(Input_GetBufferArgs) If s = vbNullString Then GoTo CleanUp If Engine_FileExist(MessagePath & s & "*.ini", vbNormal) Then s = Dir$(MessagePath & s & "*.ini", vbNormal) s = Left$(s, Len(s) - 4) s = Engine_Init_Messages(s) Engine_Init_Signs s Var_Write DataPath & "Game.ini", "INIT", "Language", s Engine_AddToChatTextBuffer Replace$(Message(90), "<lang>", s), FontColor_Info Else Engine_AddToChatTextBuffer Message(87), FontColor_Info End If ElseIf Input_GetCommand("/SKIN") Then s = LCase$(Input_GetBufferArgs) If s = vbNullString Then Engine_AddToChatTextBuffer Engine_BuildSkinsList, FontColor_Info GoTo CleanUp End If If Engine_FileExist(DataPath & "Skins\" & s & "*.ini", vbNormal) Then s = Dir$(DataPath & "Skins\" & s & "*.ini", vbNormal) CurrentSkin = Left$(s, Len(s) - 4) Engine_Init_GUI 0 Var_Write DataPath & "Game.ini", "INIT", "CurrentSkin", CurrentSkin Engine_AddToChatTextBuffer Replace$(Message(89), "<skin>", CurrentSkin), FontColor_Info Else Engine_AddToChatTextBuffer Message(88), FontColor_Info End If ElseIf Input_GetCommand("/QUEST") Then If QuestInfoUBound = 0 Then 'No quests in place Engine_AddToChatTextBuffer Message(103), FontColor_Quest Else j = Val(Input_GetBufferArgs) If j < 1 Or j > QuestInfoUBound Then 'No valid number specified, give the list Engine_AddToChatTextBuffer Message(104), FontColor_Quest For i = 1 To QuestInfoUBound Engine_AddToChatTextBuffer " " & i & ". " & QuestInfo(i).Name, FontColor_Quest Next i Else 'Give the info on the specific quest Engine_AddToChatTextBuffer QuestInfo(j).Name & ":", FontColor_Quest Engine_AddToChatTextBuffer QuestInfo(j).Desc, FontColor_Quest End If End If ElseIf Input_GetCommand("/CANCELQUEST") Or Input_GetCommand("/ENDQUEST") Then If QuestInfoUBound = 0 Then GoTo CleanUp j = Val(Input_GetBufferArgs) If j < 1 Or j > QuestInfoUBound Then GoTo CleanUp sndBuf.Put_Byte DataCode.User_CancelQuest sndBuf.Put_Byte CByte(j) ElseIf Input_GetCommand("/THR") Then TempS = Split(EnterTextBuffer) If UBound(TempS) <> 0 Then If IsNumeric(TempS(1)) Then sndBuf.Put_Byte DataCode.GM_Thrall sndBuf.Put_Integer Val(TempS(1)) If UBound(TempS) > 1 Then If IsNumeric(TempS(2)) Then sndBuf.Put_Integer Val(TempS(2)) Else sndBuf.Put_Integer 1 End If sndBuf.Put_Integer 1 End If End If End If ElseIf Input_GetCommand("/DETHR") Then sndBuf.Put_Byte DataCode.GM_DeThrall ElseIf Input_GetCommand("/QUIT") Then IsUnloading = 1 ElseIf Input_GetCommand("/ACCEPT") Then sndBuf.Put_Byte DataCode.User_StartQuest ElseIf Input_GetCommand("/DESC") Then s = Input_GetBufferArgs sndBuf.Put_Byte DataCode.User_Desc sndBuf.Put_String s ElseIf Input_GetCommand("/HELP") Then sndBuf.Put_Byte DataCode.Server_Help ElseIf Input_GetCommand("/APPR") Then s = Input_GetBufferArgs If s = vbNullString Then GoTo CleanUp sndBuf.Put_Byte DataCode.GM_Approach sndBuf.Put_String s ElseIf Input_GetCommand("/SUM") Then s = Input_GetBufferArgs If s = vbNullString Then GoTo CleanUp sndBuf.Put_Byte DataCode.GM_Summon sndBuf.Put_String s ElseIf Input_GetCommand("/SETGM") Then s = Input_GetBufferArgs If s = vbNullString Then GoTo CleanUp TempS = Split(s, " ") If UBound(TempS) > 0 Then If IsNumeric(TempS(1)) Then sndBuf.Allocate 3 + Len(TempS(0)) sndBuf.Put_Byte DataCode.GM_SetGMLevel sndBuf.Put_String TempS(0) sndBuf.Put_Byte CByte(TempS(1)) End If End If ElseIf Input_GetCommand("/CLICKWARP") Then If UseClickWarp = 1 Then UseClickWarp = 0 Else UseClickWarp = 1 Engine_AddToChatTextBuffer Replace$(Message(124), "<value>", UseClickWarp), FontColor_Info ElseIf Input_GetCommand("/BANIP") Then s = Input_GetBufferArgs 'Remove the command If LenB(s) < 4 Then 'Not enough information entered Engine_AddToChatTextBuffer Message(92), FontColor_Info GoTo CleanUp End If TempS = Split(s, " ", 2) 'Split up the IP and reason If UBound(TempS) = 0 Then Engine_AddToChatTextBuffer Message(93), FontColor_Info GoTo CleanUp Else s = TempS(0) s2 = TempS(1) End If TempS = Split(s, ".") If UBound(TempS) <> 3 Then Engine_AddToChatTextBuffer Message(92), FontColor_Info GoTo CleanUp End If For j = 0 To 3 If Val(TempS(j)) < 0 Or Val(TempS(j)) > 255 Then Engine_AddToChatTextBuffer Message(92), FontColor_Info GoTo CleanUp End If Next j sndBuf.Put_Byte DataCode.GM_BanIP sndBuf.Put_String Trim$(s) sndBuf.Put_String Trim$(s2) ElseIf Input_GetCommand("/UNBANIP") Then s = Input_GetBufferArgs 'Remove the command If LenB(s) < 4 Then 'Not enough information entered Engine_AddToChatTextBuffer Message(92), FontColor_Info GoTo CleanUp End If TempS = Split(s, ".") If UBound(TempS) <> 3 Then Engine_AddToChatTextBuffer Message(92), FontColor_Info GoTo CleanUp End If For j = 0 To 3 If TempS(j) <> "*" Then If Val(TempS(j)) < 0 Or Val(TempS(j)) > 255 Then Engine_AddToChatTextBuffer Message(92), FontColor_Info GoTo CleanUp End If End If Next j sndBuf.Put_Byte DataCode.GM_UnBanIP sndBuf.Put_String Trim$(s) ElseIf Input_GetCommand("/KICK") Then s = Input_GetBufferArgs If s = vbNullString Then GoTo CleanUp sndBuf.Put_Byte DataCode.GM_Kick sndBuf.Put_String s ElseIf Input_GetCommand("/SEARCHI") Or Input_GetCommand("/FINDI") Or Input_GetCommand("/FINDO") Or Input_GetCommand("/SEARCHO") Then s = Input_GetBufferArgs If s = vbNullString Then GoTo CleanUp sndBuf.Put_Byte DataCode.GM_FindItem sndBuf.Put_String s ElseIf Input_GetCommand("/GIVESK") Or Input_GetCommand("/GIVESP") Then s = Input_GetBufferArgs If s = vbNullString Then GoTo CleanUp TempS = Split(s, " ") If UBound(TempS) <> 1 Then GoTo CleanUp If Val(TempS(1)) <= 0 Or Val(TempS(1)) > 255 Then Exit Sub sndBuf.Put_Byte DataCode.GM_GiveSkill sndBuf.Put_String TempS(0) sndBuf.Put_Long Val(TempS(1)) ElseIf Input_GetCommand("/SQL") Then s = Input_GetBufferArgs If s = vbNullString Then GoTo CleanUp sndBuf.Put_Byte DataCode.GM_SQL sndBuf.Put_String s ElseIf Input_GetCommand("/KILLMAP") Then sndBuf.Put_Byte DataCode.GM_KillMap ElseIf Input_GetCommand("/KILL") Then If TargetCharIndex = UserCharIndex Or TargetCharIndex = 0 Then Engine_AddToChatTextBuffer "Suicide is not the answer...", FontColor_Info Else sndBuf.Put_Byte DataCode.GM_Kill End If ElseIf Input_GetCommand("/GIVEGO") Then s = Input_GetBufferArgs If Val(s) <= 0 Or Val(s) > MAXLONG Then Engine_AddToChatTextBuffer "Please enter an amount greater than 0.", FontColor_Info GoTo CleanUp End If sndBuf.Put_Byte DataCode.GM_GiveGold sndBuf.Put_Long Val(s) ElseIf Input_GetCommand("/GIVEOBJ") Then s = Input_GetBufferArgs If s = vbNullString Then GoTo CleanUp TempS = Split(s, " ") If UBound(TempS) <> 1 Then Engine_AddToChatTextBuffer "Please use the format: <ObjIndex> <Amount>", FontColor_Info GoTo CleanUp End If If Val(TempS(0)) <= 0 Or Val(TempS(0)) > MAXINT Then Engine_AddToChatTextBuffer "Invalid ObjIndex parameter - enter a value between 1 and " & MAXINT & ".", FontColor_Info GoTo CleanUp End If If Val(TempS(1)) <= 0 Or Val(TempS(1)) > MAXINT Then Engine_AddToChatTextBuffer "Invalid Amount parameter - enter a value between 1 and " & MAXINT & ".", FontColor_Info GoTo CleanUp End If sndBuf.Put_Byte DataCode.GM_GiveObject sndBuf.Put_Integer Val(TempS(0)) sndBuf.Put_Integer Val(TempS(1)) ElseIf Input_GetCommand("/WARP") Then i = Val(Input_GetBufferArgs) If Not Engine_FileExist(MapPath & i & ".map", vbNormal) Then Engine_AddToChatTextBuffer "Please enter a valid map number.", FontColor_Info GoTo CleanUp End If sndBuf.Put_Byte DataCode.GM_WarpToMap sndBuf.Put_Integer i ElseIf Input_GetCommand("/IPINFO") Then s = Input_GetBufferArgs If s = vbNullString Then GoTo CleanUp TempS = Split(s, ".") 'All of this is just a check for a valid IP If UBound(TempS) <> 3 Then 'Check for 3 periods Engine_AddToChatTextBuffer Message(92), FontColor_Info GoTo CleanUp End If For j = 0 To 3 'Check for values between 0 and 255 If Val(TempS(j)) < 0 Or Val(TempS(j)) > 255 Then Engine_AddToChatTextBuffer Message(92), FontColor_Info GoTo CleanUp End If Next j sndBuf.Put_Byte DataCode.GM_IPInfo sndBuf.Put_String s ElseIf Input_GetCommand("/BANLIST") Then sndBuf.Put_Byte DataCode.GM_BanList ElseIf Input_GetCommand("/RAISE") Then TempS() = Split(Input_GetBufferArgs, " ") If UBound(TempS) > 0 Then If IsNumeric(TempS(1)) Then sndBuf.Allocate 6 + Len(TempS(0)) sndBuf.Put_Byte DataCode.GM_Raise sndBuf.Put_String TempS(0) sndBuf.Put_Long CLng(TempS(1)) End If End If Else '*** No commands sent, send as text *** EnterTextBuffer = Trim$(EnterTextBuffer) sndBuf.Allocate 2 + Len(EnterTextBuffer) sndBuf.Put_Byte DataCode.Comm_Talk sndBuf.Put_String EnterTextBuffer 'We just sent a chat message, so check if it had triggers! Engine_NPCChat_CheckForChatTriggers EnterTextBuffer End If CleanUp: 'Cleans up the buffer EnterTextBuffer = vbNullString EnterTextBufferWidth = 10 ShownText = vbNullString End Sub Sub Input_Keys_General() '***************************************************************** 'Checks keys and respond 'More info: http://www.vbgore.com/GameClient.Input.Input_Keys_General '***************************************************************** If GetActiveWindow = 0 Then Exit Sub 'Dont move when Control is pressed If GetAsyncKeyState(vbKeyControl) Then Exit Sub 'Check if certain screens are open that require ASDW keys If ShowGameWindow(WriteMessageWindow) Then If WMSelCon <> 0 Then Exit Sub End If 'Zoom in / out If LastClickedWindow <> TradeWindow Then If LastClickedWindow <> ChatWindow Then If GetAsyncKeyState(KeyDefinitions.ZoomIn) Then 'In ZoomLevel = ZoomLevel + (ElapsedTime * 0.0003) If ZoomLevel > MaxZoomLevel Then ZoomLevel = MaxZoomLevel ElseIf GetAsyncKeyState(KeyDefinitions.ZoomOut) Then 'Out ZoomLevel = ZoomLevel - (ElapsedTime * 0.0003) If ZoomLevel < 0 Then ZoomLevel = 0 End If End If End If 'Don't allow any these keys during movement.. If UserMoving = 0 Then If GetAsyncKeyState(vbKeyTab) Then 'Move Up-Right If GetKeyState(vbKeyUp) < 0 And GetKeyState(vbKeyRight) < 0 Then Engine_ChangeHeading NORTHEAST Exit Sub End If 'Move Up-Left If GetKeyState(vbKeyUp) < 0 And GetKeyState(vbKeyLeft) < 0 Then Engine_ChangeHeading NORTHWEST Exit Sub End If 'Move Down-Right If GetKeyState(vbKeyDown) < 0 And GetKeyState(vbKeyRight) < 0 Then Engine_ChangeHeading SOUTHEAST Exit Sub End If 'Move Down-Left If GetKeyState(vbKeyDown) < 0 And GetKeyState(vbKeyLeft) < 0 Then Engine_ChangeHeading SOUTHWEST Exit Sub End If 'Move Up If GetKeyState(vbKeyUp) < 0 Then Engine_ChangeHeading NORTH Exit Sub End If 'Move Right If GetKeyState(vbKeyRight) < 0 Then Engine_ChangeHeading EAST Exit Sub End If 'Move down If GetKeyState(vbKeyDown) < 0 Then Engine_ChangeHeading SOUTH Exit Sub End If 'Move left If GetKeyState(vbKeyLeft) < 0 Then Engine_ChangeHeading WEST Exit Sub End If If EnterText = False Then If GetKeyState(KeyDefinitions.MoveNorth) < 0 And GetKeyState(KeyDefinitions.MoveEast) < 0 Then Engine_ChangeHeading NORTHEAST Exit Sub End If If GetKeyState(KeyDefinitions.MoveNorth) < 0 And GetKeyState(KeyDefinitions.MoveWest) < 0 Then Engine_ChangeHeading NORTHWEST Exit Sub End If If GetKeyState(KeyDefinitions.MoveSouth) < 0 And GetKeyState(KeyDefinitions.MoveEast) < 0 Then Engine_ChangeHeading SOUTHEAST Exit Sub End If If GetKeyState(KeyDefinitions.MoveSouth) < 0 And GetKeyState(KeyDefinitions.MoveWest) < 0 Then Engine_ChangeHeading SOUTHWEST Exit Sub End If If GetKeyState(KeyDefinitions.MoveNorth) < 0 Then Engine_ChangeHeading NORTH Exit Sub End If If GetKeyState(KeyDefinitions.MoveEast) < 0 Then Engine_ChangeHeading EAST Exit Sub End If If GetKeyState(KeyDefinitions.MoveSouth) < 0 Then Engine_ChangeHeading SOUTH Exit Sub End If If GetKeyState(KeyDefinitions.MoveWest) < 0 Then Engine_ChangeHeading WEST Exit Sub End If End If Else 'Move Up-Right If GetKeyState(vbKeyUp) < 0 And GetKeyState(vbKeyRight) < 0 Then Engine_MoveUser NORTHEAST Exit Sub End If 'Move Up-Left If GetKeyState(vbKeyUp) < 0 And GetKeyState(vbKeyLeft) < 0 Then Engine_MoveUser NORTHWEST Exit Sub End If 'Move Down-Right If GetKeyState(vbKeyDown) < 0 And GetKeyState(vbKeyRight) < 0 Then Engine_MoveUser SOUTHEAST Exit Sub End If 'Move Down-Left If GetKeyState(vbKeyDown) < 0 And GetKeyState(vbKeyLeft) < 0 Then Engine_MoveUser SOUTHWEST Exit Sub End If 'Move Up If GetKeyState(vbKeyUp) < 0 Then Engine_MoveUser NORTH Exit Sub End If 'Move Right If GetKeyState(vbKeyRight) < 0 Then Engine_MoveUser EAST Exit Sub End If 'Move down If GetKeyState(vbKeyDown) < 0 Then Engine_MoveUser SOUTH Exit Sub End If 'Move left If GetKeyState(vbKeyLeft) < 0 Then Engine_MoveUser WEST Exit Sub End If If EnterText = False Then If GetKeyState(KeyDefinitions.MoveNorth) < 0 And GetKeyState(KeyDefinitions.MoveEast) < 0 Then Engine_MoveUser NORTHEAST Exit Sub End If If GetKeyState(KeyDefinitions.MoveNorth) < 0 And GetKeyState(KeyDefinitions.MoveWest) < 0 Then Engine_MoveUser NORTHWEST Exit Sub End If If GetKeyState(KeyDefinitions.MoveSouth) < 0 And GetKeyState(KeyDefinitions.MoveEast) < 0 Then Engine_MoveUser SOUTHEAST Exit Sub End If If GetKeyState(KeyDefinitions.MoveSouth) < 0 And GetKeyState(KeyDefinitions.MoveWest) < 0 Then Engine_MoveUser SOUTHWEST Exit Sub End If If GetKeyState(KeyDefinitions.MoveNorth) < 0 Then Engine_MoveUser NORTH Exit Sub End If If GetKeyState(KeyDefinitions.MoveEast) < 0 Then Engine_MoveUser EAST Exit Sub End If If GetKeyState(KeyDefinitions.MoveSouth) < 0 Then Engine_MoveUser SOUTH Exit Sub End If If GetKeyState(KeyDefinitions.MoveWest) < 0 Then Engine_MoveUser WEST Exit Sub End If End If End If End If End Sub Sub Input_Mouse_LeftClick() '***************************************************************** 'Left click mouse 'More info: http://www.vbgore.com/GameClient.Input.Input_Mouse_LeftClick '***************************************************************** Dim tX As Integer Dim tY As Integer Dim i As Long 'Make sure engine is running If Not EngineRun Then Exit Sub '***Check for skill list click*** 'Skill lists, because it is not actually a window, must be handled differently If QuickBarSetSlot <= 0 Then DrawSkillList = 0 If DrawSkillList Then If SkillListSize Then For tX = 1 To SkillListSize If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, SkillList(tX).X, SkillList(tX).Y, 32, 32) Then QuickBarID(QuickBarSetSlot).ID = SkillList(tX).SkillID QuickBarID(QuickBarSetSlot).Type = QuickBarType_Skill DrawSkillList = 0 QuickBarSetSlot = 0 Exit Sub End If Next tX End If End If '***Check for a window click*** WMSelCon = 0 'Start with the last clicked window, then move in order of importance If LastClickedWindow > 0 Then If Input_Mouse_LeftClick_Window(LastClickedWindow) = 1 Then Exit Sub End If For i = 1 To NumGameWindows If LastClickedWindow <> i Then If Input_Mouse_LeftClick_Window(i) = 1 Then Exit Sub End If Next i 'No windows clicked, so a tile click will take place 'Get the tile positions Engine_ConvertCPtoTP MousePos.X, MousePos.Y, tX, tY 'Send left click sndBuf.Allocate 3 sndBuf.Put_Byte DataCode.User_LeftClick sndBuf.Put_Byte CByte(tX) sndBuf.Put_Byte CByte(tY) 'If there was a click on the game screen and the ' skill list is up, but no window clicked, set to 0 If DrawSkillList Then If QuickBarSetSlot Then QuickBarID(QuickBarSetSlot).ID = 0 QuickBarID(QuickBarSetSlot).Type = 0 DrawSkillList = 0 QuickBarSetSlot = 0 End If End If 'Last clicked window was nothing, so set to nothing :) LastClickedWindow = 0 End Sub Function Input_Mouse_LeftClick_Window(ByVal WindowIndex As Byte) As Byte '***************************************************************** 'Left click a game window 'More info: http://www.vbgore.com/GameClient.Input.Input_Mouse_LeftClick_Window '***************************************************************** Dim i As Byte Dim j As Byte Select Case WindowIndex Case TradeWindow If ShowGameWindow(TradeWindow) Then With GameWindow.Trade If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_LeftClick_Window = 1 LastClickedWindow = TradeWindow 'Item window For i = 1 To 9 If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X + .Trade1(i).X, .Screen.Y + .Trade1(i).Y, 32, 32) Then sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_Trade_RemoveItem sndBuf.Put_Byte i Exit Function End If Next i 'Accept button If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X + .Accept.X, .Screen.Y + .Accept.Y, .Accept.Width, .Accept.Height) Then sndBuf.Put_Byte DataCode.User_Trade_Accept Exit Function End If 'Finish button If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X + .Trade.X, .Screen.Y + .Trade.Y, .Trade.Width, .Trade.Height) Then sndBuf.Put_Byte DataCode.User_Trade_Finish Exit Function End If 'Cancel button If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X + .Cancel.X, .Screen.Y + .Cancel.Y, .Cancel.Width, .Cancel.Height) Then sndBuf.Put_Byte DataCode.User_Trade_Cancel Exit Function End If SelGameWindow = TradeWindow End If End With End If Case NPCChatWindow If ShowGameWindow(NPCChatWindow) Then With GameWindow.NPCChat If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_LeftClick_Window = 1 LastClickedWindow = NPCChatWindow For i = 1 To .NumAnswers If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X + .Answer(i).X, .Screen.Y + .Answer(i).Y, .Answer(i).Width, .Answer(i).Height) Then j = NPCChat(ActiveAsk.ChatIndex).Ask.Ask(ActiveAsk.AskIndex).Answer(i).GotoID If j > 0 Then Engine_ShowNPCChatWindow ActiveAsk.AskName, ActiveAsk.ChatIndex, j Else ShowGameWindow(NPCChatWindow) = 0 If LastClickedWindow = NPCChatWindow Then LastClickedWindow = 0 End If Exit For End If Next i SelGameWindow = NPCChatWindow End If End With End If Case MenuWindow If ShowGameWindow(MenuWindow) Then With GameWindow.Menu If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_LeftClick_Window = 1 LastClickedWindow = MenuWindow 'Quit button If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X + .QuitLbl.X, .Screen.Y + .QuitLbl.Y, .QuitLbl.Width, .QuitLbl.Height) Then IsUnloading = 1 Exit Function End If SelGameWindow = MenuWindow End If End With End If Case StatWindow If ShowGameWindow(StatWindow) Then With GameWindow.StatWindow 'Check if the screen was clicked If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_LeftClick_Window = 1 LastClickedWindow = StatWindow 'Raise str If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X + .AddStr.X, .Screen.Y + .AddStr.Y, .AddStr.Width, .AddStr.Height) Then sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_BaseStat sndBuf.Put_Byte SID.Str End If 'Raise agi If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X + .AddAgi.X, .Screen.Y + .AddAgi.Y, .AddAgi.Width, .AddAgi.Height) Then sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_BaseStat sndBuf.Put_Byte SID.Agi End If 'Raise mag If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X + .AddMag.X, .Screen.Y + .AddMag.Y, .AddMag.Width, .AddMag.Height) Then sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_BaseStat sndBuf.Put_Byte SID.Mag End If SelGameWindow = StatWindow End If End With End If Case ChatWindow If ShowGameWindow(ChatWindow) Then With GameWindow.ChatWindow 'Check if the screen was clicked If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X + .Text.X, .Screen.Y + .Text.Y, .Text.Width, .Text.Height) Then EnterText = True End If Input_Mouse_LeftClick_Window = 1 LastClickedWindow = ChatWindow SelGameWindow = ChatWindow Exit Function End If End With End If Case QuickBarWindow If ShowGameWindow(QuickBarWindow) Then With GameWindow.QuickBar 'Check if the screen was clicked If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_LeftClick_Window = 1 LastClickedWindow = QuickBarWindow 'Cancel changes to quick bar items DrawSkillList = 0 QuickBarSetSlot = 0 'Check if an item was clicked For i = 1 To 12 If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Image(i).X + .Screen.X, .Image(i).Y + .Screen.Y, .Image(i).Width, .Image(i).Height) Then If GetAsyncKeyState(vbKeyShift) Then QuickBarSetSlot = i DrawSkillList = 1 Else Engine_UseQuickBar i End If Exit Function End If Next i 'Item was not clicked SelGameWindow = QuickBarWindow Exit Function End If End With End If Case InventoryWindow If ShowGameWindow(InventoryWindow) Then With GameWindow.Inventory 'Check if the screen was clicked If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_LeftClick_Window = 1 LastClickedWindow = InventoryWindow 'Check if an item was clicked For i = 1 To MAX_INVENTORY_SLOTS If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Image(i).X + .Screen.X, .Image(i).Y + .Screen.Y, .Image(i).Width, .Image(i).Height) Then If GetAsyncKeyState(vbKeyShift) Then If Game_ClickItem(i) Then If UserInventory(i).Amount = 1 Then 'Drop item into mailbox If ShowGameWindow(WriteMessageWindow) Then 'Check for duplicate entries For j = 1 To MaxMailObjs If WriteMailData.ObjIndex(j) = i Then Exit Function Next j 'Place item in next free slot (if any) j = 0 Do j = j + 1 If j > MaxMailObjs Then Exit Function Loop While WriteMailData.ObjIndex(j) > 0 WriteMailData.ObjIndex(j) = i WriteMailData.ObjAmount(j) = 1 'Sell item to shopkeeper ElseIf ShowGameWindow(ShopWindow) Then sndBuf.Allocate 4 sndBuf.Put_Byte DataCode.User_Trade_SellToNPC sndBuf.Put_Byte i sndBuf.Put_Integer 1 'Put item in the bank ElseIf ShowGameWindow(BankWindow) Then sndBuf.Allocate 4 sndBuf.Put_Byte DataCode.User_Bank_PutItem sndBuf.Put_Byte i sndBuf.Put_Integer 1 'Drop item on ground Else sndBuf.Allocate 4 sndBuf.Put_Byte DataCode.User_Drop sndBuf.Put_Byte i sndBuf.Put_Integer 1 End If Else 'Drop item into mailbox If ShowGameWindow(WriteMessageWindow) Then 'Check for duplicate entries For j = 1 To MaxMailObjs If WriteMailData.ObjIndex(j) = i Then Exit Function Next j 'Check for free slots j = 0 Do j = j + 1 If j > MaxMailObjs Then Exit Function Loop While WriteMailData.ObjIndex(j) > 0 'Open the amount window ShowGameWindow(AmountWindow) = 1 LastClickedWindow = AmountWindow AmountWindowValue = vbNullString AmountWindowItemIndex = i AmountWindowUsage = AW_InvToMail 'Sell item to shopkeeper ElseIf ShowGameWindow(ShopWindow) Then ShowGameWindow(AmountWindow) = 1 LastClickedWindow = AmountWindow AmountWindowValue = vbNullString AmountWindowItemIndex = i AmountWindowUsage = AW_InvToShop 'Put item in the bank ElseIf ShowGameWindow(BankWindow) Then ShowGameWindow(AmountWindow) = 1 LastClickedWindow = AmountWindow AmountWindowValue = vbNullString AmountWindowItemIndex = i AmountWindowUsage = AW_InvToBank 'Drop item on ground Else ShowGameWindow(AmountWindow) = 1 LastClickedWindow = AmountWindow AmountWindowValue = vbNullString AmountWindowItemIndex = i AmountWindowUsage = AW_Drop End If End If End If Else If Game_ClickItem(i) Then sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_Use sndBuf.Put_Byte i End If End If Exit Function End If Next i 'Item was not clicked SelGameWindow = InventoryWindow Exit Function End If End With End If Case ShopWindow If ShowGameWindow(ShopWindow) Then With GameWindow.Shop 'Check if the screen was clicked If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_LeftClick_Window = 1 LastClickedWindow = ShopWindow 'Check if an item was clicked For i = 1 To MAX_INVENTORY_SLOTS If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Image(i).X + .Screen.X, .Image(i).Y + .Screen.Y, .Image(i).Width, .Image(i).Height) Then If Game_ClickItem(i, 2) > 0 Then sndBuf.Allocate 4 sndBuf.Put_Byte DataCode.User_Trade_BuyFromNPC sndBuf.Put_Byte i sndBuf.Put_Integer 1 End If Exit Function End If Next i 'Item was not clicked SelGameWindow = ShopWindow Exit Function End If End With End If Case BankWindow If ShowGameWindow(BankWindow) Then With GameWindow.Bank 'Check if the screen was clicked If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_LeftClick_Window = 1 LastClickedWindow = BankWindow 'Check if an item was clicked For i = 1 To MAX_INVENTORY_SLOTS If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Image(i).X + .Screen.X, .Image(i).Y + .Screen.Y, .Image(i).Width, .Image(i).Height) Then If Game_ClickItem(i, 3) > 0 Then sndBuf.Allocate 4 sndBuf.Put_Byte DataCode.User_Bank_TakeItem sndBuf.Put_Byte i sndBuf.Put_Integer 1 End If Exit Function End If Next i 'Item was not clicked SelGameWindow = BankWindow Exit Function End If End With End If Case MailboxWindow If ShowGameWindow(MailboxWindow) Then With GameWindow.Mailbox 'Check if the screen was clicked If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_LeftClick_Window = 1 LastClickedWindow = MailboxWindow 'Check if Write was clicked If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X + .WriteLbl.X, .Screen.Y + .WriteLbl.Y, .WriteLbl.Width, .WriteLbl.Height) Then For i = 1 To MaxMailObjs WriteMailData.ObjIndex(i) = 0 WriteMailData.ObjAmount(i) = 0 Next i WriteMailData.Message = vbNullString WriteMailData.Subject = vbNullString WriteMailData.RecieverName = vbNullString ShowGameWindow(MailboxWindow) = 0 ShowGameWindow(WriteMessageWindow) = 1 LastClickedWindow = WriteMessageWindow Exit Function End If If SelMessage > 0 Then 'Check if Delete was clicked If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X + .DeleteLbl.X, .Screen.Y + .DeleteLbl.Y, .DeleteLbl.Width, .DeleteLbl.Height) Then sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.Server_MailDelete sndBuf.Put_Byte SelMessage Exit Function End If 'Check if Read was clicked If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X + .ReadLbl.X, .Screen.Y + .ReadLbl.Y, .ReadLbl.Width, .ReadLbl.Height) Then sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.Server_MailMessage sndBuf.Put_Byte SelMessage Exit Function End If End If 'Check if List was clicked If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .List.X + .List.X, .Screen.Y + .List.Y, .List.Width, .List.Height) Then For i = 1 To (.List.Height \ Font_Default.CharHeight) If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .List.X + .List.X, .Screen.Y + .List.Y + ((i - 1) * Font_Default.CharHeight), .List.Width, Font_Default.CharHeight) Then If SelMessage = i Then sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.Server_MailMessage sndBuf.Put_Byte i Else SelMessage = i End If Exit Function End If Next i Exit Function End If SelGameWindow = MailboxWindow Exit Function End If End With End If Case ViewMessageWindow If ShowGameWindow(ViewMessageWindow) Then With GameWindow.ViewMessage 'Check if the screen was clicked If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_LeftClick_Window = 1 LastClickedWindow = ViewMessageWindow 'Click an item For i = 1 To MaxMailObjs If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X + .Image(i).X, .Screen.Y + .Image(i).Y, .Image(i).Width, .Image(i).Height) Then sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.Server_MailItemTake sndBuf.Put_Byte i Exit Function End If Next i SelGameWindow = ViewMessageWindow Exit Function End If End With End If Case WriteMessageWindow If ShowGameWindow(WriteMessageWindow) Then With GameWindow.WriteMessage 'Check if the screen was clicked If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_LeftClick_Window = 1 LastClickedWindow = WriteMessageWindow 'Click From If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .From.X + .Screen.X, .From.Y + .Screen.Y, .From.Width, .From.Height) Then WMSelCon = wmFrom Exit Function End If 'Click Subject If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Subject.X + .Screen.X, .Subject.Y + .Screen.Y, .Subject.Width, .Subject.Height) Then WMSelCon = wmSubject Exit Function End If 'Click Message If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Message.X + .Screen.X, .Message.Y + .Screen.Y, .Message.Width, .Message.Height) Then WMSelCon = wmMessage Exit Function End If 'Click an item For i = 1 To MaxMailObjs If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X + .Image(i).X, .Screen.Y + .Image(i).Y, .Image(i).Width, .Image(i).Height) Then WriteMailData.ObjIndex(i) = 0 WriteMailData.ObjAmount(i) = 0 Exit Function End If Next i SelGameWindow = WriteMessageWindow Exit Function End If End With End If Case AmountWindow If ShowGameWindow(AmountWindow) Then With GameWindow.Amount 'Check if the screen was clicked If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_LeftClick_Window = 1 LastClickedWindow = AmountWindow End If SelGameWindow = AmountWindow Exit Function End With End If End Select End Function Sub Input_Mouse_Move() '***************************************************************** 'Handles events for when the mouse moves (mostly just game window moving) 'More info: http://www.vbgore.com/GameClient.Input.Input_Mouse_Move '***************************************************************** 'Make sure engine is running If Not EngineRun Then Exit Sub 'Clear item info display ItemDescLines = 0 'Check if left mouse is pressed If MouseLeftDown Then Select Case SelGameWindow 'Move QuickBar Case QuickBarWindow With GameWindow.QuickBar.Screen .X = .X + MousePosAdd.X .Y = .Y + MousePosAdd.Y If WindowsInScreen Then If .X < 0 Then .X = 0 If .Y < 0 Then .Y = 0 If .X > ScreenWidth - .Width Then .X = ScreenWidth - .Width If .Y > ScreenHeight - .Height Then .Y = ScreenHeight - .Height End If End With 'Move ChatWindow Case ChatWindow With GameWindow.ChatWindow.Screen .X = .X + MousePosAdd.X .Y = .Y + MousePosAdd.Y If WindowsInScreen Then If .X < 0 Then .X = 0 If .Y < 0 Then .Y = 0 If .X > ScreenWidth - .Width Then .X = ScreenWidth - .Width If .Y > ScreenHeight - .Height Then .Y = ScreenHeight - .Height End If Engine_UpdateChatArray End With 'Move Stat Window Case StatWindow With GameWindow.StatWindow.Screen .X = .X + MousePosAdd.X .Y = .Y + MousePosAdd.Y If WindowsInScreen Then If .X < 0 Then .X = 0 If .Y < 0 Then .Y = 0 If .X > ScreenWidth - .Width Then .X = ScreenWidth - .Width If .Y > ScreenHeight - .Height Then .Y = ScreenHeight - .Height End If End With 'Move Inventory Case InventoryWindow With GameWindow.Inventory.Screen .X = .X + MousePosAdd.X .Y = .Y + MousePosAdd.Y If WindowsInScreen Then If .X < 0 Then .X = 0 If .Y < 0 Then .Y = 0 If .X > ScreenWidth - .Width Then .X = ScreenWidth - .Width If .Y > ScreenHeight - .Height Then .Y = ScreenHeight - .Height End If End With 'Move Shop Case ShopWindow With GameWindow.Shop.Screen .X = .X + MousePosAdd.X .Y = .Y + MousePosAdd.Y If WindowsInScreen Then If .X < 0 Then .X = 0 If .Y < 0 Then .Y = 0 If .X > ScreenWidth - .Width Then .X = ScreenWidth - .Width If .Y > ScreenHeight - .Height Then .Y = ScreenHeight - .Height End If End With 'Move Bank Case BankWindow With GameWindow.Bank.Screen .X = .X + MousePosAdd.X .Y = .Y + MousePosAdd.Y If WindowsInScreen Then If .X < 0 Then .X = 0 If .Y < 0 Then .Y = 0 If .X > ScreenWidth - .Width Then .X = ScreenWidth - .Width If .Y > ScreenHeight - .Height Then .Y = ScreenHeight - .Height End If End With 'Move Mailbox Case MailboxWindow With GameWindow.Mailbox.Screen .X = .X + MousePosAdd.X .Y = .Y + MousePosAdd.Y If WindowsInScreen Then If .X < 0 Then .X = 0 If .Y < 0 Then .Y = 0 If .X > ScreenWidth - .Width Then .X = ScreenWidth - .Width If .Y > ScreenHeight - .Height Then .Y = ScreenHeight - .Height End If End With 'Move View Message Case ViewMessageWindow With GameWindow.ViewMessage.Screen .X = .X + MousePosAdd.X .Y = .Y + MousePosAdd.Y If WindowsInScreen Then If .X < 0 Then .X = 0 If .Y < 0 Then .Y = 0 If .X > ScreenWidth - .Width Then .X = ScreenWidth - .Width If .Y > ScreenHeight - .Height Then .Y = ScreenHeight - .Height End If End With 'Move write message Case WriteMessageWindow With GameWindow.WriteMessage.Screen .X = .X + MousePosAdd.X .Y = .Y + MousePosAdd.Y If WindowsInScreen Then If .X < 0 Then .X = 0 If .Y < 0 Then .Y = 0 If .X > ScreenWidth - .Width Then .X = ScreenWidth - .Width If .Y > ScreenHeight - .Height Then .Y = ScreenHeight - .Height End If End With 'Move Amount Case AmountWindow With GameWindow.Amount.Screen .X = .X + MousePosAdd.X .Y = .Y + MousePosAdd.Y If WindowsInScreen Then If .X < 0 Then .X = 0 If .Y < 0 Then .Y = 0 If .X > ScreenWidth - .Width Then .X = ScreenWidth - .Width If .Y > ScreenHeight - .Height Then .Y = ScreenHeight - .Height End If End With 'Move Chat window Case NPCChatWindow With GameWindow.NPCChat.Screen .X = .X + MousePosAdd.X .Y = .Y + MousePosAdd.Y If WindowsInScreen Then If .X < 0 Then .X = 0 If .Y < 0 Then .Y = 0 If .X > ScreenWidth - .Width Then .X = ScreenWidth - .Width If .Y > ScreenHeight - .Height Then .Y = ScreenHeight - .Height End If End With 'Move the trade window Case TradeWindow With GameWindow.Trade.Screen .X = .X + MousePosAdd.X .Y = .Y + MousePosAdd.Y If WindowsInScreen Then If .X < 0 Then .X = 0 If .Y < 0 Then .Y = 0 If .X > ScreenWidth - .Width Then .X = ScreenWidth - .Width If .Y > ScreenHeight - .Height Then .Y = ScreenHeight - .Height End If End With End Select End If End Sub Sub Input_Mouse_RightClick() '***************************************************************** 'Handles mouse right-click events 'More info: http://www.vbgore.com/GameClient.Input.Input_Mouse_RightClick '***************************************************************** Dim tX As Integer Dim tY As Integer Dim i As Long 'Make sure engine is running If Not EngineRun Then Exit Sub '***Check for a window click*** 'Start with the last clicked window, then move in order of importance If Input_Mouse_RightClick_Window(LastClickedWindow) = 1 Then Exit Sub For i = 1 To NumGameWindows If Input_Mouse_RightClick_Window(i) = 1 Then Exit Sub Next i 'No windows clicked, so a tile click will take place 'Get the tile positions Engine_ConvertCPtoTP MousePos.X, MousePos.Y, tX, tY 'Check if a NPC was clicked that has ASK responses For i = 1 To LastChar If CharList(i).Pos.X = tX Then If CharList(i).Pos.Y = tY Then If CharList(i).NPCChatIndex > 0 Then If NPCChat(CharList(i).NPCChatIndex).Ask.StartAsk > 0 Then Engine_ShowNPCChatWindow CharList(i).Name, CharList(i).NPCChatIndex, NPCChat(CharList(i).NPCChatIndex).Ask.StartAsk End If End If Exit For End If End If Next i 'Normal click If UseClickWarp = 0 Then 'Check if a sign was clicked If MapData(tX, tY).Sign Then Engine_AddToChatTextBuffer Replace$(Message(126), "<text>", Signs(MapData(tX, tY).Sign)), FontColor_Info 'Send left click sndBuf.Allocate 3 sndBuf.Put_Byte DataCode.User_RightClick sndBuf.Put_Byte CByte(tX) sndBuf.Put_Byte CByte(tY) 'Warp click Else sndBuf.Allocate 3 sndBuf.Put_Byte DataCode.GM_Warp sndBuf.Put_Byte CByte(tX) sndBuf.Put_Byte CByte(tY) End If End Sub Function Input_Mouse_RightClick_Window(ByVal WindowIndex As Byte) As Byte '***************************************************************** 'If a game window was right-clicked 'More info: http://www.vbgore.com/GameClient.Input.Input_Mouse_RightClick_Window '***************************************************************** Dim i As Integer Select Case WindowIndex Case TradeWindow If ShowGameWindow(TradeWindow) Then With GameWindow.Trade If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_RightClick_Window = 1 LastClickedWindow = TradeWindow 'Item window for user 1 For i = 1 To 9 If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X + .Trade1(i).X, .Screen.Y + .Trade1(i).Y, 32, 32) Then If TradeTable.Trade1(i).Grh > 0 Then Engine_SetItemDesc TradeTable.Trade1(i).Name, TradeTable.Trade1(i).Amount, TradeTable.Trade1(i).Value Exit Function End If End If Next i 'Item window for user 2 For i = 1 To 9 If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X + .Trade2(i).X, .Screen.Y + .Trade2(i).Y, 32, 32) Then If TradeTable.Trade2(i).Grh > 0 Then Engine_SetItemDesc TradeTable.Trade2(i).Name, TradeTable.Trade2(i).Amount, TradeTable.Trade2(i).Value Exit Function End If End If Next i End If End With End If Case QuickBarWindow If ShowGameWindow(QuickBarWindow) Then With GameWindow.QuickBar 'Check if the screen was clicked If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_RightClick_Window = 1 LastClickedWindow = QuickBarWindow 'Check if an item was clicked For i = 1 To 12 If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Image(i).X + .Screen.X, .Image(i).Y + .Screen.Y, .Image(i).Width, .Image(i).Height) Then 'An item in the quickbar was clicked - get description If QuickBarID(i).Type = QuickBarType_Item Then Engine_SetItemDesc UserInventory(QuickBarID(i).ID).Name, UserInventory(QuickBarID(i).ID).Amount 'A skill in the quickbar was clicked - get the name ElseIf QuickBarID(i).Type = QuickBarType_Skill Then Engine_SetItemDesc Engine_SkillIDtoSkillName(QuickBarID(i).ID) End If Exit Function End If Next i End If End With End If Case InventoryWindow If ShowGameWindow(InventoryWindow) Then With GameWindow.Inventory 'Check if the screen was clicked If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_RightClick_Window = 1 LastClickedWindow = InventoryWindow 'Check if an item was clicked For i = 1 To MAX_INVENTORY_SLOTS If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Image(i).X + .Screen.X, .Image(i).Y + .Screen.Y, .Image(i).Width, .Image(i).Height) Then If UserInventory(i).GrhIndex > 0 Then Engine_SetItemDesc UserInventory(i).Name, UserInventory(i).Amount, UserInventory(i).Value DragSourceWindow = InventoryWindow DragItemSlot = i End If Exit Function End If Next i End If End With End If Case ShopWindow If ShowGameWindow(ShopWindow) Then With GameWindow.Shop 'Check if the screen was clicked If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_RightClick_Window = 1 LastClickedWindow = ShopWindow 'Check if an item was clicked For i = 1 To MAX_INVENTORY_SLOTS If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Image(i).X + .Screen.X, .Image(i).Y + .Screen.Y, .Image(i).Width, .Image(i).Height) Then If i <= NPCTradeItemArraySize Then If NPCTradeItems(i).GrhIndex > 0 Then Engine_SetItemDesc NPCTradeItems(i).Name, 0, NPCTradeItems(i).Value DragSourceWindow = ShopWindow DragItemSlot = i End If End If Exit Function End If Next i End If End With End If Case BankWindow If ShowGameWindow(BankWindow) Then With GameWindow.Bank 'Check if the screen was clicked If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_RightClick_Window = 1 LastClickedWindow = BankWindow 'Check if an item was clicked For i = 1 To MAX_INVENTORY_SLOTS If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Image(i).X + .Screen.X, .Image(i).Y + .Screen.Y, .Image(i).Width, .Image(i).Height) Then If UserBank(i).GrhIndex > 0 Then Engine_SetItemDesc UserBank(i).Name, UserBank(i).Amount DragSourceWindow = BankWindow DragItemSlot = i Exit Function End If Next i End If End With End If Case ViewMessageWindow If ShowGameWindow(ViewMessageWindow) Then With GameWindow.ViewMessage 'Check if the screen was clicked If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_RightClick_Window = 1 LastClickedWindow = ViewMessageWindow 'Click an item For i = 1 To MaxMailObjs If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X + .Image(i).X, .Screen.Y + .Image(i).Y, .Image(i).Width, .Image(i).Height) Then Engine_SetItemDesc ReadMailData.ObjName(i), ReadMailData.ObjAmount(i) Exit Function End If Next i End If End With End If Case WriteMessageWindow If ShowGameWindow(WriteMessageWindow) Then With GameWindow.WriteMessage 'Check if the screen was clicked If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_RightClick_Window = 1 LastClickedWindow = WriteMessageWindow 'Click an item For i = 1 To MaxMailObjs If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X + .Image(i).X, .Screen.Y + .Image(i).Y, .Image(i).Width, .Image(i).Height) Then Engine_SetItemDesc UserInventory(WriteMailData.ObjIndex(i)).Name, WriteMailData.ObjAmount(i) Exit Function End If Next i End If End With End If Case ChatWindow If ShowGameWindow(ChatWindow) Then With GameWindow.ChatWindow If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_RightClick_Window = 1 LastClickedWindow = ChatWindow End If End With End If Case MenuWindow If ShowGameWindow(MenuWindow) Then With GameWindow.Menu If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_RightClick_Window = 1 LastClickedWindow = MenuWindow End If End With End If Case StatWindow If ShowGameWindow(StatWindow) Then With GameWindow.StatWindow If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_RightClick_Window = 1 LastClickedWindow = StatWindow End If End With End If Case ViewMessageWindow If ShowGameWindow(ViewMessageWindow) Then With GameWindow.ViewMessage If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_RightClick_Window = 1 LastClickedWindow = ViewMessageWindow End If End With End If Case AmountWindow If ShowGameWindow(AmountWindow) Then With GameWindow.Amount If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_RightClick_Window = 1 LastClickedWindow = AmountWindow End If End With End If Case NPCChatWindow If ShowGameWindow(NPCChatWindow) Then With GameWindow.NPCChat If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then Input_Mouse_RightClick_Window = 1 LastClickedWindow = NPCChatWindow End If End With End If End Select End Function Sub Input_Mouse_RightRelease() '***************************************************************** 'Right mouse button released events 'More info: http://www.vbgore.com/GameClient.Input.Input_Mouse_RightRelease '***************************************************************** Dim i As Byte 'Check if we released mouse and have an item in being dragged If DragItemSlot Then 'Inventory -> Trade Window If DragSourceWindow = InventoryWindow Then If ShowGameWindow(TradeWindow) Then With GameWindow.Trade If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then For i = 1 To 9 If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Trade1(i).X + .Screen.X, .Trade1(i).Y + .Screen.Y, 32, 32) Then If UserInventory(DragItemSlot).Amount = 1 Then sndBuf.Put_Byte DataCode.User_Trade_UpdateTrade sndBuf.Put_Byte DragItemSlot sndBuf.Put_Long 1 Else ShowGameWindow(AmountWindow) = 1 LastClickedWindow = AmountWindow AmountWindowItemIndex = DragItemSlot AmountWindowValue = vbNullString AmountWindowUsage = AW_InvToTrade End If 'Clear and leave DragSourceWindow = 0 DragItemSlot = 0 Exit Sub End If Next i End If End With End If End If 'Inventory -> Inventory (change slot) If DragSourceWindow = InventoryWindow Then If ShowGameWindow(InventoryWindow) Then With GameWindow.Inventory If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then For i = 1 To MAX_INVENTORY_SLOTS If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Image(i).X + .Screen.X, .Image(i).Y + .Screen.Y, .Image(i).Width, .Image(i).Height) Then If DragItemSlot <> i Then 'Switch slots sndBuf.Allocate 3 sndBuf.Put_Byte DataCode.User_ChangeInvSlot sndBuf.Put_Byte DragItemSlot sndBuf.Put_Byte i 'Clear and leave DragSourceWindow = 0 DragItemSlot = 0 Exit Sub End If End If Next i 'Clear and leave DragSourceWindow = 0 DragItemSlot = 0 Exit Sub End If End With End If End If 'Inventory -> Quick Bar If DragSourceWindow = InventoryWindow Then If ShowGameWindow(QuickBarWindow) Then With GameWindow.QuickBar If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then For i = 1 To 12 If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Image(i).X + .Screen.X, .Image(i).Y + .Screen.Y, .Image(i).Width, .Image(i).Height) Then 'Drop into quick use slot QuickBarID(i).Type = QuickBarType_Item QuickBarID(i).ID = DragItemSlot 'Clear and leave DragSourceWindow = 0 DragItemSlot = 0 Exit Sub End If Next i End If End With End If End If 'Inventory -> Depot If DragSourceWindow = InventoryWindow Then If ShowGameWindow(BankWindow) Then With GameWindow.Bank If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then 'Single item If UserInventory(DragItemSlot).Amount = 1 Then sndBuf.Allocate 4 sndBuf.Put_Byte DataCode.User_Bank_PutItem sndBuf.Put_Byte DragItemSlot sndBuf.Put_Integer 1 'Multiple items Else ShowGameWindow(AmountWindow) = 1 LastClickedWindow = AmountWindow AmountWindowValue = vbNullString AmountWindowItemIndex = DragItemSlot AmountWindowUsage = AW_InvToBank End If 'Clear and leave DragSourceWindow = 0 DragItemSlot = 0 End If End With End If End If 'Inventory -> Shop If DragSourceWindow = InventoryWindow Then If ShowGameWindow(ShopWindow) Then With GameWindow.Shop If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then 'Single item If UserInventory(DragItemSlot).Amount = 1 Then sndBuf.Allocate 4 sndBuf.Put_Byte DataCode.User_Trade_SellToNPC sndBuf.Put_Byte DragItemSlot sndBuf.Put_Integer 1 'Multiple items Else ShowGameWindow(AmountWindow) = 1 LastClickedWindow = AmountWindow AmountWindowValue = vbNullString AmountWindowItemIndex = DragItemSlot AmountWindowUsage = AW_InvToShop End If 'Clear and leave DragSourceWindow = 0 DragItemSlot = 0 Exit Sub End If End With End If End If 'Shop -> Inventory If DragSourceWindow = ShopWindow Then If ShowGameWindow(InventoryWindow) Then With GameWindow.Inventory If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then 'Bring up amount window for bulk buying ShowGameWindow(AmountWindow) = 1 LastClickedWindow = AmountWindow AmountWindowValue = vbNullString AmountWindowItemIndex = DragItemSlot AmountWindowUsage = AW_ShopToInv 'Clear and leave DragSourceWindow = 0 DragItemSlot = 0 Exit Sub End If End With End If End If 'Bank -> Inventory If DragSourceWindow = BankWindow Then If ShowGameWindow(InventoryWindow) Then With GameWindow.Inventory If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then If UserBank(DragItemSlot).Amount > 1 Then 'Bring up amount window for bulk withdrawing ShowGameWindow(AmountWindow) = 1 LastClickedWindow = AmountWindow AmountWindowValue = vbNullString AmountWindowItemIndex = DragItemSlot AmountWindowUsage = AW_BankToInv Else sndBuf.Allocate 4 sndBuf.Put_Byte DataCode.User_Bank_TakeItem sndBuf.Put_Byte DragItemSlot sndBuf.Put_Integer 1 End If 'Clear and leave DragSourceWindow = 0 DragItemSlot = 0 Exit Sub End If End With End If End If 'Inventory -> Mail If DragSourceWindow = InventoryWindow Then If ShowGameWindow(WriteMessageWindow) Then With GameWindow.WriteMessage If Engine_Collision_Rect(MousePos.X, MousePos.Y, 1, 1, .Screen.X, .Screen.Y, .Screen.Width, .Screen.Height) Then 'Single item If UserInventory(DragItemSlot).Amount = 1 Then 'Check for duplicate entries For i = 1 To MaxMailObjs If WriteMailData.ObjIndex(i) = DragItemSlot Then DragSourceWindow = 0 DragItemSlot = 0 Exit Sub End If Next i 'Place item in next free slot (if any) i = 0 Do i = i + 1 If i > MaxMailObjs Then DragSourceWindow = 0 DragItemSlot = 0 Exit Sub End If Loop While WriteMailData.ObjIndex(i) > 0 WriteMailData.ObjIndex(i) = DragItemSlot WriteMailData.ObjAmount(i) = 1 'Multiple items Else ShowGameWindow(AmountWindow) = 1 LastClickedWindow = AmountWindow AmountWindowValue = vbNullString AmountWindowItemIndex = DragItemSlot AmountWindowUsage = AW_InvToMail End If 'Clear and leave DragSourceWindow = 0 DragItemSlot = 0 Exit Sub End If End With End If End If 'Inventory -> Ground If DragSourceWindow = InventoryWindow Then 'Single item If UserInventory(DragItemSlot).Amount = 1 Then sndBuf.Allocate 4 sndBuf.Put_Byte DataCode.User_Drop sndBuf.Put_Byte DragItemSlot sndBuf.Put_Integer 1 'Multiple items Else ShowGameWindow(AmountWindow) = 1 LastClickedWindow = AmountWindow AmountWindowValue = vbNullString AmountWindowItemIndex = DragItemSlot AmountWindowUsage = AW_Drop End If 'Clear and leave DragSourceWindow = 0 DragItemSlot = 0 Exit Sub End If 'Didn't release over a valid area DragSourceWindow = 0 DragItemSlot = 0 End If End Sub
[edit] Particles
Option Explicit Private Type Effect X As Single 'Location of effect Y As Single GoToX As Single 'Location to move to GoToY As Single KillWhenAtTarget As Boolean 'If the effect is at its target (GoToX/Y), then Progression is set to 0 KillWhenTargetLost As Boolean 'Kill the effect if the target is lost (sets progression = 0) Gfx As Byte 'Particle texture used Used As Boolean 'If the effect is in use EffectNum As Byte 'What number of effect that is used Modifier As Integer 'Misc variable (depends on the effect) FloatSize As Long 'The size of the particles Direction As Integer 'Misc variable (depends on the effect) Particles() As Particle 'Information on each particle Progression As Single 'Progression state, best to design where 0 = effect ends PartVertex() As TLVERTEX 'Used to point render particles PreviousFrame As Long 'Tick time of the last frame ParticleCount As Integer 'Number of particles total ParticlesLeft As Integer 'Number of particles left - only for non-repetitive effects BindToChar As Integer 'Setting this value will bind the effect to move towards the character BindSpeed As Single 'How fast the effect moves towards the character BoundToMap As Byte 'If the effect is bound to the map or not (used only by the map editor) End Type Public NumEffects As Byte 'Maximum number of effects at once Public Effect() As Effect 'List of all the active effects 'Constants With The Order Number For Each Effect Public Const EffectNum_Fire As Byte = 1 'Burn baby, burn! Flame from a central point that blows in a specified direction Public Const EffectNum_Snow As Byte = 2 'Snow that covers the screen - weather effect Public Const EffectNum_Heal As Byte = 3 'Healing effect that can bind to a character, ankhs float up and fade Public Const EffectNum_Bless As Byte = 4 'Following three effects are same: create a circle around the central point Public Const EffectNum_Protection As Byte = 5 ' (often the character) and makes the given particle on the perimeter Public Const EffectNum_Strengthen As Byte = 6 ' which float up and fade out Public Const EffectNum_Rain As Byte = 7 'Exact same as snow, but moves much faster and more alpha value - weather effect Public Const EffectNum_EquationTemplate As Byte = 8 'Template for creating particle effects through equations - a page with some equations can be found here: http://www.vbgore.com/modules.php?name=Forums&file=viewtopic&t=221 Public Const EffectNum_Waterfall As Byte = 9 'Waterfall effect Public Const EffectNum_Summon As Byte = 10 'Summon effect Private Declare Sub ZeroMemory Lib "kernel32.dll" Alias "RtlZeroMemory" (ByRef Destination As Any, ByVal Length As Long) Function Effect_EquationTemplate_Begin(ByVal X As Single, ByVal Y As Single, ByVal Gfx As Integer, ByVal Particles As Integer, Optional ByVal Progression As Single = 1) As Integer '***************************************************************** 'Particle effect template for effects as described on the 'wiki page: http://www.vbgore.com/Particle_effect_equations 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_EquationTemplate_Begin '***************************************************************** Dim EffectIndex As Integer Dim LoopC As Long 'Get the next open effect slot EffectIndex = Effect_NextOpenSlot If EffectIndex = -1 Then Exit Function 'Return the index of the used slot Effect_EquationTemplate_Begin = EffectIndex 'Set The Effect's Variables Effect(EffectIndex).EffectNum = EffectNum_EquationTemplate 'Set the effect number Effect(EffectIndex).ParticleCount = Particles 'Set the number of particles Effect(EffectIndex).Used = True 'Enable the effect Effect(EffectIndex).X = X 'Set the effect's X coordinate Effect(EffectIndex).Y = Y 'Set the effect's Y coordinate Effect(EffectIndex).Gfx = Gfx 'Set the graphic Effect(EffectIndex).Progression = Progression 'If we loop the effect 'Set the number of particles left to the total avaliable Effect(EffectIndex).ParticlesLeft = Effect(EffectIndex).ParticleCount 'Set the float variables Effect(EffectIndex).FloatSize = Effect_FToDW(8) 'Size of the particles 'Redim the number of particles ReDim Effect(EffectIndex).Particles(0 To Effect(EffectIndex).ParticleCount) ReDim Effect(EffectIndex).PartVertex(0 To Effect(EffectIndex).ParticleCount) 'Create the particles For LoopC = 0 To Effect(EffectIndex).ParticleCount Set Effect(EffectIndex).Particles(LoopC) = New Particle Effect(EffectIndex).Particles(LoopC).Used = True Effect(EffectIndex).PartVertex(LoopC).Rhw = 1 Effect_EquationTemplate_Reset EffectIndex, LoopC Next LoopC 'Set The Initial Time Effect(EffectIndex).PreviousFrame = timeGetTime End Function Private Sub Effect_EquationTemplate_Reset(ByVal EffectIndex As Integer, ByVal Index As Long) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_EquationTemplate_Reset '***************************************************************** Dim X As Single Dim Y As Single Dim R As Single Effect(EffectIndex).Progression = Effect(EffectIndex).Progression + 0.1 R = (Index / 20) * EXP(Index / Effect(EffectIndex).Progression Mod 3) X = R * Cos(Index) Y = R * Sin(Index) 'Reset the particle Effect(EffectIndex).Particles(Index).ResetIt Effect(EffectIndex).X + X, Effect(EffectIndex).Y + Y, 0, 0, 0, 0 Effect(EffectIndex).Particles(Index).ResetColor 1, 1, 1, 1, 0.2 + (Rnd * 0.2) End Sub Private Sub Effect_EquationTemplate_Update(ByVal EffectIndex As Integer) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_EquationTemplate_Update '***************************************************************** Dim ElapsedTime As Single Dim LoopC As Long 'Calculate The Time Difference ElapsedTime = (timeGetTime - Effect(EffectIndex).PreviousFrame) * 0.01 Effect(EffectIndex).PreviousFrame = timeGetTime 'Go Through The Particle Loop For LoopC = 0 To Effect(EffectIndex).ParticleCount 'Check If Particle Is In Use If Effect(EffectIndex).Particles(LoopC).Used Then 'Update The Particle Effect(EffectIndex).Particles(LoopC).UpdateParticle ElapsedTime 'Check if the particle is ready to die If Effect(EffectIndex).Particles(LoopC).sngA <= 0 Then 'Check if the effect is ending If Effect(EffectIndex).Progression > 0 Then 'Reset the particle Effect_EquationTemplate_Reset EffectIndex, LoopC Else 'Disable the particle Effect(EffectIndex).Particles(LoopC).Used = False 'Subtract from the total particle count Effect(EffectIndex).ParticlesLeft = Effect(EffectIndex).ParticlesLeft - 1 'Check if the effect is out of particles If Effect(EffectIndex).ParticlesLeft = 0 Then Effect(EffectIndex).Used = False 'Clear the color (dont leave behind any artifacts) Effect(EffectIndex).PartVertex(LoopC).Color = 0 End If Else 'Set the particle information on the particle vertex Effect(EffectIndex).PartVertex(LoopC).Color = D3DColorMake(Effect(EffectIndex).Particles(LoopC).sngR, Effect(EffectIndex).Particles(LoopC).sngG, Effect(EffectIndex).Particles(LoopC).sngB, Effect(EffectIndex).Particles(LoopC).sngA) Effect(EffectIndex).PartVertex(LoopC).X = Effect(EffectIndex).Particles(LoopC).sngX Effect(EffectIndex).PartVertex(LoopC).Y = Effect(EffectIndex).Particles(LoopC).sngY End If End If Next LoopC End Sub Function Effect_Bless_Begin(ByVal X As Single, ByVal Y As Single, ByVal Gfx As Integer, ByVal Particles As Integer, Optional ByVal Size As Byte = 30, Optional ByVal Time As Single = 10) As Integer '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Bless_Begin '***************************************************************** Dim EffectIndex As Integer Dim LoopC As Long 'Get the next open effect slot EffectIndex = Effect_NextOpenSlot If EffectIndex = -1 Then Exit Function 'Return the index of the used slot Effect_Bless_Begin = EffectIndex 'Set The Effect's Variables Effect(EffectIndex).EffectNum = EffectNum_Bless 'Set the effect number Effect(EffectIndex).ParticleCount = Particles 'Set the number of particles Effect(EffectIndex).Used = True 'Enabled the effect Effect(EffectIndex).X = X 'Set the effect's X coordinate Effect(EffectIndex).Y = Y 'Set the effect's Y coordinate Effect(EffectIndex).Gfx = Gfx 'Set the graphic Effect(EffectIndex).Modifier = Size 'How large the circle is Effect(EffectIndex).Progression = Time 'How long the effect will last 'Set the number of particles left to the total avaliable Effect(EffectIndex).ParticlesLeft = Effect(EffectIndex).ParticleCount 'Set the float variables Effect(EffectIndex).FloatSize = Effect_FToDW(20) 'Size of the particles 'Redim the number of particles ReDim Effect(EffectIndex).Particles(0 To Effect(EffectIndex).ParticleCount) ReDim Effect(EffectIndex).PartVertex(0 To Effect(EffectIndex).ParticleCount) 'Create the particles For LoopC = 0 To Effect(EffectIndex).ParticleCount Set Effect(EffectIndex).Particles(LoopC) = New Particle Effect(EffectIndex).Particles(LoopC).Used = True Effect(EffectIndex).PartVertex(LoopC).Rhw = 1 Effect_Bless_Reset EffectIndex, LoopC Next LoopC 'Set The Initial Time Effect(EffectIndex).PreviousFrame = timeGetTime End Function Private Sub Effect_Bless_Reset(ByVal EffectIndex As Integer, ByVal Index As Long) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Bless_Reset '***************************************************************** Dim a As Single Dim X As Single Dim Y As Single 'Get the positions a = Rnd * 360 * DegreeToRadian X = Effect(EffectIndex).X - (Sin(a) * Effect(EffectIndex).Modifier) Y = Effect(EffectIndex).Y + (Cos(a) * Effect(EffectIndex).Modifier) 'Reset the particle Effect(EffectIndex).Particles(Index).ResetIt X, Y, 0, Rnd * -1, 0, -2 Effect(EffectIndex).Particles(Index).ResetColor 1, 1, 0.2, 0.6 + (Rnd * 0.4), 0.06 + (Rnd * 0.2) End Sub Private Sub Effect_Bless_Update(ByVal EffectIndex As Integer) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Bless_Update '***************************************************************** Dim ElapsedTime As Single Dim LoopC As Long 'Calculate The Time Difference ElapsedTime = (timeGetTime - Effect(EffectIndex).PreviousFrame) * 0.01 Effect(EffectIndex).PreviousFrame = timeGetTime 'Update the life span If Effect(EffectIndex).Progression > 0 Then Effect(EffectIndex).Progression = Effect(EffectIndex).Progression - ElapsedTime 'Go Through The Particle Loop For LoopC = 0 To Effect(EffectIndex).ParticleCount 'Check If Particle Is In Use If Effect(EffectIndex).Particles(LoopC).Used Then 'Update The Particle Effect(EffectIndex).Particles(LoopC).UpdateParticle ElapsedTime 'Check if the particle is ready to die If Effect(EffectIndex).Particles(LoopC).sngA <= 0 Then 'Check if the effect is ending If Effect(EffectIndex).Progression > 0 Then 'Reset the particle Effect_Bless_Reset EffectIndex, LoopC Else 'Disable the particle Effect(EffectIndex).Particles(LoopC).Used = False 'Subtract from the total particle count Effect(EffectIndex).ParticlesLeft = Effect(EffectIndex).ParticlesLeft - 1 'Check if the effect is out of particles If Effect(EffectIndex).ParticlesLeft = 0 Then Effect(EffectIndex).Used = False 'Clear the color (dont leave behind any artifacts) Effect(EffectIndex).PartVertex(LoopC).Color = 0 End If Else 'Set the particle information on the particle vertex Effect(EffectIndex).PartVertex(LoopC).Color = D3DColorMake(Effect(EffectIndex).Particles(LoopC).sngR, Effect(EffectIndex).Particles(LoopC).sngG, Effect(EffectIndex).Particles(LoopC).sngB, Effect(EffectIndex).Particles(LoopC).sngA) Effect(EffectIndex).PartVertex(LoopC).X = Effect(EffectIndex).Particles(LoopC).sngX Effect(EffectIndex).PartVertex(LoopC).Y = Effect(EffectIndex).Particles(LoopC).sngY End If End If Next LoopC End Sub Function Effect_Fire_Begin(ByVal X As Single, ByVal Y As Single, ByVal Gfx As Integer, ByVal Particles As Integer, Optional ByVal Direction As Integer = 180, Optional ByVal Progression As Single = 1) As Integer '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Fire_Begin '***************************************************************** Dim EffectIndex As Integer Dim LoopC As Long 'Get the next open effect slot EffectIndex = Effect_NextOpenSlot If EffectIndex = -1 Then Exit Function 'Return the index of the used slot Effect_Fire_Begin = EffectIndex 'Set The Effect's Variables Effect(EffectIndex).EffectNum = EffectNum_Fire 'Set the effect number Effect(EffectIndex).ParticleCount = Particles 'Set the number of particles Effect(EffectIndex).Used = True 'Enabled the effect Effect(EffectIndex).X = X 'Set the effect's X coordinate Effect(EffectIndex).Y = Y 'Set the effect's Y coordinate Effect(EffectIndex).Gfx = Gfx 'Set the graphic Effect(EffectIndex).Direction = Direction 'The direction the effect is animat Effect(EffectIndex).Progression = Progression 'Loop the effect 'Set the number of particles left to the total avaliable Effect(EffectIndex).ParticlesLeft = Effect(EffectIndex).ParticleCount 'Set the float variables Effect(EffectIndex).FloatSize = Effect_FToDW(15) 'Size of the particles 'Redim the number of particles ReDim Effect(EffectIndex).Particles(0 To Effect(EffectIndex).ParticleCount) ReDim Effect(EffectIndex).PartVertex(0 To Effect(EffectIndex).ParticleCount) 'Create the particles For LoopC = 0 To Effect(EffectIndex).ParticleCount Set Effect(EffectIndex).Particles(LoopC) = New Particle Effect(EffectIndex).Particles(LoopC).Used = True Effect(EffectIndex).PartVertex(LoopC).Rhw = 1 Effect_Fire_Reset EffectIndex, LoopC Next LoopC 'Set The Initial Time Effect(EffectIndex).PreviousFrame = timeGetTime End Function Private Sub Effect_Fire_Reset(ByVal EffectIndex As Integer, ByVal Index As Long) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Fire_Reset '***************************************************************** 'Reset the particle Effect(EffectIndex).Particles(Index).ResetIt Effect(EffectIndex).X - 10 + Rnd * 20, Effect(EffectIndex).Y - 10 + Rnd * 20, -Sin((Effect(EffectIndex).Direction + (Rnd * 70) - 35) * DegreeToRadian) * 8, Cos((Effect(EffectIndex).Direction + (Rnd * 70) - 35) * DegreeToRadian) * 8, 0, 0 Effect(EffectIndex).Particles(Index).ResetColor 1, 0.2, 0.2, 0.4 + (Rnd * 0.2), 0.03 + (Rnd * 0.07) End Sub Private Sub Effect_Fire_Update(ByVal EffectIndex As Integer) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Fire_Update '***************************************************************** Dim ElapsedTime As Single Dim LoopC As Long 'Calculate The Time Difference ElapsedTime = (timeGetTime - Effect(EffectIndex).PreviousFrame) * 0.01 Effect(EffectIndex).PreviousFrame = timeGetTime 'Go Through The Particle Loop For LoopC = 0 To Effect(EffectIndex).ParticleCount 'Check If Particle Is In Use If Effect(EffectIndex).Particles(LoopC).Used Then 'Update The Particle Effect(EffectIndex).Particles(LoopC).UpdateParticle ElapsedTime 'Check if the particle is ready to die If Effect(EffectIndex).Particles(LoopC).sngA <= 0 Then 'Check if the effect is ending If Effect(EffectIndex).Progression <> 0 Then 'Reset the particle Effect_Fire_Reset EffectIndex, LoopC Else 'Disable the particle Effect(EffectIndex).Particles(LoopC).Used = False 'Subtract from the total particle count Effect(EffectIndex).ParticlesLeft = Effect(EffectIndex).ParticlesLeft - 1 'Check if the effect is out of particles If Effect(EffectIndex).ParticlesLeft = 0 Then Effect(EffectIndex).Used = False 'Clear the color (dont leave behind any artifacts) Effect(EffectIndex).PartVertex(LoopC).Color = 0 End If Else 'Set the particle information on the particle vertex Effect(EffectIndex).PartVertex(LoopC).Color = D3DColorMake(Effect(EffectIndex).Particles(LoopC).sngR, Effect(EffectIndex).Particles(LoopC).sngG, Effect(EffectIndex).Particles(LoopC).sngB, Effect(EffectIndex).Particles(LoopC).sngA) Effect(EffectIndex).PartVertex(LoopC).X = Effect(EffectIndex).Particles(LoopC).sngX Effect(EffectIndex).PartVertex(LoopC).Y = Effect(EffectIndex).Particles(LoopC).sngY End If End If Next LoopC End Sub Private Function Effect_FToDW(F As Single) As Long '***************************************************************** 'Converts a float to a D-Word, or in Visual Basic terms, a Single to a Long 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_FToDW '***************************************************************** Dim Buf As D3DXBuffer 'Converts a single into a long (Float to DWORD) Set Buf = D3DX.CreateBuffer(4) D3DX.BufferSetData Buf, 0, 4, 1, F D3DX.BufferGetData Buf, 0, 4, 1, Effect_FToDW End Function Function Effect_Heal_Begin(ByVal X As Single, ByVal Y As Single, ByVal Gfx As Integer, ByVal Particles As Integer, Optional ByVal Progression As Single = 1) As Integer '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Heal_Begin '***************************************************************** Dim EffectIndex As Integer Dim LoopC As Long 'Get the next open effect slot EffectIndex = Effect_NextOpenSlot If EffectIndex = -1 Then Exit Function 'Return the index of the used slot Effect_Heal_Begin = EffectIndex 'Set The Effect's Variables Effect(EffectIndex).EffectNum = EffectNum_Heal 'Set the effect number Effect(EffectIndex).ParticleCount = Particles 'Set the number of particles Effect(EffectIndex).Used = True 'Enabled the effect Effect(EffectIndex).X = X 'Set the effect's X coordinate Effect(EffectIndex).Y = Y 'Set the effect's Y coordinate Effect(EffectIndex).Gfx = Gfx 'Set the graphic Effect(EffectIndex).Progression = Progression 'Loop the effect Effect(EffectIndex).KillWhenAtTarget = True 'End the effect when it reaches the target (progression = 0) Effect(EffectIndex).KillWhenTargetLost = True 'End the effect if the target is lost (progression = 0) 'Set the number of particles left to the total avaliable Effect(EffectIndex).ParticlesLeft = Effect(EffectIndex).ParticleCount 'Set the float variables Effect(EffectIndex).FloatSize = Effect_FToDW(16) 'Size of the particles 'Redim the number of particles ReDim Effect(EffectIndex).Particles(0 To Effect(EffectIndex).ParticleCount) ReDim Effect(EffectIndex).PartVertex(0 To Effect(EffectIndex).ParticleCount) 'Create the particles For LoopC = 0 To Effect(EffectIndex).ParticleCount Set Effect(EffectIndex).Particles(LoopC) = New Particle Effect(EffectIndex).Particles(LoopC).Used = True Effect(EffectIndex).PartVertex(LoopC).Rhw = 1 Effect_Heal_Reset EffectIndex, LoopC Next LoopC 'Set The Initial Time Effect(EffectIndex).PreviousFrame = timeGetTime End Function Private Sub Effect_Heal_Reset(ByVal EffectIndex As Integer, ByVal Index As Long) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Heal_Reset '***************************************************************** 'Reset the particle Effect(EffectIndex).Particles(Index).ResetIt Effect(EffectIndex).X - 10 + Rnd * 20, Effect(EffectIndex).Y - 10 + Rnd * 20, -Sin((180 + (Rnd * 90) - 45) * 0.0174533) * 8 + (Rnd * 3), Cos((180 + (Rnd * 90) - 45) * 0.0174533) * 8 + (Rnd * 3), 0, 0 Effect(EffectIndex).Particles(Index).ResetColor 0.8, 0.2, 0.2, 0.6 + (Rnd * 0.2), 0.01 + (Rnd * 0.5) End Sub Private Sub Effect_Heal_Update(ByVal EffectIndex As Integer) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Heal_Update '***************************************************************** Dim ElapsedTime As Single Dim LoopC As Long Dim i As Integer 'Calculate the time difference ElapsedTime = (timeGetTime - Effect(EffectIndex).PreviousFrame) * 0.01 Effect(EffectIndex).PreviousFrame = timeGetTime 'Go through the particle loop For LoopC = 0 To Effect(EffectIndex).ParticleCount 'Check If Particle Is In Use If Effect(EffectIndex).Particles(LoopC).Used Then 'Update The Particle Effect(EffectIndex).Particles(LoopC).UpdateParticle ElapsedTime 'Check if the particle is ready to die If Effect(EffectIndex).Particles(LoopC).sngA <= 0 Then 'Check if the effect is ending If Effect(EffectIndex).Progression <> 0 Then 'Reset the particle Effect_Heal_Reset EffectIndex, LoopC Else 'Disable the particle Effect(EffectIndex).Particles(LoopC).Used = False 'Subtract from the total particle count Effect(EffectIndex).ParticlesLeft = Effect(EffectIndex).ParticlesLeft - 1 'Check if the effect is out of particles If Effect(EffectIndex).ParticlesLeft = 0 Then Effect(EffectIndex).Used = False 'Clear the color (dont leave behind any artifacts) Effect(EffectIndex).PartVertex(LoopC).Color = 0 End If Else 'Set the particle information on the particle vertex Effect(EffectIndex).PartVertex(LoopC).Color = D3DColorMake(Effect(EffectIndex).Particles(LoopC).sngR, Effect(EffectIndex).Particles(LoopC).sngG, Effect(EffectIndex).Particles(LoopC).sngB, Effect(EffectIndex).Particles(LoopC).sngA) Effect(EffectIndex).PartVertex(LoopC).X = Effect(EffectIndex).Particles(LoopC).sngX Effect(EffectIndex).PartVertex(LoopC).Y = Effect(EffectIndex).Particles(LoopC).sngY End If End If Next LoopC End Sub Sub Effect_Kill(ByVal EffectIndex As Integer, Optional ByVal KillAll As Boolean = False) '***************************************************************** 'Kills (stops) a single effect or all effects 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Kill '***************************************************************** Dim LoopC As Long 'Check If To Kill All Effects If KillAll = True Then 'Loop Through Every Effect For LoopC = 1 To NumEffects 'Stop The Effect Effect(LoopC).Used = False Next Else 'Stop The Selected Effect Effect(EffectIndex).Used = False End If End Sub Private Function Effect_NextOpenSlot() As Integer '***************************************************************** 'Finds the next open effects index 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_NextOpenSlot '***************************************************************** Dim EffectIndex As Integer 'Find The Next Open Effect Slot Do EffectIndex = EffectIndex + 1 'Check The Next Slot If EffectIndex > NumEffects Then 'Dont Go Over Maximum Amount Effect_NextOpenSlot = -1 Exit Function End If Loop While Effect(EffectIndex).Used = True 'Check Next If Effect Is In Use 'Return the next open slot Effect_NextOpenSlot = EffectIndex 'Clear the old information from the effect Erase Effect(EffectIndex).Particles() Erase Effect(EffectIndex).PartVertex() ZeroMemory Effect(EffectIndex), LenB(Effect(EffectIndex)) Effect(EffectIndex).GoToX = -30000 Effect(EffectIndex).GoToY = -30000 End Function Function Effect_Protection_Begin(ByVal X As Single, ByVal Y As Single, ByVal Gfx As Integer, ByVal Particles As Integer, Optional ByVal Size As Byte = 30, Optional ByVal Time As Single = 10) As Integer '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Protection_Begin '***************************************************************** Dim EffectIndex As Integer Dim LoopC As Long 'Get the next open effect slot EffectIndex = Effect_NextOpenSlot If EffectIndex = -1 Then Exit Function 'Return the index of the used slot Effect_Protection_Begin = EffectIndex 'Set The Effect's Variables Effect(EffectIndex).EffectNum = EffectNum_Protection 'Set the effect number Effect(EffectIndex).ParticleCount = Particles 'Set the number of particles Effect(EffectIndex).Used = True 'Enabled the effect Effect(EffectIndex).X = X 'Set the effect's X coordinate Effect(EffectIndex).Y = Y 'Set the effect's Y coordinate Effect(EffectIndex).Gfx = Gfx 'Set the graphic Effect(EffectIndex).Modifier = Size 'How large the circle is Effect(EffectIndex).Progression = Time 'How long the effect will last 'Set the number of particles left to the total avaliable Effect(EffectIndex).ParticlesLeft = Effect(EffectIndex).ParticleCount 'Set the float variables Effect(EffectIndex).FloatSize = Effect_FToDW(20) 'Size of the particles 'Redim the number of particles ReDim Effect(EffectIndex).Particles(0 To Effect(EffectIndex).ParticleCount) ReDim Effect(EffectIndex).PartVertex(0 To Effect(EffectIndex).ParticleCount) 'Create the particles For LoopC = 0 To Effect(EffectIndex).ParticleCount Set Effect(EffectIndex).Particles(LoopC) = New Particle Effect(EffectIndex).Particles(LoopC).Used = True Effect(EffectIndex).PartVertex(LoopC).Rhw = 1 Effect_Protection_Reset EffectIndex, LoopC Next LoopC 'Set The Initial Time Effect(EffectIndex).PreviousFrame = timeGetTime End Function Private Sub Effect_Protection_Reset(ByVal EffectIndex As Integer, ByVal Index As Long) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Protection_Reset '***************************************************************** Dim a As Single Dim X As Single Dim Y As Single 'Get the positions a = Rnd * 360 * DegreeToRadian X = Effect(EffectIndex).X - (Sin(a) * Effect(EffectIndex).Modifier) Y = Effect(EffectIndex).Y + (Cos(a) * Effect(EffectIndex).Modifier) 'Reset the particle Effect(EffectIndex).Particles(Index).ResetIt X, Y, 0, Rnd * -1, 0, -2 Effect(EffectIndex).Particles(Index).ResetColor 0.1, 0.1, 0.9, 0.6 + (Rnd * 0.4), 0.06 + (Rnd * 0.2) End Sub Private Sub Effect_UpdateOffset(ByVal EffectIndex As Integer) '*************************************************** 'Update an effect's position if the screen has moved 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_UpdateOffset '*************************************************** Effect(EffectIndex).X = Effect(EffectIndex).X + (LastOffsetX - ParticleOffsetX) Effect(EffectIndex).Y = Effect(EffectIndex).Y + (LastOffsetY - ParticleOffsetY) End Sub Private Sub Effect_UpdateBinding(ByVal EffectIndex As Integer) '*************************************************** 'Updates the binding of a particle effect to a target, if 'the effect is bound to a character 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_UpdateBinding '*************************************************** Dim TargetI As Integer Dim TargetA As Single 'Update position through character binding If Effect(EffectIndex).BindToChar > 0 Then 'Store the character index TargetI = Effect(EffectIndex).BindToChar 'Check for a valid binding index If TargetI > LastChar Then Effect(EffectIndex).BindToChar = 0 If Effect(EffectIndex).KillWhenTargetLost Then Effect(EffectIndex).Progression = 0 Exit Sub End If ElseIf CharList(TargetI).Active = 0 Then Effect(EffectIndex).BindToChar = 0 If Effect(EffectIndex).KillWhenTargetLost Then Effect(EffectIndex).Progression = 0 Exit Sub End If Else 'Calculate the X and Y positions Effect(EffectIndex).GoToX = Engine_TPtoSPX(CharList(Effect(EffectIndex).BindToChar).Pos.X) + 16 Effect(EffectIndex).GoToY = Engine_TPtoSPY(CharList(Effect(EffectIndex).BindToChar).Pos.Y) End If End If 'Move to the new position if needed If Effect(EffectIndex).GoToX > -30000 Or Effect(EffectIndex).GoToY > -30000 Then If Effect(EffectIndex).GoToX <> Effect(EffectIndex).X Or Effect(EffectIndex).GoToY <> Effect(EffectIndex).Y Then 'Calculate the angle TargetA = Engine_GetAngle(Effect(EffectIndex).X, Effect(EffectIndex).Y, Effect(EffectIndex).GoToX, Effect(EffectIndex).GoToY) + 180 'Update the position of the effect Effect(EffectIndex).X = Effect(EffectIndex).X - Sin(TargetA * DegreeToRadian) * Effect(EffectIndex).BindSpeed Effect(EffectIndex).Y = Effect(EffectIndex).Y + Cos(TargetA * DegreeToRadian) * Effect(EffectIndex).BindSpeed 'Check if the effect is close enough to the target to just stick it at the target If Effect(EffectIndex).GoToX > -30000 Then If Abs(Effect(EffectIndex).X - Effect(EffectIndex).GoToX) < 6 Then Effect(EffectIndex).X = Effect(EffectIndex).GoToX End If If Effect(EffectIndex).GoToY > -30000 Then If Abs(Effect(EffectIndex).Y - Effect(EffectIndex).GoToY) < 6 Then Effect(EffectIndex).Y = Effect(EffectIndex).GoToY End If 'Check if the position of the effect is equal to that of the target If Effect(EffectIndex).X = Effect(EffectIndex).GoToX Then If Effect(EffectIndex).Y = Effect(EffectIndex).GoToY Then 'For some effects, if the position is reached, we want to end the effect If Effect(EffectIndex).KillWhenAtTarget Then Effect(EffectIndex).BindToChar = 0 Effect(EffectIndex).Progression = 0 Effect(EffectIndex).GoToX = Effect(EffectIndex).X Effect(EffectIndex).GoToY = Effect(EffectIndex).Y End If Exit Sub 'The effect is at the right position, don't update End If End If End If End If End Sub Private Sub Effect_Protection_Update(ByVal EffectIndex As Integer) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Protection_Update '***************************************************************** Dim ElapsedTime As Single Dim LoopC As Long 'Calculate The Time Difference ElapsedTime = (timeGetTime - Effect(EffectIndex).PreviousFrame) * 0.01 Effect(EffectIndex).PreviousFrame = timeGetTime 'Update the life span If Effect(EffectIndex).Progression > 0 Then Effect(EffectIndex).Progression = Effect(EffectIndex).Progression - ElapsedTime 'Go through the particle loop For LoopC = 0 To Effect(EffectIndex).ParticleCount 'Check If Particle Is In Use If Effect(EffectIndex).Particles(LoopC).Used Then 'Update The Particle Effect(EffectIndex).Particles(LoopC).UpdateParticle ElapsedTime 'Check if the particle is ready to die If Effect(EffectIndex).Particles(LoopC).sngA <= 0 Then 'Check if the effect is ending If Effect(EffectIndex).Progression > 0 Then 'Reset the particle Effect_Protection_Reset EffectIndex, LoopC Else 'Disable the particle Effect(EffectIndex).Particles(LoopC).Used = False 'Subtract from the total particle count Effect(EffectIndex).ParticlesLeft = Effect(EffectIndex).ParticlesLeft - 1 'Check if the effect is out of particles If Effect(EffectIndex).ParticlesLeft = 0 Then Effect(EffectIndex).Used = False 'Clear the color (dont leave behind any artifacts) Effect(EffectIndex).PartVertex(LoopC).Color = 0 End If Else 'Set the particle information on the particle vertex Effect(EffectIndex).PartVertex(LoopC).Color = D3DColorMake(Effect(EffectIndex).Particles(LoopC).sngR, Effect(EffectIndex).Particles(LoopC).sngG, Effect(EffectIndex).Particles(LoopC).sngB, Effect(EffectIndex).Particles(LoopC).sngA) Effect(EffectIndex).PartVertex(LoopC).X = Effect(EffectIndex).Particles(LoopC).sngX Effect(EffectIndex).PartVertex(LoopC).Y = Effect(EffectIndex).Particles(LoopC).sngY End If End If Next LoopC End Sub Public Sub Effect_Render(ByVal EffectIndex As Integer, Optional ByVal SetRenderStates As Boolean = True) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Render '***************************************************************** 'Check if we have the device If D3DDevice.TestCooperativeLevel <> D3D_OK Then Exit Sub 'Set the render state for the size of the particle D3DDevice.SetRenderState D3DRS_POINTSIZE, Effect(EffectIndex).FloatSize 'Set the render state to point blitting If SetRenderStates Then D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_ONE 'Set the last texture to a random number to force the engine to reload the texture LastTexture = -65489 'Set the texture D3DDevice.SetTexture 0, ParticleTexture(Effect(EffectIndex).Gfx) 'Draw all the particles at once D3DDevice.DrawPrimitiveUP D3DPT_POINTLIST, Effect(EffectIndex).ParticleCount, Effect(EffectIndex).PartVertex(0), Len(Effect(EffectIndex).PartVertex(0)) 'Reset the render state back to normal If SetRenderStates Then D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA End Sub Function Effect_Snow_Begin(ByVal Gfx As Integer, ByVal Particles As Integer) As Integer '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Snow_Begin '***************************************************************** Dim EffectIndex As Integer Dim LoopC As Long 'Get the next open effect slot EffectIndex = Effect_NextOpenSlot If EffectIndex = -1 Then Exit Function 'Return the index of the used slot Effect_Snow_Begin = EffectIndex 'Set The Effect's Variables Effect(EffectIndex).EffectNum = EffectNum_Snow 'Set the effect number Effect(EffectIndex).ParticleCount = Particles 'Set the number of particles Effect(EffectIndex).Used = True 'Enabled the effect Effect(EffectIndex).Gfx = Gfx 'Set the graphic 'Set the number of particles left to the total avaliable Effect(EffectIndex).ParticlesLeft = Effect(EffectIndex).ParticleCount 'Set the float variables Effect(EffectIndex).FloatSize = Effect_FToDW(15) 'Size of the particles 'Redim the number of particles ReDim Effect(EffectIndex).Particles(0 To Effect(EffectIndex).ParticleCount) ReDim Effect(EffectIndex).PartVertex(0 To Effect(EffectIndex).ParticleCount) 'Create the particles For LoopC = 0 To Effect(EffectIndex).ParticleCount Set Effect(EffectIndex).Particles(LoopC) = New Particle Effect(EffectIndex).Particles(LoopC).Used = True Effect(EffectIndex).PartVertex(LoopC).Rhw = 1 Effect_Snow_Reset EffectIndex, LoopC, 1 Next LoopC 'Set the initial time Effect(EffectIndex).PreviousFrame = timeGetTime End Function Private Sub Effect_Snow_Reset(ByVal EffectIndex As Integer, ByVal Index As Long, Optional ByVal FirstReset As Byte = 0) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Snow_Reset '***************************************************************** If FirstReset = 1 Then 'The very first reset Effect(EffectIndex).Particles(Index).ResetIt -200 + (Rnd * (ScreenWidth + 400)), Rnd * (ScreenHeight + 50), Rnd * 5, 5 + Rnd * 3, 0, 0 Else 'Any reset after first Effect(EffectIndex).Particles(Index).ResetIt -200 + (Rnd * (ScreenWidth + 400)), -15 - Rnd * 185, Rnd * 5, 5 + Rnd * 3, 0, 0 If Effect(EffectIndex).Particles(Index).sngX < -20 Then Effect(EffectIndex).Particles(Index).sngY = Rnd * (ScreenHeight + 50) If Effect(EffectIndex).Particles(Index).sngX > ScreenWidth Then Effect(EffectIndex).Particles(Index).sngY = Rnd * (ScreenHeight + 50) If Effect(EffectIndex).Particles(Index).sngY > ScreenHeight Then Effect(EffectIndex).Particles(Index).sngX = Rnd * (ScreenWidth + 50) End If 'Set the color Effect(EffectIndex).Particles(Index).ResetColor 1, 1, 1, 0.8, 0 End Sub Private Sub Effect_Snow_Update(ByVal EffectIndex As Integer) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Snow_Update '***************************************************************** Dim ElapsedTime As Single Dim LoopC As Long 'Calculate the time difference ElapsedTime = (timeGetTime - Effect(EffectIndex).PreviousFrame) * 0.01 Effect(EffectIndex).PreviousFrame = timeGetTime 'Go through the particle loop For LoopC = 0 To Effect(EffectIndex).ParticleCount 'Check if particle is in use If Effect(EffectIndex).Particles(LoopC).Used Then 'Update The Particle Effect(EffectIndex).Particles(LoopC).UpdateParticle ElapsedTime 'Check if to reset the particle If Effect(EffectIndex).Particles(LoopC).sngX < -200 Then Effect(EffectIndex).Particles(LoopC).sngA = 0 If Effect(EffectIndex).Particles(LoopC).sngX > (ScreenWidth + 200) Then Effect(EffectIndex).Particles(LoopC).sngA = 0 If Effect(EffectIndex).Particles(LoopC).sngY > (ScreenHeight + 200) Then Effect(EffectIndex).Particles(LoopC).sngA = 0 'Time for a reset, baby! If Effect(EffectIndex).Particles(LoopC).sngA <= 0 Then 'Reset the particle Effect_Snow_Reset EffectIndex, LoopC Else 'Set the particle information on the particle vertex Effect(EffectIndex).PartVertex(LoopC).Color = D3DColorMake(Effect(EffectIndex).Particles(LoopC).sngR, Effect(EffectIndex).Particles(LoopC).sngG, Effect(EffectIndex).Particles(LoopC).sngB, Effect(EffectIndex).Particles(LoopC).sngA) Effect(EffectIndex).PartVertex(LoopC).X = Effect(EffectIndex).Particles(LoopC).sngX Effect(EffectIndex).PartVertex(LoopC).Y = Effect(EffectIndex).Particles(LoopC).sngY End If End If Next LoopC End Sub Function Effect_Strengthen_Begin(ByVal X As Single, ByVal Y As Single, ByVal Gfx As Integer, ByVal Particles As Integer, Optional ByVal Size As Byte = 30, Optional ByVal Time As Single = 10) As Integer '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Strengthen_Begin '***************************************************************** Dim EffectIndex As Integer Dim LoopC As Long 'Get the next open effect slot EffectIndex = Effect_NextOpenSlot If EffectIndex = -1 Then Exit Function 'Return the index of the used slot Effect_Strengthen_Begin = EffectIndex 'Set the effect's variables Effect(EffectIndex).EffectNum = EffectNum_Strengthen 'Set the effect number Effect(EffectIndex).ParticleCount = Particles 'Set the number of particles Effect(EffectIndex).Used = True 'Enabled the effect Effect(EffectIndex).X = X 'Set the effect's X coordinate Effect(EffectIndex).Y = Y 'Set the effect's Y coordinate Effect(EffectIndex).Gfx = Gfx 'Set the graphic Effect(EffectIndex).Modifier = Size 'How large the circle is Effect(EffectIndex).Progression = Time 'How long the effect will last 'Set the number of particles left to the total avaliable Effect(EffectIndex).ParticlesLeft = Effect(EffectIndex).ParticleCount 'Set the float variables Effect(EffectIndex).FloatSize = Effect_FToDW(20) 'Size of the particles 'Redim the number of particles ReDim Effect(EffectIndex).Particles(0 To Effect(EffectIndex).ParticleCount) ReDim Effect(EffectIndex).PartVertex(0 To Effect(EffectIndex).ParticleCount) 'Create the particles For LoopC = 0 To Effect(EffectIndex).ParticleCount Set Effect(EffectIndex).Particles(LoopC) = New Particle Effect(EffectIndex).Particles(LoopC).Used = True Effect(EffectIndex).PartVertex(LoopC).Rhw = 1 Effect_Strengthen_Reset EffectIndex, LoopC Next LoopC 'Set The Initial Time Effect(EffectIndex).PreviousFrame = timeGetTime End Function Private Sub Effect_Strengthen_Reset(ByVal EffectIndex As Integer, ByVal Index As Long) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Strengthen_Reset '***************************************************************** Dim a As Single Dim X As Single Dim Y As Single 'Get the positions a = Rnd * 360 * DegreeToRadian X = Effect(EffectIndex).X - (Sin(a) * Effect(EffectIndex).Modifier) Y = Effect(EffectIndex).Y + (Cos(a) * Effect(EffectIndex).Modifier) 'Reset the particle Effect(EffectIndex).Particles(Index).ResetIt X, Y, 0, Rnd * -1, 0, -2 Effect(EffectIndex).Particles(Index).ResetColor 0.2, 1, 0.2, 0.6 + (Rnd * 0.4), 0.06 + (Rnd * 0.2) End Sub Private Sub Effect_Strengthen_Update(ByVal EffectIndex As Integer) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Strengthen_Update '***************************************************************** Dim ElapsedTime As Single Dim LoopC As Long 'Calculate the time difference ElapsedTime = (timeGetTime - Effect(EffectIndex).PreviousFrame) * 0.01 Effect(EffectIndex).PreviousFrame = timeGetTime 'Update the life span If Effect(EffectIndex).Progression > 0 Then Effect(EffectIndex).Progression = Effect(EffectIndex).Progression - ElapsedTime 'Go through the particle loop For LoopC = 0 To Effect(EffectIndex).ParticleCount 'Check if particle is in use If Effect(EffectIndex).Particles(LoopC).Used Then 'Update the particle Effect(EffectIndex).Particles(LoopC).UpdateParticle ElapsedTime 'Check if the particle is ready to die If Effect(EffectIndex).Particles(LoopC).sngA <= 0 Then 'Check if the effect is ending If Effect(EffectIndex).Progression > 0 Then 'Reset the particle Effect_Strengthen_Reset EffectIndex, LoopC Else 'Disable the particle Effect(EffectIndex).Particles(LoopC).Used = False 'Subtract from the total particle count Effect(EffectIndex).ParticlesLeft = Effect(EffectIndex).ParticlesLeft - 1 'Check if the effect is out of particles If Effect(EffectIndex).ParticlesLeft = 0 Then Effect(EffectIndex).Used = False 'Clear the color (dont leave behind any artifacts) Effect(EffectIndex).PartVertex(LoopC).Color = 0 End If Else 'Set the particle information on the particle vertex Effect(EffectIndex).PartVertex(LoopC).Color = D3DColorMake(Effect(EffectIndex).Particles(LoopC).sngR, Effect(EffectIndex).Particles(LoopC).sngG, Effect(EffectIndex).Particles(LoopC).sngB, Effect(EffectIndex).Particles(LoopC).sngA) Effect(EffectIndex).PartVertex(LoopC).X = Effect(EffectIndex).Particles(LoopC).sngX Effect(EffectIndex).PartVertex(LoopC).Y = Effect(EffectIndex).Particles(LoopC).sngY End If End If Next LoopC End Sub Sub Effect_UpdateAll() '***************************************************************** 'Updates all of the effects and renders them 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_UpdateAll '***************************************************************** Dim LoopC As Long 'Make sure we have effects If NumEffects = 0 Then Exit Sub 'Set the render state for the particle effects D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_ONE 'Update every effect in use For LoopC = 1 To NumEffects 'Make sure the effect is in use If Effect(LoopC).Used Then 'Update the effect position if the screen has moved Effect_UpdateOffset LoopC 'Update the effect position if it is binded Effect_UpdateBinding LoopC 'Find out which effect is selected, then update it If Effect(LoopC).EffectNum = EffectNum_Fire Then Effect_Fire_Update LoopC If Effect(LoopC).EffectNum = EffectNum_Snow Then Effect_Snow_Update LoopC If Effect(LoopC).EffectNum = EffectNum_Heal Then Effect_Heal_Update LoopC If Effect(LoopC).EffectNum = EffectNum_Bless Then Effect_Bless_Update LoopC If Effect(LoopC).EffectNum = EffectNum_Protection Then Effect_Protection_Update LoopC If Effect(LoopC).EffectNum = EffectNum_Strengthen Then Effect_Strengthen_Update LoopC If Effect(LoopC).EffectNum = EffectNum_Rain Then Effect_Rain_Update LoopC If Effect(LoopC).EffectNum = EffectNum_EquationTemplate Then Effect_EquationTemplate_Update LoopC If Effect(LoopC).EffectNum = EffectNum_Waterfall Then Effect_Waterfall_Update LoopC If Effect(LoopC).EffectNum = EffectNum_Summon Then Effect_Summon_Update LoopC 'Render the effect Effect_Render LoopC, False End If Next 'Set the render state back for normal rendering D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA End Sub Function Effect_Rain_Begin(ByVal Gfx As Integer, ByVal Particles As Integer) As Integer '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Rain_Begin '***************************************************************** Dim EffectIndex As Integer Dim LoopC As Long 'Get the next open effect slot EffectIndex = Effect_NextOpenSlot If EffectIndex = -1 Then Exit Function 'Return the index of the used slot Effect_Rain_Begin = EffectIndex 'Set the effect's variables Effect(EffectIndex).EffectNum = EffectNum_Rain 'Set the effect number Effect(EffectIndex).ParticleCount = Particles 'Set the number of particles Effect(EffectIndex).Used = True 'Enabled the effect Effect(EffectIndex).Gfx = Gfx 'Set the graphic 'Set the number of particles left to the total avaliable Effect(EffectIndex).ParticlesLeft = Effect(EffectIndex).ParticleCount 'Set the float variables Effect(EffectIndex).FloatSize = Effect_FToDW(10) 'Size of the particles 'Redim the number of particles ReDim Effect(EffectIndex).Particles(0 To Effect(EffectIndex).ParticleCount) ReDim Effect(EffectIndex).PartVertex(0 To Effect(EffectIndex).ParticleCount) 'Create the particles For LoopC = 0 To Effect(EffectIndex).ParticleCount Set Effect(EffectIndex).Particles(LoopC) = New Particle Effect(EffectIndex).Particles(LoopC).Used = True Effect(EffectIndex).PartVertex(LoopC).Rhw = 1 Effect_Rain_Reset EffectIndex, LoopC, 1 Next LoopC 'Set The Initial Time Effect(EffectIndex).PreviousFrame = timeGetTime End Function Private Sub Effect_Rain_Reset(ByVal EffectIndex As Integer, ByVal Index As Long, Optional ByVal FirstReset As Byte = 0) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Rain_Reset '***************************************************************** If FirstReset = 1 Then 'The very first reset Effect(EffectIndex).Particles(Index).ResetIt -200 + (Rnd * (ScreenWidth + 400)), Rnd * (ScreenHeight + 50), Rnd * 5, 25 + Rnd * 12, 0, 0 Else 'Any reset after first Effect(EffectIndex).Particles(Index).ResetIt -200 + (Rnd * 1200), -15 - Rnd * 185, Rnd * 5, 25 + Rnd * 12, 0, 0 If Effect(EffectIndex).Particles(Index).sngX < -20 Then Effect(EffectIndex).Particles(Index).sngY = Rnd * (ScreenHeight + 50) If Effect(EffectIndex).Particles(Index).sngX > ScreenWidth Then Effect(EffectIndex).Particles(Index).sngY = Rnd * (ScreenHeight + 50) If Effect(EffectIndex).Particles(Index).sngY > ScreenHeight Then Effect(EffectIndex).Particles(Index).sngX = Rnd * (ScreenWidth + 50) End If 'Set the color Effect(EffectIndex).Particles(Index).ResetColor 1, 1, 1, 0.4, 0 End Sub Private Sub Effect_Rain_Update(ByVal EffectIndex As Integer) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Rain_Update '***************************************************************** Dim ElapsedTime As Single Dim LoopC As Long 'Calculate the time difference ElapsedTime = (timeGetTime - Effect(EffectIndex).PreviousFrame) * 0.01 Effect(EffectIndex).PreviousFrame = timeGetTime 'Go through the particle loop For LoopC = 0 To Effect(EffectIndex).ParticleCount 'Check if the particle is in use If Effect(EffectIndex).Particles(LoopC).Used Then 'Update the particle Effect(EffectIndex).Particles(LoopC).UpdateParticle ElapsedTime 'Check if to reset the particle If Effect(EffectIndex).Particles(LoopC).sngX < -200 Then Effect(EffectIndex).Particles(LoopC).sngA = 0 If Effect(EffectIndex).Particles(LoopC).sngX > (ScreenWidth + 200) Then Effect(EffectIndex).Particles(LoopC).sngA = 0 If Effect(EffectIndex).Particles(LoopC).sngY > (ScreenHeight + 200) Then Effect(EffectIndex).Particles(LoopC).sngA = 0 'Time for a reset, baby! If Effect(EffectIndex).Particles(LoopC).sngA <= 0 Then 'Reset the particle Effect_Rain_Reset EffectIndex, LoopC Else 'Set the particle information on the particle vertex Effect(EffectIndex).PartVertex(LoopC).Color = D3DColorMake(Effect(EffectIndex).Particles(LoopC).sngR, Effect(EffectIndex).Particles(LoopC).sngG, Effect(EffectIndex).Particles(LoopC).sngB, Effect(EffectIndex).Particles(LoopC).sngA) Effect(EffectIndex).PartVertex(LoopC).X = Effect(EffectIndex).Particles(LoopC).sngX Effect(EffectIndex).PartVertex(LoopC).Y = Effect(EffectIndex).Particles(LoopC).sngY End If End If Next LoopC End Sub Public Sub Effect_Begin(ByVal EffectIndex As Integer, ByVal X As Single, ByVal Y As Single, ByVal GfxIndex As Byte, ByVal Particles As Byte, Optional ByVal Direction As Single = 180, Optional ByVal BindToMap As Boolean = False) '***************************************************************** 'A very simplistic form of initialization for particle effects 'Should only be used for starting map-based effects 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Begin '***************************************************************** Dim RetNum As Byte Select Case EffectIndex Case EffectNum_Fire RetNum = Effect_Fire_Begin(X, Y, GfxIndex, Particles, Direction, 1) Case EffectNum_Waterfall RetNum = Effect_Waterfall_Begin(X, Y, GfxIndex, Particles) End Select 'Bind the effect to the map if needed If BindToMap Then Effect(RetNum).BoundToMap = 1 End Sub Function Effect_Waterfall_Begin(ByVal X As Single, ByVal Y As Single, ByVal Gfx As Integer, ByVal Particles As Integer) As Integer '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Waterfall_Begin '***************************************************************** Dim EffectIndex As Integer Dim LoopC As Long 'Get the next open effect slot EffectIndex = Effect_NextOpenSlot If EffectIndex = -1 Then Exit Function 'Return the index of the used slot Effect_Waterfall_Begin = EffectIndex 'Set the effect's variables Effect(EffectIndex).EffectNum = EffectNum_Waterfall 'Set the effect number Effect(EffectIndex).ParticleCount = Particles 'Set the number of particles Effect(EffectIndex).Used = True 'Enabled the effect Effect(EffectIndex).X = X 'Set the effect's X coordinate Effect(EffectIndex).Y = Y 'Set the effect's Y coordinate Effect(EffectIndex).Gfx = Gfx 'Set the graphic 'Set the number of particles left to the total avaliable Effect(EffectIndex).ParticlesLeft = Effect(EffectIndex).ParticleCount 'Set the float variables Effect(EffectIndex).FloatSize = Effect_FToDW(20) 'Size of the particles 'Redim the number of particles ReDim Effect(EffectIndex).Particles(0 To Effect(EffectIndex).ParticleCount) ReDim Effect(EffectIndex).PartVertex(0 To Effect(EffectIndex).ParticleCount) 'Create the particles For LoopC = 0 To Effect(EffectIndex).ParticleCount Set Effect(EffectIndex).Particles(LoopC) = New Particle Effect(EffectIndex).Particles(LoopC).Used = True Effect(EffectIndex).PartVertex(LoopC).Rhw = 1 Effect_Waterfall_Reset EffectIndex, LoopC Next LoopC 'Set The Initial Time Effect(EffectIndex).PreviousFrame = timeGetTime End Function Private Sub Effect_Waterfall_Reset(ByVal EffectIndex As Integer, ByVal Index As Long) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Waterfall_Reset '***************************************************************** If Int(Rnd * 10) = 1 Then Effect(EffectIndex).Particles(Index).ResetIt Effect(EffectIndex).X + (Rnd * 60), Effect(EffectIndex).Y + (Rnd * 130), 0, 8 + (Rnd * 6), 0, 0 Else Effect(EffectIndex).Particles(Index).ResetIt Effect(EffectIndex).X + (Rnd * 60), Effect(EffectIndex).Y + (Rnd * 10), 0, 8 + (Rnd * 6), 0, 0 End If Effect(EffectIndex).Particles(Index).ResetColor 0.1, 0.1, 0.9, 0.6 + (Rnd * 0.4), 0 End Sub Private Sub Effect_Waterfall_Update(ByVal EffectIndex As Integer) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Waterfall_Update '***************************************************************** Dim ElapsedTime As Single Dim LoopC As Long 'Calculate The Time Difference ElapsedTime = (timeGetTime - Effect(EffectIndex).PreviousFrame) * 0.01 Effect(EffectIndex).PreviousFrame = timeGetTime 'Update the life span If Effect(EffectIndex).Progression > 0 Then Effect(EffectIndex).Progression = Effect(EffectIndex).Progression - ElapsedTime 'Go through the particle loop For LoopC = 0 To Effect(EffectIndex).ParticleCount With Effect(EffectIndex).Particles(LoopC) 'Check if the particle is in use If .Used Then 'Update The Particle .UpdateParticle ElapsedTime 'Check if the particle is ready to die If (.sngY > Effect(EffectIndex).Y + 140) Or (.sngA = 0) Then 'Reset the particle Effect_Waterfall_Reset EffectIndex, LoopC Else 'Set the particle information on the particle vertex Effect(EffectIndex).PartVertex(LoopC).Color = D3DColorMake(.sngR, .sngG, .sngB, .sngA) Effect(EffectIndex).PartVertex(LoopC).X = .sngX Effect(EffectIndex).PartVertex(LoopC).Y = .sngY End If End If End With Next LoopC End Sub Function Effect_Summon_Begin(ByVal X As Single, ByVal Y As Single, ByVal Gfx As Integer, ByVal Particles As Integer, Optional ByVal Progression As Single = 0) As Integer '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Summon_Begin '***************************************************************** Dim EffectIndex As Integer Dim LoopC As Long 'Get the next open effect slot EffectIndex = Effect_NextOpenSlot If EffectIndex = -1 Then Exit Function 'Return the index of the used slot Effect_Summon_Begin = EffectIndex 'Set The Effect's Variables Effect(EffectIndex).EffectNum = EffectNum_Summon 'Set the effect number Effect(EffectIndex).ParticleCount = Particles 'Set the number of particles Effect(EffectIndex).Used = True 'Enable the effect Effect(EffectIndex).X = X 'Set the effect's X coordinate Effect(EffectIndex).Y = Y 'Set the effect's Y coordinate Effect(EffectIndex).Gfx = Gfx 'Set the graphic Effect(EffectIndex).Progression = Progression 'If we loop the effect 'Set the number of particles left to the total avaliable Effect(EffectIndex).ParticlesLeft = Effect(EffectIndex).ParticleCount 'Set the float variables Effect(EffectIndex).FloatSize = Effect_FToDW(8) 'Size of the particles 'Redim the number of particles ReDim Effect(EffectIndex).Particles(0 To Effect(EffectIndex).ParticleCount) ReDim Effect(EffectIndex).PartVertex(0 To Effect(EffectIndex).ParticleCount) 'Create the particles For LoopC = 0 To Effect(EffectIndex).ParticleCount Set Effect(EffectIndex).Particles(LoopC) = New Particle Effect(EffectIndex).Particles(LoopC).Used = True Effect(EffectIndex).PartVertex(LoopC).Rhw = 1 Effect_Summon_Reset EffectIndex, LoopC Next LoopC 'Set The Initial Time Effect(EffectIndex).PreviousFrame = timeGetTime End Function Private Sub Effect_Summon_Reset(ByVal EffectIndex As Integer, ByVal Index As Long) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Summon_Reset '***************************************************************** Dim X As Single Dim Y As Single Dim R As Single If Effect(EffectIndex).Progression > 1000 Then Effect(EffectIndex).Progression = Effect(EffectIndex).Progression + 1.4 Else Effect(EffectIndex).Progression = Effect(EffectIndex).Progression + 0.5 End If R = (Index / 30) * EXP(Index / Effect(EffectIndex).Progression) X = R * Cos(Index) Y = R * Sin(Index) 'Reset the particle Effect(EffectIndex).Particles(Index).ResetIt Effect(EffectIndex).X + X, Effect(EffectIndex).Y + Y, 0, 0, 0, 0 Effect(EffectIndex).Particles(Index).ResetColor 0, Rnd, 0, 0.9, 0.2 + (Rnd * 0.2) End Sub Private Sub Effect_Summon_Update(ByVal EffectIndex As Integer) '***************************************************************** 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Summon_Update '***************************************************************** Dim ElapsedTime As Single Dim LoopC As Long 'Calculate The Time Difference ElapsedTime = (timeGetTime - Effect(EffectIndex).PreviousFrame) * 0.01 Effect(EffectIndex).PreviousFrame = timeGetTime 'Go Through The Particle Loop For LoopC = 0 To Effect(EffectIndex).ParticleCount 'Check If Particle Is In Use If Effect(EffectIndex).Particles(LoopC).Used Then 'Update The Particle Effect(EffectIndex).Particles(LoopC).UpdateParticle ElapsedTime 'Check if the particle is ready to die If Effect(EffectIndex).Particles(LoopC).sngA <= 0 Then 'Check if the effect is ending If Effect(EffectIndex).Progression < 1800 Then 'Reset the particle Effect_Summon_Reset EffectIndex, LoopC Else 'Disable the particle Effect(EffectIndex).Particles(LoopC).Used = False 'Subtract from the total particle count Effect(EffectIndex).ParticlesLeft = Effect(EffectIndex).ParticlesLeft - 1 'Check if the effect is out of particles If Effect(EffectIndex).ParticlesLeft = 0 Then Effect(EffectIndex).Used = False 'Clear the color (dont leave behind any artifacts) Effect(EffectIndex).PartVertex(LoopC).Color = 0 End If Else 'Set the particle information on the particle vertex Effect(EffectIndex).PartVertex(LoopC).Color = D3DColorMake(Effect(EffectIndex).Particles(LoopC).sngR, Effect(EffectIndex).Particles(LoopC).sngG, Effect(EffectIndex).Particles(LoopC).sngB, Effect(EffectIndex).Particles(LoopC).sngA) Effect(EffectIndex).PartVertex(LoopC).X = Effect(EffectIndex).Particles(LoopC).sngX Effect(EffectIndex).PartVertex(LoopC).Y = Effect(EffectIndex).Particles(LoopC).sngY End If End If Next LoopC End Sub
[edit] PictureTextBox
Option Explicit 'Notice - Text boxes must be multiline for this to work! 'I know this isn't the best way to go about doing this, but it isn't 'used for very long nor is it used in any other projects, so no point in wasting time 'making it very versitile 'Holds the returns from SetWindowLong Private frmNewPrev As Long Private frmConnectPrev As Long 'APIs we will be using Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long Private Declare Function BitBlt Lib "GDI32" (ByVal hDC As Long, ByVal DX As Long, ByVal DY As Long, ByVal DWidth As Long, ByVal DHeight As Long, ByVal ShDC As Long, ByVal SX As Long, ByVal SY As Long, ByVal vbSrCopy As Long) As Long Private Declare Function SetBkMode Lib "GDI32" (ByVal hDC As Long, ByVal hMode As Long) As Long Private Declare Function WindowFromDC Lib "user32" (ByVal hDC As Long) As Long Public Sub SetPictureTextboxes(ByVal hwnd As Long) '***************************************************************** 'Sets the textboxes either on frmConnect or frmNew to a picture background 'More info: http://www.vbgore.com/GameClient.PictureTextBox.SetPictureTextboxes '***************************************************************** 'Set the form to subclass and the textbox heights Select Case hwnd Case frmConnect.hwnd frmConnectPrev = SetWindowLong(hwnd, -4, AddressOf frmConnectProc) With frmConnect .NameTxt.Height = Int(.NameTxt.Height \ .TextHeight("_")) * .TextHeight("_") .PasswordTxt.Height = Int(.PasswordTxt.Height \ .TextHeight("_")) * .TextHeight("_") End With Case frmNew.hwnd frmNewPrev = SetWindowLong(hwnd, -4, AddressOf frmNewProc) With frmNew .NameTxt.Height = Int(.NameTxt.Height \ .TextHeight("_")) * .TextHeight("_") .PasswordTxt.Height = Int(.PasswordTxt.Height \ .TextHeight("_")) * .TextHeight("_") End With End Select End Sub Public Sub FreePictureTextboxes(ByVal hwnd As Long) '***************************************************************** 'Removes the picture textboxes (must be done when the form is unloaded!) 'More info: http://www.vbgore.com/GameClient.PictureTextBox.FreePictureTextboxes '***************************************************************** 'Free the form Select Case hwnd Case frmConnect.hwnd SetWindowLong hwnd, -4, frmConnectPrev Case frmNew.hwnd SetWindowLong hwnd, -4, frmNewPrev End Select End Sub Private Function frmNewProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long '***************************************************************** 'Subclassing routine for frmNew 'More info: http://www.vbgore.com/GameClient.PictureTextBox.frmNewProc '***************************************************************** 'Check for a message we want If uMsg = &H133 Then 'Make sure our form is visible If frmNew.Visible Then 'Look for the hWnds we want and handle accordingly Select Case WindowFromDC(wParam) Case frmNew.PasswordTxt.hwnd With frmNew.PasswordTxt SetBkMode wParam, 1 BitBlt wParam, 0, 0, .Width, .Height, frmNew.hDC, .Left, .Top, vbSrcCopy End With Case frmNew.NameTxt.hwnd With frmNew.NameTxt SetBkMode wParam, 1 BitBlt wParam, 0, 0, .Width, .Height, frmNew.hDC, .Left, .Top, vbSrcCopy End With Case frmNew.ClassCmb.hwnd With frmNew.ClassCmb SetBkMode wParam, 1 BitBlt wParam, 0, 0, .Width, .Height, frmNew.hDC, .Left, .Top, vbSrcCopy End With Case frmNew.BodyCmb.hwnd With frmNew.BodyCmb SetBkMode wParam, 1 BitBlt wParam, 0, 0, .Width, .Height, frmNew.hDC, .Left, .Top, vbSrcCopy End With Case frmNew.HeadCmb.hwnd With frmNew.HeadCmb SetBkMode wParam, 1 BitBlt wParam, 0, 0, .Width, .Height, frmNew.hDC, .Left, .Top, vbSrcCopy End With End Select End If End If 'Send the message to the form frmNewProc = CallWindowProc(frmNewPrev, hwnd, uMsg, wParam, lParam) End Function Private Function frmConnectProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long '***************************************************************** 'Subclassing routine for frmConnect 'More info: http://www.vbgore.com/GameClient.PictureTextBox.frmConnectProc '***************************************************************** 'Check for a message we want If uMsg = &H133 Then 'Make sure our form is visible If frmConnect.Visible Then 'Look for the hWnds we want and handle accordingly Select Case WindowFromDC(wParam) Case frmConnect.PasswordTxt.hwnd With frmConnect.PasswordTxt SetBkMode wParam, 1 BitBlt wParam, 0, 0, .Width, .Height, frmConnect.hDC, .Left, .Top, vbSrcCopy End With Case frmConnect.NameTxt.hwnd With frmConnect.NameTxt SetBkMode wParam, 1 BitBlt wParam, 0, 0, .Width, .Height, frmConnect.hDC, .Left, .Top, vbSrcCopy End With End Select End If End If 'Send the message to the form frmConnectProc = CallWindowProc(frmConnectPrev, hwnd, uMsg, wParam, lParam) End Function
[edit] Sound
Option Explicit Public Const SoundBufferTimerMax As Long = 300000 'How long a sound stays in memory unused (miliseconds) Public SoundBufferTimer() As Long 'How long until the sound buffer unloads Public DS As DirectSound8 Public DSBDesc As DSBUFFERDESC Public DSBuffer() As DirectSoundSecondaryBuffer8 Public Sub Sound_Init() '************************************************************ 'Initialize the 3D sound device 'More info: http://www.vbgore.com/GameClient.Sound.Sound_Init '************************************************************ 'Make sure we try not to load a file while the engine is unloading If IsUnloading Then Exit Sub On Error GoTo ErrOut If UseSfx = 0 Then Exit Sub 'Create the DirectSound device (with the default device) Set DS = DX.DirectSoundCreate("") DS.SetCooperativeLevel frmMain.hwnd, DSSCL_PRIORITY 'Set up the buffer description for later use 'We are only using panning and volume - combined, we will use this to create a custom 3D effect DSBDesc.lFlags = DSBCAPS_CTRLPAN Or DSBCAPS_CTRLVOLUME 'Check if the texture exists If Engine_FileExist(SfxPath & "Sfx.ini", vbNormal) = False Then MsgBox "Error! Could not find the following data file:" & vbCrLf & SfxPath & "Sfx.ini", vbOKOnly IsUnloading = 1 Exit Sub End If 'Get the number of sound effects NumSfx = Val(Var_Get(SfxPath & "Sfx.ini", "INIT", "NumSfx")) 'Resize the sound buffer array If NumSfx > 0 Then ReDim DSBuffer(1 To NumSfx) ReDim SoundBufferTimer(1 To NumSfx) End If On Error GoTo 0 Exit Sub ErrOut: 'Failure loading sounds, so we won't use them UseSfx = 0 UseMusic = 0 End Sub Public Sub Sound_SetToMap(ByVal SoundID As Integer, ByVal TileX As Byte, ByVal TileY As Byte) '************************************************************ 'Create a looping sound on the tile 'More info: http://www.vbgore.com/GameClient.Sound.Sound_SetToMap '************************************************************ If UseSfx = 0 Then Exit Sub 'Make sure the sound isn't already going If Not MapData(TileX, TileY).Sfx Is Nothing Then MapData(TileX, TileY).Sfx.Stop Set MapData(TileX, TileY).Sfx = Nothing End If 'Create the buffer Sound_Set MapData(TileX, TileY).Sfx, SoundID 'Exit if theres an error If MapData(TileX, TileY).Sfx Is Nothing Then Exit Sub 'Start the loop MapData(TileX, TileY).Sfx.Play DSBPLAY_LOOPING 'Since we dont want to start hearing the sound until we have calculated the panning/volume, we set the volume to off for now MapData(TileX, TileY).Sfx.SetVolume -10000 End Sub Public Sub Sound_UpdateMap() '************************************************************ 'Update the panning and volume on the map sounds to create a 3d effect 'More info: http://www.vbgore.com/GameClient.Sound.Sound_UpdateMap '************************************************************ Dim SX As Integer Dim SY As Integer Dim X As Byte Dim Y As Byte Dim L As Long If UseSfx = 0 Then Exit Sub 'Set the user's position to sX/sY SX = CharList(UserCharIndex).Pos.X SY = CharList(UserCharIndex).Pos.Y 'Loop through all the map tiles For X = 1 To MapInfo.Width For Y = 1 To MapInfo.Height 'Only update used tiles If Not MapData(X, Y).Sfx Is Nothing Then 'Calculate the volume and check for valid range L = Sound_CalcVolume(SX, SY, X, Y) If L < -5000 Then MapData(X, Y).Sfx.Stop Else If L > 0 Then L = 0 If MapData(X, Y).Sfx.GetStatus <> DSBSTATUS_LOOPING Then MapData(X, Y).Sfx.Play DSBPLAY_LOOPING MapData(X, Y).Sfx.SetVolume L End If 'Calculate the panning and check for a valid range L = Sound_CalcPan(SX, X) If L > 10000 Then L = 10000 If L < -10000 Then L = -10000 MapData(X, Y).Sfx.SetPan L End If Next Y Next X End Sub Public Sub Sound_Play(ByRef SoundBuffer As DirectSoundSecondaryBuffer8, Optional ByVal flags As CONST_DSBPLAYFLAGS = DSBPLAY_DEFAULT) '************************************************************ 'Used for non area-specific sound effects, such as weather 'More info: http://www.vbgore.com/GameClient.Sound.Sound_Play '************************************************************ 'Make sure we are using sound If UseSfx = 0 Then Exit Sub 'Confirm the buffer exists If Not SoundBuffer Is Nothing Then 'Reset the sounds values (in case they were ever changed) SoundBuffer.SetCurrentPosition 0 Sound_Pan SoundBuffer, 0 Sound_Volume SoundBuffer, 0 'Play the sound SoundBuffer.Play flags End If End Sub Public Sub Sound_Erase(ByRef SoundBuffer As DirectSoundSecondaryBuffer8) '************************************************************ 'Erase the sound buffer 'More info: http://www.vbgore.com/GameClient.Sound.Sound_Erase '************************************************************ If UseSfx = 0 Then Exit Sub 'Make sure the object exists If Not SoundBuffer Is Nothing Then 'If it is playing, we have to stop it first If SoundBuffer.GetStatus > 0 Then SoundBuffer.Stop 'Clear the object Set SoundBuffer = Nothing End If End Sub Public Sub Sound_Set(ByRef SoundBuffer As DirectSoundSecondaryBuffer8, ByVal SoundID As Integer) '************************************************************ 'Set the SoundID to the sound buffer 'More info: http://www.vbgore.com/GameClient.Sound.Sound_Set '************************************************************ If UseSfx = 0 Then Exit Sub 'Check if the sound buffer is in use Sound_Erase SoundBuffer 'Set the buffer If Engine_FileExist(SfxPath & SoundID & ".wav", vbNormal) Then Set SoundBuffer = DS.CreateSoundBufferFromFile(SfxPath & SoundID & ".wav", DSBDesc) End Sub Public Sub Sound_Play3D(ByVal SoundID As Integer, ByVal TileX As Integer, ByVal TileY As Integer) '************************************************************ 'Play a pseudo-3D sound by the sound buffer ID 'More info: http://www.vbgore.com/GameClient.Sound.Sound_Play3D '************************************************************ Dim SX As Integer Dim SY As Integer If UseSfx = 0 Then Exit Sub 'Make sure we have the UserCharIndex, or else we cant play the sound! :o If UserCharIndex = 0 Then Exit Sub 'Check for a valid sound If SoundID <= 0 Then Exit Sub 'Create the buffer if needed If SoundBufferTimer(SoundID) < timeGetTime Then If DSBuffer(SoundID) Is Nothing Then Sound_Set DSBuffer(SoundID), SoundID End If 'Update the timer SoundBufferTimer(SoundID) = timeGetTime + SoundBufferTimerMax 'Clear the position (used in case the sound was already playing - we can only have one of each sound play at a time) DSBuffer(SoundID).SetCurrentPosition 0 'Set the user's position to sX/sY SX = CharList(UserCharIndex).Pos.X SY = CharList(UserCharIndex).Pos.Y 'Calculate the panning Sound_Pan DSBuffer(SoundID), Sound_CalcPan(SX, TileX) 'Calculate the volume Sound_Volume DSBuffer(SoundID), Sound_CalcVolume(SX, SY, TileX, TileY) 'Play the sound DSBuffer(SoundID).Play DSBPLAY_DEFAULT End Sub Public Function Sound_CalcPan(ByVal x1 As Integer, ByVal x2 As Integer) As Long '************************************************************ 'Calculate the panning for 3D sound based on the user's position and the sound's position 'More info: http://www.vbgore.com/GameClient.Sound.Sound_CalcPan '************************************************************ If UseSfx = 0 Then Exit Function Sound_CalcPan = (x1 - x2) * 75 * ReverseSound End Function Public Function Sound_CalcVolume(ByVal x1 As Integer, ByVal Y1 As Integer, ByVal x2 As Integer, ByVal Y2 As Integer) As Long '************************************************************ 'Calculate the volume for 3D sound based on the user's position and the sound's position 'the (Abs(sX - TileX) * 25) is put on the end to make up for the simulated ' volume loss during panning (since one speaker gets muted to create the panning) 'More info: http://www.vbgore.com/GameClient.Sound.Sound_CalcVolume '************************************************************ Dim Dist As Single If UseSfx = 0 Then Exit Function 'Store the distance Dist = Sqr(((Y1 - Y2) * (Y1 - Y2)) + ((x1 - x2) * (x1 - x2))) 'Apply the initial value Sound_CalcVolume = -(Dist * 80) + (Abs(x1 - x2) * 25) 'Once we get out of the screen (>= 13 tiles away) then we want to fade fast If Dist > 13 Then Sound_CalcVolume = Sound_CalcVolume - ((Dist - 13) * 180) End Function Private Sub Sound_Pan(ByRef SoundBuffer As DirectSoundSecondaryBuffer8, ByVal Value As Long) '************************************************************ 'Pan the selected SoundID (-10,000 to 10,000) 'More info: http://www.vbgore.com/GameClient.Sound.Sound_Pan '************************************************************ If UseSfx = 0 Then Exit Sub If SoundBuffer Is Nothing Then Exit Sub SoundBuffer.SetPan Value End Sub Private Sub Sound_Volume(ByRef SoundBuffer As DirectSoundSecondaryBuffer8, ByVal Value As Long) '************************************************************ 'Pan the selected SoundID (-10,000 to 0) 'More info: http://www.vbgore.com/GameClient.Sound.Sound_Volume '************************************************************ If UseSfx = 0 Then Exit Sub If SoundBuffer Is Nothing Then Exit Sub If Value > 0 Then Value = 0 If Value < -10000 Then Value = -10000 SoundBuffer.SetVolume Value End Sub Public Sub Music_Load(ByVal FilePath As String, ByVal BufferNumber As Long) '************************************************************ 'Loads a mp3 by the specified path 'More info: http://www.vbgore.com/GameClient.Sound.Music_Load '************************************************************ If UseMusic = 0 Then Exit Sub On Error GoTo Error_Handler If Right$(FilePath, 4) = ".mp3" Then Set DirectShow_Control(BufferNumber) = New FilgraphManager DirectShow_Control(BufferNumber).RenderFile FilePath Set DirectShow_Audio(BufferNumber) = DirectShow_Control(BufferNumber) DirectShow_Audio(BufferNumber).Volume = 0 DirectShow_Audio(BufferNumber).Balance = 0 Set DirectShow_Event(BufferNumber) = DirectShow_Control(BufferNumber) Set DirectShow_Position(BufferNumber) = DirectShow_Control(BufferNumber) DirectShow_Position(BufferNumber).Rate = 1 DirectShow_Position(BufferNumber).CurrentPosition = 0 End If Error_Handler: End Sub Public Sub Music_Play(ByVal BufferNumber As Long) '************************************************************ 'Plays the mp3 in the specified buffer 'More info: http://www.vbgore.com/GameClient.Sound.Music_Play '************************************************************ On Error GoTo Error_Handler If UseMusic = 0 Then Exit Sub DirectShow_Control(BufferNumber).Run Error_Handler: End Sub Public Sub Music_Stop(ByVal BufferNumber As Long) '************************************************************ 'Stops the mp3 in the specified buffer 'More info: http://www.vbgore.com/GameClient.Sound.Music_Stop '************************************************************ On Error GoTo Error_Handler If UseMusic = 0 Then Exit Sub DirectShow_Control(BufferNumber).Stop DirectShow_Position(BufferNumber).CurrentPosition = 0 Exit Sub Error_Handler: End Sub Public Sub Music_Pause(ByVal BufferNumber As Long) '************************************************************ 'Pause the music in the specified buffer 'More info: http://www.vbgore.com/GameClient.Sound.Music_Pause '************************************************************ On Error GoTo Error_Handler If UseMusic = 0 Then Exit Sub DirectShow_Control(BufferNumber).Stop Error_Handler: End Sub Public Sub Music_Volume(ByVal Volume As Long, ByVal BufferNumber As Long) '************************************************************ 'Set the volume of the music in the specified buffer 'More info: http://www.vbgore.com/GameClient.Sound.Music_Volume '************************************************************ On Error GoTo Error_Handler If UseMusic = 0 Then Exit Sub If Volume >= Music_MaxVolume Then Volume = Music_MaxVolume If Volume <= 0 Then Volume = 0 DirectShow_Audio(BufferNumber).Volume = (Volume * Music_MaxVolume) - 10000 Error_Handler: End Sub Public Sub Music_Balance(ByVal Balance As Long, ByVal BufferNumber As Long) '************************************************************ 'Set the balance of the music in the specified buffer 'More info: http://www.vbgore.com/GameClient.Sound.Music_Balance '************************************************************ On Error GoTo Error_Handler If UseMusic = 0 Then Exit Sub If Balance >= Music_MaxBalance Then Balance = Music_MaxBalance If Balance <= -Music_MaxBalance Then Balance = -Music_MaxBalance DirectShow_Audio(BufferNumber).Balance = Balance * Music_MaxBalance Error_Handler: End Sub Public Sub Music_Speed(ByVal Speed As Single, ByVal BufferNumber As Long) '************************************************************ 'Set the speed of the music in the specified buffer 'More info: http://www.vbgore.com/GameClient.Sound.Music_Speed '************************************************************ On Error GoTo Error_Handler If UseMusic = 0 Then Exit Sub If Speed >= Music_MaxSpeed Then Speed = Music_MaxSpeed If Speed <= 0 Then Speed = 0 DirectShow_Position(BufferNumber).Rate = Speed / 100 Error_Handler: End Sub Public Sub Music_SetPosition(ByVal Hours As Long, ByVal Minutes As Long, ByVal Seconds As Long, Milliseconds As Single, ByVal BufferNumber As Long) '************************************************************ 'Set the speed of the music in the specified buffer 'More info: http://www.vbgore.com/GameClient.Sound.Music_SetPosition '************************************************************ On Error GoTo Error_Handler Dim Max_Position As Single Dim Position As Double Dim Decimal_Milliseconds As Single If UseMusic = 0 Then Exit Sub 'Keep minutes within range Minutes = Minutes Mod 60 'Keep seconds within range Seconds = Seconds Mod 60 'Keep milliseconds within range and keep decimal Decimal_Milliseconds = Milliseconds - Int(Milliseconds) Milliseconds = Milliseconds Mod 1000 Milliseconds = Milliseconds + Decimal_Milliseconds 'Convert Minutes & Seconds to Position time Position = (Hours * 3600) + (Minutes * 60) + Seconds + (Milliseconds * 0.001) Max_Position = DirectShow_Position(BufferNumber).StopTime If Position >= Max_Position Then Position = 0 GoTo Error_Handler End If If Position <= 0 Then Position = 0 GoTo Error_Handler End If DirectShow_Position(BufferNumber).CurrentPosition = Position Error_Handler: End Sub Public Sub Music_End(ByVal BufferNumber As Long) '************************************************************ 'End the music in the specified buffer 'More info: http://www.vbgore.com/GameClient.Sound.Music_End '************************************************************ On Error GoTo Error_Handler If UseMusic = 0 Then Exit Sub 'Check if the buffer is looping If Not Music_Loop(BufferNumber) Then 'Check if the current position is past the stop time If DirectShow_Position(BufferNumber).CurrentPosition >= DirectShow_Position(BufferNumber).StopTime Then Music_Stop BufferNumber End If Error_Handler: End Sub Public Function Music_Loop(ByVal Media_Number As Long) As Boolean '************************************************************ 'Loop the music in the specified buffer 'More info: http://www.vbgore.com/GameClient.Sound.Music_Loop '************************************************************ On Error GoTo Error_Handler If UseMusic = 0 Then Exit Function 'Check if the current position is past the stop time - if so, reset it If DirectShow_Position(Media_Number).CurrentPosition >= DirectShow_Position(Media_Number).StopTime Then DirectShow_Position(Media_Number).CurrentPosition = 0 End If Music_Loop = True Exit Function Error_Handler: Music_Loop = False End Function
[edit] TCP
Option Explicit '************************************************************ 'ABOUT THE TCP MODULE PACKET HEADER COMMENTS '************************************************************ 'All Data_ methods in the TCP module, in both the server and client, are used to handle 'packets coming in to the application (forwarded from GOREsock_DataArrival). These methods 'all contain a comment in their header on how the packet is formatted. For example: ' '<Name(S)><Class(B)><Etc(L)> ' 'Each <> denotes a different variable. Inside the <>, you see two parts - the name of the 'packet part and the variable type. For example: ' '<Name(S)> ' 'The name of the packet part is "Name", and the variable type is S. Below is a list 'of all variable types used: ' 'B = Byte (1 byte) 'I = Integer (2 bytes) 'L = Long (4 bytes) 'S = String aka Short String(1 + string length bytes) 'S-EX = StringEX aka Long String (2 + string length bytes) '************************************************************ Private Type typHOSTENT hName As Long hAliases As Long hAddrType As Integer hLength As Integer hAddrList As Long End Type Private Type WSADATA wversion As Integer wHighVersion As Integer szDescription(0 To 255) As Byte szSystemStatus(0 To 127) As Byte iMaxSockets As Integer iMaxUdpDg As Integer lpszVendorInfo As Long End Type Private Declare Sub apiCopyMemory Lib "kernel32" Alias "RtlMoveMemory" (hpvDest As Any, ByVal hpvSource As Long, ByVal cbCopy As Long) Private Declare Function apiGetHostByName Lib "wsock32" Alias "gethostbyname" (ByVal HostName As String) As Long Private Declare Function WSACleanup Lib "wsock32" () As Long Private Declare Function WSAStartup Lib "wsock32" (ByVal VersionReq As Long, WSADataReturn As WSADATA) As Long Private Function IsIP(ByVal IPAddress As String) As Boolean '************************************************************ 'Checks if a string is in a valid IP address format 'More info: http://www.vbgore.com/GameClient.TCP.IsIP '************************************************************ Dim s() As String Dim i As Long 'If there are no periods, I have no idea what we have... If InStr(1, IPAddress, ".") = 0 Then Exit Function 'Split up the string by the periods s = Split(IPAddress, ".") 'Confirm we have ubound = 3, since xxx.xxx.xxx.xxx has 4 elements and we start at index 0 If UBound(s) <> 3 Then Exit Function 'Check that the values are numeric and in a valid range For i = 0 To 3 If Val(s(i)) < 0 Then Exit Function If Val(s(i)) > 255 Then Exit Function Next i 'Looks like we were passed a valid IP! IsIP = True End Function Public Function GetIPFromHost(ByVal HostName As String) As String '************************************************************ 'Returns the IP address given a host name (such as "www.vbgore.com" to 123.45.6.7) 'More info: http://www.vbgore.com/GameClient.TCP.GetIPFromHost '************************************************************ Dim udtWSAData As WSADATA Dim HostAddress As Long Dim HostInfo As typHOSTENT Dim IPLong As Long Dim IPBytes() As Byte Dim i As Integer On Error Resume Next If WSAStartup(257, udtWSAData) Then MsgBox "Error initializing winsock on WSAStartup!" GetIPFromHost = HostName Exit Function End If 'Make sure a HTTP:// or FTP:// something wasn't added... some people like to do that If UCase$(Left$(HostName, 7)) = "HTTP://" Then HostName = Right$(HostName, Len(HostName) - 7) ElseIf UCase$(Left$(HostName, 6)) = "FTP://" Then HostName = Right$(HostName, Len(HostName) - 6) End If 'If we were already passed an IP, just abort since we have what we want If IsIP(HostName) Then GetIPFromHost = HostName Exit Function End If 'Get the host address HostAddress = apiGetHostByName(HostName) 'Failure! If HostAddress = 0 Then Exit Function 'Move the memory around to get it in a format we can read apiCopyMemory HostInfo, HostAddress, LenB(HostInfo) apiCopyMemory IPLong, HostInfo.hAddrList, 4 'Get the number of parts to the IP (will always be 4 as far as I know) ReDim IPBytes(1 To HostInfo.hLength) 'Convert the address, stored in the format of a long, to 4 bytes (just simple long -> byte array conversion) apiCopyMemory IPBytes(1), IPLong, HostInfo.hLength 'Add in the periods For i = 1 To HostInfo.hLength GetIPFromHost = GetIPFromHost & IPBytes(i) & "." Next 'Remove the final period GetIPFromHost = Left$(GetIPFromHost, Len(GetIPFromHost) - 1) 'Clean up the socket WSACleanup On Error GoTo 0 End Function Sub InitSocket() '***************************************************************** 'Init the GOREsock socket 'More info: http://www.vbgore.com/GameClient.TCP.InitSocket '***************************************************************** 'Save the game ini Call Var_Write(DataPath & "Game.ini", "INIT", "Name", UserName) If Not SavePass Then 'If the password wont be saved, clear it out Call Var_Write(DataPath & "Game.ini", "INIT", "Password", "") Else Call Var_Write(DataPath & "Game.ini", "INIT", "Password", UserPassword) End If 'Clear the SoxID SoxID = 0 'Clean out the socket so we can make a fresh new connection If frmMain.GOREsock.ShutDown <> soxERROR Then 'Set up the socket 'Leave the GetIPFromHost() wrapper there, this will convert a host name to IP if needed, or leave it as an IP if you pass an IP SoxID = frmMain.GOREsock.Connect(GetIPFromHost("127.0.0.1"), 10200) 'If the SoxID = -1, then the connection failed, elsewise, we're good to go! W00t! ^_^ If SoxID = -1 Then MsgBox "Unable to connect to the game server!" & vbCrLf & "Either the server is down or you are not connected to the internet.", vbOKOnly Else frmMain.GOREsock.SetOption SoxID, soxSO_TCP_NODELAY, True End If End If End Sub Sub Data_User_Trade_Trade(ByRef rBuf As DataBuffer) '************************************************************ 'Begins the trading sequence '<Name(S)><MyIndex(B)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_User_Trade_Trade '************************************************************ Dim i As Long For i = 1 To 9 TradeTable.Trade1(i).Amount = 0 TradeTable.Trade1(i).Grh = 0 TradeTable.Trade1(i).Name = vbNullString TradeTable.Trade1(i).Value = 0 TradeTable.Trade2(i).Amount = 0 TradeTable.Trade2(i).Grh = 0 TradeTable.Trade2(i).Name = vbNullString TradeTable.Trade2(i).Value = 0 Next i TradeTable.Gold1 = 0 TradeTable.Gold2 = 0 TradeTable.User1Accepted = 0 TradeTable.User2Accepted = 0 TradeTable.User1Name = vbNullString TradeTable.User2Name = vbNullString TradeTable.MyIndex = 0 TradeTable.User1Name = rBuf.Get_String TradeTable.User2Name = rBuf.Get_String TradeTable.MyIndex = rBuf.Get_Byte ShowGameWindow(TradeWindow) = 1 LastClickedWindow = TradeWindow End Sub Sub Data_User_Trade_UpdateTrade(ByRef rBuf As DataBuffer) '************************************************************ 'Update something about the trade currently taking place '<UserTableIndex(B)><TableSlot(B)><Amount(L)> (<GrhIndex(L)><ObjName(S)><ObjValue(L)>) 'More info: http://www.vbgore.com/GameClient.TCP.Data_User_Trade_UpdateTrade '************************************************************ Dim UserTableIndex As Byte Dim TableSlot As Byte Dim Amount As Long Dim GrhIndex As Long Dim ObjName As String Dim ObjValue As Long UserTableIndex = rBuf.Get_Byte TableSlot = rBuf.Get_Byte Amount = rBuf.Get_Long 'Update the gold If TableSlot = 0 Then If TradeTable.MyIndex = UserTableIndex Then TradeTable.Gold1 = Amount Else TradeTable.Gold2 = Amount End If 'Update an item ElseIf TableSlot <= 9 Then GrhIndex = rBuf.Get_Long ObjName = rBuf.Get_String ObjValue = rBuf.Get_Long If TradeTable.MyIndex = UserTableIndex Then TradeTable.Trade1(TableSlot).Amount = Amount TradeTable.Trade1(TableSlot).Grh = GrhIndex TradeTable.Trade1(TableSlot).Name = ObjName TradeTable.Trade1(TableSlot).Value = ObjValue Else TradeTable.Trade2(TableSlot).Amount = Amount TradeTable.Trade2(TableSlot).Grh = GrhIndex TradeTable.Trade2(TableSlot).Name = ObjName TradeTable.Trade2(TableSlot).Value = ObjValue End If End If End Sub Sub Data_User_Bank_UpdateSlot(ByRef rBuf As DataBuffer) '************************************************************ 'Updates a specific bank item '<Slot(B)><GrhIndex(L)> If GrhIndex > 0, <Amount(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_User_Bank_UpdateSlot '************************************************************ Dim GrhIndex As Long Dim Amount As Integer Dim Slot As Byte 'Get the values Slot = rBuf.Get_Byte GrhIndex = rBuf.Get_Long 'Check if to get the amount If GrhIndex > 0 Then Amount = rBuf.Get_Integer 'Update the item UserBank(Slot).Amount = Amount UserBank(Slot).GrhIndex = GrhIndex End Sub Sub Data_User_Bank_Open(ByRef rBuf As DataBuffer) '************************************************************ 'Sends the list of bank items 'Loop: <Slot(B)><GrhIndex(L)><Amount(I)> until Slot = 255 'More info: http://www.vbgore.com/GameClient.TCP.Data_User_Bank_Open '************************************************************ Dim GrhIndex As Long Dim Amount As Integer Dim Slot As Byte 'Loop through the items until we get the terminator slot (255) Do 'Get the slot Slot = rBuf.Get_Byte 'Check if we have acquired the terminator slot If Slot = 255 Then Exit Do 'Get the amount and obj index GrhIndex = rBuf.Get_Long Amount = rBuf.Get_Integer 'Store the values UserBank(Slot).Amount = Amount UserBank(Slot).GrhIndex = GrhIndex Loop 'Show the bank window ShowGameWindow(BankWindow) = 1 LastClickedWindow = BankWindow End Sub Sub Data_Server_MakeProjectile(ByRef rBuf As DataBuffer) '************************************************************ 'Create a projectile from a ranged weapon '<AttackerIndex(I)><TargetIndex(I)><GrhIndex(L)><Rotate(B)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_MakeProjectile '************************************************************ Dim AttackerIndex As Integer Dim TargetIndex As Integer Dim GrhIndex As Long Dim Rotate As Byte AttackerIndex = rBuf.Get_Integer TargetIndex = rBuf.Get_Integer GrhIndex = rBuf.Get_Long Rotate = rBuf.Get_Byte 'If the char doesn't exist, request to create it If Not Engine_ValidChar(AttackerIndex) Then Exit Sub If Not Engine_ValidChar(TargetIndex) Then Exit Sub 'Create the projectile Engine_Projectile_Create AttackerIndex, TargetIndex, GrhIndex, Rotate End Sub Sub Data_User_SetWeaponRange(ByRef rBuf As DataBuffer) '************************************************************ 'Set the range of the current weapon used so we can do client-side ' distance checks before sending the attack to the server '<Range(B)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_User_SetWeaponRange '************************************************************ UserAttackRange = rBuf.Get_Byte End Sub Sub Data_Server_SetCharSpeed(ByRef rBuf As DataBuffer) '************************************************************ 'Update a char's speed so we can move them the right speed '<CharIndex(I)><Speed(B)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_SetCharSpeed '************************************************************ Dim CharIndex As Integer Dim Speed As Byte CharIndex = rBuf.Get_Integer Speed = rBuf.Get_Byte 'If the char doesn't exist, request to create it If Not Engine_ValidChar(CharIndex) Then Exit Sub CharList(CharIndex).Speed = Speed End Sub Sub Data_Server_Message(ByRef rBuf As DataBuffer) '************************************************************ 'Server sending a common message to client (reccomended you send ' as many messages as possible via this method to save bandwidth) '<MessageID(B)><...depends on the message> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_Message '************************************************************ Dim MessageID As Byte Dim TempStr As String Dim TempInt As Integer Dim Str1 As String Dim Str2 As String Dim Lng1 As Long Dim Int1 As Integer Dim Int2 As Integer Dim Int3 As Integer Dim Byt1 As Byte 'Get the message ID MessageID = rBuf.Get_Byte 'Check what to do depending on the message ID '*** Please refer to the language file for the description of the numbers *** Select Case MessageID Case 1 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(1), "<npcname>", Str1), FontColor_Info Case 2 Engine_AddToChatTextBuffer Message(2), FontColor_Fight Case 3 Lng1 = rBuf.Get_Long Engine_AddToChatTextBuffer Replace$(Message(3), "<exp>", Lng1), FontColor_Info Case 4 Lng1 = rBuf.Get_Long Engine_AddToChatTextBuffer Replace$(Message(4), "<gold>", Lng1), FontColor_Info Case 5 Byt1 = rBuf.Get_Byte Engine_AddToChatTextBuffer Replace$(Message(5), "<skill>", Engine_SkillIDtoSkillName(Byt1)), FontColor_Info Case 6 Byt1 = rBuf.Get_Byte Engine_AddToChatTextBuffer Replace$(Message(6), "<skill>", Engine_SkillIDtoSkillName(Byt1)), FontColor_Info Case 7 Engine_AddToChatTextBuffer Message(7), FontColor_Quest Case 8 Engine_AddToChatTextBuffer Message(8), FontColor_Quest Case 9 Int1 = rBuf.Get_Integer Str1 = rBuf.Get_String Int3 = rBuf.Get_Integer TempStr = Replace$(Message(9), "<amount>", Int1) TempStr = Replace$(TempStr, "<npcname>", Str1) Engine_AddToChatTextBuffer TempStr, FontColor_Quest Engine_MakeChatBubble Int3, Engine_WordWrap(TempStr, BubbleMaxWidth) Case 10 Int1 = rBuf.Get_Integer Str1 = rBuf.Get_String Int3 = rBuf.Get_Integer TempStr = Replace$(Message(10), "<amount>", Int1) TempStr = Replace$(TempStr, "<objname>", Str1) Engine_AddToChatTextBuffer TempStr, FontColor_Quest Engine_MakeChatBubble Int3, Engine_WordWrap(TempStr, BubbleMaxWidth) Case 11 Int1 = rBuf.Get_Integer Str1 = rBuf.Get_String Int2 = rBuf.Get_Integer Str2 = rBuf.Get_String Int3 = rBuf.Get_Integer TempStr = Replace$(Message(11), "<npcamount>", Int1) TempStr = Replace$(TempStr, "<npcname>", Str1) TempStr = Replace$(TempStr, "<objamount>", Int2) TempStr = Replace$(TempStr, "<objname>", Str2) Engine_AddToChatTextBuffer TempStr, FontColor_Quest Engine_MakeChatBubble Int3, Engine_WordWrap(TempStr, BubbleMaxWidth) Case 12 Engine_AddToChatTextBuffer Message(12), FontColor_Quest Case 13 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(13), "<name>", Str1), FontColor_Info Case 14 Lng1 = rBuf.Get_Long Engine_AddToChatTextBuffer Replace$(Message(14), "<cost>", Lng1), FontColor_Info Case 15 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(15), "<sender>", Str1), FontColor_Info Case 16 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(16), "<receiver>", Str1), FontColor_Info Case 17 Engine_AddToChatTextBuffer Message(17), FontColor_Info Case 18 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(18), "<sender>", Str1), FontColor_Info Case 19 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(19), "<receiver>", Str1), FontColor_Info Case 20 Engine_AddToChatTextBuffer Message(20), FontColor_Info Case 21 Lng1 = rBuf.Get_Long Engine_AddToChatTextBuffer Replace$(Message(21), "<cost>", Lng1), FontColor_Info Case 22 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(22), "<name>", Str1), FontColor_Info Case 23 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(23), "<name>", Str1), FontColor_Info Case 24 Engine_AddToChatTextBuffer Message(24), FontColor_Info Case 25 Engine_AddToChatTextBuffer Message(25), FontColor_Info Case 26 Engine_AddToChatTextBuffer Message(26), FontColor_Info Case 27 Int1 = rBuf.Get_Integer Str1 = rBuf.Get_String TempStr = Replace$(Message(27), "<amount>", Int1) Engine_AddToChatTextBuffer Replace$(TempStr, "<name>", Str1), FontColor_Info Case 28 Int1 = rBuf.Get_Integer Str1 = rBuf.Get_String TempStr = Replace$(Message(28), "<amount>", Int1) Engine_AddToChatTextBuffer Replace$(TempStr, "<name>", Str1), FontColor_Info Case 29 Engine_AddToChatTextBuffer Message(29), FontColor_Info Case 30 Str1 = rBuf.Get_String Str2 = rBuf.Get_String TempStr = Replace$(Message(30), "<name>", Str1) Engine_AddToChatTextBuffer Replace$(TempStr, "<desc>", Str2), FontColor_Info Case 31 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(31), "<name>", Str1), FontColor_Info Case 32 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(32), "<name>", Str1), FontColor_Info Case 33 Engine_AddToChatTextBuffer Message(33), FontColor_Info Case 34 Engine_AddToChatTextBuffer Message(34), FontColor_Info Case 35 Byt1 = rBuf.Get_Byte Engine_AddToChatTextBuffer Replace$(Message(35), "<amount>", Byt1), FontColor_Info Case 36 Engine_AddToChatTextBuffer Message(36), FontColor_Info Case 37 Engine_AddToChatTextBuffer Message(37), FontColor_Info Case 38 Engine_AddToChatTextBuffer Message(38), FontColor_Info Case 39 Str1 = rBuf.Get_String Str2 = rBuf.Get_String TempStr = Replace$(Message(39), "<skill>", Str1) Engine_AddToChatTextBuffer Replace$(TempStr, "<name>", Str2), FontColor_Info Case 40 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(40), "<name>", Str1), FontColor_Info Case 41 Str1 = rBuf.Get_String Int1 = rBuf.Get_Integer TempStr = Replace$(Message(41), "<name>", Str1) Engine_AddToChatTextBuffer Replace$(TempStr, "<power>", Int1), FontColor_Info Case 42 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(42), "<name>", Str1), FontColor_Info Case 43 Str1 = rBuf.Get_String Int1 = rBuf.Get_Integer TempStr = Replace$(Message(43), "<name>", Str1) Engine_AddToChatTextBuffer Replace$(TempStr, "<power>", Int1), FontColor_Info Case 44 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(44), "<name>", Str1), FontColor_Info Case 45 Str1 = rBuf.Get_String Int1 = rBuf.Get_Integer TempStr = Replace$(Message(45), "<name>", Str1) Engine_AddToChatTextBuffer Replace$(TempStr, "<power>", Int1), FontColor_Info Case 46 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(46), "<name>", Str1), FontColor_Info Case 47 Str1 = rBuf.Get_String Int1 = rBuf.Get_Integer TempStr = Replace$(Message(47), "<name>", Str1) Engine_AddToChatTextBuffer Replace$(TempStr, "<power>", Int1), FontColor_Info Case 48 Engine_AddToChatTextBuffer Message(48), FontColor_Info Case 49 Engine_AddToChatTextBuffer Message(49), FontColor_Info Case 50 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(50), "<name>", Str1), FontColor_Info Case 51 Engine_AddToChatTextBuffer Message(51), FontColor_Info Case 52 Str1 = rBuf.Get_String Str2 = rBuf.Get_String TempStr = Replace$(Message(52), "<name>", Str1) Engine_AddToChatTextBuffer Replace$(TempStr, "<message>", Str2), FontColor_Talk LastWhisperName = Str1 'Set the name of the last person to whisper us Case 53 Str1 = rBuf.Get_String Str2 = rBuf.Get_String TempStr = Replace$(Message(53), "<name>", Str1) Engine_AddToChatTextBuffer Replace$(TempStr, "<message>", Str2), FontColor_Talk Case 54 Str1 = rBuf.Get_String Byt1 = rBuf.Get_Byte TempStr = Replace$(Message(54), "<name>", Str1) Engine_AddToChatTextBuffer Replace$(TempStr, "<value>", Byt1), FontColor_Info Case 55 Lng1 = rBuf.Get_Long Engine_AddToChatTextBuffer Replace$(Message(55), "<value>", Lng1), FontColor_Info Case 56 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(56), "<name>", Str1), FontColor_Info Case 57 Engine_AddToChatTextBuffer Message(57), FontColor_Info Case 58 Str1 = rBuf.Get_String Int1 = rBuf.Get_Integer TempStr = Replace$(Message(58), "<name>", Str1) Engine_AddToChatTextBuffer Replace$(TempStr, "<amount>", Int1), FontColor_Info Case 59 Str1 = rBuf.Get_String Int1 = rBuf.Get_Integer Int2 = rBuf.Get_Integer TempStr = Replace$(Message(59), "<name>", Str1) TempStr = Replace$(TempStr, "<amount>", Int1) Engine_AddToChatTextBuffer Replace$(TempStr, "<leftover>", Int2), FontColor_Info Case 60 Engine_AddToChatTextBuffer Message(60), FontColor_Info Case 61 Engine_AddToChatTextBuffer Message(61), FontColor_Info Case 62 Lng1 = rBuf.Get_Long Engine_AddToChatTextBuffer Replace$(Message(62), "<level>", Lng1), FontColor_Info Case 63 Int1 = rBuf.Get_Integer Str1 = rBuf.Get_String TempStr = Replace$(Message(63), "<amount>", Int1) Engine_AddToChatTextBuffer Replace$(TempStr, "<name>", Str1), FontColor_Info Case 64 Engine_AddToChatTextBuffer Message(64), FontColor_Info Case 65 Int1 = rBuf.Get_Integer Str1 = rBuf.Get_String TempStr = Replace$(Message(65), "<amount>", Int1) Engine_AddToChatTextBuffer Replace$(TempStr, "<name>", Str1), FontColor_Info Case 66 Int1 = rBuf.Get_Integer Str1 = rBuf.Get_String Int2 = rBuf.Get_Integer TempStr = Replace$(Message(66), "<amount>", Int1) TempStr = Replace$(TempStr, "<name>", Str1) Engine_AddToChatTextBuffer Replace$(TempStr, "<leftover>", Int2), FontColor_Info Case 67 Int1 = rBuf.Get_Integer Str1 = rBuf.Get_String Lng1 = rBuf.Get_Long TempStr = Replace$(Message(67), "<amount>", Int1) TempStr = Replace$(TempStr, "<name>", Str1) Engine_AddToChatTextBuffer Replace$(TempStr, "<cost>", Lng1), FontColor_Info Case 68 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(68), "<name>", Str1), FontColor_Info Case 69 Engine_AddToChatTextBuffer Message(69), FontColor_Info Case 70 Engine_AddToChatTextBuffer Message(70), FontColor_Info Case 71 Byt1 = rBuf.Get_Byte Engine_AddToChatTextBuffer Replace$(Message(71), "<value>", Byt1), FontColor_Info Case 72 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(72), "<name>", Str1), FontColor_Info Case 73 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(73), "<name>", Str1), FontColor_Info Case 74 Int1 = rBuf.Get_Integer Int2 = rBuf.Get_Integer Str1 = rBuf.Get_String TempStr = Replace$(Message(74), "<amount>", Int1) TempStr = Replace$(TempStr, "<total>", Int2) Engine_AddToChatTextBuffer Replace$(TempStr, "<name>", Str1), FontColor_Quest Case 75 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(75), "<name>", Str1), FontColor_Info Case 76 Str1 = rBuf.Get_String Str2 = rBuf.Get_String TempInt = rBuf.Get_Integer TempStr = Replace$(Message(76), "<name>", Str1) TempStr = Replace$(TempStr, "<message>", Str2) Engine_AddToChatTextBuffer TempStr, FontColor_Talk If TempInt > 0 Then Engine_MakeChatBubble TempInt, Engine_WordWrap(TempStr, BubbleMaxWidth) Case 77 Str1 = rBuf.Get_String Str2 = rBuf.Get_String TempStr = Replace$(Message(77), "<name>", Str1) Engine_AddToChatTextBuffer Replace$(TempStr, "<gm>", Str2), FontColor_Info Case 78 Int1 = rBuf.Get_Integer Engine_AddToChatTextBuffer Replace$(Message(78), "<value>", Int1), FontColor_Info Case 79 MsgBox Message(79) Case 80 Str1 = rBuf.Get_String MsgBox Replace$(Message(80), "<name>", Str1) Case 81 MsgBox Message(81) Case 82 MsgBox Message(82) Case 83 MsgBox Message(83) Case 84 MsgBox Message(84) Case 85 MsgBox Message(85) Case 86 Str1 = rBuf.Get_String Int1 = rBuf.Get_Integer TempStr = Replace$(Message(86), "<name>", Str1) Engine_AddToChatTextBuffer Replace$(TempStr, "<amount>", Int1), FontColor_Info 'Case 87 to 93 - these are only used by the client Case 94 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(94), "<name>", Str1), FontColor_Info Case 95 Int1 = rBuf.Get_Integer Engine_AddToChatTextBuffer Replace$(Message(95), "<index>", Int1), FontColor_Info Case 96 Int1 = rBuf.Get_Integer Str1 = rBuf.Get_String Lng1 = rBuf.Get_Long TempStr = Replace$(Message(96), "<amount>", Int1) TempStr = Replace$(TempStr, "<name>", Str1) Engine_AddToChatTextBuffer Replace$(TempStr, "<cost>", Lng1), FontColor_Info Case 97 Engine_AddToChatTextBuffer Message(97), FontColor_Info Case 98 Engine_AddToChatTextBuffer Message(98), FontColor_Info Case 99 Engine_AddToChatTextBuffer Message(99), FontColor_Info Case 100 Str1 = rBuf.Get_String TempStr = Replace$(Message(100), "<linebreak>", vbCrLf) MsgBox Replace$(TempStr, "<reason>", Str1), vbOKOnly Or vbCritical IsUnloading = 1 Engine_UnloadAllForms Case 101 Engine_AddToChatTextBuffer Message(101), FontColor_Info Case 102 Engine_AddToChatTextBuffer Message(102), FontColor_Info Case 106 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(106), "<name>", Str1), FontColor_Group Case 107 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(107), "<name>", Str1), FontColor_Group Case 108 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(108), "<name>", Str1), FontColor_Group Case 109 Engine_AddToChatTextBuffer Message(109), FontColor_Group Case 110 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(110), "<name>", Str1), FontColor_Group Case 111 Engine_AddToChatTextBuffer Message(111), FontColor_Group Case 112 Engine_AddToChatTextBuffer Message(112), FontColor_Group Case 113 Engine_AddToChatTextBuffer Message(113), FontColor_Group Case 114 Engine_AddToChatTextBuffer Message(114), FontColor_Group Case 115 Str1 = rBuf.Get_String Int1 = rBuf.Get_Integer TempStr = Replace$(Message(115), "<name>", Str1) Engine_AddToChatTextBuffer Replace$(TempStr, "<time>", Int1), FontColor_Group Case 116 Engine_AddToChatTextBuffer Message(116), FontColor_Group Case 117 Lng1 = rBuf.Get_Long Engine_AddToChatTextBuffer Replace$(Message(117), "<amount>", Lng1), FontColor_Info Case 118 Lng1 = rBuf.Get_Long Engine_AddToChatTextBuffer Replace$(Message(118), "<amount>", Lng1), FontColor_Info Case 119 Engine_AddToChatTextBuffer Message(119), FontColor_Info Case 120 Lng1 = rBuf.Get_Long Engine_AddToChatTextBuffer Replace$(Message(120), "<amount>", Lng1), FontColor_Info Case 121 Engine_AddToChatTextBuffer Message(121), FontColor_Info Case 123 Engine_AddToChatTextBuffer Message(123), FontColor_Group Case 125 Engine_AddToChatTextBuffer Message(125), FontColor_Info Case 127 Engine_AddToChatTextBuffer Message(127), FontColor_Info Case 128 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(128), "<name>", Str1), FontColor_Info Case 129 Byt1 = rBuf.Get_Byte If Byt1 <= QuestInfoUBound Then Str1 = QuestInfo(Byt1).Name QuestInfo(Byt1).Desc = vbNullString QuestInfo(Byt1).Name = vbNullString Lng1 = QuestInfoUBound Do If Lng1 = 0 Then Exit Do If QuestInfo(Lng1).Name <> vbNullString Then Exit Do Lng1 = Lng1 - 1 Loop If Lng1 = 0 Then Erase QuestInfo QuestInfoUBound = 0 Else ReDim Preserve QuestInfo(1 To Lng1) QuestInfoUBound = Lng1 End If If Str1 <> vbNullString Then Engine_AddToChatTextBuffer Replace$(Message(129), "<name>", Str1), FontColor_Quest End If End If Case 130 Engine_AddToChatTextBuffer Message(130), FontColor_Info Case 131 Engine_AddToChatTextBuffer Message(131), FontColor_Info Case 132 Engine_AddToChatTextBuffer Message(132), FontColor_Info Case 134 Str1 = rBuf.Get_String Engine_AddToChatTextBuffer Replace$(Message(134), "<name>", Str1), FontColor_Quest Case 137 Engine_AddToChatTextBuffer Message(137), FontColor_Info Case 138 Lng1 = rBuf.Get_Long Engine_AddToChatTextBuffer Replace$(Message(138), "<amount>", Lng1), FontColor_Info Case 139 Lng1 = rBuf.Get_Long Engine_AddToChatTextBuffer Replace$(Message(139), "<amount>", Lng1), FontColor_Info End Select End Sub Sub Data_Server_Connect() '************************************************************ 'Server is telling the client they have successfully logged in '<> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_Connect '************************************************************ 'Set the socket state SocketOpen = 1 If EngineRun = False Then 'Load user config Game_Config_Load 'Unload the connect form Unload frmConnect 'Load main form Load frmMain frmMain.Visible = True frmMain.Show frmMain.SetFocus Input_Keys_ClearQueue DoEvents 'Load the engine Engine_Init_TileEngine 'Get the device frmMain.Show frmMain.SetFocus DoEvents DIDevice.Acquire Unload frmNew Unload frmConnect End If 'Send the data Data_Send End Sub Sub Data_Server_Disconnect() '************************************************************ 'Forces the client to disconnect from the server '<> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_Disconnect '************************************************************ IsUnloading = 1 End Sub Sub Data_Comm_Talk(ByRef rBuf As DataBuffer) '************************************************************ 'Send data to chat buffer '<Text(S)><FontColorID(B)>(<CharIndex(I)>) 'More info: http://www.vbgore.com/GameClient.TCP.Data_Comm_Talk '************************************************************ Dim CharIndex As Integer Dim TempStr As String Dim TempLng As Long Dim TempByte As Byte 'Get the text TempStr = rBuf.Get_String TempByte = rBuf.Get_Byte 'Filter the temp string TempStr = Game_FilterString(TempStr) 'See if we have to make a bubble If TempByte And DataCode.Comm_UseBubble Then 'We need a char index CharIndex = rBuf.Get_Integer End If 'Now that we have all the values, check if it is a valid string If Not Game_ValidString(TempStr) Then Exit Sub 'Split up the string for our chat bubble and assign it to the character If CharIndex > 0 Then If CharIndex <= LastChar Then Engine_MakeChatBubble CharIndex, Engine_WordWrap(TempStr, BubbleMaxWidth) End If End If 'Get the color Select Case TempByte Case DataCode.Comm_FontType_Fight TempLng = FontColor_Fight Case DataCode.Comm_FontType_Info TempLng = FontColor_Info Case DataCode.Comm_FontType_Quest TempLng = FontColor_Quest Case DataCode.Comm_FontType_Talk TempLng = FontColor_Talk Case DataCode.Comm_FontType_Group TempLng = FontColor_Group Case Else TempLng = FontColor_Talk End Select 'Add the text in the text box Engine_AddToChatTextBuffer TempStr, TempLng End Sub Sub Data_Map_LoadMap(ByRef rBuf As DataBuffer) '************************************************************ 'Load the map the server told us to load '<MapNum(I)><ServerSideVersion(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Map_LoadMap '************************************************************ Dim FileNum As Byte Dim MapNumInt As Integer Dim SSV As Integer Dim TempInt As Integer 'Clear the target character TargetCharIndex = 0 MapNumInt = rBuf.Get_Integer SSV = rBuf.Get_Integer If Engine_FileExist(MapPath & MapNumInt & ".map", vbNormal) Then 'Get Version Num FileNum = FreeFile Open MapPath & MapNumInt & ".map" For Binary As #FileNum Seek #FileNum, 1 Get #FileNum, , TempInt Close #FileNum If TempInt = SSV Then 'Correct Version Game_Map_Switch MapNumInt sndBuf.Put_Byte DataCode.Map_DoneLoadingMap 'Tell the server we are done loading map Else 'Not correct version MsgBox Message(105), vbOKOnly Or vbCritical EngineRun = False IsUnloading = 1 End If Else 'Didn't find map MsgBox Message(105), vbOKOnly Or vbCritical EngineRun = False IsUnloading = 1 End If End Sub Sub Data_Map_SendName(ByRef rBuf As DataBuffer) '************************************************************ 'Set the map name and weather '<Name(S)><Weather(B)><Music(B)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Map_SendName '************************************************************ Dim Music As Byte MapInfo.Name = rBuf.Get_String MapInfo.Weather = rBuf.Get_Byte 'Change the music file if we need to Music = rBuf.Get_Byte If MapInfo.Music <> Music Then Music_Stop 1 If Music <> 0 Then MapInfo.Music = Music Music_Load MusicPath & Music & ".mp3", 1 Music_Play 1 Music_Volume 86, 1 End If End If End Sub Sub Data_Send() '************************************************************ 'Send data buffer to the server 'More info: http://www.vbgore.com/GameClient.TCP.Data_Send '************************************************************ 'Check that we have data to send If SocketOpen = 0 Then DoEvents If sndBuf.HasBuffer Then If SocketOpen = 0 Then DoEvents 'Send the data frmMain.GOREsock.SendData SoxID, sndBuf.Get_Buffer 'Clear the buffer, get it ready for next use sndBuf.Clear End If End Sub Sub Data_Server_ChangeCharType(ByRef rBuf As DataBuffer) '************************************************************ 'Change a character by the character index '<CharIndex(I)><CharType(B)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_ChangeCharType '************************************************************ Dim CharIndex As Integer Dim CharType As Byte CharIndex = rBuf.Get_Integer CharType = rBuf.Get_Byte 'If the char doesn't exist, request to create it If Not Engine_ValidChar(CharIndex) Then Exit Sub 'Change the character's type CharList(CharIndex).CharType = CharType End Sub Sub Data_Server_ChangeChar(ByRef rBuf As DataBuffer) '************************************************************ 'Change a character by the character index '<CharIndex(I)><Flags(B)>(<Body(I)><Head(I)><Weapon(I)><Hair(I)><Wings(I)>) 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_ChangeChar '************************************************************ Dim flags As Byte Dim CharIndex As Integer Dim CharBody As Integer Dim CharHead As Integer Dim CharWeapon As Integer Dim CharHair As Integer Dim CharWings As Integer Dim DontSetData As Boolean 'Get the character index we are changing CharIndex = rBuf.Get_Integer 'Get the flags on what data we need to get flags = rBuf.Get_Byte 'If the char doesn't exist, request to create it If Not Engine_ValidChar(CharIndex) Then DontSetData = True 'Get the data needed If flags And 1 Then CharBody = rBuf.Get_Integer If Not DontSetData Then CharList(CharIndex).Body = BodyData(CharBody) End If If flags And 2 Then CharHead = rBuf.Get_Integer If Not DontSetData Then CharList(CharIndex).Head = HeadData(CharHead) End If If flags And 4 Then CharWeapon = rBuf.Get_Integer If Not DontSetData Then CharList(CharIndex).Weapon = WeaponData(CharWeapon) End If If flags And 8 Then CharHair = rBuf.Get_Integer If Not DontSetData Then CharList(CharIndex).Hair = HairData(CharHair) End If If flags And 16 Then CharWings = rBuf.Get_Integer If Not DontSetData Then CharList(CharIndex).Wings = WingData(CharWings) End If End Sub Sub Data_Server_CharHP(ByRef rBuf As DataBuffer) '************************************************************ 'Set the character HP '<HP(B)><CharIndex(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_CharHP '************************************************************ Dim CharIndex As Integer Dim HP As Byte HP = rBuf.Get_Byte CharIndex = rBuf.Get_Integer 'If the char doesn't exist, request to create it If Not Engine_ValidChar(CharIndex) Then Exit Sub CharList(CharIndex).HealthPercent = HP End Sub Sub Data_Server_CharMP(ByRef rBuf As DataBuffer) '************************************************************ 'Set the character MP '<MP(B)><CharIndex(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_CharMP '************************************************************ Dim CharIndex As Integer Dim MP As Byte MP = rBuf.Get_Byte CharIndex = rBuf.Get_Integer 'If the char doesn't exist, request to create it If Not Engine_ValidChar(CharIndex) Then Exit Sub CharList(CharIndex).ManaPercent = MP End Sub Sub Data_Server_EraseChar(ByRef rBuf As DataBuffer) '************************************************************ 'Erase a character by the character index '<CharIndex(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_EraseChar '************************************************************ Engine_Char_Erase rBuf.Get_Integer End Sub Sub Data_Server_EraseObject(ByRef rBuf As DataBuffer) '************************************************************ 'Erase an object on the object layer '<X(B)><Y(B)><Grh(L)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_EraseObject '************************************************************ Dim j As Integer Dim X As Byte Dim Y As Byte Dim Grh As Long X = rBuf.Get_Byte Y = rBuf.Get_Byte Grh = rBuf.Get_Long 'Loop through until we find the object on (X,Y) then kill it For j = 1 To LastObj If OBJList(j).Pos.X = X Then If OBJList(j).Pos.Y = Y Then If OBJList(j).Grh.GrhIndex = Grh Then Engine_OBJ_Erase j Exit Sub End If End If End If Next j End Sub Sub Data_Server_IconBlessed(ByRef rBuf As DataBuffer) '************************************************************ 'Hide/show blessed icon '<State(B)><CharIndex(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_IconBlessed '************************************************************ Dim State As Byte Dim CharIndex As Integer State = rBuf.Get_Byte CharIndex = rBuf.Get_Integer 'If the char doesn't exist, request to create it If Not Engine_ValidChar(CharIndex) Then Exit Sub CharList(CharIndex).CharStatus.Blessed = State End Sub Sub Data_Server_IconCursed(ByRef rBuf As DataBuffer) '************************************************************ 'Hide/show cursed icon '<State(B)><CharIndex(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_IconCursed '************************************************************ Dim State As Byte Dim CharIndex As Integer State = rBuf.Get_Byte CharIndex = rBuf.Get_Integer 'If the char doesn't exist, request to create it If Not Engine_ValidChar(CharIndex) Then Exit Sub CharList(CharIndex).CharStatus.Cursed = State End Sub Sub Data_Server_IconIronSkin(ByRef rBuf As DataBuffer) '************************************************************ 'Hide/show ironskinned icon '<State(B)><CharIndex(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_IconIronSkin '************************************************************ Dim State As Byte Dim CharIndex As Integer State = rBuf.Get_Byte CharIndex = rBuf.Get_Integer 'If the char doesn't exist, request to create it If Not Engine_ValidChar(CharIndex) Then Exit Sub CharList(CharIndex).CharStatus.IronSkinned = State End Sub Sub Data_Server_IconProtected(ByRef rBuf As DataBuffer) '************************************************************ 'Hide/show protected icon '<State(B)><CharIndex(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_IconProtected '************************************************************ Dim State As Byte Dim CharIndex As Integer State = rBuf.Get_Byte CharIndex = rBuf.Get_Integer 'If the char doesn't exist, request to create it If Not Engine_ValidChar(CharIndex) Then Exit Sub CharList(CharIndex).CharStatus.Protected = State End Sub Sub Data_Server_IconSpellExhaustion(ByRef rBuf As DataBuffer) '************************************************************ 'Hide/show spell exhaustion icon '<State(B)><CharIndex(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_IconSpellExhaustion '************************************************************ Dim State As Byte Dim CharIndex As Integer State = rBuf.Get_Byte CharIndex = rBuf.Get_Integer 'If the char doesn't exist, request to create it If Not Engine_ValidChar(CharIndex) Then Exit Sub CharList(CharIndex).CharStatus.Exhausted = State End Sub Sub Data_Server_IconStrengthened(ByRef rBuf As DataBuffer) '************************************************************ 'Hide/show strengthened icon '<State(B)><CharIndex(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_IconStrengthened '************************************************************ Dim State As Byte Dim CharIndex As Integer State = rBuf.Get_Byte CharIndex = rBuf.Get_Integer 'If the char doesn't exist, request to create it If Not Engine_ValidChar(CharIndex) Then Exit Sub CharList(CharIndex).CharStatus.Strengthened = State End Sub Sub Data_Server_IconWarCursed(ByRef rBuf As DataBuffer) '************************************************************ 'Hide/show warcursed icon '<State(B)><CharIndex(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_IconWarCursed '************************************************************ Dim State As Byte Dim CharIndex As Integer State = rBuf.Get_Byte CharIndex = rBuf.Get_Integer 'If the char doesn't exist, request to create it If Not Engine_ValidChar(CharIndex) Then Exit Sub CharList(CharIndex).CharStatus.WarCursed = State End Sub Sub Data_Server_Mailbox(ByRef rBuf As DataBuffer) '************************************************************ 'Recieve the list of messages from a mailbox 'Loop: <New(B)><WriterName(S)><Date(S)><Subject(S)>...<EndFlag(B)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_Mailbox '************************************************************ Dim NewB As Byte Dim WName As String Dim SDate As String Dim Subj As String ShowGameWindow(MailboxWindow) = 1 SelMessage = 0 LastClickedWindow = MailboxWindow MailboxListBuffer = vbNullString Do NewB = rBuf.Get_Byte If NewB = 255 Then Exit Do 'If 1 or 0, it is a message, if 255, it is the EndFlag WName = rBuf.Get_String SDate = rBuf.Get_String Subj = rBuf.Get_String MailboxListBuffer = MailboxListBuffer & IIf(NewB, "New - ", "Old - ") & Subj & " - " & WName & " - " & SDate & vbCrLf Loop End Sub Sub Data_Server_MailItemRemove(ByRef rBuf As DataBuffer) '************************************************************ 'Remove item from mailbox '<ItemIndex(B)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_MailItemRemove '************************************************************ Dim ItemIndex As Byte ItemIndex = rBuf.Get_Byte ReadMailData.Obj(ItemIndex) = 0 End Sub Sub Data_Server_MailObjUpdate(ByRef rBuf As DataBuffer) '************************************************************ 'Updates the objects in a mail message '<NumObjs(B)> Loop: <ObjGrhIndex(L)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_MailObjUpdate '************************************************************ Dim NumObjs As Byte Dim X As Byte 'Clear the current objects For X = 1 To MaxMailObjs ReadMailData.Obj(X) = 0 ReadMailData.ObjName(X) = 0 ReadMailData.ObjAmount(X) = 0 Next X 'Get the number of objects NumObjs = rBuf.Get_Byte 'Get the mail objects For X = 1 To NumObjs ReadMailData.Obj(X) = rBuf.Get_Long ReadMailData.ObjName(X) = rBuf.Get_String ReadMailData.ObjAmount(X) = rBuf.Get_Integer Next X End Sub Sub Data_Server_MailMessage(ByRef rBuf As DataBuffer) '************************************************************ 'Recieve message that was requested to be read '<Message(S-EX)><Subject(S)><WriterName(S)><NumObjs(B)> Loop: <ObjGrhIndex(L)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_MailMessage '************************************************************ Dim NumObjs As Byte Dim i As Long 'Clear the current objects For i = 1 To MaxMailObjs ReadMailData.Obj(i) = 0 ReadMailData.ObjName(i) = 0 ReadMailData.ObjAmount(i) = 0 Next i 'Show the correct windows ShowGameWindow(MailboxWindow) = 0 ShowGameWindow(ViewMessageWindow) = 1 LastClickedWindow = ViewMessageWindow 'Get the data ReadMailData.Message = rBuf.Get_StringEX ReadMailData.Message = Engine_WordWrap(ReadMailData.Message, GameWindow.ViewMessage.Message.Width) ReadMailData.Subject = rBuf.Get_String ReadMailData.WriterName = rBuf.Get_String NumObjs = rBuf.Get_Byte For i = 1 To NumObjs ReadMailData.Obj(i) = rBuf.Get_Long ReadMailData.ObjName(i) = rBuf.Get_String ReadMailData.ObjAmount(i) = rBuf.Get_Integer Next i End Sub Sub Data_Server_MakeCharCached(ByRef rBuf As DataBuffer) '************************************************************ 'Create a character and set their information '<Flags(I)><Body(I)><Head(I)><Heading(B)><CharIndex(I)><X(B)><Y(B)><Speed(B)><Name(S)><Weapon(I)><Hair(I)><Wings(I)> ' <HP%(B)><MP%(B)><ChatID(B)><CharType(B)> (<OwnerCharIndex(I)>) 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_MakeCharCached '************************************************************ Dim flags As Integer Dim Body As Integer Dim Head As Integer Dim Heading As Byte Dim CharIndex As Integer Dim X As Byte Dim Y As Byte Dim Speed As Byte Dim Name As String Dim Weapon As Integer Dim Hair As Integer Dim Wings As Integer Dim HP As Byte Dim MP As Byte Dim ChatID As Byte Dim CharType As Byte Dim OwnerChar As Integer 'Retrieve all the information flags = rBuf.Get_Integer If flags And 1 Then Body = rBuf.Get_Integer Else Body = PacketCache.Server_MakeChar.Body If flags And 2 Then Head = rBuf.Get_Integer Else Head = PacketCache.Server_MakeChar.Head If flags And 4 Then Heading = rBuf.Get_Byte Else Heading = PacketCache.Server_MakeChar.Heading CharIndex = rBuf.Get_Integer If flags And 8 Then X = rBuf.Get_Byte Else X = PacketCache.Server_MakeChar.X If flags And 16 Then Y = rBuf.Get_Byte Else Y = PacketCache.Server_MakeChar.Y If flags And 32 Then Speed = rBuf.Get_Byte Else Speed = PacketCache.Server_MakeChar.Speed If flags And 64 Then Name = rBuf.Get_String Else Name = PacketCache.Server_MakeChar.Name If flags And 128 Then Weapon = rBuf.Get_Integer Else Weapon = PacketCache.Server_MakeChar.Weapon If flags And 256 Then Hair = rBuf.Get_Integer Else Hair = PacketCache.Server_MakeChar.Hair If flags And 512 Then Wings = rBuf.Get_Integer Else Wings = PacketCache.Server_MakeChar.Wings If flags And 1024 Then HP = rBuf.Get_Byte Else HP = PacketCache.Server_MakeChar.HP If flags And 2048 Then MP = rBuf.Get_Byte Else MP = PacketCache.Server_MakeChar.MP If flags And 4096 Then ChatID = rBuf.Get_Byte Else ChatID = PacketCache.Server_MakeChar.ChatID If flags And 8192 Then CharType = rBuf.Get_Byte Else CharType = PacketCache.Server_MakeChar.CharType 'Check for the owner char index if the char is a slave NPC If CharType = ClientCharType_Slave Then OwnerChar = rBuf.Get_Integer 'Store the new values for the cache With PacketCache.Server_MakeChar .Body = Body .Head = Head .Heading = Heading .X = X .Y = Y .Speed = Speed .Name = Name .Weapon = Weapon .Hair = Hair .Wings = Wings .HP = HP .MP = MP .ChatID = ChatID .CharType = CharType End With 'Create the character Engine_Char_Make CharIndex, Body, Head, Heading, X, Y, Speed, Name, Weapon, Hair, Wings, ChatID, CharType, HP, MP 'Apply the owner index value CharList(CharIndex).OwnerChar = OwnerChar End Sub Sub Data_Server_MakeChar(ByRef rBuf As DataBuffer) '************************************************************ 'Create a character and set their information '<Body(I)><Head(I)><Heading(B)><CharIndex(I)><X(B)><Y(B)><Speed(B)><Name(S)><Weapon(I)><Hair(I)><Wings(I)> ' <HP%(B)><MP%(B)><ChatID(B)><CharType(B)> (<OwnerCharIndex(I)>) 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_MakeChar '************************************************************ Dim Body As Integer Dim Head As Integer Dim Heading As Byte Dim CharIndex As Integer Dim X As Byte Dim Y As Byte Dim Speed As Byte Dim Name As String Dim Weapon As Integer Dim Hair As Integer Dim Wings As Integer Dim HP As Byte Dim MP As Byte Dim ChatID As Byte Dim CharType As Byte Dim OwnerChar As Integer 'Retrieve all the information Body = rBuf.Get_Integer Head = rBuf.Get_Integer Heading = rBuf.Get_Byte CharIndex = rBuf.Get_Integer X = rBuf.Get_Byte Y = rBuf.Get_Byte Speed = rBuf.Get_Byte Name = rBuf.Get_String Weapon = rBuf.Get_Integer Hair = rBuf.Get_Integer Wings = rBuf.Get_Integer HP = rBuf.Get_Byte MP = rBuf.Get_Byte ChatID = rBuf.Get_Byte CharType = rBuf.Get_Byte 'Check for the owner char index if the char is a slave NPC If CharType = ClientCharType_Slave Then OwnerChar = rBuf.Get_Integer 'Create the character Engine_Char_Make CharIndex, Body, Head, Heading, X, Y, Speed, Name, Weapon, Hair, Wings, ChatID, CharType, HP, MP 'Apply the owner index value CharList(CharIndex).OwnerChar = OwnerChar End Sub Sub Data_Server_MakeObject(ByRef rBuf As DataBuffer) '************************************************************ 'Create an object on the object layer '<GrhIndex(L)><X(B)><Y(B)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_MakeObject '************************************************************ Dim GrhIndex As Long Dim X As Byte Dim Y As Byte 'Get the values GrhIndex = rBuf.Get_Long X = rBuf.Get_Byte Y = rBuf.Get_Byte 'Create the object If GrhIndex > 0 Then Engine_OBJ_Create GrhIndex, X, Y End Sub Sub Data_Server_MoveChar(ByRef rBuf As DataBuffer) '************************************************************ 'Move a character '<CharIndex(I)><X(B)><Y(B)><Heading(B)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_MoveChar '************************************************************ Dim CharIndex As Integer Dim X As Integer Dim Y As Integer Dim nX As Integer Dim nY As Integer Dim Heading As Byte Dim Running As Byte CharIndex = rBuf.Get_Integer X = rBuf.Get_Byte Y = rBuf.Get_Byte Heading = rBuf.Get_Byte 'If the char doesn't exist, request to create it If Not Engine_ValidChar(CharIndex) Then Exit Sub 'Check if running If Heading > 128 Then Heading = Heading Xor 128 Running = 1 End If 'Make sure the char is the right starting position Select Case Heading Case NORTH: nX = 0: nY = -1 Case EAST: nX = 1: nY = 0 Case SOUTH: nX = 0: nY = 1 Case WEST: nX = -1: nY = 0 Case NORTHEAST: nX = 1: nY = -1 Case SOUTHEAST: nX = 1: nY = 1 Case SOUTHWEST: nX = -1: nY = 1 Case NORTHWEST: nX = -1: nY = -1 End Select CharList(CharIndex).Pos.X = X - nX CharList(CharIndex).Pos.Y = Y - nY 'Move the character Engine_Char_Move_ByPos CharIndex, X, Y, Running End Sub Sub Data_Server_PlaySound(ByRef rBuf As DataBuffer) '************************************************************ 'Play a wave file '<WaveNum(B)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_PlaySound '************************************************************ Dim WaveNum As Byte WaveNum = rBuf.Get_Byte 'Check that we are using sounds If UseSfx = 0 Then Exit Sub 'Create the buffer if needed If SoundBufferTimer(WaveNum) < timeGetTime Then If DSBuffer(WaveNum) Is Nothing Then Sound_Set DSBuffer(WaveNum), WaveNum End If 'Update the timer SoundBufferTimer(WaveNum) = timeGetTime + SoundBufferTimerMax Sound_Play DSBuffer(WaveNum), DSBPLAY_DEFAULT End Sub Sub Data_Server_PlaySound3D(ByRef rBuf As DataBuffer) '************************************************************ 'Play a wave file with 3D effect '<WaveNum(B)><X(B)><Y(B)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_PlaySound3D '************************************************************ Dim WaveNum As Byte Dim X As Integer Dim Y As Integer WaveNum = rBuf.Get_Byte X = rBuf.Get_Byte Y = rBuf.Get_Byte Sound_Play3D WaveNum, X, Y End Sub Sub Data_Server_SetCharDamage(ByRef rBuf As DataBuffer) '************************************************************ 'Damage a character and display it '<CharIndex(I)><Damage(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_SetCharDamage '************************************************************ Dim CharIndex As Integer Dim Damage As Integer CharIndex = rBuf.Get_Integer Damage = rBuf.Get_Integer 'If the char doesn't exist, request to create it If Not Engine_ValidChar(CharIndex) Then Exit Sub 'Create the blood (if damage) If Damage > 0 Then Engine_Blood_Create CharList(CharIndex).Pos.X, CharList(CharIndex).Pos.Y 'Create the damage Engine_Damage_Create CharList(CharIndex).Pos.X, CharList(CharIndex).Pos.Y, Damage 'Aggressive face If Damage > 0 Then CharList(CharIndex).Aggressive = 1 CharList(CharIndex).AggressiveCounter = timeGetTime + AGGRESSIVEFACETIME End If End Sub Sub Data_Server_SetUserPosition(ByRef rBuf As DataBuffer) '************************************************************ 'Set the user's position '<X(B)><Y(B)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_SetUserPosition '************************************************************ Dim X As Byte Dim Y As Byte 'Get the position X = rBuf.Get_Byte Y = rBuf.Get_Byte 'Check for a valid range If X < 1 Then Exit Sub If X > MapInfo.Width Then Exit Sub If Y < 1 Then Exit Sub If Y > MapInfo.Height Then Exit Sub 'Check for a valid UserCharIndex If UserCharIndex <= 0 Or UserCharIndex > LastChar Then 'We have an invalid user char index, so we must have the wrong one - request an update on the right one sndBuf.Put_Byte DataCode.User_RequestUserCharIndex Exit Sub End If 'Check if the position is even different If X <> UserPos.X Or Y <> UserPos.Y Then 'Update the user's position UserPos.X = X UserPos.Y = Y CharList(UserCharIndex).Pos = UserPos 'If there is a targeted char, check if the path is valid If TargetCharIndex > 0 Then If TargetCharIndex <= LastChar Then On Error Resume Next 'Sometimes something strange will cause this to fail when a target dies - just ignore it ClearPathToTarget = Engine_ClearPath(CharList(UserCharIndex).Pos.X, CharList(UserCharIndex).Pos.Y, CharList(TargetCharIndex).Pos.X, CharList(TargetCharIndex).Pos.Y) On Error GoTo 0 End If End If End If End Sub Sub Data_Server_UserCharIndex(ByRef rBuf As DataBuffer) '************************************************************ 'Set the user character index '<CharIndex(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_UserCharIndex '************************************************************ 'Retrieve the index of the user's character UserCharIndex = rBuf.Get_Integer UserPos = CharList(UserCharIndex).Pos 'Update the map-bound sound effects Sound_UpdateMap End Sub Sub Data_Combo_SlashSoundRotateDamage(ByRef rBuf As DataBuffer) '************************************************************ 'Combines slash, 3d sound, damage and rotation packets together '<AttackerIndex(I)><TargetIndex(I)><SlashGrh(L)><Sfx(B)><Damage(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Combo_SlashSoundRotateDamage '************************************************************ Dim AttackerIndex As Integer Dim TargetIndex As Integer Dim SlashGrh As Long Dim Sfx As Byte Dim Damage As Integer Dim NewHeading As Byte Dim Angle As Integer AttackerIndex = rBuf.Get_Integer TargetIndex = rBuf.Get_Integer SlashGrh = rBuf.Get_Long Sfx = rBuf.Get_Byte Damage = rBuf.Get_Integer 'If the char doesn't exist, request to create it If Not Engine_ValidChar(AttackerIndex) Then Exit Sub If Not Engine_ValidChar(TargetIndex) Then Exit Sub 'Rotate the AttackerIndex to face TargetIndex NewHeading = Engine_FindDirection(CharList(AttackerIndex).Pos, CharList(TargetIndex).Pos) CharList(AttackerIndex).HeadHeading = NewHeading CharList(AttackerIndex).Heading = NewHeading 'Get the new heading Select Case CharList(AttackerIndex).Heading Case NORTH Angle = 0 Case NORTHEAST Angle = 45 Case EAST Angle = 90 Case SOUTHEAST Angle = 135 Case SOUTH Angle = 180 Case SOUTHWEST Angle = 225 Case WEST Angle = 270 Case NORTHWEST Angle = 315 End Select 'Create the effect Engine_Effect_Create CharList(AttackerIndex).Pos.X, CharList(AttackerIndex).Pos.Y, SlashGrh, Angle, 150, 0 'Play the sound Sound_Play3D Sfx, CharList(AttackerIndex).Pos.X, CharList(AttackerIndex).Pos.Y 'Create the blood (if damage) If Damage > 0 Then Engine_Blood_Create CharList(TargetIndex).Pos.X, CharList(TargetIndex).Pos.Y 'Create the damage Engine_Damage_Create CharList(TargetIndex).Pos.X, CharList(TargetIndex).Pos.Y, Damage 'Start the attack animation CharList(AttackerIndex).Body.Attack(CharList(AttackerIndex).Heading).Started = 1 CharList(AttackerIndex).Body.Attack(CharList(AttackerIndex).Heading).FrameCounter = 1 CharList(AttackerIndex).Body.Attack(CharList(AttackerIndex).Heading).LastCount = timeGetTime CharList(AttackerIndex).Weapon.Attack(CharList(AttackerIndex).Heading).FrameCounter = 1 CharList(AttackerIndex).ActionIndex = 2 'Aggressive face If Damage > 0 Then CharList(TargetIndex).Aggressive = 1 CharList(TargetIndex).AggressiveCounter = timeGetTime + AGGRESSIVEFACETIME End If End Sub Sub Data_Combo_ProjectileSoundRotateDamage(ByRef rBuf As DataBuffer) '************************************************************ 'Combines projectile, 3d sound, damage and rotation packets together '<AttackerIndex(I)><TargetIndex(I)><ProjectileGrh(L)><RotateSpeed(B)><Sfx(B)><Damage(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Combo_ProjectileSoundRotateDamage '************************************************************ Dim AttackerIndex As Integer Dim TargetIndex As Integer Dim GrhIndex As Long Dim RotateSpeed As Byte Dim Sfx As Byte Dim NewHeading As Byte Dim Damage As Integer AttackerIndex = rBuf.Get_Integer TargetIndex = rBuf.Get_Integer GrhIndex = rBuf.Get_Long RotateSpeed = rBuf.Get_Byte Sfx = rBuf.Get_Byte Damage = rBuf.Get_Integer 'If the char doesn't exist, request to create it If Not Engine_ValidChar(AttackerIndex) Then Exit Sub If Not Engine_ValidChar(TargetIndex) Then Exit Sub 'Rotate the AttackerIndex to face TargetIndex NewHeading = Engine_FindDirection(CharList(AttackerIndex).Pos, CharList(TargetIndex).Pos) CharList(AttackerIndex).HeadHeading = NewHeading CharList(AttackerIndex).Heading = NewHeading 'Create the projectile Engine_Projectile_Create AttackerIndex, TargetIndex, GrhIndex, RotateSpeed 'Play the sound Sound_Play3D Sfx, CharList(AttackerIndex).Pos.X, CharList(AttackerIndex).Pos.Y 'Create the blood (if damage) If Damage > 0 Then Engine_Blood_Create CharList(TargetIndex).Pos.X, CharList(TargetIndex).Pos.Y 'Start the attack animation CharList(AttackerIndex).Body.Attack(CharList(AttackerIndex).Heading).Started = 1 CharList(AttackerIndex).Body.Attack(CharList(AttackerIndex).Heading).FrameCounter = 1 CharList(AttackerIndex).Body.Attack(CharList(AttackerIndex).Heading).LastCount = timeGetTime CharList(AttackerIndex).Weapon.Attack(CharList(AttackerIndex).Heading).FrameCounter = 1 CharList(AttackerIndex).ActionIndex = 2 'Create the damage Engine_Damage_Create CharList(TargetIndex).Pos.X, CharList(TargetIndex).Pos.Y, Damage 'Aggressive face If Damage > 0 Then CharList(TargetIndex).Aggressive = 1 CharList(TargetIndex).AggressiveCounter = timeGetTime + AGGRESSIVEFACETIME End If End Sub Sub Data_Combo_SoundRotateDamage(ByRef rBuf As DataBuffer) '************************************************************ 'Combines sound playing, damage and rotation packets together '<AttackerIndex(I)><TargetIndex(I)><Sfx(B)><Damage(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Combo_SoundRotateDamage '************************************************************ Dim AttackerIndex As Integer Dim TargetIndex As Integer Dim Damage As Integer Dim Sfx As Byte Dim NewHeading As Byte AttackerIndex = rBuf.Get_Integer TargetIndex = rBuf.Get_Integer Sfx = rBuf.Get_Byte Damage = rBuf.Get_Integer 'If the char doesn't exist, request to create it If Not Engine_ValidChar(AttackerIndex) Then Exit Sub If Not Engine_ValidChar(TargetIndex) Then Exit Sub 'Rotate the AttackerIndex to face TargetIndex NewHeading = Engine_FindDirection(CharList(AttackerIndex).Pos, CharList(TargetIndex).Pos) CharList(AttackerIndex).HeadHeading = NewHeading CharList(AttackerIndex).Heading = NewHeading 'Play the sound Sound_Play3D Sfx, CharList(AttackerIndex).Pos.X, CharList(AttackerIndex).Pos.Y 'Start the attack animation CharList(AttackerIndex).Body.Attack(CharList(AttackerIndex).Heading).Started = 1 CharList(AttackerIndex).Body.Attack(CharList(AttackerIndex).Heading).FrameCounter = 1 CharList(AttackerIndex).Body.Attack(CharList(AttackerIndex).Heading).LastCount = timeGetTime CharList(AttackerIndex).Weapon.Attack(CharList(AttackerIndex).Heading).FrameCounter = 1 CharList(AttackerIndex).ActionIndex = 2 'Create the blood (if damage) If Damage > 0 Then Engine_Blood_Create CharList(TargetIndex).Pos.X, CharList(TargetIndex).Pos.Y 'Create the damage Engine_Damage_Create CharList(TargetIndex).Pos.X, CharList(TargetIndex).Pos.Y, Damage 'Aggressive face If Damage > 0 Then CharList(TargetIndex).Aggressive = 1 CharList(TargetIndex).AggressiveCounter = timeGetTime + AGGRESSIVEFACETIME End If End Sub Sub Data_User_Attack(ByRef rBuf As DataBuffer) '************************************************************ 'Change character animation to attack animation '<CharIndex(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_User_Attack '************************************************************ Dim CharIndex As Integer CharIndex = rBuf.Get_Integer 'If the char doesn't exist, request to create it If Not Engine_ValidChar(CharIndex) Then Exit Sub 'Start the attack animation CharList(CharIndex).Body.Attack(CharList(CharIndex).Heading).Started = 1 CharList(CharIndex).Body.Attack(CharList(CharIndex).Heading).FrameCounter = 1 CharList(CharIndex).Body.Attack(CharList(CharIndex).Heading).LastCount = timeGetTime CharList(CharIndex).Weapon.Attack(CharList(CharIndex).Heading).FrameCounter = 1 CharList(CharIndex).ActionIndex = 2 End Sub Sub Data_User_BaseStat(ByRef rBuf As DataBuffer) '************************************************************ 'Update base stat '<StatID(B)><Value(L)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_User_BaseStat '************************************************************ Dim StatID As Byte StatID = rBuf.Get_Byte BaseStats(StatID) = rBuf.Get_Long End Sub Sub Data_User_Blink(ByRef rBuf As DataBuffer) '************************************************************ 'Make a character blink '<CharIndex(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_User_Blink '************************************************************ Dim CharIndex As Integer CharIndex = rBuf.Get_Integer 'If the char doesn't exist, request to create it If Not Engine_ValidChar(CharIndex) Then Exit Sub CharList(CharIndex).StartBlinkTimer = 0 CharList(CharIndex).BlinkTimer = 0 End Sub Sub Data_User_CastSkill(ByRef rBuf As DataBuffer) '************************************************************ 'User casted a skill '<SkillID(B)> (Rest depends on the SkillID) 'More info: http://www.vbgore.com/GameClient.TCP.Data_User_CastSkill '************************************************************ Dim CasterIndex As Integer Dim TargetIndex As Integer Dim TempIndex As Integer Dim SkillID As Byte Dim X As Long Dim Y As Long SkillID = rBuf.Get_Byte Select Case SkillID Case SkID.Heal CasterIndex = rBuf.Get_Integer TargetIndex = rBuf.Get_Integer If Not Engine_ValidChar(CasterIndex) Then Exit Sub If Not Engine_ValidChar(TargetIndex) Then Exit Sub 'Set the position X = Engine_TPtoSPX(CharList(CasterIndex).Pos.X) + 16 Y = Engine_TPtoSPY(CharList(CasterIndex).Pos.Y) 'If not casted on self, bind to character If TargetIndex <> CasterIndex Then TempIndex = Effect_Heal_Begin(X, Y, 3, 120, 1) Effect(TempIndex).BindToChar = TargetIndex Effect(TempIndex).BindSpeed = 7 Else TempIndex = Effect_Heal_Begin(X, Y, 3, 120, 0) End If Case SkID.Protection CasterIndex = rBuf.Get_Integer TargetIndex = rBuf.Get_Integer If Not Engine_ValidChar(CasterIndex) Then Exit Sub If Not Engine_ValidChar(TargetIndex) Then Exit Sub 'Create the effect at (not bound to) the target character X = Engine_TPtoSPX(CharList(TargetIndex).Pos.X) + 16 Y = Engine_TPtoSPY(CharList(TargetIndex).Pos.Y) TempIndex = Effect_Protection_Begin(X, Y, 11, 120, 40, 15) Effect(TempIndex).BindToChar = TargetIndex Effect(TempIndex).BindSpeed = 25 Case SkID.Strengthen CasterIndex = rBuf.Get_Integer TargetIndex = rBuf.Get_Integer If Not Engine_ValidChar(CasterIndex) Then Exit Sub If Not Engine_ValidChar(TargetIndex) Then Exit Sub 'Create the effect at (not bound to) the target character X = Engine_TPtoSPX(CharList(TargetIndex).Pos.X) + 16 Y = Engine_TPtoSPY(CharList(TargetIndex).Pos.Y) TempIndex = Effect_Strengthen_Begin(X, Y, 12, 120, 40, 15) Effect(TempIndex).BindToChar = TargetIndex Effect(TempIndex).BindSpeed = 25 Case SkID.Bless CasterIndex = rBuf.Get_Integer TargetIndex = rBuf.Get_Integer If Not Engine_ValidChar(CasterIndex) Then Exit Sub If Not Engine_ValidChar(TargetIndex) Then Exit Sub 'Create the effect X = Engine_TPtoSPX(CharList(TargetIndex).Pos.X) + 16 Y = Engine_TPtoSPY(CharList(TargetIndex).Pos.Y) TempIndex = Effect_Bless_Begin(X, Y, 3, 120, 40, 15) Effect(TempIndex).BindToChar = TargetIndex Effect(TempIndex).BindSpeed = 25 Case SkID.SummonBandit TargetIndex = rBuf.Get_Integer If Not Engine_ValidChar(TargetIndex) Then Exit Sub X = Engine_TPtoSPX(CharList(TargetIndex).Pos.X) + 16 Y = Engine_TPtoSPY(CharList(TargetIndex).Pos.Y) 'Create the effect TempIndex = Effect_Summon_Begin(X, Y, 1, 500, 0) Effect(TempIndex).BindToChar = TargetIndex Effect(TempIndex).BindSpeed = 25 Case SkID.SpikeField CasterIndex = rBuf.Get_Integer If Not Engine_ValidChar(CasterIndex) Then Exit Sub 'Create the spike field depending on the direction the user is facing X = CharList(CasterIndex).Pos.X Y = CharList(CasterIndex).Pos.Y If CharList(CasterIndex).HeadHeading = NORTH Or CharList(CasterIndex).HeadHeading = NORTHEAST Then Engine_Effect_Create X - 1, Y + 1, 59 Engine_Effect_Create X, Y + 1, 59 Engine_Effect_Create X + 1, Y + 1, 59 Engine_Effect_Create X - 2, Y, 59, , , , 0.5 Engine_Effect_Create X - 1, Y, 59, , , , 0.5 Engine_Effect_Create X, Y, 59, , , , 0.5 Engine_Effect_Create X + 1, Y, 59, , , , 0.5 Engine_Effect_Create X + 2, Y, 59, , , , 0.5 Engine_Effect_Create X - 2, Y - 1, 59, , , , 1 Engine_Effect_Create X - 1, Y - 1, 59, , , , 1 Engine_Effect_Create X, Y - 1, 59, , , , 1 Engine_Effect_Create X + 1, Y - 1, 59, , , , 1 Engine_Effect_Create X + 2, Y - 1, 59, , , , 1 Engine_Effect_Create X - 2, Y - 2, 59, , , , 1.5 Engine_Effect_Create X - 1, Y - 2, 59, , , , 1.5 Engine_Effect_Create X, Y - 2, 59, , , , 1.5 Engine_Effect_Create X + 1, Y - 2, 59, , , , 1.5 Engine_Effect_Create X + 2, Y - 2, 59, , , , 1.5 Engine_Effect_Create X - 1, Y - 3, 59, , , , 2 Engine_Effect_Create X, Y - 3, 59, , , , 2 Engine_Effect_Create X + 1, Y - 3, 59, , , , 2 Engine_Effect_Create X, Y - 4, 59, , , , 2.5 ElseIf CharList(CasterIndex).HeadHeading = EAST Or CharList(CasterIndex).HeadHeading = SOUTHEAST Then Engine_Effect_Create X - 1, Y - 1, 59 Engine_Effect_Create X - 1, Y, 59 Engine_Effect_Create X - 1, Y + 1, 59 Engine_Effect_Create X, Y - 2, 59, , , , 0.5 Engine_Effect_Create X, Y - 1, 59, , , , 0.5 Engine_Effect_Create X, Y, 59, , , , 0.5 Engine_Effect_Create X, Y + 1, 59, , , , 0.5 Engine_Effect_Create X, Y + 2, 59, , , , 0.5 Engine_Effect_Create X + 1, Y - 2, 59, , , , 1 Engine_Effect_Create X + 1, Y - 1, 59, , , , 1 Engine_Effect_Create X + 1, Y, 59, , , , 1 Engine_Effect_Create X + 1, Y + 1, 59, , , , 1 Engine_Effect_Create X + 1, Y + 2, 59, , , , 1 Engine_Effect_Create X + 2, Y - 2, 59, , , , 1.5 Engine_Effect_Create X + 2, Y - 1, 59, , , , 1.5 Engine_Effect_Create X + 2, Y, 59, , , , 1.5 Engine_Effect_Create X + 2, Y + 1, 59, , , , 1.5 Engine_Effect_Create X + 2, Y + 2, 59, , , , 1.5 Engine_Effect_Create X + 3, Y - 1, 59, , , , 2 Engine_Effect_Create X + 3, Y, 59, , , , 2 Engine_Effect_Create X + 3, Y + 1, 59, , , , 2 Engine_Effect_Create X + 4, Y, 59, , , , 2.5 ElseIf CharList(CasterIndex).HeadHeading = SOUTH Or CharList(CasterIndex).HeadHeading = SOUTHWEST Then Engine_Effect_Create X - 1, Y - 1, 59 Engine_Effect_Create X, Y - 1, 59 Engine_Effect_Create X + 1, Y - 1, 59 Engine_Effect_Create X - 2, Y, 59, , , , 0.5 Engine_Effect_Create X - 1, Y, 59, , , , 0.5 Engine_Effect_Create X, Y, 59, , , , 0.5 Engine_Effect_Create X + 1, Y, 59, , , , 0.5 Engine_Effect_Create X + 2, Y, 59, , , , 0.5 Engine_Effect_Create X - 2, Y + 1, 59, , , , 1 Engine_Effect_Create X - 1, Y + 1, 59, , , , 1 Engine_Effect_Create X, Y + 1, 59, , , , 1 Engine_Effect_Create X + 1, Y + 1, 59, , , , 1 Engine_Effect_Create X + 2, Y + 1, 59, , , , 1 Engine_Effect_Create X - 2, Y + 2, 59, , , , 1.5 Engine_Effect_Create X - 1, Y + 2, 59, , , , 1.5 Engine_Effect_Create X, Y + 2, 59, , , , 1.5 Engine_Effect_Create X + 1, Y + 2, 59, , , , 1.5 Engine_Effect_Create X + 2, Y + 2, 59, , , , 1.5 Engine_Effect_Create X - 1, Y + 3, 59, , , , 2 Engine_Effect_Create X, Y + 3, 59, , , , 2 Engine_Effect_Create X + 1, Y + 3, 59, , , , 2 Engine_Effect_Create X, Y + 4, 59, , , , 2.5 ElseIf CharList(CasterIndex).HeadHeading = WEST Or CharList(CasterIndex).HeadHeading = NORTHWEST Then Engine_Effect_Create X + 1, Y - 1, 59 Engine_Effect_Create X + 1, Y, 59 Engine_Effect_Create X + 1, Y + 1, 59 Engine_Effect_Create X, Y - 2, 59, , , , 0.5 Engine_Effect_Create X, Y - 1, 59, , , , 0.5 Engine_Effect_Create X, Y, 59, , , , 0.5 Engine_Effect_Create X, Y + 1, 59, , , , 0.5 Engine_Effect_Create X, Y + 2, 59, , , , 0.5 Engine_Effect_Create X - 1, Y - 2, 59, , , , 1 Engine_Effect_Create X - 1, Y - 1, 59, , , , 1 Engine_Effect_Create X - 1, Y, 59, , , , 1 Engine_Effect_Create X - 1, Y + 1, 59, , , , 1 Engine_Effect_Create X - 1, Y + 2, 59, , , , 1 Engine_Effect_Create X - 2, Y - 2, 59, , , , 1.5 Engine_Effect_Create X - 2, Y - 1, 59, , , , 1.5 Engine_Effect_Create X - 2, Y, 59, , , , 1.5 Engine_Effect_Create X - 2, Y + 1, 59, , , , 1.5 Engine_Effect_Create X - 2, Y + 2, 59, , , , 1.5 Engine_Effect_Create X - 3, Y - 1, 59, , , , 2 Engine_Effect_Create X - 3, Y, 59, , , , 2 Engine_Effect_Create X - 3, Y + 1, 59, , , , 2 Engine_Effect_Create X - 4, Y, 59, , , , 2.5 End If End Select End Sub Sub Data_Server_MakeEffect(ByRef rBuf As DataBuffer) '************************************************************ 'Create an effect on the effects layer '<X(B)><Y(B)><GrhIndex(L)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_MakeEffect '************************************************************ Dim X As Byte Dim Y As Byte Dim GrhIndex As Long 'Get the values X = rBuf.Get_Byte Y = rBuf.Get_Byte GrhIndex = rBuf.Get_Long 'Create the effect Engine_Effect_Create X, Y, GrhIndex, 0, 0, 1 End Sub Sub Data_Server_MakeSlash(ByRef rBuf As DataBuffer) '************************************************************ 'Create a slash effect on the effects layer '<CharIndex(I)><GrhIndex(L)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_MakeSlash '************************************************************ Dim CharIndex As Integer Dim GrhIndex As Long Dim Angle As Single 'Get the values CharIndex = rBuf.Get_Integer GrhIndex = rBuf.Get_Long 'If the char doesn't exist, request to create it If Not Engine_ValidChar(CharIndex) Then Exit Sub 'Get the new heading Select Case CharList(CharIndex).Heading Case NORTH Angle = 0 Case NORTHEAST Angle = 45 Case EAST Angle = 90 Case SOUTHEAST Angle = 135 Case SOUTH Angle = 180 Case SOUTHWEST Angle = 225 Case WEST Angle = 270 Case NORTHWEST Angle = 315 End Select 'Create the effect Engine_Effect_Create CharList(CharIndex).Pos.X, CharList(CharIndex).Pos.Y, GrhIndex, Angle, 150, 0 End Sub Sub Data_User_Emote(ByRef rBuf As DataBuffer) '************************************************************ 'A character uses an emoticon '<EmoticonIndex(B)><CharIndex(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_User_Emote '************************************************************ Dim EmoticonIndex As Byte Dim CharIndex As Integer EmoticonIndex = rBuf.Get_Byte CharIndex = rBuf.Get_Integer 'If the char doesn't exist, request to create it If Not Engine_ValidChar(CharIndex) Then Exit Sub 'Reset the fade value CharList(CharIndex).EmoFade = 0 CharList(CharIndex).EmoDir = 1 'Set the user's emoticon Grh by the emoticon index 'Grh values are pulled directly from Grh1.raw - refer to that file Select Case EmoticonIndex Case EmoID.Dots: Engine_Init_Grh CharList(CharIndex).Emoticon, 78 Case EmoID.Exclimation: Engine_Init_Grh CharList(CharIndex).Emoticon, 81 Case EmoID.Question: Engine_Init_Grh CharList(CharIndex).Emoticon, 84 Case EmoID.Surprised: Engine_Init_Grh CharList(CharIndex).Emoticon, 87 Case EmoID.Heart: Engine_Init_Grh CharList(CharIndex).Emoticon, 90 Case EmoID.Hearts: Engine_Init_Grh CharList(CharIndex).Emoticon, 93 Case EmoID.HeartBroken: Engine_Init_Grh CharList(CharIndex).Emoticon, 96 Case EmoID.Utensils: Engine_Init_Grh CharList(CharIndex).Emoticon, 99 Case EmoID.Meat: Engine_Init_Grh CharList(CharIndex).Emoticon, 102 Case EmoID.ExcliQuestion: Engine_Init_Grh CharList(CharIndex).Emoticon, 105 End Select End Sub Sub Data_User_KnownSkills(ByRef rBuf As DataBuffer) '************************************************************ 'Retrieve known skills list '<KnowSkillList()(B)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_User_KnownSkills '************************************************************ Dim KnowSkillList() As Long 'Note that each byte holds 8 skills Dim Index As Long 'Which KnowSkillList array index to use Dim X As Byte Dim Y As Byte Dim i As Byte 'Retrieve the skill list ReDim KnowSkillList(1 To NumBytesForSkills) For i = 1 To NumBytesForSkills KnowSkillList(i) = rBuf.Get_Byte Next i 'Clear the skill list size SkillListSize = 0 'Set the values For i = 1 To NumSkills 'Find the index to use Index = Int((i - 1) / 8) + 1 'Check if the skill is known If KnowSkillList(Index) And (2 ^ (i - ((Index - 1) * 8) - 1)) Then 'Update the SkillList position and size SkillListSize = SkillListSize + 1 ReDim Preserve SkillList(1 To SkillListSize) 'Set that the user knows the skill UserKnowSkill(i) = 1 'Update position for skill list X = X + 1 If X > SkillListWidth Then X = 1 Y = Y + 1 End If 'Set the skill list ID and Position SkillList(SkillListSize).SkillID = i SkillList(SkillListSize).X = SkillListX - (X * 32) SkillList(SkillListSize).Y = SkillListY - (Y * 32) Else 'User does not know the skill UserKnowSkill(i) = 0 End If Next i End Sub Sub Data_User_LookLeft(ByRef rBuf As DataBuffer) '************************************************************ 'Make a character look to the specified direction (Used for LookLeft and LookRight) '<CharIndex(I)><Heading(B)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_User_LookLeft '************************************************************ Dim CharIndex As Integer Dim Heading As Byte CharIndex = rBuf.Get_Integer Heading = rBuf.Get_Byte 'If the char doesn't exist, request to create it If Not Engine_ValidChar(CharIndex) Then Exit Sub CharList(CharIndex).HeadHeading = Heading End Sub Sub Data_User_ModStat(ByRef rBuf As DataBuffer) '************************************************************ 'Update mod stat '<StatID(B)><Value(L)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_User_ModStat '************************************************************ Dim StatID As Byte StatID = rBuf.Get_Byte ModStats(StatID) = rBuf.Get_Long End Sub Sub Data_User_Rotate(ByRef rBuf As DataBuffer) '************************************************************ 'Rotate a character by their CharIndex - works like it does in ' ChangeChar, but used to save ourselves a little bandwidth :) '<CharIndex(I)><Heading(B)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_User_Rotate '************************************************************ Dim Heading As Byte Dim CharIndex As Integer CharIndex = rBuf.Get_Integer Heading = rBuf.Get_Byte 'If the char doesn't exist, request to create it If Not Engine_ValidChar(CharIndex) Then Exit Sub CharList(CharIndex).Heading = Heading CharList(CharIndex).HeadHeading = CharList(CharIndex).Heading End Sub Sub Data_User_SetInventorySlot(ByRef rBuf As DataBuffer) '************************************************************ 'Set an inventory slot's information 'The information in the () is only sent if the ObjIndex <> 0 '<Slot(B)><OBJIndex(L)>(<OBJName(S)><OBJAmount(L)><Equipted(B)><GrhIndex(L)>) 'More info: http://www.vbgore.com/GameClient.TCP.Data_User_SetInventorySlot '************************************************************ Dim Slot As Byte 'Get the slot Slot = rBuf.Get_Byte 'Start gathering the data UserInventory(Slot).ObjIndex = rBuf.Get_Long 'If the object index = 0, then we are deleting a slot, so the rest is null If UserInventory(Slot).ObjIndex = 0 Then UserInventory(Slot).Name = "(None)" UserInventory(Slot).Amount = 0 UserInventory(Slot).Equipped = 0 UserInventory(Slot).GrhIndex = 0 UserInventory(Slot).Value = 0 Else 'Index <> 0, so we have to get the information UserInventory(Slot).Name = rBuf.Get_String UserInventory(Slot).Amount = rBuf.Get_Long UserInventory(Slot).Equipped = rBuf.Get_Byte UserInventory(Slot).GrhIndex = rBuf.Get_Long UserInventory(Slot).Value = rBuf.Get_Long End If End Sub Sub Data_User_Target(ByRef rBuf As DataBuffer) '************************************************************ 'User targets a character '<CharIndex(I)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_User_Target '************************************************************ TargetCharIndex = rBuf.Get_Integer 'Check for a valid UserCharIndex If UserCharIndex <= 0 Or UserCharIndex > LastChar Then 'We have an invalid user char index, so we must have the wrong one - request an update on the right one sndBuf.Put_Byte DataCode.User_RequestUserCharIndex Exit Sub End If 'Check if the path to the targeted character is valid (if any) If TargetCharIndex > 0 Then ClearPathToTarget = Engine_ClearPath(CharList(UserCharIndex).Pos.X, CharList(UserCharIndex).Pos.Y, CharList(TargetCharIndex).Pos.X, CharList(TargetCharIndex).Pos.Y) End Sub Sub Data_User_ChangeServer(ByRef rBuf As DataBuffer) '************************************************************ 'Changes a user to a different server '<Port(I)><IP(S)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_User_ChangeServer '************************************************************ Dim Port As Integer Dim IP As String 'Get the values Port = rBuf.Get_Integer IP = rBuf.Get_String 'Clean out the socket so we can make a fresh new connection If SocketOpen = 1 Then SocketOpen = 0 frmMain.GOREsock.Shut SoxID End If 'Set the variables to move to the new server SocketMoveToIP = IP SocketMoveToPort = Port 'Clear the map CurMap = 0 End Sub Sub Data_User_Trade_StartNPCTrade(ByRef rBuf As DataBuffer) '************************************************************ 'Start trading with a NPC '<NPCName(S)><NumVendItems(I)> Loop: <GrhIndex(L)><Name(S)><Price(L)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_User_Trade_StartNPCTrade '************************************************************ Dim NPCName As String Dim NumItems As Integer Dim Item As Integer NPCName = rBuf.Get_String NumItems = rBuf.Get_Integer ReDim NPCTradeItems(1 To NumItems) NPCTradeItemArraySize = NumItems For Item = 1 To NumItems NPCTradeItems(Item).GrhIndex = rBuf.Get_Long NPCTradeItems(Item).Name = rBuf.Get_String NPCTradeItems(Item).Value = rBuf.Get_Long Next Item ShowGameWindow(ShopWindow) = 1 LastClickedWindow = ShopWindow End Sub Sub Data_User_Trade_Accept(ByRef rBuf As DataBuffer) '************************************************************ 'One of the users of the trade has pressed the accept button '<UserTableIndex(B)> 'More info: http://www.vbgore.com/GameClient.TCP.Data_User_Trade_Accept '************************************************************ Dim UserTableIndex As Byte UserTableIndex = rBuf.Get_Byte 'Find which name to high-light If UserTableIndex = 1 Then If TradeTable.MyIndex = 1 Then TradeTable.User1Accepted = 1 Else TradeTable.User2Accepted = 1 Else If TradeTable.MyIndex = 2 Then TradeTable.User1Accepted = 1 Else TradeTable.User2Accepted = 1 End If End Sub Sub Data_User_Trade_Cancel() '************************************************************ 'Trade table was closed or canceled '<> 'More info: http://www.vbgore.com/GameClient.TCP.Data_User_Trade_Cancel '************************************************************ Dim i As Long ShowGameWindow(TradeWindow) = 0 If LastClickedWindow = TradeWindow Then LastClickedWindow = 0 For i = 1 To 9 TradeTable.Trade1(i).Amount = 0 TradeTable.Trade1(i).Grh = 0 TradeTable.Trade1(i).Name = vbNullString TradeTable.Trade1(i).Value = 0 TradeTable.Trade2(i).Amount = 0 TradeTable.Trade2(i).Grh = 0 TradeTable.Trade2(i).Name = vbNullString TradeTable.Trade2(i).Value = 0 Next i TradeTable.Gold1 = 0 TradeTable.Gold2 = 0 TradeTable.User1Accepted = 0 TradeTable.User2Accepted = 0 TradeTable.User1Name = vbNullString TradeTable.User2Name = vbNullString TradeTable.MyIndex = 0 End Sub Sub Data_Server_SendQuestInfo(ByRef rBuf As DataBuffer) '************************************************************ 'Server sent the information on a quest '<QuestID(B)><Name(S)>(<Description(S-EX)>) 'More info: http://www.vbgore.com/GameClient.TCP.Data_Server_SendQuestInfo '************************************************************ Dim QuestID As Byte Dim Name As String Dim Desc As String Dim i As Long Dim Changed As Byte 'Get the variables QuestID = rBuf.Get_Byte Name = rBuf.Get_String If LenB(Name) <> 0 Then Desc = rBuf.Get_StringEX 'Only get the desc if the name exists 'Resize the questinfo array if needed If QuestID > QuestInfoUBound Then QuestInfoUBound = QuestID ReDim Preserve QuestInfo(1 To QuestInfoUBound) End If 'Store the information QuestInfo(QuestID).Name = Name QuestInfo(QuestID).Desc = Desc 'Loop through the quests, remove any unused slots on the end If QuestInfoUBound > 1 Then For i = QuestInfoUBound To 1 Step -1 If QuestInfo(i).Name = vbNullString Then QuestInfoUBound = QuestInfoUBound - 1 Changed = 1 Else 'Exit on the first section of information Exit For End If Next i If Changed Then If QuestInfoUBound > 0 Then ReDim Preserve QuestInfo(1 To QuestInfoUBound) Else Erase QuestInfo End If End If Else If QuestInfo(1).Name = vbNullString Then Erase QuestInfo QuestInfoUBound = 0 End If End If End Sub
[edit] TileEngine
Option Explicit Public Const ShadowColor As Long = 1677721600 'ARGB 100/0/0/0 Public Const HealthColor As Long = -1761673216 'ARGB 150/255/0/0 Public Const ManaColor As Long = -1778384641 'ARGB 150/0/0/255 Public ParticleOffsetX As Long Public ParticleOffsetY As Long Public LastOffsetX As Integer 'The last offset values stored, used to get the offset difference Public LastOffsetY As Integer ' so the particle engine can adjust weather particles accordingly Public EnterText As Boolean 'If the text buffer is used (the user is typing a message) Public EnterTextBuffer As String 'The text in the text buffer Public EnterTextBufferWidth As Long 'Width of the text buffer Public AlternateRender As Byte Public AlternateRenderDefault As Byte Public AlternateRenderMap As Byte Public AlternateRenderText As Byte 'Describes a transformable lit vertex Private Const FVF As Long = D3DFVF_XYZRHW Or D3DFVF_TEX1 Or D3DFVF_DIFFUSE Public Type TLVERTEX X As Single Y As Single Z As Single Rhw As Single Color As Long tU As Single tV As Single End Type 'The size of a FVF vertex Public Const FVF_Size As Long = 28 '********** CONSTANTS *********** 'Keep window in the game screen - dont let them move outside of the window bounds Public Const WindowsInScreen As Boolean = True 'Screen resolution and information (resolution must be identical to the values on the server!) Public ReverseSound As Integer 'Reverse the left and right speakers Public TextureCompress As Long 'Compress textures, saving lots of RAM at an insignifcant CPU usage cost (may reduce graphic quality!) Public DisableChatBubbles As Byte 'If chat bubbles are drawn or not - chat bubbles can be a huge FPS drainer Public Bit32 As Byte 'If 32-bit format is used (0 = 16-bit) Public UseVSync As Byte 'If vertical synchronization copy is used Public Windowed As Boolean 'If the screen is windowed or fullscreen Public Const ScreenWidth As Long = 800 'Keep this identical to the value on the server! Public Const ScreenHeight As Long = 600 'Keep this identical to the value on the server! Private Const BufferWidth As Long = 1024 'If ScreenWidth is <= 1024, this will = 1024, else set it as 2048 Private Const BufferHeight As Long = 1024 'Same as the BufferWidth, but with the ScreenHeight 'Heading constants Public Const NORTH As Byte = 1 Public Const EAST As Byte = 2 Public Const SOUTH As Byte = 3 Public Const WEST As Byte = 4 Public Const NORTHEAST As Byte = 5 Public Const SOUTHEAST As Byte = 6 Public Const SOUTHWEST As Byte = 7 Public Const NORTHWEST As Byte = 8 'Font colors Public Const FontColor_Talk As Long = -1 Public Const FontColor_Info As Long = -16711936 Public Const FontColor_Fight As Long = -65536 Public Const FontColor_Quest As Long = -256 Public Const FontColor_Group As Long = -16711681 Private Const ChatTextBufferSize As Integer = 200 Public Const DamageDisplayTime As Integer = 2000 Public Const MouseSpeed As Single = 1.5 '********** MUSIC *********** Public Const Music_MaxVolume As Long = 100 Public Const Music_MaxBalance As Long = 100 Public Const Music_MaxSpeed As Long = 226 Public Const NumMusicBuffers As Long = 1 Public DirectShow_Event(1 To NumMusicBuffers) As IMediaEvent Public DirectShow_Control(1 To NumMusicBuffers) As IMediaControl Public DirectShow_Position(1 To NumMusicBuffers) As IMediaPosition Public DirectShow_Audio(1 To NumMusicBuffers) As IBasicAudio '********** Custom Fonts ************ 'Point API Public Type POINTAPI X As Long Y As Long End Type 'vbGORE Font Header Private Type CharVA Vertex(0 To 3) As TLVERTEX End Type Private Type VFH BitmapWidth As Long 'Size of the bitmap itself BitmapHeight As Long CellWidth As Long 'Size of the cells (area for each character) CellHeight As Long BaseCharOffset As Byte 'The character we start from CharWidth(0 To 255) As Byte 'The actual factual width of each character CharVA(0 To 255) As CharVA End Type Private Type CustomFont HeaderInfo As VFH 'Holds the header information Texture As Direct3DTexture8 'Holds the texture of the text RowPitch As Integer 'Number of characters per row RowFactor As Single 'Percentage of the texture width each character takes ColFactor As Single 'Percentage of the texture height each character takes CharHeight As Byte 'Height to use for the text - easiest to start with CellHeight value, and keep lowering until you get a good value TextureSize As POINTAPI 'Size of the texture End Type Public Const Font_Default_TextureNum As Long = -1 'The texture number used to represent this font - only used for AlternateRendering - keep negative to prevent interfering with game textures Public Font_Default As CustomFont 'Describes our custom font "default" '********** TYPES *********** 'Text buffer Type ChatTextBuffer Text As String Color As Long End Type Private ChatTextBuffer(1 To ChatTextBufferSize) As ChatTextBuffer 'Holds a position on a 2d grid Public Type Position X As Long Y As Long End Type 'Holds a position on a 2d grid in floating variables (singles) Public Type FloatPos X As Single Y As Single End Type 'Holds a world position Private Type WorldPos X As Byte Y As Byte End Type 'Holds data about where a png can be found, 'How big it is and animation info Public Type GrhData SX As Integer SY As Integer FileNum As Long pixelWidth As Integer pixelHeight As Integer TileWidth As Single TileHeight As Single NumFrames As Byte Frames() As Long Speed As Single End Type 'Points to a grhData and keeps animation info Public Type Grh GrhIndex As Long LastCount As Long FrameCounter As Single Started As Byte End Type 'Bodies list Public Type BodyData Walk(1 To 8) As Grh Attack(1 To 8) As Grh HeadOffset As Position End Type 'Wings list Public Type WingData Walk(1 To 8) As Grh Attack(1 To 8) As Grh End Type 'Weapons list Public Type WeaponData Walk(1 To 8) As Grh Attack(1 To 8) As Grh End Type 'Heads list Public Type HeadData Head(1 To 8) As Grh Blink(1 To 8) As Grh AgrHead(1 To 8) As Grh AgrBlink(1 To 8) As Grh End Type 'Hair list Public Type HairData Hair(1 To 8) As Grh End Type 'Hold info about the character's status Public Type CharStatus Cursed As Byte WarCursed As Byte Blessed As Byte Protected As Byte Strengthened As Byte IronSkinned As Byte Exhausted As Byte End Type 'Hold info about a character Public Type Char Active As Byte Heading As Byte HeadHeading As Byte CharType As Byte OwnerChar As Integer 'If CharType = Slave then this is the index of the owner (used for summoned NPCs to display on the mini-map) Pos As Position 'Tile position on the map RealPos As Position 'Position on the game screen Body As BodyData Head As HeadData Weapon As WeaponData Hair As HairData Wings As WingData Moving As Byte Speed As Byte Running As Byte Aggressive As Byte AggressiveCounter As Long MoveOffset As FloatPos BlinkTimer As Single 'The length of the actual blinking StartBlinkTimer As Single 'How long until a blink starts ScrollDirectionX As Integer ScrollDirectionY As Integer BubbleStr As String BubbleTime As Long Name As String NameOffset As Integer 'Used to acquire the center position for the name ActionIndex As Byte HealthPercent As Byte ManaPercent As Byte CharStatus As CharStatus Emoticon As Grh EmoFade As Single EmoDir As Byte 'Direction the fading is going - 0 = Stopped, 1 = Up, 2 = Down NPCChatIndex As Byte NPCChatLine As Byte NPCChatDelay As Long End Type 'Holds info about each tile position Public Type MapBlock BlockedAttack As Byte Graphic(1 To 6) As Grh Light(1 To 24) As Long Shadow(1 To 6) As Byte Sign As Integer Blocked As Byte Warp As Byte Sfx As DirectSoundSecondaryBuffer8 End Type 'Hold info about each map Public Type MapInfo Name As String Weather As Byte Music As Byte Width As Byte Height As Byte End Type 'Describes the return from a texture init Private Type D3DXIMAGE_INFO_A Width As Long Height As Long Depth As Long MipLevels As Long Format As CONST_D3DFORMAT ResourceType As CONST_D3DRESOURCETYPE ImageFileFormat As Long End Type 'Describes a layer bound to tile position but not in the map array (to save memory) Private Type FloatSurface Pos As WorldPos Offset As Position Grh As Grh End Type 'Describes the effects layer Private Type EffectSurface Pos As WorldPos Grh As Grh Angle As Single Time As Long Animated As Byte End Type 'Describes the damage counters Public Type DamageTxt Pos As FloatPos Value As String Counter As Single Width As Integer End Type '********** Public VARS *********** 'User status vars Public CurMap As Integer 'Current map loaded Public UserMoving As Boolean Public UserPos As Position 'Holds current user pos Private AddtoUserPos As Position 'For moving user Public UserCharIndex As Integer Public EngineRun As Boolean Private FPS As Long Private FramesPerSecCounter As Long Private FPSLastCheck As Long Private SaveLastCheck As Long 'How many tiles the engine "looks ahead" when drawing the screen Public TileBufferSize As Integer Public TileBufferOffset As Long 'Used to calculate offset value in certain cases 'Main view size size in tiles Public Const WindowTileWidth As Integer = ScreenWidth \ 32 Public Const WindowTileHeight As Integer = ScreenHeight \ 32 'Tile size in pixels Public Const TilePixelHeight As Integer = 32 Public Const TilePixelWidth As Integer = 32 'Number of pixels the engine scrolls per frame. MUST divide evenly into pixels per tile Public Const ScrollPixelsPerFrameX As Integer = 4 Public Const ScrollPixelsPerFrameY As Integer = 4 'Totals Private NumBodies As Integer 'Number of bodies Private NumHeads As Integer 'Number of heads Private NumHairs As Integer 'Number of hairs Private NumWeapons As Integer 'Number of weapons Private NumGrhs As Long 'Number of grhs Private NumWings As Integer 'Number of wings Public NumSfx As Integer 'Number of sound effects Public NumGrhFiles As Integer 'Number of pngs Public LastChar As Integer 'Last character Public LastObj As Integer 'Last object Public LastBlood As Integer 'Last blood splatter index used Public LastEffect As Integer 'Last effect index used Public LastDamage As Integer 'Last damage counter text index used Public LastProjectile As Integer 'Last projectile index used 'Screen positioning Public minY As Integer 'Start Y pos on current screen + tilebuffer Public maxY As Integer 'End Y pos on current screen Public minX As Integer 'Start X pos on current screen Public maxX As Integer 'End X pos on current screen Public ScreenMinY As Integer 'Start Y pos on current screen Public ScreenMaxY As Integer 'End Y pos on current screen Public ScreenMinX As Integer 'Start X pos on current screen Public ScreenMaxX As Integer 'End X pos on current screen Public LastTileX As Integer Public LastTileY As Integer '********** GAME WINDOWS *********** Public Const SkillListX As Integer = 750 'Position where the skill list where appear Public Const SkillListY As Integer = 525 ' (indicates the bottom-right corner) Public Const SkillListWidth As Integer = 5 'How many skills wide the skill popup list is Public Const GUIColorValue As Long = -1090519041 'ARGB 190/255/255/255 'Important: Windows are ordered by priority, where 1 = highest! Public Const AmountWindow As Byte = 1 Public Const MenuWindow As Byte = 2 Public Const NPCChatWindow As Byte = 3 Public Const TradeWindow As Byte = 4 Public Const WriteMessageWindow As Byte = 5 Public Const ViewMessageWindow As Byte = 6 Public Const MailboxWindow As Byte = 7 Public Const InventoryWindow As Byte = 8 Public Const ShopWindow As Byte = 9 Public Const BankWindow As Byte = 10 Public Const StatWindow As Byte = 11 Public Const ChatWindow As Byte = 12 Public Const QuickBarWindow As Byte = 13 Public Const NumGameWindows As Byte = 13 Public Const MaxMailObjs As Byte = 10 Public SelGameWindow As Byte 'The selected game window (mouse is down, not last-clicked) Public SelMessage As Byte 'The selected message in the mailbox Public LastClickedWindow As Byte 'The last game window to be clicked Public ShowGameWindow(1 To NumGameWindows) As Byte 'What game windows are visible Public MailboxListBuffer As String 'Holds the list of text for the mailbox Public AmountWindowValue As String 'How much of the item will be dropped from the amount window Public AmountWindowItemIndex As Byte 'Index of the item to be dropped/sold/sent when the amount window pops up Public AmountWindowUsage As Byte 'The usage combination for the amount window (as defined with below constants) Public DrawSkillList As Byte 'If the skills list is to be drawn Public QuickBarSetSlot As Byte 'What slot on the quickbar was clicked to be set Public DragSourceWindow As Byte 'The window the item was dragged from Public DragItemSlot As Byte 'Holds what slot an item is being dragged from in the inventory 'AmountWindowUsage constants Public Const AW_Drop As Byte = 0 Public Const AW_InvToShop As Byte = 2 Public Const AW_InvToBank As Byte = 3 Public Const AW_InvToMail As Byte = 4 Public Const AW_ShopToInv As Byte = 5 Public Const AW_BankToInv As Byte = 6 Public Const AW_InvToTrade As Byte = 7 Private Type QuickBarIDData Type As Byte 'Type of information in the quick bar (Item, Skill, etc) ID As Byte 'The ID of whatever is being held (Item = Inventory Slot, Skill = SkillID) End Type Public QuickBarID(1 To 12) As QuickBarIDData Public Const QuickBarType_Skill As Byte = 1 Public Const QuickBarType_Item As Byte = 2 Private Type SkillListData SkillID As Byte X As Long Y As Long End Type Public SkillList() As SkillListData Public SkillListSize As Byte Private Type RMailData 'The mail data for the message being read Subject As String WriterName As String Message As String Obj(1 To MaxMailObjs) As Integer ObjName(1 To MaxMailObjs) As String ObjAmount(1 To MaxMailObjs) As Integer End Type Public ReadMailData As RMailData Private Type WMailData 'The mail data for the message being written Subject As String RecieverName As String Message As String ObjIndex(1 To MaxMailObjs) As Integer ObjAmount(1 To MaxMailObjs) As Integer End Type Public WriteMailData As WMailData Public Enum WriteMailSelectedControl wmFrom = 1 wmSubject = 2 wmMessage = 3 End Enum #If False Then Private From, Subject, Message #End If Public WMSelCon As WriteMailSelectedControl Private Type Rectangle 'A normal little rectangle X As Integer Y As Integer Width As Integer Height As Integer End Type Private Type WindowMessage 'Write/Read message window Screen As Rectangle From As Rectangle Subject As Rectangle Message As Rectangle Image(1 To MaxMailObjs) As Rectangle SkinGrh As Grh End Type Private Type WindowQuickBar 'Quick bar window Screen As Rectangle Image(1 To 12) As Rectangle SkinGrh As Grh End Type Private Type WindowInventory 'User inventory window Screen As Rectangle Image(1 To MAX_INVENTORY_SLOTS) As Rectangle SkinGrh As Grh End Type Private Type WindowMailbox 'Mailbox window Screen As Rectangle WriteLbl As Rectangle DeleteLbl As Rectangle ReadLbl As Rectangle List As Rectangle SkinGrh As Grh End Type Private Type WindowAmount 'Amount window Screen As Rectangle Value As Rectangle SkinGrh As Grh End Type Private Type ChatWindow 'Chat buffer/input window Screen As Rectangle Text As Rectangle SkinGrh As Grh End Type Private Type WindowMenu Screen As Rectangle QuitLbl As Rectangle SkinGrh As Grh End Type Private Type StatWindow Screen As Rectangle AddStr As Rectangle AddAgi As Rectangle AddMag As Rectangle Str As Rectangle Agi As Rectangle Mag As Rectangle Points As Rectangle Dmg As Rectangle DEF As Rectangle Gold As Rectangle AddGrh As Grh SkinGrh As Grh End Type Private Type WindowNPCChat Screen As Rectangle NumAnswers As Byte Answer() As Rectangle SkinGrh As Grh End Type 'Info about the trade window Public Type TradeWindow Screen As Rectangle User1Name As Rectangle User2Name As Rectangle Trade1(1 To 9) As Rectangle Trade2(1 To 9) As Rectangle Gold1 As Rectangle Gold2 As Rectangle Accept As Rectangle Trade As Rectangle Cancel As Rectangle SkinGrh As Grh End Type Public Type GameWindow 'List of all the different game windows QuickBar As WindowQuickBar Inventory As WindowInventory Shop As WindowInventory Mailbox As WindowMailbox ViewMessage As WindowMessage WriteMessage As WindowMessage Amount As WindowAmount Menu As WindowMenu ChatWindow As ChatWindow StatWindow As StatWindow Bank As WindowInventory NPCChat As WindowNPCChat Trade As TradeWindow End Type Public GameWindow As GameWindow '********** Direct X *********** Public Const SurfaceTimerMax As Long = 300000 'How long a texture stays in memory unused (miliseconds) Public SurfaceDB() As Direct3DTexture8 'The list of all the textures Public SurfaceTimer() As Long 'How long until the surface unloads Public LastTexture As Long 'The last texture used Public D3DWindow As D3DPRESENT_PARAMETERS 'Describes the viewport and used to restore when in fullscreen Public UsedCreateFlags As CONST_D3DCREATEFLAGS 'The flags we used to create the device when it first succeeded Public DispMode As D3DDISPLAYMODE 'Describes the display mode 'Texture for particle effects - this is handled differently then the rest of the graphics Public ParticleTexture(1 To 12) As Direct3DTexture8 'DirectX 8 Objects Public DX As DirectX8 Public D3D As Direct3D8 Public D3DX As D3DX8 Public D3DDevice As Direct3DDevice8 'Used for alternate rendering only Private Sprite As D3DXSprite Private SpriteBegun As Byte Private SpriteScaleVector As D3DVECTOR2 'Motion-bluring information Public UseMotionBlur As Byte 'If motion blur is enabled or not Public BlurIntensity As Single Public BlurTexture As Direct3DTexture8 Public BlurSurf As Direct3DSurface8 Public BlurStencil As Direct3DSurface8 Public DeviceStencil As Direct3DSurface8 Public DeviceBuffer As Direct3DSurface8 Public BlurTA(0 To 3) As TLVERTEX 'Chat vertex buffer (only kept in memory if using alternate rendering) Private ChatVA() As TLVERTEX 'Chat vertex buffer information Private ChatArrayUbound As Long Private ChatVB As Direct3DVertexBuffer8 'Projectile information Public Type Projectile X As Single Y As Single tX As Single tY As Single RotateSpeed As Byte Rotate As Single Grh As Grh End Type 'Texture information Public Type TexInfo X As Long Y As Long End Type 'Used to hold the graphic layers in a quick-to-draw format Public Type Tile TileX As Byte TileY As Byte PixelPosX As Integer PixelPosY As Integer End Type Public Type TileLayer Tile() As Tile NumTiles As Integer End Type Public TileLayer(1 To 6) As TileLayer '********** WEATHER *********** Public Type LightType Light(1 To 24) As Long End Type Public SaveLightBuffer() As LightType Public WeatherEffectIndex As Integer 'Index returned by the weather effect initialization Public WeatherDoLightning As Byte 'Are we using lightning? >1 = Yes, 0 = No Public WeatherFogX1 As Single 'Fog 1 position Public WeatherFogY1 As Single 'Fog 1 position Public WeatherFogX2 As Single 'Fog 2 position Public WeatherFogY2 As Single 'Fog 2 position Public WeatherDoFog As Byte 'Are we using fog? >1 = Yes, 0 = No Public WeatherFogCount As Byte 'How many fog effects there are Public LightningTimer As Single 'How long until our next lightning bolt strikes Public FlashTimer As Single 'How long until the flash goes away (being > 0 states flash is happening) Public WeatherSfx1 As DirectSoundSecondaryBuffer8 'Weather buffers - dont add more unless you need more for Public WeatherSfx2 As DirectSoundSecondaryBuffer8 ' one weather effect (ie rain, wind, lightning) '********** Public ARRAYS *********** Public GrhData() As GrhData 'Holds data for the graphic structure Public SurfaceSize() As TexInfo 'Holds the size of the surfaces for SurfaceDB() Public BodyData() As BodyData 'Holds data about body structure Public HeadData() As HeadData 'Holds data about head structure Public HairData() As HairData 'Holds data about hair structure Public WeaponData() As WeaponData 'Holds data about weapon structure Public WingData() As WingData 'Holds data about wing structure Public MapData() As MapBlock 'Holds map data for current map Public MapInfo As MapInfo 'Holds map info for current map Public CharList() As Char 'Holds info about all characters on the map Public OBJList() As FloatSurface 'Holds info about all objects on the map Public BloodList() As FloatSurface 'Holds info about all the active blood splatters Public EffectList() As EffectSurface 'Holds info about all the active effects of all types Public ProjectileList() As Projectile 'Holds info about all the active projectiles (arrows, ninja stars, bullets, etc) Public DamageList() As DamageTxt 'Holds info on the damage displays 'FPS Public EndTime As Long Public ElapsedTime As Single Public TickPerFrame As Single Public Const EngineBaseSpeed As Single = 0.011 Public OffsetCounterX As Single Public OffsetCounterY As Single Private NotFirstRender As Boolean Public ShownText As String 'Weather information Public LastWeather As Byte Public UseWeather As Byte 'Mini-map tiles Public Type MiniMapTile X As Single 'X and Y index of the tile (using the tile position, not pixel position) Y As Single Color As Long 'The color of the tile End Type Public MiniMapVBSize As Long 'Size of the vertex buffer (number of verticies, or Tiles x 8) Public MiniMapVB As Direct3DVertexBuffer8 'Holds the information needed to render the mini-map (not including characters) Public ShowMiniMap As Byte '********** OUTSIDE FUNCTIONS *********** Public Declare Function GetAsyncKeyState Lib "user32.dll" (ByVal vKey As Long) As Integer Sub Engine_MakeChatBubble(ByVal CharIndex As Integer, ByVal Text As String) '************************************************************ 'Adds text to a chat bubble 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_MakeChatBubble '************************************************************ If DisableChatBubbles Then Exit Sub If LenB(Text) = 0 Then Exit Sub 'No text passed CharList(CharIndex).BubbleStr = Text CharList(CharIndex).BubbleTime = 5000 End Sub Public Function Engine_TPtoSPX(ByVal X As Byte) As Long '************************************************************ 'Tile Position to Screen Position 'Takes the tile position and returns the pixel location on the screen 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_TPtoSPX '************************************************************ Engine_TPtoSPX = Engine_PixelPosX(X - minX) + OffsetCounterX - 288 + TileBufferOffset End Function Public Function Engine_TPtoSPY(ByVal Y As Byte) As Long '************************************************************ 'Tile Position to Screen Position 'Takes the tile position and returns the pixel location on the screen 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_TPtoSPY '************************************************************ Engine_TPtoSPY = Engine_PixelPosY(Y - minY) + OffsetCounterY - 288 + TileBufferOffset End Function Public Sub Engine_AddToChatTextBuffer(ByVal Text As String, ByVal Color As Long) '************************************************************ 'Adds text to the chat text buffer 'Buffer is order from bottom to top 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_AddToChatTextBuffer '************************************************************ Dim TempSplit() As String Dim TSLoop As Long Dim LastSpace As Long Dim Size As Long Dim i As Long Dim b As Long 'Check if there are any line breaks - if so, we will support them TempSplit = Split(Text, vbCrLf) For TSLoop = 0 To UBound(TempSplit) 'Clear the values for the new line Size = 0 b = 1 LastSpace = 1 'Loop through all the characters For i = 1 To Len(TempSplit(TSLoop)) 'If it is a space, store it so we can easily break at it Select Case Mid$(TempSplit(TSLoop), i, 1) Case " ": LastSpace = i Case "_": LastSpace = i Case "-": LastSpace = i End Select 'Add up the size - Do not count the "|" character (high-lighter)! If Not Mid$(TempSplit(TSLoop), i, 1) = "|" Then Size = Size + Font_Default.HeaderInfo.CharWidth(Asc(Mid$(TempSplit(TSLoop), i, 1))) End If 'Check for too large of a size If Size > GameWindow.ChatWindow.Text.Width Then 'Check if the last space was too far back If i - LastSpace > 10 Then 'Too far away to the last space, so break at the last character Engine_AddToChatTextBuffer2 Trim$(Mid$(TempSplit(TSLoop), b, (i - 1) - b)), Color b = i - 1 Size = 0 Else 'Break at the last space to preserve the word Engine_AddToChatTextBuffer2 Trim$(Mid$(TempSplit(TSLoop), b, LastSpace - b)), Color b = LastSpace + 1 'Count all the words we ignored (the ones that weren't printed, but are before "i") Size = Engine_GetTextWidth(Font_Default, Mid$(TempSplit(TSLoop), LastSpace, i - LastSpace)) End If End If 'This handles the remainder If i = Len(TempSplit(TSLoop)) Then If b <> i Then Engine_AddToChatTextBuffer2 Mid$(TempSplit(TSLoop), b, i), Color End If Next i Next TSLoop 'Only update if we have set up the text (that way we can add to the buffer before it is even made) If Font_Default.RowPitch = 0 Then Exit Sub 'Update the array Engine_UpdateChatArray End Sub Private Sub Engine_AddToChatTextBuffer2(ByVal Text As String, ByVal Color As Long) '************************************************************ 'Actually adds the text to the buffer 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_AddToChatTextBuffer2 '************************************************************ Dim LoopC As Long 'Move all other text up For LoopC = (ChatTextBufferSize - 1) To 1 Step -1 ChatTextBuffer(LoopC + 1) = ChatTextBuffer(LoopC) Next LoopC 'Set the values ChatTextBuffer(1).Text = Text ChatTextBuffer(1).Color = Color End Sub Public Sub Engine_UpdateChatArray() '************************************************************ 'Update the array representing the text in the chat buffer 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_UpdateChatArray '************************************************************ Dim Chunk As Integer Dim Count As Integer Dim LoopC As Byte Dim Ascii As Byte Dim Row As Long Dim Pos As Long Dim u As Single Dim v As Single Dim X As Single Dim Y As Single Dim Y2 As Single Dim i As Long Dim j As Long Dim Size As Integer Dim KeyPhrase As Byte Dim ResetColor As Byte Dim TempColor As Long On Error Resume Next 'Set the position If ChatBufferChunk <= 1 Then ChatBufferChunk = 1 Chunk = 12 'Get the number of characters in all the visible buffer Size = 0 For LoopC = (Chunk * ChatBufferChunk) - 11 To Chunk * ChatBufferChunk If LoopC > ChatTextBufferSize Then Exit For Size = Size + Len(ChatTextBuffer(LoopC).Text) 'Remove the "|"'s from the count For i = 1 To Size If Mid$(ChatTextBuffer(LoopC).Text, i, 1) = "|" Then j = j + 1 Next i Next LoopC Size = Size - j ChatArrayUbound = Size * 6 - 1 If ChatArrayUbound < 0 Then Exit Sub ReDim ChatVA(0 To ChatArrayUbound) 'Size our array to fix the 6 verticies of each character 'Set the base position X = GameWindow.ChatWindow.Screen.X + GameWindow.ChatWindow.Text.X Y = GameWindow.ChatWindow.Screen.Y + GameWindow.ChatWindow.Text.X 'We assume the border is the same size on all sides 'Loop through each buffer string For LoopC = (Chunk * ChatBufferChunk) - 11 To Chunk * ChatBufferChunk If LoopC > ChatTextBufferSize Then Exit For If ChatBufferChunk * Chunk > ChatTextBufferSize Then ChatBufferChunk = ChatBufferChunk - 1 'Set the temp color TempColor = ChatTextBuffer(LoopC).Color 'Set the Y position to be used Y2 = Y - (LoopC * 10) + (Chunk * ChatBufferChunk * 10) 'Loop through each line if there are line breaks (vbCrLf) Count = 0 'Counts the offset value we are on If LenB(ChatTextBuffer(LoopC).Text) <> 0 Then 'Dont bother with empty strings 'Loop through the characters For j = 1 To Len(ChatTextBuffer(LoopC).Text) 'Convert the character to the ascii value Ascii = Asc(Mid$(ChatTextBuffer(LoopC).Text, j, 1)) 'Check for a key phrase If Ascii = 124 Then KeyPhrase = (Not KeyPhrase) If KeyPhrase Then TempColor = D3DColorARGB(255, 255, 0, 0) Else ResetColor = 1 Else 'tU and tV value (basically tU = BitmapXPosition / BitmapWidth, and height for tV) Row = (Ascii - Font_Default.HeaderInfo.BaseCharOffset) \ Font_Default.RowPitch u = ((Ascii - Font_Default.HeaderInfo.BaseCharOffset) - (Row * Font_Default.RowPitch)) * Font_Default.ColFactor v = Row * Font_Default.RowFactor 'Set up the verticies ' 4____5 ' 1|\\ | 1 = 4 ' | \\ | 3 = 6 ' | \\ | ' | \\ | ' 2|____\\| ' 3 6 'Triangle 1 With ChatVA(0 + (6 * Pos)) 'Top-left corner .Color = TempColor .X = X + Count .Y = Y2 .tU = u .tV = v .Rhw = 1 End With With ChatVA(1 + (6 * Pos)) 'Bottom-left corner .Color = TempColor .X = X + Count .Y = Y2 + Font_Default.HeaderInfo.CellHeight .tU = u .tV = v + Font_Default.RowFactor .Rhw = 1 End With With ChatVA(2 + (6 * Pos)) 'Bottom-right corner .Color = TempColor .X = X + Count + Font_Default.HeaderInfo.CellWidth .Y = Y2 + Font_Default.HeaderInfo.CellHeight .tU = u + Font_Default.ColFactor .tV = v + Font_Default.RowFactor .Rhw = 1 End With 'Triangle 2 (only one new verticy is needed) ChatVA(3 + (6 * Pos)) = ChatVA(0 + (6 * Pos)) 'Top-left corner With ChatVA(4 + (6 * Pos)) 'Top-right corner .Color = TempColor .X = X + Count + Font_Default.HeaderInfo.CellWidth .Y = Y2 .tU = u + Font_Default.ColFactor .tV = v .Rhw = 1 End With ChatVA(5 + (6 * Pos)) = ChatVA(2 + (6 * Pos)) 'Update the character we are on Pos = Pos + 1 'Shift over the the position to render the next character Count = Count + Font_Default.HeaderInfo.CharWidth(Ascii) End If 'Check to reset the color If ResetColor Then ResetColor = 0 TempColor = ChatTextBuffer(LoopC).Color End If Next j End If Next LoopC On Error GoTo 0 'Check what rendering method we're using If AlternateRenderText = 0 Then 'Set the vertex array to the vertex buffer If Pos <= 0 Then Pos = 1 If Not D3DDevice Is Nothing Then 'Make sure the D3DDevice exists - this will only return false if we received messages before it had time to load Set ChatVB = D3DDevice.CreateVertexBuffer(FVF_Size * Pos * 6, 0, FVF, D3DPOOL_MANAGED) D3DVertexBuffer8SetData ChatVB, 0, FVF_Size * Pos * 6, 0, ChatVA(0) End If Erase ChatVA() End If End Sub Public Sub Engine_Blood_Create(ByVal X As Integer, ByVal Y As Integer) '***************************************************************** 'Create a blood splatter 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Blood_Create '***************************************************************** Dim BloodIndex As Integer 'Get the next open blood slot Do BloodIndex = BloodIndex + 1 'Update LastBlood if we go over the size of the current array If BloodIndex > LastBlood Then LastBlood = BloodIndex ReDim Preserve BloodList(1 To LastBlood) Exit Do End If Loop While BloodList(BloodIndex).Grh.GrhIndex > 0 'Fill in the values BloodList(BloodIndex).Pos.X = X BloodList(BloodIndex).Pos.Y = Y Engine_Init_Grh BloodList(BloodIndex).Grh, 21 End Sub Public Sub Engine_Blood_Erase(ByVal BloodIndex As Integer) '***************************************************************** 'Erase a blood splatter 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Blood_Erase '***************************************************************** 'Clear the selected index BloodList(BloodIndex).Grh.FrameCounter = 0 BloodList(BloodIndex).Grh.GrhIndex = 0 BloodList(BloodIndex).Pos.X = 0 BloodList(BloodIndex).Pos.Y = 0 'Update LastBlood If BloodIndex = LastBlood Then Do Until BloodList(LastBlood).Grh.GrhIndex > 1 'Move down one splatter LastBlood = LastBlood - 1 If LastBlood = 0 Then Erase BloodList Exit Sub Else 'We still have blood, resize the array to end at the last used slot ReDim Preserve BloodList(1 To LastBlood) End If Loop End If End Sub Sub Engine_ChangeHeading(ByVal Direction As Byte) '***************************************************************** 'Face user in appropriate direction 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_ChangeHeading '***************************************************************** 'Check for a valid UserCharIndex If UserCharIndex <= 0 Or UserCharIndex > LastChar Then 'We have an invalid user char index, so we must have the wrong one - request an update on the right one sndBuf.Put_Byte DataCode.User_RequestUserCharIndex Exit Sub End If 'Only rotate if the user is not already facing that direction If CharList(UserCharIndex).Heading <> Direction Then sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_Rotate sndBuf.Put_Byte Direction End If End Sub Sub Engine_Char_Erase(ByVal CharIndex As Integer) '***************************************************************** 'Erases a character from CharList and map 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Char_Erase '***************************************************************** 'Check for targeted character If TargetCharIndex = CharIndex Then TargetCharIndex = 0 If CharIndex = 0 Then Exit Sub If CharIndex > LastChar Then Exit Sub 'Make inactive CharList(CharIndex).Active = 0 'Update LastChar If CharIndex = LastChar Then Do Until CharList(LastChar).Active = 1 LastChar = LastChar - 1 If LastChar = 0 Then Exit Do Else ReDim Preserve CharList(1 To LastChar) End If Loop End If End Sub Function Engine_UserIsFacingChar() As Boolean '***************************************************************** 'Checks if the user is facing a character - used to check if a character ' is at a tile before making a melee attack 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_UserIsFacingChar '***************************************************************** Dim i As Long Dim X As Long Dim Y As Long Dim AddX As Long Dim AddY As Long 'Get the co-ordinates of the tile the user is facing Select Case CharList(UserCharIndex).Heading Case NORTH AddY = -1 Case EAST AddX = 1 Case SOUTH AddY = 1 Case WEST AddX = -1 Case NORTHEAST AddY = -1 AddX = 1 Case SOUTHEAST AddY = 1 AddX = 1 Case SOUTHWEST AddY = 1 AddX = -1 Case NORTHWEST AddY = -1 AddX = -1 End Select X = CharList(UserCharIndex).Pos.X + AddX Y = CharList(UserCharIndex).Pos.Y + AddY 'Make sure the tile is valid If X <= 0 Then Exit Function If Y <= 0 Then Exit Function If X > MapInfo.Width Then Exit Function If Y > MapInfo.Height Then Exit Function 'Loop through all the characters For i = 1 To LastChar If i <> UserCharIndex Then 'Check if the character is located at the tile If CharList(i).Pos.X = X Then If CharList(i).Pos.Y = Y Then 'We have an character here! Engine_UserIsFacingChar = True Exit Function End If End If End If Next i End Function Sub Engine_Char_Make(ByVal CharIndex As Integer, ByVal Body As Integer, ByVal Head As Integer, ByVal Heading As Byte, ByVal X As Integer, ByVal Y As Integer, ByVal Speed As Byte, ByVal Name As String, ByVal Weapon As Integer, ByVal Hair As Integer, ByVal Wings As Integer, ByVal ChatID As Byte, ByVal CharType As Byte, Optional ByVal HP As Byte = 100, Optional ByVal MP As Byte = 100) '***************************************************************** 'Makes a new character and puts it on the map 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Char_Make '***************************************************************** Dim EmptyChar As Char 'Update LastChar If CharIndex > LastChar Then LastChar = CharIndex ReDim Preserve CharList(1 To LastChar) End If 'Clear the character CharList(CharIndex) = EmptyChar 'Set the apperances CharList(CharIndex).Body = BodyData(Body) CharList(CharIndex).Head = HeadData(Head) CharList(CharIndex).Hair = HairData(Hair) CharList(CharIndex).Weapon = WeaponData(Weapon) CharList(CharIndex).Wings = WingData(Wings) CharList(CharIndex).Heading = Heading CharList(CharIndex).HeadHeading = Heading CharList(CharIndex).HealthPercent = HP CharList(CharIndex).ManaPercent = MP CharList(CharIndex).Speed = Speed CharList(CharIndex).NPCChatIndex = ChatID CharList(CharIndex).CharType = CharType 'Update position CharList(CharIndex).Pos.X = X CharList(CharIndex).Pos.Y = Y 'Make active CharList(CharIndex).Active = 1 'Calculate the name length so we can center the name above the head CharList(CharIndex).Name = Name CharList(CharIndex).NameOffset = Engine_GetTextWidth(Font_Default, Name) * 0.5 'Set action index CharList(CharIndex).ActionIndex = 0 End Sub Sub Engine_Char_Move_ByHead(ByVal CharIndex As Integer, ByVal nHeading As Byte, ByVal Running As Byte) '***************************************************************** 'Starts the movement of a character in nHeading direction 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Char_Move_ByHead '***************************************************************** Dim AddX As Integer Dim AddY As Integer Dim X As Integer Dim Y As Integer Dim nX As Integer Dim nY As Integer 'Check for a valid CharIndex If CharIndex <= 0 Then Exit Sub X = CharList(CharIndex).Pos.X Y = CharList(CharIndex).Pos.Y 'Figure out which way to move Select Case nHeading Case NORTH AddY = -1 Case EAST AddX = 1 Case SOUTH AddY = 1 Case WEST AddX = -1 Case NORTHEAST AddY = -1 AddX = 1 Case SOUTHEAST AddY = 1 AddX = 1 Case SOUTHWEST AddY = 1 AddX = -1 Case NORTHWEST AddY = -1 AddX = -1 End Select 'Update the character position and settings nX = X + AddX nY = Y + AddY CharList(CharIndex).Pos.X = nX CharList(CharIndex).Pos.Y = nY CharList(CharIndex).MoveOffset.X = -(TilePixelWidth * AddX) CharList(CharIndex).MoveOffset.Y = -(TilePixelHeight * AddY) CharList(CharIndex).Moving = 1 CharList(CharIndex).Heading = nHeading CharList(CharIndex).HeadHeading = nHeading CharList(CharIndex).ScrollDirectionX = AddX CharList(CharIndex).ScrollDirectionY = AddY CharList(CharIndex).ActionIndex = 1 CharList(CharIndex).Running = Running End Sub Sub Engine_Char_Move_ByPos(ByVal CharIndex As Integer, ByVal nX As Integer, ByVal nY As Integer, ByVal Running As Byte) '***************************************************************** 'Starts the movement of a character to nX,nY 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Char_Move_ByPos '***************************************************************** Dim X As Integer Dim Y As Integer Dim AddX As Integer Dim AddY As Integer Dim nHeading As Byte X = CharList(CharIndex).Pos.X Y = CharList(CharIndex).Pos.Y AddX = nX - X AddY = nY - Y 'Figure out the direction the character is going If Sgn(AddX) = 1 Then nHeading = EAST If Sgn(AddX) = -1 Then nHeading = WEST If Sgn(AddY) = -1 Then nHeading = NORTH If Sgn(AddY) = 1 Then nHeading = SOUTH If Sgn(AddX) = 1 And Sgn(AddY) = -1 Then nHeading = NORTHEAST End If If Sgn(AddX) = 1 And Sgn(AddY) = 1 Then nHeading = SOUTHEAST End If If Sgn(AddX) = -1 And Sgn(AddY) = 1 Then nHeading = SOUTHWEST End If If Sgn(AddX) = -1 And Sgn(AddY) = -1 Then nHeading = NORTHWEST End If 'Update the character position and settings CharList(CharIndex).Running = Running CharList(CharIndex).Pos.X = nX CharList(CharIndex).Pos.Y = nY CharList(CharIndex).MoveOffset.X = -1 * (TilePixelWidth * AddX) CharList(CharIndex).MoveOffset.Y = -1 * (TilePixelHeight * AddY) CharList(CharIndex).Moving = 1 CharList(CharIndex).Heading = nHeading CharList(CharIndex).HeadHeading = nHeading CharList(CharIndex).ScrollDirectionX = Sgn(AddX) CharList(CharIndex).ScrollDirectionY = Sgn(AddY) CharList(CharIndex).ActionIndex = 1 'If the targeted character move, re-check if the path is blocked If TargetCharIndex > 0 Then If CharIndex = UserCharIndex Or CharIndex = TargetCharIndex Then ClearPathToTarget = Engine_ClearPath(CharList(UserCharIndex).Pos.X, CharList(UserCharIndex).Pos.Y, CharList(CharIndex).Pos.X, CharList(CharIndex).Pos.Y) End If End If End Sub Sub Engine_ConvertCPtoTP(ByVal cx As Integer, ByVal cy As Integer, ByRef tX As Integer, ByRef tY As Integer) '****************************************** 'Converts where the user clicks in the main window 'to a tile position 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_ConvertCPtoTP '****************************************** tX = UserPos.X + cx \ TilePixelWidth - WindowTileWidth \ 2 tY = UserPos.Y + cy \ TilePixelHeight - WindowTileHeight \ 2 End Sub Public Sub Engine_Damage_Create(ByVal X As Integer, ByVal Y As Integer, ByVal Value As Integer) '***************************************************************** 'Create damage text 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Damage_Create '***************************************************************** Dim DamageIndex As Integer 'Get the next open damage slot Do DamageIndex = DamageIndex + 1 'Update LastDamage if we go over the size of the current array If DamageIndex > LastDamage Then LastDamage = DamageIndex ReDim Preserve DamageList(1 To LastDamage) Exit Do End If Loop While DamageList(DamageIndex).Counter > 0 'Set the values If Value < 1 Then DamageList(DamageIndex).Value = "Miss" Else DamageList(DamageIndex).Value = Value DamageList(DamageIndex).Counter = DamageDisplayTime DamageList(DamageIndex).Width = Engine_GetTextWidth(Font_Default, DamageList(DamageIndex).Value) DamageList(DamageIndex).Pos.X = X DamageList(DamageIndex).Pos.Y = Y End Sub Public Sub Engine_Damage_Erase(ByVal DamageIndex As Integer) '***************************************************************** 'Erase damage text 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Damage_Erase '***************************************************************** 'Clear the selected index DamageList(DamageIndex).Counter = 0 DamageList(DamageIndex).Value = vbNullString DamageList(DamageIndex).Width = 0 'Update LastDamage If DamageIndex = LastDamage Then Do Until DamageList(LastDamage).Counter > 0 'Move down one splatter LastDamage = LastDamage - 1 If LastDamage = 0 Then Erase DamageList Exit Sub Else 'We still have damage text, resize the array to end at the last used slot ReDim Preserve DamageList(1 To LastDamage) End If Loop End If End Sub Public Sub Engine_Projectile_Create(ByVal AttackerIndex As Integer, ByVal TargetIndex As Integer, ByVal GrhIndex As Long, ByVal Rotation As Byte) '***************************************************************** 'Creates a projectile for a ranged weapon 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Projectile_Create '***************************************************************** Dim ProjectileIndex As Integer If AttackerIndex = 0 Then Exit Sub If TargetIndex = 0 Then Exit Sub If AttackerIndex > UBound(CharList) Then Exit Sub If TargetIndex > UBound(CharList) Then Exit Sub 'Get the next open projectile slot Do ProjectileIndex = ProjectileIndex + 1 'Update LastProjectile if we go over the size of the current array If ProjectileIndex > LastProjectile Then LastProjectile = ProjectileIndex ReDim Preserve ProjectileList(1 To LastProjectile) Exit Do End If Loop While ProjectileList(ProjectileIndex).Grh.GrhIndex > 0 'Figure out the initial rotation value ProjectileList(ProjectileIndex).Rotate = Engine_GetAngle(CharList(AttackerIndex).Pos.X, CharList(AttackerIndex).Pos.Y, CharList(TargetIndex).Pos.X, CharList(TargetIndex).Pos.Y) 'Fill in the values ProjectileList(ProjectileIndex).tX = CharList(TargetIndex).Pos.X * 32 ProjectileList(ProjectileIndex).tY = CharList(TargetIndex).Pos.Y * 32 ProjectileList(ProjectileIndex).RotateSpeed = Rotation ProjectileList(ProjectileIndex).X = CharList(AttackerIndex).Pos.X * 32 ProjectileList(ProjectileIndex).Y = CharList(AttackerIndex).Pos.Y * 32 Engine_Init_Grh ProjectileList(ProjectileIndex).Grh, GrhIndex End Sub Public Sub Engine_Effect_Create(ByVal X As Integer, ByVal Y As Integer, ByVal GrhIndex As Long, Optional ByVal Angle As Single = 0, Optional ByVal Time As Long = 0, Optional ByVal Animated As Byte = 1, Optional ByVal DelayFrames As Single = 0) '***************************************************************** 'Creates an effect layer for spells and such 'Life is only used if the effect is looped 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Effect_Create '***************************************************************** Dim EffectIndex As Integer 'Get the next open effect slot Do EffectIndex = EffectIndex + 1 'Update LastEffect if we go over the size of the current array If EffectIndex > LastEffect Then LastEffect = EffectIndex ReDim Preserve EffectList(1 To LastEffect) Exit Do End If Loop While EffectList(EffectIndex).Grh.GrhIndex > 0 'Fill in the values If Time > 0 Then EffectList(EffectIndex).Time = timeGetTime + Time Else EffectList(EffectIndex).Time = 0 EffectList(EffectIndex).Animated = Animated EffectList(EffectIndex).Angle = Angle EffectList(EffectIndex).Pos.X = X EffectList(EffectIndex).Pos.Y = Y Engine_Init_Grh EffectList(EffectIndex).Grh, GrhIndex EffectList(EffectIndex).Grh.FrameCounter = 1 - DelayFrames End Sub Public Sub Engine_Projectile_Erase(ByVal ProjectileIndex As Integer) '***************************************************************** 'Erase a projectile by the projectile index 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Projectile_Erase '***************************************************************** 'Clear the selected index ProjectileList(ProjectileIndex).Grh.FrameCounter = 0 ProjectileList(ProjectileIndex).Grh.GrhIndex = 0 ProjectileList(ProjectileIndex).X = 0 ProjectileList(ProjectileIndex).Y = 0 ProjectileList(ProjectileIndex).tX = 0 ProjectileList(ProjectileIndex).tY = 0 ProjectileList(ProjectileIndex).Rotate = 0 ProjectileList(ProjectileIndex).RotateSpeed = 0 'Update LastProjectile If ProjectileIndex = LastProjectile Then Do Until ProjectileList(ProjectileIndex).Grh.GrhIndex > 1 'Move down one projectile LastProjectile = LastProjectile - 1 If LastProjectile = 0 Then Exit Do Loop If ProjectileIndex <> LastProjectile Then 'We still have projectiles, resize the array to end at the last used slot If LastProjectile > 0 Then ReDim Preserve ProjectileList(1 To LastProjectile) Else Erase ProjectileList End If End If End If End Sub Public Sub Engine_Effect_Erase(ByVal EffectIndex As Integer) '***************************************************************** 'Erase an effect by the effect index 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Effect_Erase '***************************************************************** 'Clear the selected index ZeroMemory EffectList(EffectIndex), LenB(EffectList(EffectIndex)) 'Update LastEffect If EffectIndex = LastEffect Then Do Until EffectList(LastEffect).Grh.GrhIndex > 1 'Move down one effect LastEffect = LastEffect - 1 If LastEffect = 0 Then Erase EffectList Exit Sub Else 'We still have effects, resize the array to end at the last used slot ReDim Preserve EffectList(1 To LastEffect) End If Loop End If End Sub Private Function Engine_ElapsedTime() As Long '************************************************************** 'Gets the time that past since the last call 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_ElapsedTime '************************************************************** Dim Start_Time As Long 'Get current time Start_Time = timeGetTime 'Calculate elapsed time Engine_ElapsedTime = Start_Time - EndTime 'Get next end time EndTime = Start_Time End Function Function Engine_FileExist(File As String, FileType As VbFileAttribute) As Boolean '***************************************************************** 'Checks to see if a file exists 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_FileExist '***************************************************************** On Error GoTo ErrOut If LenB(Dir$(File, FileType)) <> 0 Then Engine_FileExist = True Exit Function 'An error will most likely be caused by invalid filenames (those that do not follow the file name rules) ErrOut: Engine_FileExist = False End Function Public Function Engine_GetAngle(ByVal CenterX As Integer, ByVal CenterY As Integer, ByVal TargetX As Integer, ByVal TargetY As Integer) As Single '************************************************************ 'Gets the angle between two points in a 2d plane 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_GetAngle '************************************************************ Dim SideA As Single Dim SideC As Single On Error GoTo ErrOut 'Check for horizontal lines (90 or 270 degrees) If CenterY = TargetY Then 'Check for going right (90 degrees) If CenterX < TargetX Then Engine_GetAngle = 90 'Check for going left (270 degrees) Else Engine_GetAngle = 270 End If 'Exit the function Exit Function End If 'Check for horizontal lines (360 or 180 degrees) If CenterX = TargetX Then 'Check for going up (360 degrees) If CenterY > TargetY Then Engine_GetAngle = 360 'Check for going down (180 degrees) Else Engine_GetAngle = 180 End If 'Exit the function Exit Function End If 'Calculate Side C SideC = Sqr(Abs(TargetX - CenterX) ^ 2 + Abs(TargetY - CenterY) ^ 2) 'Side B = CenterY 'Calculate Side A SideA = Sqr(Abs(TargetX - CenterX) ^ 2 + TargetY ^ 2) 'Calculate the angle Engine_GetAngle = (SideA ^ 2 - CenterY ^ 2 - SideC ^ 2) / (CenterY * SideC * -2) Engine_GetAngle = (Atn(-Engine_GetAngle / Sqr(-Engine_GetAngle * Engine_GetAngle + 1)) + 1.5708) * 57.29583 'If the angle is >180, subtract from 360 If TargetX < CenterX Then Engine_GetAngle = 360 - Engine_GetAngle 'Exit function Exit Function 'Check for error ErrOut: 'Return a 0 saying there was an error Engine_GetAngle = 0 Exit Function End Function Public Function Engine_GetTextWidth(ByRef UseFont As CustomFont, ByVal Text As String) As Integer '*************************************************** 'Returns the width of text 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_GetTextWidth '*************************************************** Dim i As Integer 'Make sure we have text If LenB(Text) = 0 Then Exit Function 'Loop through the text For i = 1 To Len(Text) 'Add up the stored character widths Engine_GetTextWidth = Engine_GetTextWidth + UseFont.HeaderInfo.CharWidth(Asc(Mid$(Text, i, 1))) Next i End Function Sub Engine_Init_Signs(ByVal Language As String) '***************************************************************** 'Loads the sign messages 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Init_Signs '***************************************************************** Dim NumSigns As Integer Dim LoopC As Integer Dim s As String 'Get the number of signs NumSigns = Val(Var_Get(SignsPath & "_numsigns.ini", "MAIN", "NumSigns")) If NumSigns = 0 Then Exit Sub ReDim Signs(1 To NumSigns) 'Grab the English text first For LoopC = 1 To NumSigns Signs(LoopC) = Trim$(Var_Get(SignsPath & "english.ini", "SIGNS", LoopC)) Next LoopC 'If we're not using English, grab the foreign language, this way any missing is still presented as English If LCase$(Language) <> "english" Then For LoopC = 1 To NumSigns s = Trim$(Var_Get(SignsPath & LCase$(Language) & ".ini", "SIGNS", LoopC)) If s <> vbNullString Then Signs(LoopC) = s Next LoopC End If End Sub Function Engine_Init_Messages(ByVal Language As String) As String '***************************************************************** 'Loads the game messages 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Init_Messages '***************************************************************** Dim LoopC As Byte Dim s As String 'Make sure we are working in lowercase (since all our files are in lowercase) Language = LCase$(Language) 'Check for a redirection flag (will return nothing if the flag doesn't exist) Do 'This "Do" will allow us to do redirections to redirections, even though we shouldn't even do that s = Var_Get(MessagePath & Language & ".ini", "REDIRECT", "TO") If LenB(s) <> 0 Then If Engine_FileExist(MessagePath & LCase$(s) & ".ini", vbNormal) = False Then MsgBox "Invalid language redirection! Could not load system messages!" & vbCrLf & _ "Language '" & Language & "' redirected to '" & LCase$(s) & "', which could not be found!", vbOKOnly Exit Function End If Language = LCase$(s) Else 'No redirection was found, so move on Exit Do End If Loop Engine_Init_Messages = Language 'Get the number of messages NumMessages = CByte(Var_Get(MessagePath & "_nummessages.ini", "MAIN", "NumMessages")) 'Check for a valid number of messages If NumMessages = 0 Then MsgBox "Error loading message count!", vbOKOnly Exit Function End If 'Resize our message array to hold all the messages ReDim Message(1 To NumMessages) 'Loop through every message and find the message string For LoopC = 1 To NumMessages Message(LoopC) = Var_Get(MessagePath & Language & ".ini", "MAIN", CStr(LoopC)) 'If the message wasn't found, resort to the primary language, English, since that should hold all messages If LCase$(Language) <> "english" Then 'Make sure we're not already using English If LenB(Trim$(Message(LoopC))) = 0 Then Message(LoopC) = Var_Get(MessagePath & "english.ini", "MAIN", CStr(LoopC)) End If End If Next LoopC 'Load the NPC chat messages Engine_Init_NPCChat Language End Function Sub Engine_Init_BodyData() '***************************************************************** 'Loads Body.dat 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Init_BodyData '***************************************************************** Dim LoopC As Long Dim j As Long 'Get number of bodies NumBodies = CLng(Var_Get(DataPath & "Body.dat", "INIT", "NumBodies")) 'Resize array ReDim BodyData(0 To NumBodies) As BodyData 'Fill list For LoopC = 1 To NumBodies For j = 1 To 8 Engine_Init_Grh BodyData(LoopC).Walk(j), CLng(Var_Get(DataPath & "Body.dat", LoopC, j)), 0 Engine_Init_Grh BodyData(LoopC).Attack(j), CLng(Var_Get(DataPath & "Body.dat", LoopC, "a" & j)), 1 Next j BodyData(LoopC).HeadOffset.X = CLng(Var_Get(DataPath & "Body.dat", LoopC, "HeadOffsetX")) BodyData(LoopC).HeadOffset.Y = CLng(Var_Get(DataPath & "Body.dat", LoopC, "HeadOffsetY")) Next LoopC End Sub Sub Engine_Init_WingData() '***************************************************************** 'Loads Wing.dat 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Init_WingData '***************************************************************** Dim LoopC As Long Dim j As Long 'Get number of wings NumWings = CLng(Var_Get(DataPath & "Wing.dat", "INIT", "NumWings")) 'Resize array ReDim WingData(0 To NumWings) As WingData 'Fill list For LoopC = 1 To NumWings For j = 1 To 8 Engine_Init_Grh WingData(LoopC).Walk(j), CLng(Var_Get(DataPath & "Wing.dat", LoopC, j)), 0 Engine_Init_Grh WingData(LoopC).Attack(j), CLng(Var_Get(DataPath & "Wing.dat", LoopC, "a" & j)), 1 Next j Next LoopC End Sub Private Function Engine_Init_D3DDevice(D3DCREATEFLAGS As CONST_D3DCREATEFLAGS) As Boolean '************************************************************ 'Initialize the Direct3D Device - start off trying with the 'best settings and move to the worst until one works 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Init_D3DDevice '************************************************************ 'When there is an error, destroy the D3D device and get ready to make a new one On Error GoTo ErrOut 'Retrieve current display mode D3D.GetAdapterDisplayMode D3DADAPTER_DEFAULT, DispMode 'Set format for windowed mode If Windowed Then D3DWindow.Windowed = 1 'State that using windowed mode D3DWindow.SwapEffect = D3DSWAPEFFECT_COPY D3DWindow.BackBufferFormat = DispMode.Format 'Use format just retrieved Else If Bit32 = 1 Then DispMode.Format = D3DFMT_X8R8G8B8 Else DispMode.Format = D3DFMT_R5G6B5 If UseVSync = 1 Then D3DWindow.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC Else D3DWindow.SwapEffect = D3DSWAPEFFECT_COPY DispMode.Width = ScreenWidth DispMode.Height = ScreenHeight D3DWindow.BackBufferCount = 1 D3DWindow.BackBufferFormat = DispMode.Format D3DWindow.BackBufferWidth = ScreenWidth D3DWindow.BackBufferHeight = ScreenHeight D3DWindow.hDeviceWindow = frmMain.hwnd End If If UseMotionBlur Then D3DWindow.EnableAutoDepthStencil = 1 D3DWindow.AutoDepthStencilFormat = D3DFMT_D16 End If 'Make sure the form is the correct side frmMain.Width = ScreenWidth * Screen.TwipsPerPixelX frmMain.Height = ScreenHeight * Screen.TwipsPerPixelY 'Set the D3DDevices If Not D3DDevice Is Nothing Then Set D3DDevice = Nothing Set D3DDevice = D3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, frmMain.hwnd, D3DCREATEFLAGS, D3DWindow) 'Store the create flags UsedCreateFlags = D3DCREATEFLAGS 'Everything was successful Engine_Init_D3DDevice = True 'Force the main form to refresh - vital for widescreen! Remove and find out why if you dare... >:D frmMain.Show frmMain.Refresh DoEvents Exit Function ErrOut: 'Destroy the D3DDevice so it can be remade Set D3DDevice = Nothing 'Return a failure Engine_Init_D3DDevice = False End Function Sub Engine_Init_Grh(ByRef Grh As Grh, ByVal GrhIndex As Long, Optional ByVal Started As Byte = 2) '***************************************************************** 'Sets up a grh. MUST be done before rendering 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Init_Grh '***************************************************************** If GrhIndex <= 0 Then Exit Sub Grh.GrhIndex = GrhIndex If Started = 2 Then If GrhData(Grh.GrhIndex).NumFrames > 1 Then Grh.Started = 1 Else Grh.Started = 0 End If Else 'Make sure the graphic can be started If GrhData(Grh.GrhIndex).NumFrames = 1 Then Started = 0 End If Grh.Started = Started End If Grh.LastCount = timeGetTime Grh.FrameCounter = 1 End Sub Sub Engine_Init_GrhData() '***************************************************************** 'Loads Grh.dat 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Init_GrhData '***************************************************************** Dim FileNum As Byte Dim Grh As Long Dim Frame As Long 'Get Number of Graphics NumGrhs = CLng(Var_Get(DataPath & "Grh.ini", "INIT", "NumGrhs")) 'Resize arrays ReDim GrhData(1 To NumGrhs) As GrhData 'Open files FileNum = FreeFile Open DataPath & "Grh.dat" For Binary As #FileNum Seek #FileNum, 1 'Fill Grh List Get #FileNum, , Grh Do Until Grh <= 0 'Get number of frames Get #FileNum, , GrhData(Grh).NumFrames If GrhData(Grh).NumFrames <= 0 Then GoTo ErrorHandler If GrhData(Grh).NumFrames > 1 Then 'Read a animation GRH set ReDim GrhData(Grh).Frames(1 To GrhData(Grh).NumFrames) For Frame = 1 To GrhData(Grh).NumFrames Get #FileNum, , GrhData(Grh).Frames(Frame) If GrhData(Grh).Frames(Frame) <= 0 Then GoTo ErrorHandler End If Next Frame Get #FileNum, , GrhData(Grh).Speed GrhData(Grh).Speed = GrhData(Grh).Speed * 0.075 * EngineBaseSpeed If GrhData(Grh).Speed <= 0 Then GoTo ErrorHandler 'Compute width and height GrhData(Grh).pixelHeight = GrhData(GrhData(Grh).Frames(1)).pixelHeight If GrhData(Grh).pixelHeight <= 0 Then GoTo ErrorHandler GrhData(Grh).pixelWidth = GrhData(GrhData(Grh).Frames(1)).pixelWidth If GrhData(Grh).pixelWidth <= 0 Then GoTo ErrorHandler GrhData(Grh).TileWidth = GrhData(GrhData(Grh).Frames(1)).TileWidth If GrhData(Grh).TileWidth <= 0 Then GoTo ErrorHandler GrhData(Grh).TileHeight = GrhData(GrhData(Grh).Frames(1)).TileHeight If GrhData(Grh).TileHeight <= 0 Then GoTo ErrorHandler Else 'Read in normal GRH data ReDim GrhData(Grh).Frames(1 To 1) Get #FileNum, , GrhData(Grh).FileNum If GrhData(Grh).FileNum <= 0 Then GoTo ErrorHandler Get #FileNum, , GrhData(Grh).SX If GrhData(Grh).SX < 0 Then GoTo ErrorHandler Get #FileNum, , GrhData(Grh).SY If GrhData(Grh).SY < 0 Then GoTo ErrorHandler Get #FileNum, , GrhData(Grh).pixelWidth If GrhData(Grh).pixelWidth <= 0 Then GoTo ErrorHandler Get #FileNum, , GrhData(Grh).pixelHeight If GrhData(Grh).pixelHeight <= 0 Then GoTo ErrorHandler 'Compute width and height GrhData(Grh).TileWidth = GrhData(Grh).pixelWidth / TilePixelHeight GrhData(Grh).TileHeight = GrhData(Grh).pixelHeight / TilePixelWidth GrhData(Grh).Frames(1) = Grh End If 'Get Next Grh Number Get #FileNum, , Grh Loop Close #FileNum Exit Sub ErrorHandler: Close #FileNum MsgBox "Error while loading the Grh.dat! Stopped at GRH number: " & Grh IsUnloading = 1 End Sub Public Sub Engine_Init_GUI(Optional ByVal LoadCustomPos As Byte = 1) '************************************************************ 'Load skin GUI data 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Init_GUI '************************************************************ Dim ImageOffsetX As Long Dim ImageOffsetY As Long Dim ImageSpaceX As Long Dim ImageSpaceY As Long Dim LoopC As Long Dim s As String 'Stores the path to our master skins file (.ini) Dim t As String 'Stores the path to our custom window positions file (.dat) Dim X As Long Dim Y As Long s = DataPath & "Skins\" & CurrentSkin & ".ini" t = DataPath & "Skins\" & CurrentSkin & ".dat" 'Load Quickbar With GameWindow.QuickBar If LoadCustomPos Then .Screen.X = Val(Var_Get(t, "QUICKBAR", "ScreenX")) .Screen.Y = Val(Var_Get(t, "QUICKBAR", "ScreenY")) Else .Screen.X = Val(Var_Get(s, "QUICKBAR", "ScreenX")) .Screen.Y = Val(Var_Get(s, "QUICKBAR", "ScreenY")) End If .Screen.Width = Val(Var_Get(s, "QUICKBAR", "ScreenWidth")) .Screen.Height = Val(Var_Get(s, "QUICKBAR", "ScreenHeight")) Engine_Init_Grh .SkinGrh, Val(Var_Get(s, "QUICKBAR", "Grh")) End With For LoopC = 1 To 12 With GameWindow.QuickBar.Image(LoopC) .X = Val(Var_Get(s, "QUICKBAR", "Image" & LoopC & "X")) .Y = Val(Var_Get(s, "QUICKBAR", "Image" & LoopC & "Y")) .Width = 32 .Height = 32 End With Next LoopC 'Load stats window With GameWindow.StatWindow If LoadCustomPos Then .Screen.X = Val(Var_Get(t, "STATWINDOW", "ScreenX")) .Screen.Y = Val(Var_Get(t, "STATWINDOW", "ScreenY")) Else .Screen.X = Val(Var_Get(s, "STATWINDOW", "ScreenX")) .Screen.Y = Val(Var_Get(s, "STATWINDOW", "ScreenY")) End If .Screen.Width = Val(Var_Get(s, "STATWINDOW", "ScreenWidth")) .Screen.Height = Val(Var_Get(s, "STATWINDOW", "ScreenHeight")) .AddStr.X = Val(Var_Get(s, "STATWINDOW", "AddStrX")) .AddStr.Y = Val(Var_Get(s, "STATWINDOW", "AddStrY")) .AddStr.Width = Val(Var_Get(s, "STATWINDOW", "AddStrWidth")) .AddStr.Height = Val(Var_Get(s, "STATWINDOW", "AddStrHeight")) .AddAgi.X = Val(Var_Get(s, "STATWINDOW", "AddAgiX")) .AddAgi.Y = Val(Var_Get(s, "STATWINDOW", "AddAgiY")) .AddAgi.Width = Val(Var_Get(s, "STATWINDOW", "AddAgiWidth")) .AddAgi.Height = Val(Var_Get(s, "STATWINDOW", "AddAgiHeight")) .AddMag.X = Val(Var_Get(s, "STATWINDOW", "AddMagX")) .AddMag.Y = Val(Var_Get(s, "STATWINDOW", "AddMagY")) .AddMag.Width = Val(Var_Get(s, "STATWINDOW", "AddMagWidth")) .AddMag.Height = Val(Var_Get(s, "STATWINDOW", "AddMagHeight")) .Str.X = Val(Var_Get(s, "STATWINDOW", "StrX")) .Str.Y = Val(Var_Get(s, "STATWINDOW", "StrY")) .Agi.X = Val(Var_Get(s, "STATWINDOW", "AgiX")) .Agi.Y = Val(Var_Get(s, "STATWINDOW", "AgiY")) .Mag.X = Val(Var_Get(s, "STATWINDOW", "MagX")) .Mag.Y = Val(Var_Get(s, "STATWINDOW", "MagY")) .Gold.X = Val(Var_Get(s, "STATWINDOW", "GoldX")) .Gold.Y = Val(Var_Get(s, "STATWINDOW", "GoldY")) .DEF.X = Val(Var_Get(s, "STATWINDOW", "DefX")) .DEF.Y = Val(Var_Get(s, "STATWINDOW", "DefY")) .Dmg.X = Val(Var_Get(s, "STATWINDOW", "DmgX")) .Dmg.Y = Val(Var_Get(s, "STATWINDOW", "DmgY")) .Points.X = Val(Var_Get(s, "STATWINDOW", "PointsX")) .Points.Y = Val(Var_Get(s, "STATWINDOW", "PointsY")) Engine_Init_Grh .AddGrh, Val(Var_Get(s, "STATWINDOW", "AddGrh")) Engine_Init_Grh .SkinGrh, Val(Var_Get(s, "STATWINDOW", "Grh")) End With 'Load chat window With GameWindow.ChatWindow If LoadCustomPos Then .Screen.X = Val(Var_Get(t, "CHATWINDOW", "ScreenX")) .Screen.Y = Val(Var_Get(t, "CHATWINDOW", "ScreenY")) Else .Screen.X = Val(Var_Get(s, "CHATWINDOW", "ScreenX")) .Screen.Y = Val(Var_Get(s, "CHATWINDOW", "ScreenY")) End If .Screen.Width = Val(Var_Get(s, "CHATWINDOW", "ScreenWidth")) .Screen.Height = Val(Var_Get(s, "CHATWINDOW", "ScreenHeight")) .Text.X = Val(Var_Get(s, "CHATWINDOW", "ChatX")) .Text.Y = Val(Var_Get(s, "CHATWINDOW", "ChatY")) .Text.Width = Val(Var_Get(s, "CHATWINDOW", "ChatWidth")) .Text.Height = Val(Var_Get(s, "CHATWINDOW", "ChatHeight")) Engine_Init_Grh .SkinGrh, Val(Var_Get(s, "CHATWINDOW", "Grh")) End With 'Load Inventory With GameWindow.Inventory If LoadCustomPos Then .Screen.X = Val(Var_Get(t, "INVENTORY", "ScreenX")) .Screen.Y = Val(Var_Get(t, "INVENTORY", "ScreenY")) Else .Screen.X = Val(Var_Get(s, "INVENTORY", "ScreenX")) .Screen.Y = Val(Var_Get(s, "INVENTORY", "ScreenY")) End If .Screen.Width = Val(Var_Get(s, "INVENTORY", "ScreenWidth")) .Screen.Height = Val(Var_Get(s, "INVENTORY", "ScreenHeight")) Engine_Init_Grh .SkinGrh, Val(Var_Get(s, "INVENTORY", "Grh")) End With ImageOffsetX = Val(Var_Get(s, "INVENTORY", "ImageOffsetX")) ImageOffsetY = Val(Var_Get(s, "INVENTORY", "ImageOffsetY")) ImageSpaceX = Val(Var_Get(s, "INVENTORY", "ImageSpaceX")) ImageSpaceY = Val(Var_Get(s, "INVENTORY", "ImageSpaceY")) For LoopC = 1 To MAX_INVENTORY_SLOTS With GameWindow.Inventory.Image(LoopC) .X = ImageOffsetX + ((ImageSpaceX + 32) * (((LoopC - 1) Mod 7))) .Y = ImageOffsetY + ((ImageSpaceY + 32) * ((LoopC - 1) \ 7)) .Width = 32 .Height = 32 End With Next LoopC 'Load Shop window GameWindow.Shop = GameWindow.Inventory With GameWindow.Shop If LoadCustomPos Then .Screen.X = Val(Var_Get(t, "SHOP", "ScreenX")) .Screen.Y = Val(Var_Get(t, "SHOP", "ScreenY")) Else .Screen.X = Val(Var_Get(s, "SHOP", "ScreenX")) .Screen.Y = Val(Var_Get(s, "SHOP", "ScreenY")) End If Engine_Init_Grh .SkinGrh, Val(Var_Get(s, "SHOP", "Grh")) End With 'Load bank window GameWindow.Bank = GameWindow.Inventory With GameWindow.Bank If LoadCustomPos Then .Screen.X = Val(Var_Get(t, "BANK", "ScreenX")) .Screen.Y = Val(Var_Get(t, "BANK", "ScreenY")) Else .Screen.X = Val(Var_Get(s, "BANK", "ScreenX")) .Screen.Y = Val(Var_Get(s, "BANK", "ScreenY")) End If Engine_Init_Grh .SkinGrh, Val(Var_Get(s, "BANK", "Grh")) End With 'Load Mailbox window With GameWindow.Mailbox.Screen If LoadCustomPos Then .X = Val(Var_Get(t, "MAILBOX", "ScreenX")) .Y = Val(Var_Get(t, "MAILBOX", "ScreenY")) Else .X = Val(Var_Get(s, "MAILBOX", "ScreenX")) .Y = Val(Var_Get(s, "MAILBOX", "ScreenY")) End If .Width = Val(Var_Get(s, "MAILBOX", "ScreenWidth")) .Height = Val(Var_Get(s, "MAILBOX", "ScreenHeight")) End With Engine_Init_Grh GameWindow.Mailbox.SkinGrh, Val(Var_Get(s, "MAILBOX", "Grh")) With GameWindow.Mailbox.WriteLbl .X = Val(Var_Get(s, "MAILBOX", "WriteMessageX")) .Y = Val(Var_Get(s, "MAILBOX", "WriteMessageY")) .Width = Val(Var_Get(s, "MAILBOX", "WriteMessageWidth")) .Height = Val(Var_Get(s, "MAILBOX", "WriteMessageHeight")) End With With GameWindow.Mailbox.DeleteLbl .X = Val(Var_Get(s, "MAILBOX", "DeleteMessageX")) .Y = Val(Var_Get(s, "MAILBOX", "DeleteMessageY")) .Width = Val(Var_Get(s, "MAILBOX", "DeleteMessageWidth")) .Height = Val(Var_Get(s, "MAILBOX", "DeleteMessageHeight")) End With With GameWindow.Mailbox.ReadLbl .X = Val(Var_Get(s, "MAILBOX", "ReadMessageX")) .Y = Val(Var_Get(s, "MAILBOX", "ReadMessageY")) .Width = Val(Var_Get(s, "MAILBOX", "ReadMessageWidth")) .Height = Val(Var_Get(s, "MAILBOX", "ReadMessageHeight")) End With With GameWindow.Mailbox.List .X = Val(Var_Get(s, "MAILBOX", "ListX")) .Y = Val(Var_Get(s, "MAILBOX", "ListY")) .Width = Val(Var_Get(s, "MAILBOX", "ListWidth")) .Height = Val(Var_Get(s, "MAILBOX", "ListHeight")) End With 'Load View Message window With GameWindow.ViewMessage.Screen If LoadCustomPos Then .X = Val(Var_Get(t, "VIEWMESSAGE", "ScreenX")) .Y = Val(Var_Get(t, "VIEWMESSAGE", "ScreenY")) Else .X = Val(Var_Get(s, "VIEWMESSAGE", "ScreenX")) .Y = Val(Var_Get(s, "VIEWMESSAGE", "ScreenY")) End If .Width = Val(Var_Get(s, "VIEWMESSAGE", "ScreenWidth")) .Height = Val(Var_Get(s, "VIEWMESSAGE", "ScreenHeight")) End With Engine_Init_Grh GameWindow.ViewMessage.SkinGrh, Val(Var_Get(s, "VIEWMESSAGE", "Grh")) With GameWindow.ViewMessage.From .X = Val(Var_Get(s, "VIEWMESSAGE", "FromX")) .Y = Val(Var_Get(s, "VIEWMESSAGE", "FromY")) .Width = Val(Var_Get(s, "VIEWMESSAGE", "FromWidth")) .Height = Val(Var_Get(s, "VIEWMESSAGE", "FromHeight")) End With With GameWindow.ViewMessage.Subject .X = Val(Var_Get(s, "VIEWMESSAGE", "SubjectX")) .Y = Val(Var_Get(s, "VIEWMESSAGE", "SubjectY")) .Width = Val(Var_Get(s, "VIEWMESSAGE", "SubjectWidth")) .Height = Val(Var_Get(s, "VIEWMESSAGE", "SubjectHeight")) End With With GameWindow.ViewMessage.Message .X = Val(Var_Get(s, "VIEWMESSAGE", "MessageX")) .Y = Val(Var_Get(s, "VIEWMESSAGE", "MessageY")) .Width = Val(Var_Get(s, "VIEWMESSAGE", "MessageWidth")) .Height = Val(Var_Get(s, "VIEWMESSAGE", "MessageHeight")) End With ImageOffsetX = Val(Var_Get(s, "VIEWMESSAGE", "ImageOffsetX")) ImageOffsetY = Val(Var_Get(s, "VIEWMESSAGE", "ImageOffsetY")) ImageSpaceX = Val(Var_Get(s, "VIEWMESSAGE", "ImageSpaceX")) For LoopC = 1 To MaxMailObjs With GameWindow.ViewMessage.Image(LoopC) .X = ImageOffsetX + ((LoopC - 1) * (ImageSpaceX + 32)) .Y = ImageOffsetY .Width = 32 .Height = 32 End With Next LoopC 'Load Write Message window GameWindow.WriteMessage = GameWindow.ViewMessage With GameWindow.WriteMessage.Screen If LoadCustomPos Then .X = Val(Var_Get(t, "WRITEMESSAGE", "ScreenX")) .Y = Val(Var_Get(t, "WRITEMESSAGE", "ScreenY")) Else .X = Val(Var_Get(s, "WRITEMESSAGE", "ScreenX")) .Y = Val(Var_Get(s, "WRITEMESSAGE", "ScreenY")) End If End With Engine_Init_Grh GameWindow.WriteMessage.SkinGrh, Val(Var_Get(s, "WRITEMESSAGE", "Grh")) 'Load Amount window With GameWindow.Amount.Screen If LoadCustomPos Then .X = Val(Var_Get(t, "AMOUNT", "ScreenX")) .Y = Val(Var_Get(t, "AMOUNT", "ScreenY")) Else .X = Val(Var_Get(s, "AMOUNT", "ScreenX")) .Y = Val(Var_Get(s, "AMOUNT", "ScreenY")) End If .Width = Val(Var_Get(s, "AMOUNT", "ScreenWidth")) .Height = Val(Var_Get(s, "AMOUNT", "ScreenHeight")) End With Engine_Init_Grh GameWindow.Amount.SkinGrh, Val(Var_Get(s, "AMOUNT", "Grh")) With GameWindow.Amount.Value .X = Val(Var_Get(s, "AMOUNT", "ValueX")) .Y = Val(Var_Get(s, "AMOUNT", "ValueY")) .Width = Val(Var_Get(s, "AMOUNT", "ValueWidth")) .Height = Val(Var_Get(s, "AMOUNT", "ValueHeight")) End With 'Load Menu Window With GameWindow.Menu.Screen If LoadCustomPos Then .X = Val(Var_Get(t, "MENU", "ScreenX")) .Y = Val(Var_Get(t, "MENU", "ScreenY")) Else .X = Val(Var_Get(s, "MENU", "ScreenX")) .Y = Val(Var_Get(s, "MENU", "ScreenY")) End If .Width = Val(Var_Get(s, "MENU", "ScreenWidth")) .Height = Val(Var_Get(s, "MENU", "ScreenHeight")) End With Engine_Init_Grh GameWindow.Menu.SkinGrh, Val(Var_Get(s, "MENU", "Grh")) With GameWindow.Menu.QuitLbl .X = Val(Var_Get(s, "MENU", "QuitX")) .Y = Val(Var_Get(s, "MENU", "QuitY")) .Width = Val(Var_Get(s, "MENU", "QuitWidth")) .Height = Val(Var_Get(s, "MENU", "QuitHeight")) End With 'Load the NPC Chat window With GameWindow.NPCChat.Screen .X = Val(Var_Get(s, "NPCCHAT", "ScreenX")) .Y = Val(Var_Get(s, "NPCCHAT", "ScreenY")) .Width = Val(Var_Get(s, "NPCCHAT", "ScreenWidth")) .Height = Val(Var_Get(s, "NPCCHAT", "ScreenHeight")) End With Engine_Init_Grh GameWindow.NPCChat.SkinGrh, Val(Var_Get(s, "NPCCHAT", "Grh")) 'Load the trade window With GameWindow.Trade .Screen.X = Val(Var_Get(s, "TRADE", "ScreenX")) .Screen.Y = Val(Var_Get(s, "TRADE", "ScreenY")) .Screen.Width = Val(Var_Get(s, "TRADE", "ScreenWidth")) .Screen.Height = Val(Var_Get(s, "TRADE", "ScreenHeight")) .User1Name.X = Val(Var_Get(s, "TRADE", "User1NameX")) .User1Name.Y = Val(Var_Get(s, "TRADE", "User1NameY")) .User2Name.X = Val(Var_Get(s, "TRADE", "User2NameX")) .User2Name.Y = Val(Var_Get(s, "TRADE", "User2NameY")) .Accept.X = Val(Var_Get(s, "TRADE", "AcceptX")) .Accept.Y = Val(Var_Get(s, "TRADE", "AcceptY")) .Accept.Width = Val(Var_Get(s, "TRADE", "AcceptWidth")) .Accept.Height = Val(Var_Get(s, "TRADE", "AcceptHeight")) .Trade.X = Val(Var_Get(s, "TRADE", "TradeX")) .Trade.Y = Val(Var_Get(s, "TRADE", "TradeY")) .Trade.Width = Val(Var_Get(s, "TRADE", "TradeWidth")) .Trade.Height = Val(Var_Get(s, "TRADE", "TradeHeight")) .Cancel.X = Val(Var_Get(s, "TRADE", "CancelX")) .Cancel.Y = Val(Var_Get(s, "TRADE", "CancelY")) .Cancel.Width = Val(Var_Get(s, "TRADE", "CancelWidth")) .Cancel.Height = Val(Var_Get(s, "TRADE", "CancelHeight")) .Gold1.X = Val(Var_Get(s, "TRADE", "Gold1X")) .Gold1.Y = Val(Var_Get(s, "TRADE", "gold1Y")) .Gold2.X = Val(Var_Get(s, "TRADE", "Gold2X")) .Gold2.Y = Val(Var_Get(s, "TRADE", "gold2Y")) ImageOffsetX = Val(Var_Get(s, "TRADE", "Sec1X")) ImageOffsetY = Val(Var_Get(s, "TRADE", "Sec1Y")) ImageSpaceX = Val(Var_Get(s, "TRADE", "DividerSize")) X = 0 Y = 0 For LoopC = 1 To 9 .Trade1(LoopC).X = ImageOffsetX + (X * (ImageSpaceX + 32)) .Trade1(LoopC).Y = ImageOffsetY + (Y * (ImageSpaceX + 32)) .Trade1(LoopC).Width = 32 .Trade1(LoopC).Height = 32 X = X + 1 If X = 3 Then X = 0 Y = Y + 1 End If Next LoopC ImageOffsetX = Val(Var_Get(s, "TRADE", "Sec2X")) ImageOffsetY = Val(Var_Get(s, "TRADE", "Sec2Y")) X = 0 Y = 0 For LoopC = 1 To 9 .Trade2(LoopC).X = ImageOffsetX + (X * (ImageSpaceX + 32)) .Trade2(LoopC).Y = ImageOffsetY + (Y * (ImageSpaceX + 32)) .Trade2(LoopC).Width = 32 .Trade2(LoopC).Height = 32 X = X + 1 If X = 3 Then X = 0 Y = Y + 1 End If Next LoopC End With Engine_Init_Grh GameWindow.Trade.SkinGrh, Val(Var_Get(s, "TRADE", "Grh")) 'Reset text position If CurMap > 0 Then Engine_UpdateChatArray End Sub Sub Engine_Init_HairData() '***************************************************************** 'Loads Hair.dat 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Init_HairData '***************************************************************** Dim LoopC As Long Dim i As Integer 'Get Number of hairs NumHairs = CLng(Var_Get(DataPath & "Hair.dat", "INIT", "NumHairs")) 'Resize array ReDim HairData(0 To NumHairs) As HairData 'Fill List For LoopC = 1 To NumHairs For i = 1 To 8 Engine_Init_Grh HairData(LoopC).Hair(i), CLng(Var_Get(DataPath & "Hair.dat", Str$(LoopC), Str$(i))), 0 Next i Next LoopC End Sub Sub Engine_Init_HeadData() '***************************************************************** 'Loads Head.dat 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Init_HeadData '***************************************************************** Dim LoopC As Long Dim i As Integer 'Get Number of heads NumHeads = CLng(Var_Get(DataPath & "Head.dat", "INIT", "NumHeads")) 'Resize array ReDim HeadData(0 To NumHeads) As HeadData 'Fill List For LoopC = 1 To NumHeads For i = 1 To 8 Engine_Init_Grh HeadData(LoopC).Head(i), CLng(Var_Get(DataPath & "Head.dat", LoopC, i)), 0 Engine_Init_Grh HeadData(LoopC).Blink(i), CLng(Var_Get(DataPath & "Head.dat", LoopC, "b" & i)), 0 Engine_Init_Grh HeadData(LoopC).AgrHead(i), CLng(Var_Get(DataPath & "Head.dat", LoopC, "a" & i)), 0 Engine_Init_Grh HeadData(LoopC).AgrBlink(i), CLng(Var_Get(DataPath & "Head.dat", LoopC, "ab" & i)), 0 Next i Next LoopC End Sub Public Sub Engine_Init_NPCChat(ByVal Language As String) '***************************************************************** 'Loads the NPC messages according to the language 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Init_NPCChat '***************************************************************** Dim Conditions() As NPCChatLineCondition Dim NumConditions As Byte 'The number of conditions Dim ConditionFlags As Long 'States what conditions are currently used (so we don't have to loop through the Conditions() array) Dim ChatLine As Byte 'The chat line for the current index Dim ErrTxt As String 'If there is an error, this extra text is added Dim HighIndex As Long 'Highest index retrieved Dim Index As Long 'Current index Dim FileNum As Byte Dim ln As String 'Used to grab our lines Dim Style As Byte 'Style used for the current index Dim TempSplit() As String Dim i As Long Dim F As Long Dim AskIndex As Byte Dim HighAskIndex As Long Dim AnswerIndex As Byte Dim ln2 As String On Error GoTo ErrOut 'Make sure the file exists If Not Engine_FileExist(DataPath & "NPC Chat\" & LCase$(Language) & ".ini", vbNormal) Then 'Error! Change to English before we die! Language = "english" Else 'Load English first, in case any messages are missing from the other language If Left$(LCase$(Language), 3) <> "eng" Then Engine_Init_NPCChat "english" 'Set the initial high-index (to preserve messages from English in case any are missing in the foreign language) On Error Resume Next HighIndex = UBound(NPCChat) On Error GoTo 0 End If 'Open the file FileNum = FreeFile Open DataPath & "NPC Chat\" & LCase$(Language) & ".ini" For Input Access Read As FileNum 'Loop until we reach the BEGINFILE line, stating the data is going to start coming in Do Line Input #FileNum, ln Loop While UCase$(Left$(ln, 9)) <> "BEGINFILE" 'Loop through the data Do 'Get the line Line Input #FileNum, ln ln = Trim$(ln) 'Look for empty lines If LenB(ln) = 0 Then GoTo NextLine '*** Look for a new index *** If Left$(ln, 1) = "[" Then 'Grab the index Index = Mid$(ln, 2, Len(ln) - 2) 'Clear the variables from the last line Style = 0 ChatLine = 0 Erase Conditions NumConditions = 0 ConditionFlags = 0 HighAskIndex = 0 'Resize the chat array according to the index if needed If Index > HighIndex Then ReDim Preserve NPCChat(1 To Index) HighIndex = Index End If 'Grab the format - this little loop will help us ignore blank lines Do Line Input #FileNum, ln Loop While LenB(Trim$(ln)) = 0 'Format text not found! If UCase$(Left$(ln, 6)) <> "FORMAT" Then ErrTxt = "FORMAT not found immediately after index ([x]) tag!" GoTo ErrOut End If 'Figure out what format it is ln = Trim$(ln) Select Case UCase$(Right$(ln, Len(ln) - 7)) Case "RANDOM" NPCChat(Index).Format = NPCCHAT_FORMAT_RANDOM Case "LINEAR" NPCChat(Index).Format = NPCCHAT_FORMAT_LINEAR Case Else ErrTxt = "Unknown format " & UCase$(Right$(ln, Len(ln) - 7)) & " retrieved!" GoTo ErrOut End Select GoTo NextLine End If '*** Look for a new style *** If UCase$(Left$(ln, 6)) = "STYLE " Then 'Figure out what style it is ln = Trim$(ln) Select Case UCase$(Right$(ln, Len(ln) - 6)) Case "BUBBLE" Style = NPCCHAT_STYLE_BUBBLE Case "BOX" Style = NPCCHAT_STYLE_BOX Case "BOTH" Style = NPCCHAT_STYLE_BOTH Case Else ErrTxt = "Unknown style " & UCase$(Right$(ln, Len(ln) - 6)) & " retrieved!" GoTo ErrOut End Select End If '*** Look for a new condition *** If Left$(ln, 1) = "!" Then 'Figure out what condition it is ln = Trim$(ln) 'Trim off spaces TempSplit = Split(UCase$(Right$(ln, Len(ln) - 1)), " ") 'Remove the ! and turn to uppercase Select Case UCase$(TempSplit(0)) Case "CLEAR" Erase Conditions NumConditions = 0 ConditionFlags = 0 Case "LEVELLESSTHAN" If Not ConditionFlags And NPCCHAT_COND_LEVELLESSTHAN Then NumConditions = NumConditions + 1 ReDim Preserve Conditions(1 To NumConditions) Conditions(NumConditions).Condition = NPCCHAT_COND_LEVELLESSTHAN Conditions(NumConditions).Value = Val(TempSplit(1)) ConditionFlags = ConditionFlags Or NPCCHAT_COND_LEVELLESSTHAN Else For F = 1 To NumConditions If Conditions(F).Condition = NPCCHAT_COND_LEVELLESSTHAN Then Conditions(F).Value = Val(TempSplit(1)) Exit For End If Next F End If Case "LEVELMORETHAN" If Not ConditionFlags And NPCCHAT_COND_LEVELMORETHAN Then NumConditions = NumConditions + 1 ReDim Preserve Conditions(1 To NumConditions) Conditions(NumConditions).Condition = NPCCHAT_COND_LEVELMORETHAN Conditions(NumConditions).Value = Val(TempSplit(1)) ConditionFlags = ConditionFlags Or NPCCHAT_COND_LEVELMORETHAN Else For F = 1 To NumConditions If Conditions(F).Condition = NPCCHAT_COND_LEVELMORETHAN Then Conditions(F).Value = Val(TempSplit(1)) Exit For End If Next F End If Case "HPLESSTHAN" If Not ConditionFlags And NPCCHAT_COND_HPLESSTHAN Then NumConditions = NumConditions + 1 ReDim Preserve Conditions(1 To NumConditions) Conditions(NumConditions).Condition = NPCCHAT_COND_HPLESSTHAN Conditions(NumConditions).Value = Val(TempSplit(1)) ConditionFlags = ConditionFlags Or NPCCHAT_COND_HPLESSTHAN Else For F = 1 To NumConditions If Conditions(F).Condition = NPCCHAT_COND_HPLESSTHAN Then Conditions(F).Value = Val(TempSplit(1)) Exit For End If Next F End If Case "HPMORETHAN" If Not ConditionFlags And NPCCHAT_COND_HPMORETHAN Then NumConditions = NumConditions + 1 ReDim Preserve Conditions(1 To NumConditions) Conditions(NumConditions).Condition = NPCCHAT_COND_HPMORETHAN Conditions(NumConditions).Value = Val(TempSplit(1)) ConditionFlags = ConditionFlags Or NPCCHAT_COND_HPMORETHAN Else For F = 1 To NumConditions If Conditions(F).Condition = NPCCHAT_COND_HPMORETHAN Then Conditions(F).Value = Val(TempSplit(1)) Exit For End If Next F End If Case "KNOWSKILL" If Not ConditionFlags And NPCCHAT_COND_KNOWSKILL Then NumConditions = NumConditions + 1 ReDim Preserve Conditions(1 To NumConditions) Conditions(NumConditions).Condition = NPCCHAT_COND_KNOWSKILL Conditions(NumConditions).Value = Val(TempSplit(1)) ConditionFlags = ConditionFlags Or NPCCHAT_COND_KNOWSKILL Else For F = 1 To NumConditions If Conditions(F).Condition = NPCCHAT_COND_KNOWSKILL Then Conditions(F).Value = Val(TempSplit(1)) Exit For End If Next F End If Case "DONTKNOWSKILL" If Not ConditionFlags And NPCCHAT_COND_DONTKNOWSKILL Then NumConditions = NumConditions + 1 ReDim Preserve Conditions(1 To NumConditions) Conditions(NumConditions).Condition = NPCCHAT_COND_DONTKNOWSKILL Conditions(NumConditions).Value = Val(TempSplit(1)) ConditionFlags = ConditionFlags Or NPCCHAT_COND_DONTKNOWSKILL Else For F = 1 To NumConditions If Conditions(F).Condition = NPCCHAT_COND_DONTKNOWSKILL Then Conditions(F).Value = Val(TempSplit(1)) Exit For End If Next F End If Case "SAY" If Not ConditionFlags And NPCCHAT_COND_SAY Then NumConditions = NumConditions + 1 ReDim Preserve Conditions(1 To NumConditions) Conditions(NumConditions).Condition = NPCCHAT_COND_SAY 'Notice we UCase$() the next line - this is so we can ignore the case Conditions(NumConditions).ValueStr = UCase$(Replace$(TempSplit(1), "_", " ")) 'Replace underscores with spaces ConditionFlags = ConditionFlags Or NPCCHAT_COND_SAY Else For F = 1 To NumConditions If Conditions(F).Condition = NPCCHAT_COND_SAY Then Conditions(F).ValueStr = UCase$(Replace$(TempSplit(1), "_", " ")) Exit For End If Next F End If Case Else ErrTxt = "Unknown condition " & TempSplit(0) & " retrieved!" GoTo ErrOut End Select End If '*** Look for a chat line *** If UCase$(Left$(ln, 4)) = "SAY " Then 'Split up the information (0 = "SAY", 1 = Delay, 2 = Chat text) TempSplit() = Split(ln, " ", 3) 'Raise the lines count ChatLine = ChatLine + 1 ReDim Preserve NPCChat(Index).ChatLine(1 To ChatLine) NPCChat(Index).NumLines = ChatLine 'Set the delay, style and text NPCChat(Index).ChatLine(ChatLine).Delay = Val(TempSplit(1)) NPCChat(Index).ChatLine(ChatLine).Text = Replace$(Trim$(TempSplit(2)), "/r", vbNewLine) NPCChat(Index).ChatLine(ChatLine).Style = Style 'Check for empty text lines If UCase$(NPCChat(Index).ChatLine(ChatLine).Text) = "[EMPTY]" Then NPCChat(Index).ChatLine(ChatLine).Text = vbNullString End If 'Set the conditions NPCChat(Index).ChatLine(ChatLine).NumConditions = NumConditions If NumConditions > 0 Then ReDim NPCChat(Index).ChatLine(ChatLine).Conditions(1 To NumConditions) For i = 1 To NumConditions NPCChat(Index).ChatLine(ChatLine).Conditions(i) = Conditions(i) Next i End If End If '*** Look for a STARTASK line *** If UCase$(Left$(ln, 9)) = "STARTASK " Then NPCChat(Index).Ask.StartAsk = Val(Right$(ln, Len(ln) - 9)) If NPCChat(Index).Ask.StartAsk <= 0 Then ErrTxt = "STARTASK is <= 0" GoTo ErrOut End If End If '*** Look for an ASK line *** If UCase$(Left$(ln, 4)) = "ASK " Then 'Split up the information (0 = "ASK", 1 = ID, 2 = Question text) TempSplit() = Split(ln, " ", 3) 'Update the ask information AskIndex = Val(TempSplit(1)) If HighAskIndex < AskIndex Then HighAskIndex = AskIndex ReDim Preserve NPCChat(Index).Ask.Ask(1 To AskIndex) NPCChat(Index).Ask.Ask(AskIndex).Question = Replace$(Trim$(TempSplit(2)), "/r", vbNewLine) End If 'Get the answers AnswerIndex = 0 Do Line Input #FileNum, ln2 ln2 = Trim$(ln2) If ln2 <> vbNullString Then If UCase$(Left$(ln2, 6)) = "ASKEND" Then Exit Do If UCase$(Left$(ln2, 7)) = "ANSWER " Then TempSplit() = Split(ln2, " ", 3) If UBound(TempSplit) < 2 Then ErrTxt = "Invalid number of ANSWER parameters!" & """ & ln2 & """ GoTo ErrOut End If AnswerIndex = AnswerIndex + 1 With NPCChat(Index).Ask.Ask(AskIndex) .NumAnswers = AnswerIndex ReDim Preserve .Answer(1 To AnswerIndex) .Answer(AnswerIndex).Text = Trim$(TempSplit(2)) .Answer(AnswerIndex).GotoID = Val(TempSplit(1)) End With Else ErrTxt = "Unknown command in ASK block!" & vbNewLine & """ ln2 & """ GoTo ErrOut End If End If Loop End If NextLine: Loop While Not EOF(FileNum) Close #FileNum Exit Sub ErrOut: MsgBox "Error in NPCChat routine! Stopped on line " & Loc(FileNum) & "!" & vbNewLine & _ "The remainder of the line text is: " & vbNewLine & ln & vbNewLine & vbNewLine & _ "The following message has been added:" & vbNewLine & ErrTxt, vbOKOnly Or vbCritical If FileNum > 0 Then Close #FileNum End Sub Sub Engine_Init_ParticleEngine(Optional ByVal SkipToTextures As Boolean = False) '***************************************************************** 'Loads all particles into memory - unlike normal textures, these stay in memory. This isn't 'done for any reason in particular, they just use so little memory since they are so small 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Init_ParticleEngine '***************************************************************** Dim i As Byte If Not SkipToTextures Then 'Set the particles texture NumEffects = Var_Get(DataPath & "Game.ini", "INIT", "NumEffects") ReDim Effect(1 To NumEffects) End If For i = 1 To UBound(ParticleTexture()) If ParticleTexture(i) Is Nothing Then Set ParticleTexture(i) = Nothing Set ParticleTexture(i) = D3DX.CreateTextureFromFileEx(D3DDevice, GrhPath & "p" & i & ".png", D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_FILTER_POINT, D3DX_FILTER_POINT, &HFF000000, ByVal 0, ByVal 0) Next i End Sub Private Sub Engine_Init_RenderStates() '************************************************************ 'Set the render states of the Direct3D Device 'This is in a seperate sub since if using Fullscreen and device is lost 'this is eventually called to restore settings. 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Init_RenderStates '************************************************************ With D3DDevice 'Set the shader to be used D3DDevice.SetVertexShader FVF 'Set the render states .SetRenderState D3DRS_LIGHTING, False .SetRenderState D3DRS_SRCBLEND, D3DBLEND_SRCALPHA .SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA .SetRenderState D3DRS_ALPHABLENDENABLE, True .SetRenderState D3DRS_FILLMODE, D3DFILL_SOLID .SetRenderState D3DRS_CULLMODE, D3DCULL_NONE .SetRenderState D3DRS_ZENABLE, False .SetRenderState D3DRS_ZWRITEENABLE, False .SetTextureStageState 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE 'Particle engine settings .SetRenderState D3DRS_POINTSPRITE_ENABLE, 1 .SetRenderState D3DRS_POINTSCALE_ENABLE, 0 'Set the texture stage stats (filters) .SetTextureStageState 0, D3DTSS_MAGFILTER, D3DTEXF_POINT .SetTextureStageState 0, D3DTSS_MINFILTER, D3DTEXF_POINT End With End Sub Sub Engine_Init_Texture(ByVal TextureNum As Integer) '***************************************************************** 'Loads a texture into memory 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Init_Texture '***************************************************************** Dim UseTextureFormat As CONST_D3DFORMAT Dim TexInfo As D3DXIMAGE_INFO_A Dim FilePath As String 'Check for a valid texture If TextureNum < 1 Then Exit Sub 'Make sure we even need to load the texture If SurfaceTimer(TextureNum) > timeGetTime Then Exit Sub 'Set the texture timer SurfaceTimer(TextureNum) = timeGetTime + SurfaceTimerMax 'Check if we have the device If D3DDevice.TestCooperativeLevel <> D3D_OK Then Exit Sub 'Make sure we try not to load a file while the engine is unloading If IsUnloading Then Exit Sub 'Get the path FilePath = GrhPath & TextureNum & ".png" 'Check if the texture exists If Engine_FileExist(FilePath, vbNormal) = False Then MsgBox "Error! Could not find the following texture file:" & vbNewLine & FilePath, vbOKOnly IsUnloading = 1 Exit Sub End If If SurfaceSize(TextureNum).X = 0 Then 'We need to get the size 'Set the texture (and get the dimensions) Set SurfaceDB(TextureNum) = D3DX.CreateTextureFromFileEx(D3DDevice, FilePath, D3DX_DEFAULT, D3DX_DEFAULT, 0, 0, TextureCompress, D3DPOOL_MANAGED, D3DX_FILTER_POINT, D3DX_FILTER_NONE, &HFF000000, TexInfo, ByVal 0) SurfaceSize(TextureNum).X = TexInfo.Width SurfaceSize(TextureNum).Y = TexInfo.Height Else 'Set the texture (without getting the dimensions) Set SurfaceDB(TextureNum) = D3DX.CreateTextureFromFileEx(D3DDevice, FilePath, SurfaceSize(TextureNum).X, SurfaceSize(TextureNum).Y, 0, 0, TextureCompress, D3DPOOL_MANAGED, D3DX_FILTER_POINT, D3DX_FILTER_NONE, &HFF000000, ByVal 0, ByVal 0) End If End Sub Sub Engine_Init_FontTextures() '***************************************************************** 'Init the custom font textures 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Init_FontTextures '***************************************************************** Dim TexInfo As D3DXIMAGE_INFO_A 'Check if we have the device If D3DDevice.TestCooperativeLevel <> D3D_OK Then Exit Sub '*** Default font *** 'Set the texture Set Font_Default.Texture = D3DX.CreateTextureFromFileEx(D3DDevice, DataPath & "texdefault.png", D3DX_DEFAULT, D3DX_DEFAULT, 0, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_FILTER_POINT, D3DX_FILTER_NONE, &HFF000000, TexInfo, ByVal 0) 'Store the size of the texture Font_Default.TextureSize.X = TexInfo.Width Font_Default.TextureSize.Y = TexInfo.Height End Sub Sub Engine_Init_FontSettings() '***************************************************************** 'Init the custom font settings 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Init_FontSettings '***************************************************************** Dim FileNum As Byte Dim LoopChar As Long Dim Row As Single Dim u As Single Dim v As Single '*** Default font *** 'Load the header information FileNum = FreeFile Open DataPath & "texdefault.dat" For Binary As #FileNum Get #FileNum, , Font_Default.HeaderInfo Close #FileNum 'Calculate some common values Font_Default.CharHeight = Font_Default.HeaderInfo.CellHeight - 4 Font_Default.RowPitch = Font_Default.HeaderInfo.BitmapWidth \ Font_Default.HeaderInfo.CellWidth Font_Default.ColFactor = Font_Default.HeaderInfo.CellWidth / Font_Default.HeaderInfo.BitmapWidth Font_Default.RowFactor = Font_Default.HeaderInfo.CellHeight / Font_Default.HeaderInfo.BitmapHeight 'Cache the verticies used to draw the character (only requires setting the color and adding to the X/Y values) For LoopChar = 0 To 255 'tU and tV value (basically tU = BitmapXPosition / BitmapWidth, and height for tV) Row = (LoopChar - Font_Default.HeaderInfo.BaseCharOffset) \ Font_Default.RowPitch u = ((LoopChar - Font_Default.HeaderInfo.BaseCharOffset) - (Row * Font_Default.RowPitch)) * Font_Default.ColFactor v = Row * Font_Default.RowFactor 'Set the verticies With Font_Default.HeaderInfo.CharVA(LoopChar) .Vertex(0).Color = D3DColorARGB(255, 0, 0, 0) 'Black is the most common color .Vertex(0).Rhw = 1 .Vertex(0).tU = u .Vertex(0).tV = v .Vertex(0).X = 0 .Vertex(0).Y = 0 .Vertex(0).Z = 0 .Vertex(1).Color = D3DColorARGB(255, 0, 0, 0) .Vertex(1).Rhw = 1 .Vertex(1).tU = u + Font_Default.ColFactor .Vertex(1).tV = v .Vertex(1).X = Font_Default.HeaderInfo.CellWidth .Vertex(1).Y = 0 .Vertex(1).Z = 0 .Vertex(2).Color = D3DColorARGB(255, 0, 0, 0) .Vertex(2).Rhw = 1 .Vertex(2).tU = u .Vertex(2).tV = v + Font_Default.RowFactor .Vertex(2).X = 0 .Vertex(2).Y = Font_Default.HeaderInfo.CellHeight .Vertex(2).Z = 0 .Vertex(3).Color = D3DColorARGB(255, 0, 0, 0) .Vertex(3).Rhw = 1 .Vertex(3).tU = u + Font_Default.ColFactor .Vertex(3).tV = v + Font_Default.RowFactor .Vertex(3).X = Font_Default.HeaderInfo.CellWidth .Vertex(3).Y = Font_Default.HeaderInfo.CellHeight .Vertex(3).Z = 0 End With Next LoopChar End Sub Public Sub Engine_Init_TileEngine() '***************************************************************** 'Init Tile Engine 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Init_TileEngine '***************************************************************** Dim t As Long 'Size the form frmMain.Width = ScreenWidth * Screen.TwipsPerPixelX frmMain.Height = ScreenHeight * Screen.TwipsPerPixelY 'Get some engine settings UseSfx = Val(Var_Get(DataPath & "Game.ini", "INIT", "UseSfx")) If UseSfx <> 0 Then UseSfx = 1 'Force to 1 or 0 UseMusic = Val(Var_Get(DataPath & "Game.ini", "INIT", "UseMusic")) If UseMusic <> 0 Then UseMusic = 1 'Force to 1 or 0 UseVSync = Val(Var_Get(DataPath & "Game.ini", "INIT", "VSync")) If UseVSync <> 0 Then UseVSync = 1 'Force to 1 or 0 t = Val(Var_Get(DataPath & "Game.ini", "INIT", "Windowed")) If t = 0 Then Windowed = False Else Windowed = True ReverseSound = Val(Var_Get(DataPath & "Game.ini", "INIT", "ReverseSound")) If ReverseSound <> 0 Then ReverseSound = -1 Else ReverseSound = 1 'Force to -1 or 1 TextureCompress = Val(Var_Get(DataPath & "Game.ini", "INIT", "TextureCompression")) If TextureCompress <> 0 Then TextureCompress = D3DFMT_DXT5 'Force to 0 or D3DFMT_DXT5 Bit32 = Val(Var_Get(DataPath & "Game.ini", "INIT", "32bit")) If Bit32 <> 0 Then Bit32 = 1 'Force to 1 or 0 FPSCap = Val(Var_Get(DataPath & "Game.ini", "INIT", "FPSCap")) If FPSCap < 0 Then FPSCap = 0 If FPSCap > 0 Then FPSCap = 1000 \ FPSCap DisableChatBubbles = Val(Var_Get(DataPath & "Game.ini", "INIT", "DisableChatBubbles")) If DisableChatBubbles <> 0 Then DisableChatBubbles = 1 'Force to 1 or 0 UseWeather = Val(Var_Get(DataPath & "Game.ini", "INIT", "UseWeather")) If UseWeather <> 0 Then UseWeather = 1 UseMotionBlur = Val(Var_Get(DataPath & "Game.ini", "INIT", "UseMotionBlur")) If UseMotionBlur <> 0 Then UseMotionBlur = 1 'Load the key definitions Input_Keys_LoadDefinitions '****** INIT DirectX ****** ' Create the root D3D objects Set DX = New DirectX8 Set D3D = DX.Direct3DCreate() Set D3DX = New D3DX8 Input_Init Sound_Init 'Create the D3D Device If Not Engine_Init_D3DDevice(D3DCREATE_PUREDEVICE) Then If Not Engine_Init_D3DDevice(D3DCREATE_HARDWARE_VERTEXPROCESSING) Then If Not Engine_Init_D3DDevice(D3DCREATE_MIXED_VERTEXPROCESSING) Then If Not Engine_Init_D3DDevice(D3DCREATE_SOFTWARE_VERTEXPROCESSING) Then MsgBox "Could not init D3DDevice. Exiting..." Engine_Init_UnloadTileEngine Engine_UnloadAllForms End End If End If End If End If Engine_Init_RenderStates 'Load the rest of the tile engine stuff Engine_Init_FontTextures Engine_Init_ParticleEngine 'Create the needed information for the motion bluring If UseMotionBlur Then Set DeviceBuffer = D3DDevice.GetRenderTarget Set DeviceStencil = D3DDevice.GetDepthStencilSurface Set BlurStencil = D3DDevice.CreateDepthStencilSurface(BufferWidth, BufferHeight, D3DFMT_D16, D3DMULTISAMPLE_NONE) Set BlurTexture = D3DX.CreateTexture(D3DDevice, BufferWidth, BufferHeight, 0, D3DUSAGE_RENDERTARGET, DispMode.Format, D3DPOOL_DEFAULT) Set BlurSurf = BlurTexture.GetSurfaceLevel(0) 'Create the motion-blur vertex array For t = 0 To 3 BlurTA(t).Color = D3DColorXRGB(255, 255, 255) BlurTA(t).Rhw = 1 Next t BlurTA(1).X = ScreenWidth BlurTA(2).Y = ScreenHeight BlurTA(3).X = ScreenWidth BlurTA(3).Y = ScreenHeight End If 'Set FPS value to 60 for startup FPS = 60 FramesPerSecCounter = 60 'Set the ending time to now (to prevent the client thinking there was a huge FPS jump) EndTime = timeGetTime 'Get the AlternateRender flag AlternateRender = Val(Var_Get(DataPath & "Game.ini", "INIT", "AlternateRender")) AlternateRenderMap = Val(Var_Get(DataPath & "Game.ini", "INIT", "AlternateRenderMap")) AlternateRenderText = Val(Var_Get(DataPath & "Game.ini", "INIT", "AlternateRenderText")) If AlternateRender <> 0 Then AlternateRender = 1 If AlternateRenderMap <> 0 Then AlternateRenderMap = 1 If AlternateRenderText <> 0 Then AlternateRenderText = 1 AlternateRenderDefault = AlternateRender 'Set the blur to off BlurIntensity = 255 If AlternateRender = 1 Or AlternateRenderMap = 1 Or AlternateRenderText = 1 Then 'If using alternate rendering, create the sprite object Set Sprite = D3DX.CreateSprite(D3DDevice) 'Set the scaling to default aspect ratio SpriteScaleVector.X = 1 SpriteScaleVector.Y = 1 End If 'Start the engine EngineRun = True End Sub Public Sub Engine_Init_UnloadTileEngine() '***************************************************************** 'Shutsdown engine 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Init_UnloadTileEngine '***************************************************************** On Error Resume Next Dim LoopC As Long Dim X As Long Dim Y As Long EngineRun = False '****** Clear DirectX objects ****** If Not DIDevice Is Nothing Then DIDevice.Unacquire If Not D3DDevice Is Nothing Then Set D3DDevice = Nothing If Not DIDevice Is Nothing Then Set DIDevice = Nothing If Not D3DX Is Nothing Then Set D3DX = Nothing If Not DI Is Nothing Then Set DI = Nothing 'Clear particles For LoopC = 1 To UBound(ParticleTexture) If Not ParticleTexture(LoopC) Is Nothing Then Set ParticleTexture(LoopC) = Nothing Next LoopC 'Clear GRH memory For LoopC = 1 To NumGrhFiles If Not SurfaceDB(LoopC) Is Nothing Then Set SurfaceDB(LoopC) = Nothing Next LoopC 'Clear sound buffers For LoopC = 1 To NumSfx If Not DSBuffer(LoopC) Is Nothing Then Set DSBuffer(LoopC) = Nothing Next LoopC 'Clear map sound buffers For X = 1 To MapInfo.Width For Y = 1 To MapInfo.Height If Not MapData(X, Y).Sfx Is Nothing Then Set MapData(X, Y).Sfx = Nothing Next Y Next X 'Clear music objects For LoopC = 1 To NumMusicBuffers If Not DirectShow_Position(LoopC) Is Nothing Then Set DirectShow_Position(LoopC) = Nothing If Not DirectShow_Control(LoopC) Is Nothing Then Set DirectShow_Control(LoopC) = Nothing If Not DirectShow_Event(LoopC) Is Nothing Then Set DirectShow_Event(LoopC) = Nothing If Not DirectShow_Audio(LoopC) Is Nothing Then Set DirectShow_Audio(LoopC) = Nothing Next LoopC 'Clear motion blur objects If Not BlurTexture Is Nothing Then Set BlurTexture = Nothing Set BlurSurf = Nothing Set BlurStencil = Nothing Set DeviceStencil = Nothing Set DeviceBuffer = Nothing End If 'Clear arrays Erase BlurTA Erase SurfaceTimer Erase SoundBufferTimer Erase MapData Erase GrhData Erase GrhData Erase SurfaceSize Erase BodyData Erase HeadData Erase WeaponData Erase MapData Erase CharList Erase OBJList Erase BloodList Erase EffectList Erase DamageList Erase SkillList Erase QuickBarID Erase ShowGameWindow Erase SaveLightBuffer End Sub Sub Engine_Init_WeaponData() '***************************************************************** 'Loads Weapon.dat 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Init_WeaponData '***************************************************************** Dim LoopC As Long 'Get number of weapons NumWeapons = CLng(Var_Get(DataPath & "Weapon.dat", "INIT", "NumWeapons")) 'Resize array ReDim WeaponData(0 To NumWeapons) As WeaponData 'Fill list For LoopC = 1 To NumWeapons Engine_Init_Grh WeaponData(LoopC).Walk(1), CLng(Var_Get(DataPath & "Weapon.dat", "Weapon" & LoopC, "Walk1")), 0 Engine_Init_Grh WeaponData(LoopC).Walk(2), CLng(Var_Get(DataPath & "Weapon.dat", "Weapon" & LoopC, "Walk2")), 0 Engine_Init_Grh WeaponData(LoopC).Walk(3), CLng(Var_Get(DataPath & "Weapon.dat", "Weapon" & LoopC, "Walk3")), 0 Engine_Init_Grh WeaponData(LoopC).Walk(4), CLng(Var_Get(DataPath & "Weapon.dat", "Weapon" & LoopC, "Walk4")), 0 Engine_Init_Grh WeaponData(LoopC).Walk(5), CLng(Var_Get(DataPath & "Weapon.dat", "Weapon" & LoopC, "Walk5")), 0 Engine_Init_Grh WeaponData(LoopC).Walk(6), CLng(Var_Get(DataPath & "Weapon.dat", "Weapon" & LoopC, "Walk6")), 0 Engine_Init_Grh WeaponData(LoopC).Walk(7), CLng(Var_Get(DataPath & "Weapon.dat", "Weapon" & LoopC, "Walk7")), 0 Engine_Init_Grh WeaponData(LoopC).Walk(8), CLng(Var_Get(DataPath & "Weapon.dat", "Weapon" & LoopC, "Walk8")), 0 Engine_Init_Grh WeaponData(LoopC).Attack(1), CLng(Var_Get(DataPath & "Weapon.dat", "Weapon" & LoopC, "Attack1")), 1 Engine_Init_Grh WeaponData(LoopC).Attack(2), CLng(Var_Get(DataPath & "Weapon.dat", "Weapon" & LoopC, "Attack2")), 1 Engine_Init_Grh WeaponData(LoopC).Attack(3), CLng(Var_Get(DataPath & "Weapon.dat", "Weapon" & LoopC, "Attack3")), 1 Engine_Init_Grh WeaponData(LoopC).Attack(4), CLng(Var_Get(DataPath & "Weapon.dat", "Weapon" & LoopC, "Attack4")), 1 Engine_Init_Grh WeaponData(LoopC).Attack(5), CLng(Var_Get(DataPath & "Weapon.dat", "Weapon" & LoopC, "Attack5")), 1 Engine_Init_Grh WeaponData(LoopC).Attack(6), CLng(Var_Get(DataPath & "Weapon.dat", "Weapon" & LoopC, "Attack6")), 1 Engine_Init_Grh WeaponData(LoopC).Attack(7), CLng(Var_Get(DataPath & "Weapon.dat", "Weapon" & LoopC, "Attack7")), 1 Engine_Init_Grh WeaponData(LoopC).Attack(8), CLng(Var_Get(DataPath & "Weapon.dat", "Weapon" & LoopC, "Attack8")), 1 Next LoopC End Sub Sub Engine_Weather_UpdateFog() '***************************************************************** 'Update the fog effects 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Weather_UpdateFog '***************************************************************** Dim TempGrh As Grh Dim i As Long Dim X As Long Dim Y As Long Dim c As Long 'Make sure we have the fog value If WeatherFogCount = 0 Then WeatherFogCount = 13 'Update the fog's position WeatherFogX1 = WeatherFogX1 + (ElapsedTime * (0.018 + Rnd * 0.01)) + (LastOffsetX - ParticleOffsetX) WeatherFogY1 = WeatherFogY1 + (ElapsedTime * (0.013 + Rnd * 0.01)) + (LastOffsetY - ParticleOffsetY) Do While WeatherFogX1 < -512 WeatherFogX1 = WeatherFogX1 + 512 Loop Do While WeatherFogY1 < -512 WeatherFogY1 = WeatherFogY1 + 512 Loop Do While WeatherFogX1 > 0 WeatherFogX1 = WeatherFogX1 - 512 Loop Do While WeatherFogY1 > 0 WeatherFogY1 = WeatherFogY1 - 512 Loop WeatherFogX2 = WeatherFogX2 - (ElapsedTime * (0.037 + Rnd * 0.01)) + (LastOffsetX - ParticleOffsetX) WeatherFogY2 = WeatherFogY2 - (ElapsedTime * (0.021 + Rnd * 0.01)) + (LastOffsetY - ParticleOffsetY) Do While WeatherFogX2 < -512 WeatherFogX2 = WeatherFogX2 + 512 Loop Do While WeatherFogY2 < -512 WeatherFogY2 = WeatherFogY2 + 512 Loop Do While WeatherFogX2 > 0 WeatherFogX2 = WeatherFogX2 - 512 Loop Do While WeatherFogY2 > 0 WeatherFogY2 = WeatherFogY2 - 512 Loop TempGrh.FrameCounter = 1 'Render fog 2 TempGrh.GrhIndex = 4 X = 2 Y = -1 c = D3DColorARGB(100, 255, 255, 255) For i = 1 To WeatherFogCount Engine_Render_Grh TempGrh, (X * 512) + WeatherFogX2, (Y * 512) + WeatherFogY2, 0, 0, False, c, c, c, c X = X + 1 If X > (1 + (ScreenWidth \ 512)) Then X = 0 Y = Y + 1 End If Next i 'Render fog 1 TempGrh.GrhIndex = 3 X = 0 Y = 0 c = D3DColorARGB(75, 255, 255, 255) For i = 1 To WeatherFogCount Engine_Render_Grh TempGrh, (X * 512) + WeatherFogX1, (Y * 512) + WeatherFogY1, 0, 0, False, c, c, c, c X = X + 1 If X > (2 + (ScreenWidth \ 512)) Then X = 0 Y = Y + 1 End If Next i End Sub Sub Engine_Weather_UpdateLightning() '***************************************************************** 'Updates the lightning count-down and creates the flash if its ready 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Weather_UpdateLightning '***************************************************************** Dim X As Long Dim Y As Long Dim i As Long 'Check if we are in the middle of a flash If FlashTimer > 0 Then FlashTimer = FlashTimer - ElapsedTime 'The flash has run out If FlashTimer <= 0 Then 'Change the light of all the tiles back For X = 1 To MapInfo.Width For Y = 1 To MapInfo.Height For i = 1 To 24 MapData(X, Y).Light(i) = SaveLightBuffer(X, Y).Light(i) Next i Next Y Next X End If 'Update the timer, see if it is time to flash Else LightningTimer = LightningTimer - ElapsedTime 'Flash me, baby! If LightningTimer <= 0 Then LightningTimer = 15000 + (Rnd * 15000) 'Reset timer (flash every 15 to 30 seconds) FlashTimer = 250 'How long the flash is (miliseconds) 'Sound effect Sound_Play WeatherSfx2, DSBPLAY_DEFAULT 'BAM! 'Change the light of all the tiles to white For X = 1 To MapInfo.Width For Y = 1 To MapInfo.Height For i = 1 To 24 MapData(X, Y).Light(i) = -1 Next i Next Y Next X End If End If End Sub Sub Engine_Weather_Update() '***************************************************************** 'Initializes the weather effects 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Weather_Update '***************************************************************** 'Check if we're using weather If UseWeather = 0 Then Exit Sub 'Only update the weather settings if it has changed! If LastWeather <> MapInfo.Weather Then 'Set the lastweather to the current weather LastWeather = MapInfo.Weather 'Erase sounds Sound_Erase WeatherSfx1 Sound_Erase WeatherSfx2 Select Case LastWeather Case 1 'Snow (light fall) If WeatherEffectIndex <= 0 Then WeatherEffectIndex = Effect_Snow_Begin(1, 400) ElseIf Effect(WeatherEffectIndex).EffectNum <> EffectNum_Snow Then Effect_Kill WeatherEffectIndex WeatherEffectIndex = Effect_Snow_Begin(1, 400) ElseIf Not Effect(WeatherEffectIndex).Used Then WeatherEffectIndex = Effect_Snow_Begin(1, 400) End If WeatherDoLightning = 0 WeatherDoFog = 0 Case 2 'Rain Storm (heavy rain + lightning) If WeatherEffectIndex <= 0 Then WeatherEffectIndex = Effect_Rain_Begin(9, 300) ElseIf Effect(WeatherEffectIndex).EffectNum <> EffectNum_Rain Then Effect_Kill WeatherEffectIndex WeatherEffectIndex = Effect_Rain_Begin(9, 300) ElseIf Not Effect(WeatherEffectIndex).Used Then WeatherEffectIndex = Effect_Rain_Begin(9, 300) End If LightningTimer = 15000 + (Rnd * 15000) WeatherDoLightning = 1 'We take our rain with a bit of lightning on top >:D WeatherDoFog = 0 Sound_Set WeatherSfx1, 3 Sound_Set WeatherSfx2, 2 Sound_Play WeatherSfx1, DSBPLAY_LOOPING Case 3 'Inside of a house in a storm (lightning + muted rain sound) If WeatherEffectIndex > 0 Then 'Kill the weather effect if used If Effect(WeatherEffectIndex).Used Then Effect_Kill WeatherEffectIndex End If LightningTimer = 15000 + (Rnd * 15000) WeatherDoLightning = 1 WeatherDoFog = 0 Sound_Set WeatherSfx1, 4 Sound_Set WeatherSfx2, 6 Sound_Play WeatherSfx1, DSBPLAY_LOOPING Case 4 'Inside of a cave in a storm (lightning + muted rain sound + fog) If WeatherEffectIndex > 0 Then 'Kill the weather effect if used If Effect(WeatherEffectIndex).Used Then Effect_Kill WeatherEffectIndex End If LightningTimer = 15000 + (Rnd * 15000) WeatherDoLightning = 1 WeatherDoFog = 10 'This will make it nice and spooky! >:D Sound_Set WeatherSfx1, 4 Sound_Set WeatherSfx2, 6 Sound_Play WeatherSfx1, DSBPLAY_LOOPING Case Else 'None If WeatherEffectIndex > 0 Then 'Kill the weather effect if used If Effect(WeatherEffectIndex).Used Then Effect_Kill WeatherEffectIndex Sound_Erase WeatherSfx1 'Remove the sounds Sound_Erase WeatherSfx2 End If WeatherDoLightning = 0 WeatherDoFog = 0 End Select End If 'Update fog If WeatherDoFog Then Engine_Weather_UpdateFog 'Update lightning If WeatherDoLightning Then Engine_Weather_UpdateLightning End Sub Sub Engine_ShowNPCChatWindow(ByVal NPCName As String, ByVal ChatIndex As Byte, ByVal AskIndex As Byte) '***************************************************************** 'Shows the NPC chat window 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_ShowNPCChatWindow '***************************************************************** Dim i As Long Dim Offset As Long 'Set the window values ActiveAsk.AskIndex = AskIndex ActiveAsk.ChatIndex = ChatIndex ActiveAsk.AskName = NPCName ActiveAsk.QuestionTxt = NPCName & ": " & vbNewLine & Engine_WordWrap(NPCChat(ChatIndex).Ask.Ask(AskIndex).Question, GameWindow.NPCChat.Screen.Width - 10) 'Set the window information With GameWindow.NPCChat .NumAnswers = NPCChat(ChatIndex).Ask.Ask(AskIndex).NumAnswers ReDim .Answer(1 To .NumAnswers) Offset = .Screen.Height - 5 For i = .NumAnswers To 1 Step -1 Offset = Offset - Font_Default.CharHeight .Answer(i).Y = Offset .Answer(i).Height = Font_Default.CharHeight .Answer(i).X = 5 .Answer(i).Width = Engine_GetTextWidth(Font_Default, i & ". " & NPCChat(ChatIndex).Ask.Ask(AskIndex).Answer(i).Text) Next i End With ShowGameWindow(NPCChatWindow) = 1 LastClickedWindow = NPCChatWindow SelGameWindow = NPCChatWindow End Sub Function Engine_LegalPos(ByVal X As Integer, ByVal Y As Integer, ByVal Heading As Byte) As Boolean '***************************************************************** 'Checks to see if a tile position is legal 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_LegalPos '***************************************************************** Dim i As Integer 'Check that it is in the map If X < 1 Then Exit Function If X > MapInfo.Width Then Exit Function If Y < 1 Then Exit Function If Y > MapInfo.Height Then Exit Function 'Check to see if its blocked If MapData(X, Y).Blocked = BlockedAll Then Exit Function 'Check the heading for directional blocking If Heading > 0 Then If MapData(X, Y).Blocked And BlockedNorth Then If Heading = NORTH Then Exit Function If Heading = NORTHEAST Then Exit Function If Heading = NORTHWEST Then Exit Function End If If MapData(X, Y).Blocked And BlockedEast Then If Heading = EAST Then Exit Function If Heading = NORTHEAST Then Exit Function If Heading = SOUTHEAST Then Exit Function End If If MapData(X, Y).Blocked And BlockedSouth Then If Heading = SOUTH Then Exit Function If Heading = SOUTHEAST Then Exit Function If Heading = SOUTHWEST Then Exit Function End If If MapData(X, Y).Blocked And BlockedWest Then If Heading = WEST Then Exit Function If Heading = NORTHWEST Then Exit Function If Heading = SOUTHWEST Then Exit Function End If End If 'Check for character For i = 1 To LastChar If CharList(i).Active Then If CharList(i).Pos.X = X Then If CharList(i).Pos.Y = Y Then If CharList(i).OwnerChar <> UserCharIndex Then Exit Function End If End If End If End If Next i 'The position is legal Engine_LegalPos = True End Function Sub Engine_MoveScreen(ByVal Heading As Byte) '***************************************************************** 'Starts the screen moving in a direction 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_MoveScreen '***************************************************************** Dim X As Integer Dim Y As Integer Dim tX As Integer Dim tY As Integer 'Figure out which way to move Select Case Heading Case NORTH Y = -1 Case EAST X = 1 Case SOUTH Y = 1 Case WEST X = -1 Case NORTHEAST Y = -1 X = 1 Case SOUTHEAST Y = 1 X = 1 Case SOUTHWEST Y = 1 X = -1 Case NORTHWEST Y = -1 X = -1 End Select 'Fill temp pos tX = UserPos.X + X tY = UserPos.Y + Y If tX < 1 Then tX = 1: If X < 0 Then X = 0 If tX > MapInfo.Width Then tX = MapInfo.Width: If X > 0 Then X = 0 If tY < 1 Then tY = 1: If Y < 0 Then Y = 0 If tY > MapInfo.Height Then tY = MapInfo.Height: If Y > 0 Then Y = 0 'Start moving... MainLoop does the rest AddtoUserPos.X = X UserPos.X = tX AddtoUserPos.Y = Y UserPos.Y = tY UserMoving = True End Sub Sub Engine_MoveUser(ByVal Direction As Byte) '***************************************************************** 'Move user in appropriate direction 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_MoveUser '***************************************************************** Dim ax As Integer Dim ay As Integer Dim aX2 As Integer Dim aY2 As Integer Dim aX3 As Integer Dim aY3 As Integer Dim Direction2 As Byte Dim Direction3 As Byte 'Check for a valid UserCharIndex If UserCharIndex <= 0 Or UserCharIndex > LastChar Then 'We have an invalid user char index, so we must have the wrong one - request an update on the right one sndBuf.Put_Byte DataCode.User_RequestUserCharIndex Exit Sub End If 'Dont move if the mail composing window is up If ShowGameWindow(WriteMessageWindow) Then Exit Sub 'Figure out the AddX and AddY values Select Case Direction Case NORTHEAST ax = 1 ay = -1 aX2 = 0 aY2 = -1 aX3 = 1 aY3 = 0 Direction2 = NORTH Direction3 = EAST Case NORTHWEST ax = -1 ay = -1 aX2 = 0 aY2 = -1 aX3 = -1 aY3 = 0 Direction2 = NORTH Direction3 = WEST Case SOUTHEAST ax = 1 ay = 1 aX2 = 0 aY2 = 1 aX3 = 1 aY3 = 0 Direction2 = SOUTH Direction3 = EAST Case SOUTHWEST ax = -1 ay = 1 aX2 = 0 aY2 = 1 aX3 = -1 aY3 = 0 Direction2 = SOUTH Direction3 = WEST Case NORTH ax = 0 ay = -1 Case EAST ax = 1 ay = 0 Case SOUTH ax = 0 ay = 1 Case WEST ax = -1 ay = 0 End Select 'If the shop, mailbox or read mail window are showing, hide them ShowGameWindow(MailboxWindow) = 0 ShowGameWindow(ShopWindow) = 0 ShowGameWindow(ViewMessageWindow) = 0 ShowGameWindow(AmountWindow) = 0 ShowGameWindow(BankWindow) = 0 If LastClickedWindow = MailboxWindow Or LastClickedWindow = ShopWindow Or LastClickedWindow = ViewMessageWindow Or _ LastClickedWindow = AmountWindow Or LastClickedWindow = BankWindow Then LastClickedWindow = 0 AmountWindowUsage = 0 AmountWindowItemIndex = 0 AmountWindowValue = vbNullString 'Try the first movement If Engine_LegalPos(UserPos.X + ax, UserPos.Y + ay, Direction) Then Engine_SendMovePacket Direction Exit Sub End If 'If the first movement failed, use the second and third if a diagonal direction If Direction2 > 0 Then If Engine_LegalPos(UserPos.X + aX2, UserPos.Y + aY2, Direction) Then Engine_SendMovePacket Direction2 Exit Sub End If If Engine_LegalPos(UserPos.X + aX3, UserPos.Y + aY3, Direction3) Then Engine_SendMovePacket Direction3 Exit Sub End If End If 'Movement failed, rotate the user to face the direction if needed 'Only rotate if the user is not already facing that direction If CharList(UserCharIndex).Heading <> Direction Then sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_Rotate sndBuf.Put_Byte Direction End If End Sub Sub Engine_SendMovePacket(ByVal Direction As Byte) '***************************************************************** 'Sends the user's movement packet to the server 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_SendMovePacket '***************************************************************** Dim Running As Byte 'If running If GetAsyncKeyState(vbKeyShift) Then 'Check if the user has enough stamina to run If BaseStats(SID.MinSTA) > RunningCost Then Running = 1 End If 'Send the information to the server sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_Move 'Running or not If Running = 1 Then sndBuf.Put_Byte Direction Or 128 Else sndBuf.Put_Byte Direction 'If the user changed directions or just started moving, request a position update If CharList(UserCharIndex).Moving = 0 Or CharList(UserCharIndex).Heading <> Direction Then sndBuf.Allocate 3 sndBuf.Put_Byte DataCode.Server_SetUserPosition sndBuf.Put_Byte UserPos.X sndBuf.Put_Byte UserPos.Y End If 'Move the screen and character Engine_Char_Move_ByHead UserCharIndex, Direction, Running Engine_MoveScreen Direction 'Update the map sounds Sound_UpdateMap End Sub Sub Engine_OBJ_Create(ByVal GrhIndex As Long, ByVal X As Byte, ByVal Y As Byte) '***************************************************************** 'Create an object on the map and update LastOBJ value 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_OBJ_Create '***************************************************************** Dim ObjIndex As Integer 'Get the next open obj slot Do ObjIndex = ObjIndex + 1 'Update LastObj if we go over the size of the current array If ObjIndex > LastObj Then LastObj = ObjIndex ReDim Preserve OBJList(1 To ObjIndex) Exit Do End If Loop While OBJList(ObjIndex).Grh.GrhIndex > 0 'Set the object position OBJList(ObjIndex).Pos.X = X OBJList(ObjIndex).Pos.Y = Y 'Set a random offset OBJList(ObjIndex).Offset.X = -16 + Int(Rnd * 32) OBJList(ObjIndex).Offset.Y = -16 + Int(Rnd * 32) 'Create the object Engine_Init_Grh OBJList(ObjIndex).Grh, GrhIndex End Sub Function Engine_OBJ_AtTile(ByVal X As Byte, ByVal Y As Byte) As Boolean '***************************************************************** 'Checks for an object at tile (X,Y) 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_OBJ_AtTile '***************************************************************** Dim i As Long 'Check if any objects exist If LastObj = 0 Then Exit Function 'Loop through all the objects For i = 1 To LastObj 'Check if the object is located at the tile If OBJList(i).Pos.X = X Then If OBJList(i).Pos.Y = Y Then 'We have an object here! Engine_OBJ_AtTile = True Exit Function End If End If Next i End Function Sub Engine_OBJ_Erase(ByVal ObjIndex As Integer) '***************************************************************** 'Erase an object from the map and update the LastOBJ value 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_OBJ_Erase '***************************************************************** 'Check for a valid object If ObjIndex > LastObj Then Exit Sub If ObjIndex <= 0 Then Exit Sub 'Erase the object ZeroMemory OBJList(ObjIndex), LenB(OBJList(ObjIndex)) 'Update LastOBJ If ObjIndex = LastObj Then Do Until OBJList(LastObj).Grh.GrhIndex > 1 'Move down one object LastObj = LastObj - 1 If LastObj = 0 Then Exit Do Loop If ObjIndex <> LastObj Then 'We still have objects, resize the array to end at the last used slot If LastObj <> 0 Then ReDim Preserve OBJList(1 To LastObj) Else Erase OBJList End If End If End If End Sub Function Engine_PixelPosX(ByVal X As Integer) As Integer '***************************************************************** 'Converts a tile position to a screen position 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_PixelPosX '***************************************************************** Engine_PixelPosX = (X - 1) * TilePixelWidth End Function Function Engine_PixelPosY(ByVal Y As Integer) As Integer '***************************************************************** 'Converts a tile position to a screen position 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_PixelPosY '***************************************************************** Engine_PixelPosY = (Y - 1) * TilePixelHeight End Function Private Function Engine_Collision_Between(ByVal Value As Single, ByVal Bound1 As Single, ByVal Bound2 As Single) As Byte '***************************************************************** 'Find if a value is between two other values (used for line collision) 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Collision_Between '***************************************************************** 'Checks if a value lies between two bounds If Bound1 > Bound2 Then If Value >= Bound2 Then If Value <= Bound1 Then Engine_Collision_Between = 1 End If Else If Value >= Bound1 Then If Value <= Bound2 Then Engine_Collision_Between = 1 End If End If End Function Public Function Engine_Collision_Line(ByVal L1X1 As Long, ByVal L1Y1 As Long, ByVal L1X2 As Long, ByVal L1Y2 As Long, ByVal L2X1 As Long, ByVal L2Y1 As Long, ByVal L2X2 As Long, ByVal L2Y2 As Long) As Byte '***************************************************************** 'Check if two lines intersect (return 1 if true) 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Collision_Line '***************************************************************** Dim m1 As Single Dim M2 As Single Dim B1 As Single Dim B2 As Single Dim IX As Single 'This will fix problems with vertical lines If L1X1 = L1X2 Then L1X1 = L1X1 + 1 If L2X1 = L2X2 Then L2X1 = L2X1 + 1 'Find the first slope m1 = (L1Y2 - L1Y1) / (L1X2 - L1X1) B1 = L1Y2 - m1 * L1X2 'Find the second slope M2 = (L2Y2 - L2Y1) / (L2X2 - L2X1) B2 = L2Y2 - M2 * L2X2 'Check if the slopes are the same If M2 - m1 = 0 Then If B2 = B1 Then 'The lines are the same Engine_Collision_Line = 1 Else 'The lines are parallel (can never intersect) Engine_Collision_Line = 0 End If Else 'An intersection is a point that lies on both lines. To find this, we set the Y equations equal and solve for X. 'M1X+B1 = M2X+B2 -> M1X-M2X = -B1+B2 -> X = B1+B2/(M1-M2) IX = ((B2 - B1) / (m1 - M2)) 'Check for the collision If Engine_Collision_Between(IX, L1X1, L1X2) Then If Engine_Collision_Between(IX, L2X1, L2X2) Then Engine_Collision_Line = 1 End If End If End Function Public Function Engine_Collision_LineRect(ByVal SX As Long, ByVal SY As Long, ByVal SW As Long, ByVal SH As Long, ByVal x1 As Long, ByVal Y1 As Long, ByVal x2 As Long, ByVal Y2 As Long) As Byte '***************************************************************** 'Check if a line intersects with a rectangle (returns 1 if true) 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Collision_LineRect '***************************************************************** 'Top line If Engine_Collision_Line(SX, SY, SX + SW, SY, x1, Y1, x2, Y2) Then Engine_Collision_LineRect = 1 Exit Function End If 'Right line If Engine_Collision_Line(SX + SW, SY, SX + SW, SY + SH, x1, Y1, x2, Y2) Then Engine_Collision_LineRect = 1 Exit Function End If 'Bottom line If Engine_Collision_Line(SX, SY + SH, SX + SW, SY + SH, x1, Y1, x2, Y2) Then Engine_Collision_LineRect = 1 Exit Function End If 'Left line If Engine_Collision_Line(SX, SY, SX, SY + SW, x1, Y1, x2, Y2) Then Engine_Collision_LineRect = 1 Exit Function End If End Function Function Engine_Collision_Rect(ByVal x1 As Integer, ByVal Y1 As Integer, ByVal Width1 As Integer, ByVal Height1 As Integer, ByVal x2 As Integer, ByVal Y2 As Integer, ByVal Width2 As Integer, ByVal Height2 As Integer) As Boolean '***************************************************************** 'Check for collision between two rectangles 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Collision_Rect '***************************************************************** If x1 + Width1 >= x2 Then If x1 <= x2 + Width2 Then If Y1 + Height1 >= Y2 Then If Y1 <= Y2 + Height2 Then Engine_Collision_Rect = True End If End If End If End If End Function Private Sub Engine_Render_Char(ByVal CharIndex As Long, ByVal PixelOffsetX As Single, ByVal PixelOffsetY As Single) '***************************************************************** 'Draw a character to the screen by the CharIndex 'First variables are set, then all shadows drawn, then character drawn, then extras (emoticons, icons, etc) 'Any variables not handled in "Set the variables" are set in Shadow calls - do not call a second time in the 'normal character rendering calls 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Render_Char '***************************************************************** Dim TempGrh As Grh Dim Moved As Boolean Dim IconCount As Byte Dim IconOffset As Integer Dim RenderColor(1 To 4) As Long Dim TempBlock As MapBlock Dim TempBlock2 As MapBlock Dim HeadGrh As Grh Dim BodyGrh As Grh Dim WeaponGrh As Grh Dim HairGrh As Grh Dim WingsGrh As Grh '***** Set the variables ***** 'Update blinking If CharList(CharIndex).BlinkTimer <= 0 Then CharList(CharIndex).StartBlinkTimer = CharList(CharIndex).StartBlinkTimer - ElapsedTime If CharList(CharIndex).StartBlinkTimer <= 0 Then CharList(CharIndex).BlinkTimer = 300 CharList(CharIndex).StartBlinkTimer = Engine_GetBlinkTime End If End If 'Set the map block the char is on to the TempBlock, and the block above the user as TempBlock2 TempBlock = MapData(CharList(CharIndex).Pos.X, CharList(CharIndex).Pos.Y) If CharList(CharIndex).Pos.Y > 1 Then TempBlock2 = MapData(CharList(CharIndex).Pos.X, CharList(CharIndex).Pos.Y - 1) Else TempBlock2 = TempBlock End If 'Check for selected NPC If CharIndex = TargetCharIndex Then 'Clear pathway to the targeted character If ClearPathToTarget Then RenderColor(1) = D3DColorARGB(255, 100, 255, 100) RenderColor(2) = RenderColor(1) RenderColor(3) = RenderColor(1) RenderColor(4) = RenderColor(1) Else RenderColor(1) = D3DColorARGB(255, 255, 100, 100) RenderColor(2) = RenderColor(1) RenderColor(3) = RenderColor(1) RenderColor(4) = RenderColor(1) End If Else RenderColor(1) = TempBlock2.Light(1) RenderColor(2) = TempBlock2.Light(2) RenderColor(3) = TempBlock.Light(3) RenderColor(4) = TempBlock.Light(4) End If If CharList(CharIndex).Moving Then 'If needed, move left and right If CharList(CharIndex).ScrollDirectionX <> 0 Then CharList(CharIndex).MoveOffset.X = CharList(CharIndex).MoveOffset.X + (ScrollPixelsPerFrameX + CharList(CharIndex).Speed + (RunningSpeed * CharList(CharIndex).Running)) * Sgn(CharList(CharIndex).ScrollDirectionX) * TickPerFrame 'Start animation CharList(CharIndex).Body.Walk(CharList(CharIndex).Heading).Started = 1 'Char moved Moved = True 'Check if we already got there If (Sgn(CharList(CharIndex).ScrollDirectionX) = 1 And CharList(CharIndex).MoveOffset.X >= 0) Or (Sgn(CharList(CharIndex).ScrollDirectionX) = -1 And CharList(CharIndex).MoveOffset.X <= 0) Then CharList(CharIndex).MoveOffset.X = 0 CharList(CharIndex).ScrollDirectionX = 0 End If End If 'If needed, move up and down If CharList(CharIndex).ScrollDirectionY <> 0 Then CharList(CharIndex).MoveOffset.Y = CharList(CharIndex).MoveOffset.Y + (ScrollPixelsPerFrameY + CharList(CharIndex).Speed + (RunningSpeed * CharList(CharIndex).Running)) * Sgn(CharList(CharIndex).ScrollDirectionY) * TickPerFrame 'Start animation CharList(CharIndex).Body.Walk(CharList(CharIndex).Heading).Started = 1 'Char moved Moved = True 'Check if we already got there If (Sgn(CharList(CharIndex).ScrollDirectionY) = 1 And CharList(CharIndex).MoveOffset.Y >= 0) Or (Sgn(CharList(CharIndex).ScrollDirectionY) = -1 And CharList(CharIndex).MoveOffset.Y <= 0) Then CharList(CharIndex).MoveOffset.Y = 0 CharList(CharIndex).ScrollDirectionY = 0 End If End If End If 'Update movement reset timer If CharList(CharIndex).ScrollDirectionX = 0 Or CharList(CharIndex).ScrollDirectionY = 0 Then 'If done moving stop animation If Not Moved Then If CharList(CharIndex).Body.Walk(CharList(CharIndex).Heading).Started Then 'Stop animation CharList(CharIndex).Body.Walk(CharList(CharIndex).Heading).Started = 0 CharList(CharIndex).Body.Walk(CharList(CharIndex).Heading).FrameCounter = 1 CharList(CharIndex).Moving = 0 If CharList(CharIndex).ActionIndex = 1 Then CharList(CharIndex).ActionIndex = 0 'If it is the user's character, confirm the position is correct If CharIndex = UserCharIndex Then sndBuf.Allocate 3 sndBuf.Put_Byte DataCode.Server_SetUserPosition sndBuf.Put_Byte CharList(CharIndex).Pos.X sndBuf.Put_Byte CharList(CharIndex).Pos.Y End If End If End If End If 'Set the pixel offset PixelOffsetX = PixelOffsetX + CharList(CharIndex).MoveOffset.X PixelOffsetY = PixelOffsetY + CharList(CharIndex).MoveOffset.Y 'Save the values in the realpos variable CharList(CharIndex).RealPos.X = PixelOffsetX CharList(CharIndex).RealPos.Y = PixelOffsetY '***** Render Shadows ***** 'Draw Body If CharList(CharIndex).ActionIndex <= 1 Then 'Shadow Engine_Render_Grh CharList(CharIndex).Body.Walk(CharList(CharIndex).Heading), PixelOffsetX, PixelOffsetY, 1, 1, True, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1 Engine_Render_Grh CharList(CharIndex).Weapon.Walk(CharList(CharIndex).Heading), PixelOffsetX, PixelOffsetY, 1, 1, True, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1 Else 'Shadow Engine_Render_Grh CharList(CharIndex).Body.Attack(CharList(CharIndex).Heading), PixelOffsetX, PixelOffsetY, 1, 1, False, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1 Engine_Render_Grh CharList(CharIndex).Weapon.Attack(CharList(CharIndex).Heading), PixelOffsetX, PixelOffsetY, 1, 1, False, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1 'Check if animation has stopped If CharList(CharIndex).Body.Attack(CharList(CharIndex).Heading).Started = 0 Then CharList(CharIndex).ActionIndex = 0 End If 'Update aggressive timer If CharList(CharIndex).Aggressive > 0 Then If CharList(CharIndex).AggressiveCounter < timeGetTime Then CharList(CharIndex).Aggressive = 0 CharList(CharIndex).AggressiveCounter = 0 End If End If 'Draw Head If CharList(CharIndex).Aggressive > 0 Then 'Aggressive If CharList(CharIndex).BlinkTimer > 0 Then CharList(CharIndex).BlinkTimer = CharList(CharIndex).BlinkTimer - ElapsedTime 'Blinking Engine_Render_Grh CharList(CharIndex).Head.AgrBlink(CharList(CharIndex).HeadHeading), PixelOffsetX + CharList(CharIndex).Body.HeadOffset.X, PixelOffsetY + CharList(CharIndex).Body.HeadOffset.Y, True, False, True, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1 Else 'Normal Engine_Render_Grh CharList(CharIndex).Head.AgrHead(CharList(CharIndex).HeadHeading), PixelOffsetX + CharList(CharIndex).Body.HeadOffset.X, PixelOffsetY + CharList(CharIndex).Body.HeadOffset.Y, True, False, True, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1 End If Else 'Not Aggressive If CharList(CharIndex).BlinkTimer > 0 Then CharList(CharIndex).BlinkTimer = CharList(CharIndex).BlinkTimer - ElapsedTime 'Blinking Engine_Render_Grh CharList(CharIndex).Head.Blink(CharList(CharIndex).HeadHeading), PixelOffsetX + CharList(CharIndex).Body.HeadOffset.X, PixelOffsetY + CharList(CharIndex).Body.HeadOffset.Y, True, False, True, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1 Else 'Normal Engine_Render_Grh CharList(CharIndex).Head.Head(CharList(CharIndex).HeadHeading), PixelOffsetX + CharList(CharIndex).Body.HeadOffset.X, PixelOffsetY + CharList(CharIndex).Body.HeadOffset.Y, True, False, True, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1 End If End If 'Hair Engine_Render_Grh CharList(CharIndex).Hair.Hair(CharList(CharIndex).HeadHeading), PixelOffsetX + CharList(CharIndex).Body.HeadOffset.X, PixelOffsetY + CharList(CharIndex).Body.HeadOffset.Y, True, False, True, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1 '***** Render Character ***** '***** (When updating this, make sure you copy it to the NPCEditor and MapEditor, too!) ***** CharList(CharIndex).Weapon.Walk(CharList(CharIndex).Heading).FrameCounter = CharList(CharIndex).Body.Walk(CharList(CharIndex).Heading).FrameCounter 'The body, weapon and wings If CharList(CharIndex).ActionIndex <= 1 Then 'Walking BodyGrh = CharList(CharIndex).Body.Walk(CharList(CharIndex).Heading) WeaponGrh = CharList(CharIndex).Weapon.Walk(CharList(CharIndex).Heading) WingsGrh = CharList(CharIndex).Wings.Walk(CharList(CharIndex).Heading) CharList(CharIndex).Weapon.Walk(CharList(CharIndex).Heading).FrameCounter = CharList(CharIndex).Body.Walk(CharList(CharIndex).Heading).FrameCounter Else 'Attacking BodyGrh = CharList(CharIndex).Body.Attack(CharList(CharIndex).Heading) WeaponGrh = CharList(CharIndex).Weapon.Attack(CharList(CharIndex).Heading) WingsGrh = CharList(CharIndex).Wings.Attack(CharList(CharIndex).Heading) CharList(CharIndex).Weapon.Attack(CharList(CharIndex).Heading).FrameCounter = CharList(CharIndex).Body.Attack(CharList(CharIndex).Heading).FrameCounter End If 'The head If CharList(CharIndex).Aggressive > 0 Then 'Aggressive If CharList(CharIndex).BlinkTimer > 0 Then HeadGrh = CharList(CharIndex).Head.AgrBlink(CharList(CharIndex).HeadHeading) Else HeadGrh = CharList(CharIndex).Head.AgrHead(CharList(CharIndex).HeadHeading) Else 'Non-aggressive If CharList(CharIndex).BlinkTimer > 0 Then HeadGrh = CharList(CharIndex).Head.Blink(CharList(CharIndex).HeadHeading) Else HeadGrh = CharList(CharIndex).Head.Head(CharList(CharIndex).HeadHeading) End If 'The hair HairGrh = CharList(CharIndex).Hair.Hair(CharList(CharIndex).HeadHeading) 'Make the paperdoll layering based off the direction they are heading '*** NORTH / NORTHEAST *** (1.Weapon 2.Body 3.Head 4.Hair 5.Wings) If CharList(CharIndex).Heading = NORTH Or CharList(CharIndex).Heading = NORTHEAST Then Engine_Render_Grh WeaponGrh, PixelOffsetX, PixelOffsetY, True, 0, True, RenderColor(1), RenderColor(2), RenderColor(3), RenderColor(4) Engine_Render_Grh BodyGrh, PixelOffsetX, PixelOffsetY, 1, 0, True, RenderColor(1), RenderColor(2), RenderColor(3), RenderColor(4) Engine_Render_Grh HeadGrh, PixelOffsetX + CharList(CharIndex).Body.HeadOffset.X, PixelOffsetY + CharList(CharIndex).Body.HeadOffset.Y, 1, 0, True, RenderColor(1), RenderColor(2), RenderColor(3), RenderColor(4) Engine_Render_Grh HairGrh, PixelOffsetX + CharList(CharIndex).Body.HeadOffset.X, PixelOffsetY + CharList(CharIndex).Body.HeadOffset.Y, 1, 0, True, RenderColor(1), RenderColor(2), RenderColor(3), RenderColor(4) Engine_Render_Grh WingsGrh, PixelOffsetX, PixelOffsetY, True, 0, True, RenderColor(1), RenderColor(2), RenderColor(3), RenderColor(4) '*** EAST / SOUTHEAST *** (1.Body 2.Head 3.Hair 4.Wings 5.Weapon) ElseIf CharList(CharIndex).Heading = EAST Or CharList(CharIndex).Heading = SOUTHEAST Then Engine_Render_Grh BodyGrh, PixelOffsetX, PixelOffsetY, 1, 0, True, RenderColor(1), RenderColor(2), RenderColor(3), RenderColor(4) Engine_Render_Grh HeadGrh, PixelOffsetX + CharList(CharIndex).Body.HeadOffset.X, PixelOffsetY + CharList(CharIndex).Body.HeadOffset.Y, 1, 0, True, RenderColor(1), RenderColor(2), RenderColor(3), RenderColor(4) Engine_Render_Grh HairGrh, PixelOffsetX + CharList(CharIndex).Body.HeadOffset.X, PixelOffsetY + CharList(CharIndex).Body.HeadOffset.Y, 1, 0, True, RenderColor(1), RenderColor(2), RenderColor(3), RenderColor(4) Engine_Render_Grh WingsGrh, PixelOffsetX, PixelOffsetY, True, 0, True, RenderColor(1), RenderColor(2), RenderColor(3), RenderColor(4) Engine_Render_Grh WeaponGrh, PixelOffsetX, PixelOffsetY, True, 0, True, RenderColor(1), RenderColor(2), RenderColor(3), RenderColor(4) '*** SOUTH / SOUTHWEST *** (1.Wings 2.Body 3.Head 4.Hair 5.Weapon) ElseIf CharList(CharIndex).Heading = SOUTH Or CharList(CharIndex).Heading = SOUTHWEST Then Engine_Render_Grh WingsGrh, PixelOffsetX, PixelOffsetY, True, 0, True, RenderColor(1), RenderColor(2), RenderColor(3), RenderColor(4) Engine_Render_Grh BodyGrh, PixelOffsetX, PixelOffsetY, 1, 0, True, RenderColor(1), RenderColor(2), RenderColor(3), RenderColor(4) Engine_Render_Grh HeadGrh, PixelOffsetX + CharList(CharIndex).Body.HeadOffset.X, PixelOffsetY + CharList(CharIndex).Body.HeadOffset.Y, 1, 0, True, RenderColor(1), RenderColor(2), RenderColor(3), RenderColor(4) Engine_Render_Grh HairGrh, PixelOffsetX + CharList(CharIndex).Body.HeadOffset.X, PixelOffsetY + CharList(CharIndex).Body.HeadOffset.Y, 1, 0, True, RenderColor(1), RenderColor(2), RenderColor(3), RenderColor(4) Engine_Render_Grh WeaponGrh, PixelOffsetX, PixelOffsetY, True, 0, True, RenderColor(1), RenderColor(2), RenderColor(3), RenderColor(4) '*** WEST / NORTHWEST *** (1.Weapon 1.Body 2.Head 3.Hair 4.Wings) ElseIf CharList(CharIndex).Heading = WEST Or CharList(CharIndex).Heading = NORTHWEST Then Engine_Render_Grh WeaponGrh, PixelOffsetX, PixelOffsetY, True, 0, True, RenderColor(1), RenderColor(2), RenderColor(3), RenderColor(4) Engine_Render_Grh BodyGrh, PixelOffsetX, PixelOffsetY, 1, 0, True, RenderColor(1), RenderColor(2), RenderColor(3), RenderColor(4) Engine_Render_Grh HeadGrh, PixelOffsetX + CharList(CharIndex).Body.HeadOffset.X, PixelOffsetY + CharList(CharIndex).Body.HeadOffset.Y, 1, 0, True, RenderColor(1), RenderColor(2), RenderColor(3), RenderColor(4) Engine_Render_Grh HairGrh, PixelOffsetX + CharList(CharIndex).Body.HeadOffset.X, PixelOffsetY + CharList(CharIndex).Body.HeadOffset.Y, 1, 0, True, RenderColor(1), RenderColor(2), RenderColor(3), RenderColor(4) Engine_Render_Grh WingsGrh, PixelOffsetX, PixelOffsetY, True, 0, True, RenderColor(1), RenderColor(2), RenderColor(3), RenderColor(4) End If '***** Render Extras ***** 'Draw name over head Engine_Render_Text Font_Default, CharList(CharIndex).Name, PixelOffsetX + 16 - CharList(CharIndex).NameOffset, PixelOffsetY - 40, RenderColor(1) 'Count the number of icons that will be needed to draw With CharList(CharIndex).CharStatus IconCount = 0 IconCount = .Blessed + .Protected + .Strengthened + .Cursed + .WarCursed + .IronSkinned + .Exhausted End With 'Health/Mana bars Engine_Render_Rectangle PixelOffsetX - 4, PixelOffsetY + 34, (CharList(CharIndex).HealthPercent / 100) * 40, 4, 1, 1, 1, 1, 1, 1, 0, 0, HealthColor, HealthColor, HealthColor, HealthColor, 0, False Engine_Render_Rectangle PixelOffsetX - 4, PixelOffsetY + 38, (CharList(CharIndex).ManaPercent / 100) * 40, 4, 1, 1, 1, 1, 1, 1, 0, 0, ManaColor, ManaColor, ManaColor, ManaColor, 0, False 'Draw the icons If IconCount > 0 Then 'Calculate the icon offset IconOffset = PixelOffsetX + 16 - (IconCount * 8) If CharList(CharIndex).CharStatus.Blessed Then Engine_Init_Grh TempGrh, 15 Engine_Render_Grh TempGrh, IconOffset, PixelOffsetY - 50, 0, 0, False IconOffset = IconOffset + 16 End If If CharList(CharIndex).CharStatus.Protected Then Engine_Init_Grh TempGrh, 20 Engine_Render_Grh TempGrh, IconOffset, PixelOffsetY - 50, 0, 0, False IconOffset = IconOffset + 16 End If If CharList(CharIndex).CharStatus.Strengthened Then Engine_Init_Grh TempGrh, 17 Engine_Render_Grh TempGrh, IconOffset, PixelOffsetY - 50, 0, 0, False IconOffset = IconOffset + 16 End If If CharList(CharIndex).CharStatus.Cursed Then Engine_Init_Grh TempGrh, 18 Engine_Render_Grh TempGrh, IconOffset, PixelOffsetY - 50, 0, 0, False IconOffset = IconOffset + 16 End If If CharList(CharIndex).CharStatus.WarCursed Then Engine_Init_Grh TempGrh, 19 Engine_Render_Grh TempGrh, IconOffset, PixelOffsetY - 50, 0, 0, False IconOffset = IconOffset + 16 End If If CharList(CharIndex).CharStatus.IronSkinned Then Engine_Init_Grh TempGrh, 16 Engine_Render_Grh TempGrh, IconOffset, PixelOffsetY - 50, 0, 0, False IconOffset = IconOffset + 16 End If If CharList(CharIndex).CharStatus.Exhausted Then Engine_Init_Grh TempGrh, 22 Engine_Render_Grh TempGrh, IconOffset, PixelOffsetY - 50, 0, 0, False IconOffset = IconOffset + 16 End If End If 'Emoticons If CharList(CharIndex).EmoDir > 0 Then 'Fade in If CharList(CharIndex).EmoDir = 1 Then CharList(CharIndex).EmoFade = CharList(CharIndex).EmoFade + (ElapsedTime * 1.5) If CharList(CharIndex).EmoFade >= 255 Then CharList(CharIndex).EmoFade = 255 CharList(CharIndex).EmoDir = 2 End If End If 'Fade out If CharList(CharIndex).Emoticon.Started = 0 Then 'Animation has stopped If CharList(CharIndex).EmoDir = 2 Then CharList(CharIndex).EmoFade = CharList(CharIndex).EmoFade - (ElapsedTime * 1.5) If CharList(CharIndex).EmoFade <= 0 Then CharList(CharIndex).EmoFade = 0 CharList(CharIndex).EmoDir = 0 End If 'Stop at the last frame, don't roll over to the first CharList(CharIndex).Emoticon.FrameCounter = GrhData(CharList(CharIndex).Emoticon.GrhIndex).NumFrames End If End If 'Render Engine_Render_Grh CharList(CharIndex).Emoticon, PixelOffsetX + 8, PixelOffsetY - 40, 0, 1, False, D3DColorARGB(CharList(CharIndex).EmoFade, 255, 255, 255), D3DColorARGB(CharList(CharIndex).EmoFade, 255, 255, 255), D3DColorARGB(CharList(CharIndex).EmoFade, 255, 255, 255), D3DColorARGB(CharList(CharIndex).EmoFade, 255, 255, 255) End If End Sub Private Sub Engine_Render_ChatTextBuffer() '************************************************************ 'Update and render the chat text buffer 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Render_ChatTextBuffer '************************************************************ Dim SrcRect As RECT Dim v2 As D3DVECTOR2 Dim v3 As D3DVECTOR2 Dim i As Long 'Check if we have the device If D3DDevice.TestCooperativeLevel <> D3D_OK Then Exit Sub 'Assign the alternate rendering value AlternateRender = AlternateRenderText 'Check if using alternate rendering If AlternateRender Then 'Check if the texture is no longer the font texture If LastTexture <> Font_Default_TextureNum Then 'End the old sprite we had going If SpriteBegun = 1 Then Sprite.End Sprite.Begin End If End If 'Loop through all the characters For i = 0 To UBound(ChatVA) Step 6 'Create the source rectangle With SrcRect .Left = ChatVA(i).tU * Font_Default.TextureSize.X .Top = ChatVA(i).tV * Font_Default.TextureSize.Y .Right = ChatVA(i + 5).tU * Font_Default.TextureSize.X .bottom = ChatVA(i + 5).tV * Font_Default.TextureSize.Y End With 'Set the translation (location on the screen) v3.X = ChatVA(i).X v3.Y = ChatVA(i).Y 'Draw the character Sprite.Draw Font_Default.Texture, SrcRect, SpriteScaleVector, v2, 0, v3, ChatVA(i).Color Next i Else 'Clear the LastTexture, letting the rest of the engine know that the texture needs to be changed for next rect render D3DDevice.SetTexture 0, Font_Default.Texture LastTexture = Font_Default_TextureNum 'Set up the vertex buffer If ShowGameWindow(ChatWindow) Then If ChatArrayUbound > 0 Then D3DDevice.SetStreamSource 0, ChatVB, FVF_Size D3DDevice.DrawPrimitive D3DPT_TRIANGLELIST, 0, (ChatArrayUbound + 1) \ 3 End If End If End If 'Retreive the default alternate render value AlternateRender = AlternateRenderDefault End Sub Private Function Engine_UpdateGrh(ByRef Grh As Grh, Optional ByVal LoopAnim As Boolean = True) As Boolean '***************************************************************** 'Updates the grh's animation 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_UpdateGrh '***************************************************************** 'Check that the grh is started If Grh.Started = 1 Then 'Update the frame counter Grh.FrameCounter = Grh.FrameCounter + ((timeGetTime - Grh.LastCount) * GrhData(Grh.GrhIndex).Speed) Grh.LastCount = timeGetTime 'If the frame counter is higher then the number of frames... If Grh.FrameCounter >= GrhData(Grh.GrhIndex).NumFrames + 1 Then 'Loop the animation If LoopAnim Then Do While Grh.FrameCounter >= GrhData(Grh.GrhIndex).NumFrames + 1 Grh.FrameCounter = Grh.FrameCounter - GrhData(Grh.GrhIndex).NumFrames Loop 'Looping isn't set, just kill the animation Else Grh.Started = 0 Exit Function End If End If End If 'The grpahic will be rendered Engine_UpdateGrh = True End Function Sub Engine_Render_Grh(ByRef Grh As Grh, ByVal X As Integer, ByVal Y As Integer, ByVal Center As Byte, ByVal Animate As Byte, Optional ByVal LoopAnim As Boolean = True, Optional ByVal Light1 As Long = -1, Optional ByVal Light2 As Long = -1, Optional ByVal Light3 As Long = -1, Optional ByVal Light4 As Long = -1, Optional ByVal Shadow As Byte = 0, Optional ByVal Angle As Single = 0) '***************************************************************** 'Draws a GRH transparently to a X and Y position 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Render_Grh '***************************************************************** Dim CurrGrhIndex As Long 'The grh index we will be working with (acquired after updating animations) Dim FileNum As Integer 'Check to make sure it is legal If Grh.GrhIndex < 1 Then Exit Sub If GrhData(Grh.GrhIndex).NumFrames < 1 Then Exit Sub If Grh.FrameCounter < 1 Then 'Grh has a delay, so just update the frame and then leave Engine_UpdateGrh Grh, LoopAnim Exit Sub End If If Int(Grh.FrameCounter) > GrhData(Grh.GrhIndex).NumFrames Then Grh.FrameCounter = 1 'Figure out what frame to draw (always 1 if not animated) CurrGrhIndex = GrhData(Grh.GrhIndex).Frames(Int(Grh.FrameCounter)) 'Check for in-bounds If X + GrhData(CurrGrhIndex).pixelWidth > 0 Then If Y + GrhData(CurrGrhIndex).pixelHeight > 0 Then If X < ScreenWidth Then If Y < ScreenHeight Then 'Update the animation frame If Animate Then If Not Engine_UpdateGrh(Grh, LoopAnim) Then Exit Sub End If 'Set the file number in a shorter variable FileNum = GrhData(CurrGrhIndex).FileNum 'Center Grh over X,Y pos If Center Then If GrhData(CurrGrhIndex).TileWidth > 1 Then X = X - GrhData(CurrGrhIndex).TileWidth * TilePixelWidth \ 2 + TilePixelWidth \ 2 End If If GrhData(CurrGrhIndex).TileHeight > 1 Then Y = Y - GrhData(CurrGrhIndex).TileHeight * TilePixelHeight + TilePixelHeight End If End If 'Check the rendering method to use If AlternateRender = 0 Then 'Render the texture with 2 triangles on a triangle strip Engine_Render_Rectangle X, Y, GrhData(CurrGrhIndex).pixelWidth, GrhData(CurrGrhIndex).pixelHeight, GrhData(CurrGrhIndex).SX, _ GrhData(CurrGrhIndex).SY, GrhData(CurrGrhIndex).pixelWidth, GrhData(CurrGrhIndex).pixelHeight, , , Angle, FileNum, Light1, Light2, Light3, Light4, Shadow, False Else 'Render the texture as a D3DXSprite Engine_Render_D3DXSprite X, Y, GrhData(CurrGrhIndex).pixelWidth, GrhData(CurrGrhIndex).pixelHeight, GrhData(CurrGrhIndex).SX, GrhData(CurrGrhIndex).SY, Light1, FileNum, Angle End If End If End If End If End If End Sub Private Sub Engine_Render_D3DXSprite(ByVal X As Single, ByVal Y As Single, ByVal Width As Single, ByVal Height As Single, ByVal SrcX As Single, ByVal SrcY As Single, ByVal Light As Long, ByVal TextureNum As Long, ByVal Degrees As Single) '***************************************************************** 'Renders a Grh in the form of a D3DXSprite instead of a rectangle (slower, less flexibility) 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Render_D3DXSprite '***************************************************************** Dim SrcRect As RECT Dim v2 As D3DVECTOR2 Dim v3 As D3DVECTOR2 'End the old sprite we had going (only if the texture changed) If TextureNum <> LastTexture Then If SpriteBegun = 1 Then Sprite.End Sprite.Begin End If End If 'Ready the texture Engine_ReadyTexture TextureNum 'Create the source rectangle With SrcRect .Left = SrcX .Top = SrcY .Right = .Left + Width .bottom = .Top + Height End With 'Create the rotation point If Degrees Then Degrees = ((Degrees + 180) * DegreeToRadian) If Degrees > 360 Then Degrees = Degrees - 360 With v2 .X = (Width * 0.5) .Y = (Height * 0.5) End With End If 'Set the translation (location on the screen) v3.X = X v3.Y = Y 'Draw the sprite If TextureNum > 0 Then Sprite.Draw SurfaceDB(TextureNum), SrcRect, SpriteScaleVector, v2, Degrees, v3, Light Else Sprite.Draw Nothing, SrcRect, SpriteScaleVector, v2, 0, v3, Light End If End Sub Private Sub Engine_Render_ChatBubble(ByVal Text As String, ByVal X As Integer, ByVal Y As Integer) '***************************************************************** 'Renders a chat bubble and the text for the given text and co-ordinates 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Render_ChatBubble '***************************************************************** Const BubbleSectionSize As Long = 6 'The width/height of each "sector" of the bubble in the graphic file Const RenderColor As Long = -1761607681 Dim TempGrh As Grh Dim BubbleWidth As Long Dim BubbleHeight As Long Dim TempSplit() As String Dim i As Long Dim j As Long If DisableChatBubbles Then Exit Sub 'Set up the temp grh TempGrh.FrameCounter = 1 TempGrh.Started = 1 'Split up the string TempSplit = Split(Text, vbNewLine) '*** Calculate the bubble width and height *** If UBound(TempSplit) > 0 Then 'If there are multiple lines, it is assumed it is the max width BubbleWidth = BubbleMaxWidth 'Because there are multiple lines, we have to calculate the height, too BubbleHeight = Font_Default.CharHeight * (UBound(TempSplit) + 1) Else 'Theres only one line, so that line is the width BubbleWidth = Engine_GetTextWidth(Font_Default, Text) BubbleHeight = Font_Default.CharHeight End If 'Round the width and height to the nearest BubbleSectionSize (the size of each chat bubble side section) BubbleWidth = BubbleWidth + BubbleSectionSize If BubbleWidth Mod BubbleSectionSize Then BubbleWidth = BubbleWidth + (BubbleSectionSize - (BubbleWidth Mod BubbleSectionSize)) If BubbleHeight Mod BubbleSectionSize Then BubbleHeight = BubbleHeight + (BubbleSectionSize - (BubbleHeight Mod BubbleSectionSize)) 'Modify the X and Y values the center the bubble X = X - (BubbleWidth * 0.5) + 16 'Center Y = Y - BubbleHeight - 20 'Align above the head '*** Draw the bubble *** 'Top-left corner TempGrh.GrhIndex = 109 Engine_Render_Grh TempGrh, X, Y, 0, 0, False, RenderColor, RenderColor, RenderColor, RenderColor 'Top-right corner TempGrh.GrhIndex = 111 Engine_Render_Grh TempGrh, X + BubbleWidth + BubbleSectionSize, Y, 0, 0, False, RenderColor, RenderColor, RenderColor, RenderColor 'Bottom-left corner TempGrh.GrhIndex = 115 Engine_Render_Grh TempGrh, X, Y + BubbleHeight + BubbleSectionSize, 0, 0, False, RenderColor, RenderColor, RenderColor, RenderColor 'Bottom-right corner TempGrh.GrhIndex = 117 Engine_Render_Grh TempGrh, X + BubbleWidth + BubbleSectionSize, Y + BubbleHeight + BubbleSectionSize, 0, 0, False, RenderColor, RenderColor, RenderColor, RenderColor 'Top side TempGrh.GrhIndex = 110 For i = 0 To (BubbleWidth \ BubbleSectionSize) - 1 Engine_Render_Grh TempGrh, X + ((i + 1) * BubbleSectionSize), Y, 0, 0, False, RenderColor, RenderColor, RenderColor, RenderColor Next i 'Left side TempGrh.GrhIndex = 112 For i = 0 To (BubbleHeight \ BubbleSectionSize) - 1 Engine_Render_Grh TempGrh, X, Y + ((i + 1) * BubbleSectionSize), 0, 0, False, RenderColor, RenderColor, RenderColor, RenderColor Next i 'Right side TempGrh.GrhIndex = 114 For i = 0 To (BubbleHeight \ BubbleSectionSize) - 1 Engine_Render_Grh TempGrh, X + BubbleWidth + BubbleSectionSize, Y + ((i + 1) * BubbleSectionSize), 0, 0, False, RenderColor, RenderColor, RenderColor, RenderColor Next i 'Bottom side TempGrh.GrhIndex = 116 For i = 0 To (BubbleWidth \ BubbleSectionSize) - 1 Engine_Render_Grh TempGrh, X + ((i + 1) * BubbleSectionSize), Y + BubbleHeight + BubbleSectionSize, 0, 0, False, RenderColor, RenderColor, RenderColor, RenderColor Next i 'Middle TempGrh.GrhIndex = 113 For i = 1 To (BubbleWidth \ BubbleSectionSize) For j = 1 To (BubbleHeight \ BubbleSectionSize) Engine_Render_Grh TempGrh, X + (i * BubbleSectionSize), Y + (j * BubbleSectionSize), 0, 0, False, RenderColor, RenderColor, RenderColor, RenderColor Next j Next i 'Render the text (finally!) Engine_Render_Text Font_Default, Text, X + BubbleSectionSize, Y + BubbleSectionSize, D3DColorARGB(255, 0, 0, 0) End Sub Private Sub Engine_Render_GUI() '***************************************************************** 'Render the GUI 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Render_GUI '***************************************************************** Dim TempGrh As Grh Dim i As Long 'Render the rest of the windows For i = NumGameWindows To 1 Step -1 If i <> LastClickedWindow Then If ShowGameWindow(i) Then Engine_Render_GUI_Window i End If Next i 'Render the last clicked window If LastClickedWindow > 0 Then If ShowGameWindow(LastClickedWindow) Then Engine_Render_GUI_Window LastClickedWindow End If 'Render the spells list If DrawSkillList Then Engine_Render_Skills 'Render an item where the cursor should be (item being dragged) If DragItemSlot Then Select Case DragSourceWindow Case InventoryWindow TempGrh.GrhIndex = UserInventory(DragItemSlot).GrhIndex Case ShopWindow TempGrh.GrhIndex = NPCTradeItems(DragItemSlot).GrhIndex Case BankWindow TempGrh.GrhIndex = UserBank(DragItemSlot).GrhIndex End Select 'Draw TempGrh.FrameCounter = 1 Engine_Render_Grh TempGrh, MousePos.X, MousePos.Y, 0, 0, False End If 'Render the cursor If Not Windowed Then TempGrh.FrameCounter = 1 TempGrh.GrhIndex = 69 Engine_Render_Grh TempGrh, MousePos.X, MousePos.Y, 0, 0, False End If 'Draw item description Engine_Render_ItemDesc End Sub Private Sub Engine_Render_GUI_Window(ByVal WindowIndex As Byte) '***************************************************************** 'Render a GUI window 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Render_GUI_Window '***************************************************************** Dim User1RenderColor As Long Dim User2RenderColor As Long Dim TempGrh As Grh Dim TempGrh2 As Grh Dim t As String Dim s() As String Dim i As Byte Dim j As Long TempGrh.FrameCounter = 1 TempGrh2.FrameCounter = 1 Select Case WindowIndex Case TradeWindow With GameWindow.Trade Engine_Render_Grh .SkinGrh, .Screen.X, .Screen.Y, 0, 1, True, GUIColorValue, GUIColorValue, GUIColorValue, GUIColorValue If TradeTable.User1Accepted Then User1RenderColor = D3DColorARGB(255, 0, 255, 0) Else User1RenderColor = D3DColorARGB(255, 255, 255, 255) If TradeTable.User2Accepted Then User2RenderColor = D3DColorARGB(255, 0, 255, 0) Else User2RenderColor = D3DColorARGB(255, 255, 255, 255) Engine_Render_Text Font_Default, TradeTable.User1Name, .Screen.X + .User1Name.X, .Screen.Y + .User1Name.Y, User1RenderColor Engine_Render_Text Font_Default, TradeTable.User2Name, .Screen.X + .User2Name.X, .Screen.Y + .User2Name.Y, User2RenderColor For j = 1 To 9 TempGrh.GrhIndex = TradeTable.Trade1(j).Grh TempGrh2.GrhIndex = TradeTable.Trade2(j).Grh Engine_Render_Grh TempGrh, .Screen.X + .Trade1(j).X, .Screen.Y + .Trade1(j).Y, 0, 0, False, User1RenderColor, User1RenderColor, User1RenderColor, User1RenderColor Engine_Render_Grh TempGrh2, .Screen.X + .Trade2(j).X, .Screen.Y + .Trade2(j).Y, 0, 0, False, User2RenderColor, User2RenderColor, User2RenderColor, User2RenderColor Engine_Render_Text Font_Default, TradeTable.Gold1, .Screen.X + .Gold1.X, .Screen.Y + .Gold1.Y, User1RenderColor Engine_Render_Text Font_Default, TradeTable.Gold2, .Screen.X + .Gold2.X, .Screen.Y + .Gold2.Y, User2RenderColor Next j End With Case NPCChatWindow With GameWindow.NPCChat Engine_Render_Grh .SkinGrh, .Screen.X, .Screen.Y, 0, 1, True, GUIColorValue, GUIColorValue, GUIColorValue, GUIColorValue Engine_Render_Text Font_Default, ActiveAsk.QuestionTxt, .Screen.X + 5, .Screen.Y + 5, D3DColorARGB(255, 255, 255, 255) For i = 1 To .NumAnswers Engine_Render_Text Font_Default, i & ". " & NPCChat(ActiveAsk.ChatIndex).Ask.Ask(ActiveAsk.AskIndex).Answer(i).Text, .Screen.X + .Answer(i).X, .Screen.Y + .Answer(i).Y, D3DColorARGB(255, 0, 255, 0) Next i End With Case StatWindow With GameWindow.StatWindow Engine_Render_Grh .SkinGrh, .Screen.X, .Screen.Y, 0, 1, True, GUIColorValue, GUIColorValue, GUIColorValue, GUIColorValue Engine_Render_Text Font_Default, "Str: " & BaseStats(SID.Str) & " + " & ModStats(SID.Str) - BaseStats(SID.Str) & " (" & ModStats(SID.Str) & ")", .Screen.X + .Str.X, .Screen.Y + .Str.Y, -1 Engine_Render_Text Font_Default, "Agi: " & BaseStats(SID.Agi) & " + " & ModStats(SID.Agi) - BaseStats(SID.Agi) & " (" & ModStats(SID.Agi) & ")", .Screen.X + .Agi.X, .Screen.Y + .Agi.Y, -1 Engine_Render_Text Font_Default, "Mag: " & BaseStats(SID.Mag) & " + " & ModStats(SID.Mag) - BaseStats(SID.Mag) & " (" & ModStats(SID.Mag) & ")", .Screen.X + .Mag.X, .Screen.Y + .Mag.Y, -1 If BaseStats(SID.Points) > 0 Then Engine_Render_Grh .AddGrh, .Screen.X + .AddStr.X, .Screen.Y + .AddStr.Y, 0, 1 Engine_Render_Grh .AddGrh, .Screen.X + .AddAgi.X, .Screen.Y + .AddAgi.Y, 0, 1 Engine_Render_Grh .AddGrh, .Screen.X + .AddMag.X, .Screen.Y + .AddMag.Y, 0, 1 End If Engine_Render_Text Font_Default, "Points: " & BaseStats(SID.Points), .Screen.X + .Points.X, .Screen.Y + .Points.Y, -1 Engine_Render_Text Font_Default, "Gold: " & BaseStats(SID.Gold), .Screen.X + .Gold.X, .Screen.Y + .Gold.Y, -1 Engine_Render_Text Font_Default, "Def: " & BaseStats(SID.DEF) & " + " & ModStats(SID.DEF) - BaseStats(SID.DEF) & " (" & ModStats(SID.DEF) & ")", .Screen.X + .DEF.X, .Screen.Y + .DEF.Y, -1 Engine_Render_Text Font_Default, "Dmg: " & BaseStats(SID.MinHIT) & "+" & ModStats(SID.MinHIT) - BaseStats(SID.MinHIT) & " ~ " & BaseStats(SID.MaxHIT) & "+" & ModStats(SID.MaxHIT) - BaseStats(SID.MaxHIT) & " (" & ModStats(SID.MinHIT) & " ~ " & ModStats(SID.MaxHIT) & ")", .Screen.X + .Dmg.X, .Screen.Y + .Dmg.Y, -1 End With Case ChatWindow With GameWindow.ChatWindow Engine_Render_Grh .SkinGrh, .Screen.X, .Screen.Y, 0, 1, True, GUIColorValue, GUIColorValue, GUIColorValue, GUIColorValue End With 'Render the chat text Engine_Render_ChatTextBuffer 'Draw entered text If EnterText = True Then If EnterTextBufferWidth = 0 Then EnterTextBufferWidth = 1 'Dividing by 0 is never good If LenB(ShownText) <> 0 Then Engine_Render_Text Font_Default, ShownText, GameWindow.ChatWindow.Screen.X + GameWindow.ChatWindow.Text.X, GameWindow.ChatWindow.Screen.Y + GameWindow.ChatWindow.Text.Y, FontColor_Talk If timeGetTime Mod CursorFlashRate * 2 < CursorFlashRate Then TempGrh.GrhIndex = 39 TempGrh.FrameCounter = 1 TempGrh.Started = 1 Engine_Render_Grh TempGrh, GameWindow.ChatWindow.Screen.X + GameWindow.ChatWindow.Text.X + Engine_GetTextWidth(Font_Default, ShownText), GameWindow.ChatWindow.Screen.Y + GameWindow.ChatWindow.Text.Y, 0, 0, False End If End If Case MenuWindow With GameWindow.Menu Engine_Render_Grh .SkinGrh, .Screen.X, .Screen.Y, 0, 1, True, GUIColorValue, GUIColorValue, GUIColorValue, GUIColorValue End With Case QuickBarWindow With GameWindow.QuickBar Engine_Render_Grh .SkinGrh, .Screen.X, .Screen.Y, 0, 1, True, GUIColorValue, GUIColorValue, GUIColorValue, GUIColorValue For i = 1 To 12 Select Case QuickBarID(i).Type Case QuickBarType_Skill TempGrh.GrhIndex = Engine_SkillIDtoGRHID(QuickBarID(i).ID) If TempGrh.GrhIndex Then Engine_Render_Grh TempGrh, .Screen.X + .Image(i).X, .Screen.Y + .Image(i).Y, 0, 0, False Case QuickBarType_Item TempGrh.GrhIndex = UserInventory(QuickBarID(i).ID).GrhIndex If TempGrh.GrhIndex Then Engine_Render_Grh TempGrh, .Screen.X + .Image(i).X, .Screen.Y + .Image(i).Y, 0, 0, False End Select Next i End With Case InventoryWindow With GameWindow.Inventory Engine_Render_Grh .SkinGrh, .Screen.X, .Screen.Y, 0, 1, True, GUIColorValue, GUIColorValue, GUIColorValue, GUIColorValue Engine_Render_Inventory End With Case ShopWindow With GameWindow.Shop Engine_Render_Grh .SkinGrh, .Screen.X, .Screen.Y, 0, 1, True, GUIColorValue, GUIColorValue, GUIColorValue, GUIColorValue Engine_Render_Inventory 2 End With Case BankWindow With GameWindow.Bank Engine_Render_Grh .SkinGrh, .Screen.X, .Screen.Y, 0, 1, True, GUIColorValue, GUIColorValue, GUIColorValue, GUIColorValue Engine_Render_Inventory 3 End With Case MailboxWindow With GameWindow.Mailbox Engine_Render_Grh .SkinGrh, .Screen.X, .Screen.Y, 0, 1, True, GUIColorValue, GUIColorValue, GUIColorValue, GUIColorValue Engine_Render_Text Font_Default, MailboxListBuffer, .Screen.X + .List.X, .Screen.Y + .List.Y, -1 Engine_Render_Text Font_Default, "Read", .Screen.X + .ReadLbl.X, .Screen.Y + .ReadLbl.Y, -1 Engine_Render_Text Font_Default, "Write", .Screen.X + .WriteLbl.X, .Screen.Y + .WriteLbl.Y, -1 Engine_Render_Text Font_Default, "Delete", .Screen.X + .DeleteLbl.X, .Screen.Y + .DeleteLbl.Y, -1 If SelMessage > 0 Then Engine_Render_Rectangle .Screen.X + .List.X, .Screen.Y + .List.Y + ((SelMessage - 1) * Font_Default.CharHeight), .List.Width, Font_Default.CharHeight, 1, 1, 1, 1, 1, 1, 0, 0, 2097217280, 2097217280, 2097217280, 2097217280, , False 'ARGB: 125/0/255/0 End With Case ViewMessageWindow With GameWindow.ViewMessage Engine_Render_Grh .SkinGrh, .Screen.X, .Screen.Y, 0, 1, True, GUIColorValue, GUIColorValue, GUIColorValue, GUIColorValue Engine_Render_Text Font_Default, ReadMailData.WriterName, .Screen.X + .From.X, .Screen.Y + .From.Y, -1 Engine_Render_Text Font_Default, ReadMailData.Subject, .Screen.X + .Subject.X, .Screen.Y + .Subject.Y, -1 Engine_Render_Text Font_Default, ReadMailData.Message, .Screen.X + .Message.X, .Screen.Y + .Message.Y, -1 For i = 1 To MaxMailObjs If ReadMailData.Obj(i) > 0 Then TempGrh.GrhIndex = ReadMailData.Obj(i) Engine_Render_Grh TempGrh, .Screen.X + .Image(i).X, .Screen.Y + .Image(i).Y, 0, 0, False End If Next i End With Case WriteMessageWindow With GameWindow.WriteMessage Engine_Render_Grh .SkinGrh, .Screen.X, .Screen.Y, 0, 1, True, GUIColorValue, GUIColorValue, GUIColorValue, GUIColorValue '"To" text box If LenB(WriteMailData.RecieverName) <> 0 Then Engine_Render_Text Font_Default, WriteMailData.RecieverName, .Screen.X + .From.X, .Screen.Y + .From.Y, -1 If WMSelCon = wmFrom Then If timeGetTime Mod CursorFlashRate * 2 < CursorFlashRate Then TempGrh.GrhIndex = 39 Engine_Render_Grh TempGrh, .Screen.X + .From.X + Engine_GetTextWidth(Font_Default, WriteMailData.RecieverName), .Screen.Y + .From.Y, 0, 0, False End If End If 'Subject text box If LenB(WriteMailData.Subject) <> 0 Then Engine_Render_Text Font_Default, WriteMailData.Subject, .Screen.X + .Subject.X, .Screen.Y + .Subject.Y, -1 If WMSelCon = wmSubject Then If timeGetTime Mod CursorFlashRate * 2 < CursorFlashRate Then TempGrh.GrhIndex = 39 Engine_Render_Grh TempGrh, .Screen.X + .Subject.X + Engine_GetTextWidth(Font_Default, WriteMailData.Subject), .Screen.Y + .Subject.Y, 0, 0, False End If End If 'Message body text box t = Engine_WordWrap(WriteMailData.Message, GameWindow.WriteMessage.Message.Width) If LenB(WriteMailData.Message) <> 0 Then Engine_Render_Text Font_Default, t, .Screen.X + .Message.X, .Screen.Y + .Message.Y, -1 If WMSelCon = wmMessage Then If timeGetTime Mod CursorFlashRate * 2 < CursorFlashRate Then If InStr(1, t, vbNewLine) Then s = Split(t, vbNewLine) i = UBound(s) j = Engine_GetTextWidth(Font_Default, s(i)) Else i = 0 'Ubound j = Engine_GetTextWidth(Font_Default, t) 'Size End If TempGrh.GrhIndex = 39 Engine_Render_Grh TempGrh, .Screen.X + .Message.X + j, .Screen.Y + .Message.Y + (i * Font_Default.CharHeight), 0, 0, False End If End If 'Objects For i = 1 To MaxMailObjs If WriteMailData.ObjIndex(i) > 0 Then TempGrh.GrhIndex = UserInventory(WriteMailData.ObjIndex(i)).GrhIndex Engine_Render_Grh TempGrh, .Screen.X + .Image(i).X, .Screen.Y + .Image(i).Y, 0, 0, False End If Next i End With Case AmountWindow With GameWindow.Amount Engine_Render_Grh .SkinGrh, .Screen.X, .Screen.Y, 0, 1, True, GUIColorValue, GUIColorValue, GUIColorValue, GUIColorValue If LenB(AmountWindowValue) <> 0 Then Engine_Render_Text Font_Default, AmountWindowValue, .Screen.X + .Value.X, .Screen.Y + .Value.Y, -1 End With End Select End Sub Public Sub Engine_Render_Inventory(Optional ByVal InventoryType As Long = 1) '***************************************************************** 'Renders the inventory 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Render_Inventory '***************************************************************** Dim TempGrh As Grh Dim DestX As Single Dim DestY As Single Dim LoopC As Long Select Case InventoryType 'User inventory Case 1 For LoopC = 1 To MAX_INVENTORY_SLOTS If UserInventory(LoopC).GrhIndex Then DestX = GameWindow.Inventory.Screen.X + GameWindow.Inventory.Image(LoopC).X DestY = GameWindow.Inventory.Screen.Y + GameWindow.Inventory.Image(LoopC).Y TempGrh.FrameCounter = 1 TempGrh.GrhIndex = UserInventory(LoopC).GrhIndex If DragItemSlot = LoopC And DragSourceWindow = InventoryWindow Then Engine_Render_Grh TempGrh, DestX, DestY, 0, 0, False, -1761607681, -1761607681, -1761607681, -1761607681 'ARGB 150/255/255/255 Else Engine_Render_Grh TempGrh, DestX, DestY, 0, 0, False End If 'If UserInventory(LoopC).Amount > 1 Then Engine_Render_Text Font_Default, UserInventory(LoopC).Amount, DestX, DestY, -1 'End If If UserInventory(LoopC).Equipped Then Engine_Render_Text Font_Default, "E", DestX + (30 - Engine_GetTextWidth(Font_Default, "E")), DestY, -16711936 End If Next LoopC 'Shop inventory Case 2 For LoopC = 1 To NPCTradeItemArraySize If NPCTradeItems(LoopC).GrhIndex Then DestX = GameWindow.Shop.Screen.X + GameWindow.Shop.Image(LoopC).X DestY = GameWindow.Shop.Screen.Y + GameWindow.Shop.Image(LoopC).Y TempGrh.FrameCounter = 1 TempGrh.GrhIndex = NPCTradeItems(LoopC).GrhIndex If DragItemSlot = LoopC And DragSourceWindow = ShopWindow Then Engine_Render_Grh TempGrh, DestX, DestY, 0, 0, False, -1761607681, -1761607681, -1761607681, -1761607681 'ARGB 150/255/255/255 Else Engine_Render_Grh TempGrh, DestX, DestY, 0, 0, False End If End If Next LoopC 'Bank inventory Case 3 For LoopC = 1 To MAX_INVENTORY_SLOTS If UserBank(LoopC).GrhIndex Then DestX = GameWindow.Bank.Screen.X + GameWindow.Bank.Image(LoopC).X DestY = GameWindow.Bank.Screen.Y + GameWindow.Bank.Image(LoopC).Y TempGrh.FrameCounter = 1 TempGrh.GrhIndex = UserBank(LoopC).GrhIndex If DragItemSlot = LoopC And DragSourceWindow = BankWindow Then Engine_Render_Grh TempGrh, DestX, DestY, 0, 0, False, -1761607681, -1761607681, -1761607681, -1761607681 'ARGB 150/255/255/255 Else Engine_Render_Grh TempGrh, DestX, DestY, 0, 0, False End If If UserBank(LoopC).Amount <> -1 Then Engine_Render_Text Font_Default, UserBank(LoopC).Amount, DestX, DestY, -1 End If Next LoopC End Select End Sub Private Sub Engine_Render_ItemDesc() '************************************************************ 'Draw description text 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Render_ItemDesc '************************************************************ Dim X As Integer Dim Y As Integer Dim i As Byte 'Check if the description text is there If ItemDescLines = 0 Then Exit Sub 'Check the description position X = MousePos.X Y = MousePos.Y If X < 0 Then X = 0 If X + ItemDescWidth > ScreenWidth Then X = ScreenWidth - ItemDescWidth If Y < 0 Then Y = 0 If Y + (ItemDescLines * Font_Default.CharHeight) > ScreenHeight Then Y = ScreenHeight - (ItemDescLines * Font_Default.CharHeight) 'Draw backdrop Engine_Render_Rectangle X - 5, Y - 5, ItemDescWidth + 10, (Font_Default.CharHeight * ItemDescLines) + 10, 1, 1, 1, 1, 1, 1, 0, 0, -1761607681, -1761607681, -1761607681, -1761607681, , False 'Draw text For i = 1 To ItemDescLines Engine_Render_Text Font_Default, ItemDescLine(i), X, Y + ((i - 1) * Font_Default.CharHeight), -16777216 Next i End Sub Private Sub Engine_ReadyTexture(ByVal TextureNum As Long) '************************************************************ 'Gets a texture ready to for usage 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_ReadyTexture '************************************************************ 'Load the surface into memory if it is not in memory and reset the timer If TextureNum > 0 Then If SurfaceTimer(TextureNum) < timeGetTime Then Engine_Init_Texture TextureNum SurfaceTimer(TextureNum) = timeGetTime + SurfaceTimerMax End If 'Check what render method we're using If AlternateRender Then 'Set the texture LastTexture = TextureNum If TextureNum <= 0 Then D3DDevice.SetTexture 0, Nothing Else 'Set the texture If TextureNum <= 0 Then D3DDevice.SetTexture 0, Nothing LastTexture = 0 Else If LastTexture <> TextureNum Then D3DDevice.SetTexture 0, SurfaceDB(TextureNum) LastTexture = TextureNum End If End If End If End Sub Sub Engine_Render_Rectangle(ByVal X As Single, ByVal Y As Single, ByVal Width As Single, ByVal Height As Single, ByVal SrcX As Single, ByVal SrcY As Single, ByVal SrcWidth As Single, ByVal SrcHeight As Single, Optional ByVal SrcBitmapWidth As Long = -1, Optional ByVal SrcBitmapHeight As Long = -1, Optional ByVal Degrees As Single = 0, Optional ByVal TextureNum As Long, Optional ByVal Color0 As Long = -1, Optional ByVal Color1 As Long = -1, Optional ByVal Color2 As Long = -1, Optional ByVal Color3 As Long = -1, Optional ByVal Shadow As Byte = 0, Optional ByVal InBoundsCheck As Boolean = True) '************************************************************ 'Render a square/rectangle based on the specified values then rotate it if needed 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Render_Rectangle '************************************************************ Dim VertexArray(0 To 3) As TLVERTEX Dim RadAngle As Single 'The angle in Radians Dim CenterX As Single Dim CenterY As Single Dim Index As Integer Dim NewX As Single Dim NewY As Single Dim SinRad As Single Dim CosRad As Single Dim ShadowAdd As Single Dim L As Single 'Perform in-bounds check if needed If InBoundsCheck Then If X + SrcWidth <= 0 Then Exit Sub If Y + SrcHeight <= 0 Then Exit Sub If X >= ScreenWidth Then Exit Sub If Y >= ScreenHeight Then Exit Sub End If 'Ready the texture Engine_ReadyTexture TextureNum 'Set the bitmap dimensions if needed If SrcBitmapWidth = -1 Then SrcBitmapWidth = SurfaceSize(TextureNum).X If SrcBitmapHeight = -1 Then SrcBitmapHeight = SurfaceSize(TextureNum).Y 'Set the RHWs (must always be 1) VertexArray(0).Rhw = 1 VertexArray(1).Rhw = 1 VertexArray(2).Rhw = 1 VertexArray(3).Rhw = 1 'Apply the colors VertexArray(0).Color = Color0 VertexArray(1).Color = Color1 VertexArray(2).Color = Color2 VertexArray(3).Color = Color3 If Shadow Then 'To make things easy, we just do a completely separate calculation the top two points ' with an uncropped tU / tV algorithm VertexArray(0).X = X + (Width * 0.5) VertexArray(0).Y = Y - (Height * 0.5) VertexArray(0).tU = (SrcX / SrcBitmapWidth) VertexArray(0).tV = (SrcY / SrcBitmapHeight) VertexArray(1).X = VertexArray(0).X + Width VertexArray(1).tU = ((SrcX + Width) / SrcBitmapWidth) VertexArray(2).X = X VertexArray(2).tU = (SrcX / SrcBitmapWidth) VertexArray(3).X = X + Width VertexArray(3).tU = (SrcX + SrcWidth + ShadowAdd) / SrcBitmapWidth Else '------------------------------------------------------------------------------------------------------ '------------------------------------------------------------------------------------------------------ 'If the image is partially outside of the screen, it is trimmed so only that which is in the screen is drawn 'This provides for quite a decent FPS boost if you have lots of tiles that stretch outside of the view area 'Important: Something about this doesn't seem to be functioning correctly. It is supposed to crop down the 'image and only draw that which is going to be in the screen, but it doesn't work right and I have no 'idea why. Uncomment the lines to see what happens. I have given up on this since the FPS boost really isn't 'significant for me to put any more work into it, but if someone could fix it, it would definitely be 'added back into the engine. '------------------------------------------------------------------------------------------------------ '------------------------------------------------------------------------------------------------------ 'If X < 0 Then ' SrcX = SrcX - X ' SrcWidth = SrcWidth + X ' Width = Width + X ' X = 0 'End If 'If Y < 0 Then ' SrcY = SrcY - Y ' SrcHeight = SrcHeight + Y ' Height = Height + Y ' Y = 0 'End If 'If X + Width > ScreenWidth Then ' L = X + Width - ScreenWidth ' Width = Width - L ' SrcWidth = SrcWidth - L 'End If 'If Y + Height > ScreenHeight Then ' L = Y + Height - ScreenHeight ' Height = Height - L ' SrcHeight = SrcHeight - L 'End If '------------------------------------------------------------------------------------------------------ '------------------------------------------------------------------------------------------------------ 'If we are NOT using shadows, then we add +1 to the width/height (trust me, just do it) ShadowAdd = 1 'Find the left side of the rectangle VertexArray(0).X = X VertexArray(0).tU = (SrcX / SrcBitmapWidth) 'Find the top side of the rectangle VertexArray(0).Y = Y VertexArray(0).tV = (SrcY / SrcBitmapHeight) 'Find the right side of the rectangle VertexArray(1).X = X + Width VertexArray(1).tU = (SrcX + SrcWidth + ShadowAdd) / SrcBitmapWidth 'These values will only equal each other when not a shadow VertexArray(2).X = VertexArray(0).X VertexArray(3).X = VertexArray(1).X End If 'Find the bottom of the rectangle VertexArray(2).Y = Y + Height VertexArray(2).tV = (SrcY + SrcHeight + ShadowAdd) / SrcBitmapHeight 'Because this is a perfect rectangle, all of the values below will equal one of the values we already got VertexArray(1).Y = VertexArray(0).Y VertexArray(1).tV = VertexArray(0).tV VertexArray(2).tU = VertexArray(0).tU VertexArray(3).Y = VertexArray(2).Y VertexArray(3).tU = VertexArray(1).tU VertexArray(3).tV = VertexArray(2).tV 'Check if a rotation is required If Degrees <> 0 And Degrees <> 360 Then 'Converts the angle to rotate by into radians RadAngle = Degrees * DegreeToRadian 'Set the CenterX and CenterY values CenterX = X + (Width * 0.5) CenterY = Y + (Height * 0.5) 'Pre-calculate the cosine and sine of the radiant SinRad = Sin(RadAngle) CosRad = Cos(RadAngle) 'Loops through the passed vertex buffer For Index = 0 To 3 'Calculates the new X and Y co-ordinates of the vertices for the given angle around the center co-ordinates NewX = CenterX + (VertexArray(Index).X - CenterX) * CosRad - (VertexArray(Index).Y - CenterY) * SinRad NewY = CenterY + (VertexArray(Index).Y - CenterY) * CosRad + (VertexArray(Index).X - CenterX) * SinRad 'Applies the new co-ordinates to the buffer VertexArray(Index).X = NewX VertexArray(Index).Y = NewY Next Index End If 'Render the texture to the device D3DDevice.DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, VertexArray(0), FVF_Size End Sub Public Sub Engine_CreateTileLayers() '************************************************************ 'Creates the tile layers used for rendering the tiles so they can be drawn faster 'Has to happen every time the user warps or moves a whole tile 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_CreateTileLayers '************************************************************ Dim Layer As Byte Dim ScreenX As Long Dim ScreenY As Long Dim tBuf As Integer Dim pX As Integer Dim pY As Integer Dim X As Long Dim Y As Long 'Raise the buffer up + 1 to prevent graphical errors tBuf = TileBufferSize '+ 1 'Loop through each layer and check which tiles there are that will need to be drawn For Layer = 1 To 6 'Clear the number of tiles TileLayer(Layer).NumTiles = 0 'Allocate enough memory for all the tiles ReDim TileLayer(Layer).Tile(1 To ((maxY - minY + 1) * (maxX - minX + 1))) 'Loop through all the tiles within the buffer's range ScreenY = (10 - tBuf) For Y = minY To maxY ScreenX = (10 - tBuf) For X = minX To maxX 'Check that the tile is in the range of the map If X >= 1 Then If Y >= 1 Then If X <= MapInfo.Width Then If Y <= MapInfo.Height Then 'Check if the tile even has a graphic on it If MapData(X, Y).Graphic(Layer).GrhIndex Then 'Calculate the pixel values pX = Engine_PixelPosX(ScreenX) - 288 pY = Engine_PixelPosY(ScreenY) - 288 'Check that the tile is in the screen With GrhData(MapData(X, Y).Graphic(Layer).GrhIndex) If pX >= -.pixelWidth Then If pX <= ScreenWidth + .pixelWidth Then If pY >= -.pixelHeight Then If pY <= ScreenHeight + .pixelHeight Then 'The tile is valid to be used, so raise the count TileLayer(Layer).NumTiles = TileLayer(Layer).NumTiles + 1 'Store the needed information TileLayer(Layer).Tile(TileLayer(Layer).NumTiles).TileX = X TileLayer(Layer).Tile(TileLayer(Layer).NumTiles).TileY = Y TileLayer(Layer).Tile(TileLayer(Layer).NumTiles).PixelPosX = pX + 288 TileLayer(Layer).Tile(TileLayer(Layer).NumTiles).PixelPosY = pY + 288 End If End If End If End If End With End If End If End If End If End If ScreenX = ScreenX + 1 Next X ScreenY = ScreenY + 1 Next Y 'We got all the information we need, now resize the array as small as possible to save RAM, then do the same for every other layer :o If TileLayer(Layer).NumTiles > 0 Then ReDim Preserve TileLayer(Layer).Tile(1 To TileLayer(Layer).NumTiles) Else Erase TileLayer(Layer).Tile End If Next Layer End Sub Sub Engine_Render_Screen(ByVal TileX As Integer, ByVal TileY As Integer, ByVal PixelOffsetX As Integer, ByVal PixelOffsetY As Integer) '************************************************************ 'Draw current visible to scratch area based on TileX and TileY 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Render_Screen '************************************************************ Dim FrameUseMotionBlur As Boolean 'Lets us know if this frame is using motion blur so we don't have to leave support for it on Dim LightOffset As Long Dim ChrID() As Integer Dim ChrY() As Integer Dim Y As Long 'Keeps track of where on map we are Dim X As Long Dim j As Long Dim Angle As Single Dim Layer As Byte 'Check for valid positions If UserPos.X = 0 Then Exit Sub If UserPos.Y = 0 Then Exit Sub If UserCharIndex = 0 Then Exit Sub 'Check if we need to update the graphics If TileX <> LastTileX Or TileY <> LastTileY Then 'Figure out Ends and Starts of screen ScreenMinY = TileY - (WindowTileHeight \ 2) ScreenMaxY = TileY + (WindowTileHeight \ 2) ScreenMinX = TileX - (WindowTileWidth \ 2) ScreenMaxX = TileX + (WindowTileWidth \ 2) minY = ScreenMinY - TileBufferSize maxY = ScreenMaxY + TileBufferSize minX = ScreenMinX - TileBufferSize maxX = ScreenMaxX + TileBufferSize 'Update the last position LastTileX = TileX LastTileY = TileY 'Re-create the tile layers Engine_CreateTileLayers End If 'Calculate the particle offset values 'Do NOT move this any farther down in the module or you will get "jumps" as the left/top borders on particles ParticleOffsetX = (Engine_PixelPosX(ScreenMinX) - PixelOffsetX) ParticleOffsetY = (Engine_PixelPosY(ScreenMinY) - PixelOffsetY) 'Check if we have the device If D3DDevice.TestCooperativeLevel <> D3D_OK Then 'The worst we can do at this point is avoid an error we can't fix! On Error Resume Next 'Do a loop while device is lost If D3DDevice.TestCooperativeLevel = D3DERR_DEVICELOST Then Exit Sub 'Clear all the textures LastTexture = -999 For j = 1 To NumGrhFiles Set SurfaceDB(j) = Nothing SurfaceTimer(j) = 0 SurfaceSize(j).X = 0 SurfaceSize(j).Y = 0 Next j 'Clear the D3DXSprite If AlternateRenderDefault = 1 Or AlternateRenderMap = 1 Or AlternateRenderText = 1 Then SpriteBegun = 0 Set Sprite = Nothing Set Sprite = D3DX.CreateSprite(D3DDevice) End If Set DeviceBuffer = Nothing Set DeviceStencil = Nothing Set BlurStencil = Nothing Set BlurTexture = Nothing Set BlurSurf = Nothing 'Make sure the scene is ended D3DDevice.EndScene 'Reset the device D3DDevice.Reset D3DWindow Set DeviceBuffer = D3DDevice.GetRenderTarget Set DeviceStencil = D3DDevice.GetDepthStencilSurface Set BlurStencil = D3DDevice.CreateDepthStencilSurface(BufferWidth, BufferHeight, D3DFMT_D16, D3DMULTISAMPLE_NONE) Set BlurTexture = D3DX.CreateTexture(D3DDevice, BufferWidth, BufferHeight, 0, D3DUSAGE_RENDERTARGET, DispMode.Format, D3DPOOL_DEFAULT) Set BlurSurf = BlurTexture.GetSurfaceLevel(0) 'Reset the render states Engine_Init_RenderStates 'Load the particle textures Engine_Init_ParticleEngine True On Error GoTo 0 Else 'We have to bypass the present the first time through here or else we get an error If NotFirstRender Then 'Close off the last sprite If SpriteBegun Then Sprite.End SpriteBegun = 0 LastTexture = -101 End If With D3DDevice 'End the rendering (scene) .EndScene 'Flip the backbuffer to the screen .Present ByVal 0, ByVal 0, 0, ByVal 0 End With Else 'Set NotFirstRender to True so we can start displaying NotFirstRender = True End If End If 'Check if running (turn on motion blur) If UseMotionBlur Then If UserCharIndex > 0 Then If CharList(UserCharIndex).Moving = 1 And CharList(UserCharIndex).Running Then BlurIntensity = 45 Else If BlurIntensity < 255 Then BlurIntensity = BlurIntensity + (ElapsedTime * 0.8) If BlurIntensity > 255 Then BlurIntensity = 255 End If End If End If End If 'Set the motion blur if needed If UseMotionBlur Then If BlurIntensity < 255 Or ZoomLevel > 0 Then FrameUseMotionBlur = True D3DDevice.SetRenderTarget BlurSurf, BlurStencil, 0 End If End If 'Begin the scene D3DDevice.BeginScene 'Clear the screen with a solid color (to prevent artifacts) D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET, 0, 1#, 0 '************** Layer 1 to 3 ************** 'Set the alternate rendering for the map on / off AlternateRender = AlternateRenderMap 'Loop through the lower 3 layers For Layer = 1 To 3 LightOffset = ((Layer - 1) * 4) + 1 'Loop through all the tiles we know we will draw for this layer For j = 1 To TileLayer(Layer).NumTiles With TileLayer(Layer).Tile(j) 'Check if we have to draw with a shadow or not (slighty changes because we have to animate on the shadow, not the main render) If MapData(.TileX, .TileY).Shadow(Layer) = 1 Then Engine_Render_Grh MapData(.TileX, .TileY).Graphic(Layer), .PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, 0, 1, True, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1 Engine_Render_Grh MapData(.TileX, .TileY).Graphic(Layer), .PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, 0, 0, True, MapData(.TileX, .TileY).Light(LightOffset), MapData(.TileX, .TileY).Light(LightOffset + 1), MapData(.TileX, .TileY).Light(LightOffset + 2), MapData(.TileX, .TileY).Light(LightOffset + 3) Else Engine_Render_Grh MapData(.TileX, .TileY).Graphic(Layer), .PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, 0, 1, True, MapData(.TileX, .TileY).Light(LightOffset), MapData(.TileX, .TileY).Light(LightOffset + 1), MapData(.TileX, .TileY).Light(LightOffset + 2), MapData(.TileX, .TileY).Light(LightOffset + 3) End If End With Next j Next Layer 'Set the alternate rendering back to what it was before AlternateRender = AlternateRenderDefault '************** Objects ************** For j = 1 To LastObj If OBJList(j).Grh.GrhIndex Then X = Engine_PixelPosX(OBJList(j).Pos.X - minX) + PixelOffsetX + OBJList(j).Offset.X + TileBufferOffset Y = Engine_PixelPosY(OBJList(j).Pos.Y - minY) + PixelOffsetY + OBJList(j).Offset.Y + TileBufferOffset If Y >= -32 Then If Y <= (ScreenHeight + 32) Then If X >= -32 Then If X <= (ScreenWidth + 32) Then Engine_Render_Grh OBJList(j).Grh, X, Y, 1, 1, True, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1 Engine_Render_Grh OBJList(j).Grh, X, Y, 1, 1, True, MapData(OBJList(j).Pos.X, OBJList(j).Pos.Y).Light(1), _ MapData(OBJList(j).Pos.X, OBJList(j).Pos.Y).Light(2), MapData(OBJList(j).Pos.X, OBJList(j).Pos.Y).Light(3), _ MapData(OBJList(j).Pos.X, OBJList(j).Pos.Y).Light(4) End If End If End If End If End If Next j '************** Characters ************** 'Size the to the smallest safe size (LastChar) ReDim ChrID(1 To LastChar) ReDim ChrY(1 To LastChar) 'Fill the array For j = 1 To LastChar ChrY(j) = CharList(j).Pos.Y ChrID(j) = j Next j 'Sort the char list Engine_SortIntArray ChrY, ChrID, 1, LastChar 'Loop through the sorted characters For j = 1 To LastChar If CharList(ChrID(j)).Active Then X = Engine_PixelPosX(CharList(ChrID(j)).Pos.X - minX) + PixelOffsetX + TileBufferOffset Y = Engine_PixelPosY(CharList(ChrID(j)).Pos.Y - minY) + PixelOffsetY + TileBufferOffset If Y >= -32 And Y <= (ScreenHeight + 32) And X >= -32 And X <= (ScreenWidth + 32) Then 'Update the NPC chat Engine_NPCChat_Update ChrID(j) 'Draw the character Engine_Render_Char ChrID(j), X, Y Else 'Update just the real position CharList(ChrID(j)).RealPos.X = X + CharList(ChrID(j)).MoveOffset.X CharList(ChrID(j)).RealPos.Y = Y + CharList(ChrID(j)).MoveOffset.Y End If End If Next j '************** Layer 4 to 6 ************** AlternateRender = AlternateRenderMap For Layer = 4 To 6 LightOffset = ((Layer - 1) * 4) + 1 For j = 1 To TileLayer(Layer).NumTiles With TileLayer(Layer).Tile(j) If MapData(.TileX, .TileY).Shadow(Layer) = 1 Then Engine_Render_Grh MapData(.TileX, .TileY).Graphic(Layer), .PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, 0, 1, True, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1 Engine_Render_Grh MapData(.TileX, .TileY).Graphic(Layer), .PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, 0, 0, True, MapData(.TileX, .TileY).Light(LightOffset), MapData(.TileX, .TileY).Light(LightOffset + 1), MapData(.TileX, .TileY).Light(LightOffset + 2), MapData(.TileX, .TileY).Light(LightOffset + 3) Else Engine_Render_Grh MapData(.TileX, .TileY).Graphic(Layer), .PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, 0, 1, True, MapData(.TileX, .TileY).Light(LightOffset), MapData(.TileX, .TileY).Light(LightOffset + 1), MapData(.TileX, .TileY).Light(LightOffset + 2), MapData(.TileX, .TileY).Light(LightOffset + 3) End If End With Next j Next Layer AlternateRender = AlternateRenderDefault '************** Effects ************** 'Loop to do drawing If LastEffect > 0 Then For j = 1 To LastEffect If EffectList(j).Grh.GrhIndex Then X = Engine_PixelPosX(EffectList(j).Pos.X - minX) + PixelOffsetX + TileBufferOffset Y = Engine_PixelPosY(EffectList(j).Pos.Y - minY) + PixelOffsetY + TileBufferOffset If EffectList(j).Time <> 0 And EffectList(j).Time < timeGetTime Then 'Timer ran out Engine_Effect_Erase j ElseIf Y >= -32 And Y <= (ScreenHeight + 32) And X >= -32 And X <= (ScreenWidth + 32) Then 'Timer or animation going, render Engine_Render_Grh EffectList(j).Grh, X, Y, 1, 1, 0, , , , , , EffectList(j).Angle 'Check if the animation is still running If EffectList(j).Animated = 1 Then If EffectList(j).Grh.Started = 0 Then Engine_Effect_Erase j End If Else 'Animation is going but not in screen, update the animation frame Engine_UpdateGrh EffectList(j).Grh, False 'Check if the animation is still running If EffectList(j).Animated = 1 Then If EffectList(j).Grh.Started = 0 Then Engine_Effect_Erase j End If End If End If Next j End If '************** Projectiles ************** 'Loop to do drawing If LastProjectile > 0 Then For j = 1 To LastProjectile If ProjectileList(j).Grh.GrhIndex Then 'Update the position Angle = DegreeToRadian * Engine_GetAngle(ProjectileList(j).X, ProjectileList(j).Y, ProjectileList(j).tX, ProjectileList(j).tY) ProjectileList(j).X = ProjectileList(j).X + (Sin(Angle) * ElapsedTime * 0.63) ProjectileList(j).Y = ProjectileList(j).Y - (Cos(Angle) * ElapsedTime * 0.63) 'Update the rotation If ProjectileList(j).RotateSpeed > 0 Then ProjectileList(j).Rotate = ProjectileList(j).Rotate + (ProjectileList(j).RotateSpeed * ElapsedTime * 0.01) Do While ProjectileList(j).Rotate > 360 ProjectileList(j).Rotate = ProjectileList(j).Rotate - 360 Loop End If 'Draw if within range X = ((-minX - 1) * 32) + ProjectileList(j).X + PixelOffsetX + TileBufferOffset Y = ((-minY - 1) * 32) + ProjectileList(j).Y + PixelOffsetY + TileBufferOffset If Y >= -32 Then If Y <= (ScreenHeight + 32) Then If X >= -32 Then If X <= (ScreenWidth + 32) Then If ProjectileList(j).Rotate = 0 Then Engine_Render_Grh ProjectileList(j).Grh, X, Y, 0, 1, 1, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1 Engine_Render_Grh ProjectileList(j).Grh, X, Y, 0, 0, 1 Else Engine_Render_Grh ProjectileList(j).Grh, X, Y, 0, 0, 1, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1, ProjectileList(j).Rotate Engine_Render_Grh ProjectileList(j).Grh, X, Y, 0, 1, 1, , , , , , ProjectileList(j).Rotate End If End If End If End If End If End If Next j 'Check if it is close enough to the target to remove For j = 1 To LastProjectile If ProjectileList(j).Grh.GrhIndex Then If Abs(ProjectileList(j).X - ProjectileList(j).tX) < 20 Then If Abs(ProjectileList(j).Y - ProjectileList(j).tY) < 20 Then Engine_Projectile_Erase j End If End If End If Next j End If '************** Blood Splatters ************** 'Loop to do drawing For j = 1 To LastBlood If BloodList(j).Grh.GrhIndex Then X = Engine_PixelPosX(BloodList(j).Pos.X - minX) + PixelOffsetX + TileBufferOffset Y = Engine_PixelPosY(BloodList(j).Pos.Y - minY) + PixelOffsetY + TileBufferOffset If Y >= -32 Then If Y <= (ScreenHeight + 32) Then If X >= -32 Then If X <= (ScreenWidth + 32) Then Engine_Render_Grh BloodList(j).Grh, X, Y, 1, 1, False End If End If End If End If End If Next j 'Seperate loop to remove the unused - I dont like removing while drawing For j = 1 To LastBlood If BloodList(j).Grh.GrhIndex Then If BloodList(j).Grh.Started = 0 Then Engine_Blood_Erase j End If Next j '************** Update weather ************** 'Do the general weather updating Engine_Weather_Update '************** Chat bubbles ************** 'Loop through the chars For j = 1 To LastChar If CharList(j).Active Then If LenB(CharList(j).BubbleStr) <> 0 Then If CharList(j).RealPos.X > -25 Then If CharList(j).RealPos.X < ScreenWidth + 25 Then If CharList(j).RealPos.Y > -25 Then If CharList(j).RealPos.Y < ScreenHeight + 25 Then Engine_Render_ChatBubble CharList(j).BubbleStr, CharList(j).RealPos.X, CharList(j).RealPos.Y CharList(j).BubbleTime = CharList(j).BubbleTime - ElapsedTime If CharList(j).BubbleTime <= 0 Then CharList(j).BubbleTime = 0 CharList(j).BubbleStr = vbNullString End If End If End If End If End If End If End If Next j '************** Damage text ************** 'Loop to do drawing For j = 1 To LastDamage If DamageList(j).Counter > 0 Then DamageList(j).Counter = DamageList(j).Counter - ElapsedTime X = (((DamageList(j).Pos.X - minX) - 1) * TilePixelWidth) + PixelOffsetX + TileBufferOffset Y = (((DamageList(j).Pos.Y - minY) - 1) * TilePixelHeight) + PixelOffsetY + TileBufferOffset If Y >= -32 Then If Y <= (ScreenHeight + 32) Then If X >= -32 Then If X <= (ScreenWidth + 32) Then Engine_Render_Text Font_Default, DamageList(j).Value, X, Y, D3DColorARGB(255, 255, 0, 0) End If End If End If End If DamageList(j).Pos.Y = DamageList(j).Pos.Y - (ElapsedTime * 0.001) End If Next j 'Seperate loop to remove the unused - I dont like removing while drawing For j = 1 To LastDamage If DamageList(j).Width Then If DamageList(j).Counter <= 0 Then Engine_Damage_Erase j End If Next j '************** Misc Rendering ************** 'Update and render particle effects Effect_UpdateAll 'Clear the shift-related variables LastOffsetX = ParticleOffsetX LastOffsetY = ParticleOffsetY 'Render the GUI Engine_Render_GUI '************** Mini-map ************** Const tS As Single = 3 'Size of the mini-map dots 'Check if the mini-map is being shownquit If ShowMiniMap Then 'Make sure the mini-map vertex buffer is valid If MiniMapVBSize > 0 Then 'Clear the texture LastTexture = 0 D3DDevice.SetTexture 0, Nothing 'Draw the map outline D3DDevice.SetStreamSource 0, MiniMapVB, FVF_Size D3DDevice.DrawPrimitive D3DPT_TRIANGLELIST, 0, MiniMapVBSize \ 3 'Draw the characters For X = 1 To LastChar If CharList(X).Active Then 'The user's character If X = UserCharIndex Then j = D3DColorARGB(200, 0, 255, 0) 'User's character Engine_Render_Rectangle CharList(X).Pos.X * tS, CharList(X).Pos.Y * tS, tS, tS, 1, 1, 1, 1, 1, 1, 0, 0, j, j, j, j, , False GoTo NextChar End If 'Part of the user's group or one of the user's slaves If CharList(X).CharType = ClientCharType_Grouped Or (CharList(X).CharType = ClientCharType_Slave And UserCharIndex = CharList(X).OwnerChar) Then If X <> UserCharIndex Then j = D3DColorARGB(200, 100, 220, 100) 'PC (grouped) or the user's slave Engine_Render_Rectangle CharList(X).Pos.X * tS, CharList(X).Pos.Y * tS, tS, tS, 1, 1, 1, 1, 1, 1, 0, 0, j, j, j, j, , False GoTo NextChar End If End If 'Check if the character is in screen, since the only characters drawn outside of the screen are grouped characters If CharList(X).Pos.X > ScreenMinX Then If CharList(X).Pos.X < ScreenMaxX Then If CharList(X).Pos.Y > ScreenMinY Then If CharList(X).Pos.Y < ScreenMaxY Then 'Character is a PC If CharList(X).CharType = ClientCharType_PC Then j = D3DColorARGB(200, 0, 255, 255) 'PC (not grouped) 'Character is a NPC Else j = D3DColorARGB(200, 0, 150, 150) 'NPC End If 'Any character but one part of the user's group Engine_Render_Rectangle CharList(X).Pos.X * tS, CharList(X).Pos.Y * tS, tS, tS, 1, 1, 1, 1, 1, 1, 0, 0, j, j, j, j, , False End If End If End If End If End If NextChar: Next X End If End If 'Show FPS Engine_Render_Text Font_Default, "FPS: " & FPS, ScreenWidth - 80, 2, -1 'Check if using motion blur / zooming If UseMotionBlur Then If FrameUseMotionBlur Then With D3DDevice 'Perform the zooming calculations ' * 1.333... maintains the aspect ratio ' ... / 1024 is to factor in the buffer size BlurTA(0).tU = ZoomLevel * 1.333333333 BlurTA(0).tV = ZoomLevel BlurTA(1).tU = ((ScreenWidth + 1) / 1024) - (ZoomLevel * 1.333333333) BlurTA(1).tV = ZoomLevel BlurTA(2).tU = ZoomLevel * 1.333333333 BlurTA(2).tV = ((ScreenHeight + 1) / 1024) - ZoomLevel BlurTA(3).tU = BlurTA(1).tU BlurTA(3).tV = BlurTA(2).tV 'Draw what we have drawn thus far since the last .Clear LastTexture = -100 .SetRenderTarget DeviceBuffer, DeviceStencil, 0 .SetTexture 0, BlurTexture .SetRenderState D3DRS_TEXTUREFACTOR, D3DColorARGB(BlurIntensity, 255, 255, 255) .SetTextureStageState 0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR .DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, BlurTA(0), FVF_Size .SetTextureStageState 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE End With End If End If End Sub Public Sub Engine_BuildMiniMap() '************************************************************ 'Builds the array for the minimap. Theres multiple styles available, but only one 'is used in the demo, so experiment with them and check which one you like! 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_BuildMiniMap '************************************************************ Dim NumMiniMapTiles As Long 'UBound of the MiniMapTile array Dim MiniMapTile() As MiniMapTile 'Color of each tile and their position Dim MMC_Blocked As Long Dim MMC_Exit As Long Dim MMC_Sign As Long Dim Offset As Long Dim tVA() As TLVERTEX Dim X As Long Dim Y As Long Dim j As Long 'Change to the type of map you want Const UseOption As Byte = 2 'The size of the tiles 'If you change this value, you must also change the "tS" constant in Engine_Render_Screen to the same value! Const MiniMapSize As Single = 3 'Create the colors (character colors are defined in Engine_RenderScreen when it is rendered) MMC_Blocked = D3DColorARGB(75, 255, 255, 255) 'Blocked tiles MMC_Exit = D3DColorARGB(150, 255, 0, 0) 'Exit tiles (warps) MMC_Sign = D3DColorARGB(125, 255, 255, 0) 'Tiles with a sign 'Clear the old array by resizing to the largest array we can possibly use ReDim MiniMapTile(1 To CLng(MapInfo.Width) * CLng(MapInfo.Height)) As MiniMapTile NumMiniMapTiles = 0 Select Case UseOption '***** Option 1 ***** Case 1 For Y = 1 To MapInfo.Height For X = 1 To MapInfo.Width 'Check for signs If MapData(X, Y).Sign > 1 Then NumMiniMapTiles = NumMiniMapTiles + 1 MiniMapTile(NumMiniMapTiles).X = X MiniMapTile(NumMiniMapTiles).Y = Y MiniMapTile(NumMiniMapTiles).Color = MMC_Sign Else 'Check for exits If MapData(X, Y).Warp = 1 Then NumMiniMapTiles = NumMiniMapTiles + 1 MiniMapTile(NumMiniMapTiles).X = X MiniMapTile(NumMiniMapTiles).Y = Y MiniMapTile(NumMiniMapTiles).Color = MMC_Exit Else 'Check for blocked tiles If MapData(X, Y).Blocked = 0 Then NumMiniMapTiles = NumMiniMapTiles + 1 MiniMapTile(NumMiniMapTiles).X = X MiniMapTile(NumMiniMapTiles).Y = Y MiniMapTile(NumMiniMapTiles).Color = MMC_Blocked End If End If End If Next X Next Y '***** Option 2 ***** Case 2 For Y = 1 To MapInfo.Height j = 0 'Clear the row settings For X = 1 To MapInfo.Width 'Check if there is a sign If MapData(X, Y).Sign > 1 Then NumMiniMapTiles = NumMiniMapTiles + 1 MiniMapTile(NumMiniMapTiles).X = X MiniMapTile(NumMiniMapTiles).Y = Y MiniMapTile(NumMiniMapTiles).Color = MMC_Sign Else 'Check if there is an exit If MapData(X, Y).Warp = 1 Then NumMiniMapTiles = NumMiniMapTiles + 1 MiniMapTile(NumMiniMapTiles).X = X MiniMapTile(NumMiniMapTiles).Y = Y MiniMapTile(NumMiniMapTiles).Color = MMC_Exit Else 'Only check blocked tiles If MapData(X, Y).Blocked > 0 Then 'If the row is set to draw, just keep drawing If j = 1 Then NumMiniMapTiles = NumMiniMapTiles + 1 MiniMapTile(NumMiniMapTiles).X = X MiniMapTile(NumMiniMapTiles).Y = Y MiniMapTile(NumMiniMapTiles).Color = MMC_Blocked 'The row isn't drawing, check if it is time to draw it Else 'If the next tile is not blocked, this one will be (to draw an outline) If j = 0 Then If X + 1 <= MapInfo.Width Then If MapData(X + 1, Y).Blocked = 0 Then NumMiniMapTiles = NumMiniMapTiles + 1 MiniMapTile(NumMiniMapTiles).X = X MiniMapTile(NumMiniMapTiles).Y = Y MiniMapTile(NumMiniMapTiles).Color = MMC_Blocked j = 1 End If End If End If 'If the tile above or below is blocked, draw the tile If j = 0 Then If Y > 1 Then If MapData(X, Y - 1).Blocked = 0 Then NumMiniMapTiles = NumMiniMapTiles + 1 MiniMapTile(NumMiniMapTiles).X = X MiniMapTile(NumMiniMapTiles).Y = Y MiniMapTile(NumMiniMapTiles).Color = MMC_Blocked j = 1 End If End If End If If j = 0 Then If Y < MapInfo.Height Then If MapData(X, Y + 1).Blocked = 0 Then NumMiniMapTiles = NumMiniMapTiles + 1 MiniMapTile(NumMiniMapTiles).X = X MiniMapTile(NumMiniMapTiles).Y = Y MiniMapTile(NumMiniMapTiles).Color = MMC_Blocked j = 1 End If End If End If 'If we STILL haven't drawn the tile, check to the diagonals (this makes corners smoothed) If j = 0 Then If Y > 1 Then If Y < MapInfo.Height Then If X > 1 Then If X < MapInfo.Width Then If MapData(X - 1, Y - 1).Blocked = 0 Or MapData(X - 1, Y + 1).Blocked = 0 Or MapData(X + 1, Y - 1).Blocked = 0 Or MapData(X + 1, Y + 1).Blocked = 0 Then NumMiniMapTiles = NumMiniMapTiles + 1 MiniMapTile(NumMiniMapTiles).X = X MiniMapTile(NumMiniMapTiles).Y = Y MiniMapTile(NumMiniMapTiles).Color = MMC_Blocked j = 1 End If End If End If End If End If End If End If 'If the next tile isn't blocked, we remove the row drawing If j = 1 Then If X < MapInfo.Width Then If MapData(X + 1, Y).Blocked > 0 Then j = 0 End If End If End If End If End If Next X Next Y End Select 'Resize the array to fit the amount of data we have If NumMiniMapTiles = 0 Then Erase MiniMapTile Exit Sub Else ReDim Preserve MiniMapTile(1 To NumMiniMapTiles) End If '***** Build the vertex buffer according to the information we gathered in the MiniMapTile array ***** 'Create the temp vertex array large enough to fit every tile (2 triangles per tile, 3 points per triangle) ReDim tVA(0 To (NumMiniMapTiles * 6) - 1) As TLVERTEX 'Start our offset at -6 so the first offset is 0 Offset = -6 'Fill the temp vertex array For j = 1 To NumMiniMapTiles 'Raise the offset count Offset = Offset + 6 '*** Triangle 1 *** 'Top-left corner With tVA(0 + Offset) .X = MiniMapTile(j).X * MiniMapSize .Y = MiniMapTile(j).Y * MiniMapSize .Color = MiniMapTile(j).Color .Rhw = 1 End With 'Top-right corner With tVA(1 + Offset) .X = MiniMapTile(j).X * MiniMapSize + MiniMapSize .Y = MiniMapTile(j).Y * MiniMapSize .Color = MiniMapTile(j).Color .Rhw = 1 End With 'Bottom-left corner With tVA(2 + Offset) .X = MiniMapTile(j).X * MiniMapSize .Y = MiniMapTile(j).Y * MiniMapSize + MiniMapSize .Color = MiniMapTile(j).Color .Rhw = 1 End With '*** Triangle 2 *** 'Top-right corner tVA(3 + Offset) = tVA(1 + Offset) 'Bottom-right corner With tVA(4 + Offset) .X = MiniMapTile(j).X * MiniMapSize + MiniMapSize .Y = MiniMapTile(j).Y * MiniMapSize + MiniMapSize .Color = MiniMapTile(j).Color .Rhw = 1 End With 'Bottom-left corner tVA(5 + Offset) = tVA(2 + Offset) Next j 'Build the vertex buffer MiniMapVBSize = Offset + 6 Set MiniMapVB = D3DDevice.CreateVertexBuffer(FVF_Size * MiniMapVBSize, 0, FVF, D3DPOOL_MANAGED) D3DVertexBuffer8SetData MiniMapVB, 0, FVF_Size * MiniMapVBSize, 0, tVA(0) 'Clear the temp arrays Erase tVA Erase MiniMapTile End Sub Private Function Engine_NPCChat_MeetsConditions(ByVal NPCIndex As Integer, ByVal LineIndex As Byte, Optional ByVal SayLine As String = vbNullString) As Byte '***************************************************************** 'Checks if the conditions have been satisfied for a chat line 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_NPCChat_MeetsConditions '***************************************************************** Dim s() As String Dim j As Byte Dim i As Byte 'Make sure we have a valid line and index If LineIndex = 0 Then Exit Function If CharList(NPCIndex).NPCChatIndex = 0 Then Exit Function If CharList(NPCIndex).NPCChatIndex > UBound(NPCChat()) Then Exit Function If LineIndex > UBound(NPCChat(CharList(NPCIndex).NPCChatIndex).ChatLine()) Then Exit Function 'Woo baby, we're not going to want to type THIS line more then once! With NPCChat(CharList(NPCIndex).NPCChatIndex).ChatLine(LineIndex) 'If the SayLine is used, it must be the user just talked - so we ONLY want a trigger line! If LenB(SayLine) <> 0 Then 'If the string is not empty SayLine = " " & UCase$(SayLine) & " " 'We compair it in UCase$(), since case doesn't matter If .NumConditions = 0 Then Exit Function 'If there are no conditions, then theres definintely no SAY condition For i = 1 To .NumConditions If .Conditions(i).Condition = NPCCHAT_COND_SAY Then Exit For 'Good, we have a SAY condition! We can continue... If i = .NumConditions Then Exit Function 'Last condition checked, and it wasn't a SAY, so no SAYs found - goodbye :( Next i End If 'Loop through all the conditions For i = 1 To .NumConditions 'Check what condition it is - keep in mind we exit on a "False" situation, so are checks ' are written to check if the condition is false, not true (a little more confusing, but effecient) Select Case .Conditions(i).Condition 'If there is a SAY requirement, things get tricky... Case NPCCHAT_COND_SAY If LenB(SayLine) = 0 Then Exit Function 'No chance it can be right if theres no text! s() = Split(.Conditions(i).ValueStr, ",") 'Split up our commas (which allow us to have multiple valid words) For j = 0 To UBound(s) 'Loop through each word so we can check if it is in the SayLine If InStr(1, SayLine, s(j)) Then 'Check if the trigger word is in the SayLine Exit For 'Match made! We're good to go - get the hell outta here! End If If j = UBound(s) Then Exit Function 'Oh bummer, the last trigger word was checked and was a no-go, we loose! Next j 'User doesn't know skill X Case NPCCHAT_COND_DONTKNOWSKILL If Not (UserKnowSkill(.Conditions(i).Value) = 0) Then Exit Function 'User knows skill X Case NPCCHAT_COND_KNOWSKILL If Not (UserKnowSkill(.Conditions(i).Value) = 1) Then Exit Function 'NPC's HP is less then or equal to X percent Case NPCCHAT_COND_HPLESSTHAN If Not (CharList(UserCharIndex).HealthPercent <= .Conditions(i).Value) Then Exit Function 'NPC's HP is greater then or equal to X percent Case NPCCHAT_COND_HPMORETHAN If Not (CharList(UserCharIndex).HealthPercent >= .Conditions(i).Value) Then Exit Function 'User's level is less than or equal to X Case NPCCHAT_COND_LEVELLESSTHAN If Not (BaseStats(SID.ELV) <= .Conditions(i).Value) Then Exit Function 'User level is greater than or equal to X Case NPCCHAT_COND_LEVELMORETHAN If Not (BaseStats(SID.ELV) >= .Conditions(i).Value) Then Exit Function End Select Next i End With 'We made it, horray! Engine_NPCChat_MeetsConditions = 1 End Function Public Sub Engine_NPCChat_CheckForChatTriggers(ByVal ChatTxt As String) '***************************************************************** 'Checks for a NPC chat triggers 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_NPCChat_CheckForChatTriggers '***************************************************************** Dim i As Integer Dim j As Byte For i = 1 To LastChar 'We're going to be using this object a hell of a lot... With CharList(i) 'We only want an active char If .Active Then 'Make sure the NPC has automated chat If .NPCChatIndex > 0 Then 'Check for a valid distance If Engine_RectDistance(.RealPos.X, .RealPos.Y, .RealPos.X - ((ScreenWidth - 50) \ 2), .RealPos.Y - ((ScreenHeight - 50) \ 2), ((ScreenWidth - 50) \ 2) + 1, ((ScreenHeight - 50) \ 2) + 1) Then 'Get the next line to use j = Engine_NPCChat_NextLine(i, ChatTxt) 'If j = 0, then no valid lines were found If j > 0 Then 'Assign the new line .NPCChatLine = j 'Say the chat (delay assigned through the routine) Engine_NPCChat_AddText i End If End If End If End If End With Next i End Sub Private Sub Engine_NPCChat_Update(ByVal CharIndex As Integer) '***************************************************************** 'Updates the automated NPC chatting 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_NPCChat_Update '***************************************************************** Dim i As Byte 'We're going to be using this object a hell of a lot... With CharList(CharIndex) 'Make sure the NPC has automated chat If .NPCChatIndex > 0 Then 'Check for a valid distance If Engine_RectDistance(.RealPos.X, .RealPos.Y, .RealPos.X - ((ScreenWidth - 50) \ 2), .RealPos.Y - ((ScreenHeight - 50) \ 2), ((ScreenWidth - 50) \ 2) + 1, ((ScreenHeight - 50) \ 2) + 1) Then 'Update the delay time If .NPCChatDelay > 0 Then .NPCChatDelay = .NPCChatDelay - ElapsedTime 'Time to get a new line! Else 'Get the new NPCChat line i = Engine_NPCChat_NextLine(CharIndex) If i = 0 Then Exit Sub .NPCChatLine = i 'Add the chat Engine_NPCChat_AddText CharIndex End If End If End If End With End Sub Private Sub Engine_NPCChat_AddText(ByVal CharIndex As Integer) '***************************************************************** 'Adds the NPCChat text according to the style 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_NPCChat_AddText '***************************************************************** With CharList(CharIndex) 'Check for text before adding it If LenB(NPCChat(.NPCChatIndex).ChatLine(.NPCChatLine).Text) <> 0 Then 'Find out the style used, and add the chat according to the style Select Case NPCChat(.NPCChatIndex).ChatLine(.NPCChatLine).Style Case NPCCHAT_STYLE_BUBBLE Engine_MakeChatBubble CharIndex, Engine_WordWrap(.Name & ": " & NPCChat(.NPCChatIndex).ChatLine(.NPCChatLine).Text, BubbleMaxWidth) Case NPCCHAT_STYLE_BOX Engine_AddToChatTextBuffer .Name & ": " & NPCChat(.NPCChatIndex).ChatLine(.NPCChatLine).Text, FontColor_Talk Case NPCCHAT_STYLE_BOTH Engine_MakeChatBubble CharIndex, Engine_WordWrap(.Name & ": " & NPCChat(.NPCChatIndex).ChatLine(.NPCChatLine).Text, BubbleMaxWidth) Engine_AddToChatTextBuffer .Name & ": " & NPCChat(.NPCChatIndex).ChatLine(.NPCChatLine).Text, FontColor_Talk End Select End If 'Add the chat delay (we do the delay even if theres no text) .NPCChatDelay = NPCChat(.NPCChatIndex).ChatLine(.NPCChatLine).Delay End With End Sub Private Function Engine_NPCChat_NextLine(ByVal CharIndex As Integer, Optional ByVal ChatTxt As String) As Byte '***************************************************************** 'Gets the next free line to use for the NPC chat (0 if none found) 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_NPCChat_NextLine '***************************************************************** Dim b() As Byte Dim k As Byte Dim j As Byte Dim i As Byte With CharList(CharIndex) 'Select the new line to start from according to the format Select Case NPCChat(.NPCChatIndex).Format 'Linear selection Case NPCCHAT_FORMAT_LINEAR 'Start with the next line i = .NPCChatLine + 1 If i > NPCChat(.NPCChatIndex).NumLines Then i = 1 'Loop through all the lines, checking for the next line with a valid condition For j = 1 To NPCChat(.NPCChatIndex).NumLines 'Get the new line number to check - roll over to the start if needed k = i + j If k > NPCChat(.NPCChatIndex).NumLines Then k = k - NPCChat(.NPCChatIndex).NumLines 'Check if the conditions were met If Engine_NPCChat_MeetsConditions(CharIndex, k, ChatTxt) = 1 Then Exit For 'If j is on the last index, then no conditions were met - put on a delay and leave If j = NPCChat(.NPCChatIndex).NumLines Then .NPCChatDelay = 1500 'This delay lets a load off the client Exit Function End If Next j 'Random selection Case NPCCHAT_FORMAT_RANDOM 'Scramble the numbers so we can pick randomly ReDim b(1 To NPCChat(.NPCChatIndex).NumLines) 'Room for all the lines For i = 1 To NPCChat(.NPCChatIndex).NumLines 'Loop through every line Do 'Keep looping until we get what we want j = Int(Rnd * NPCChat(.NPCChatIndex).NumLines) + 1 'We have to hold the value in a temp variable If b(j) = 0 Then 'If = 0, the index is free b(j) = i 'Store the index in the random array slot Exit Do 'Leave the DO loop since we have what we want End If Loop Next i 'Now b() holds all the line numbers scrambled up, so we can go through one by one just like with linear For j = 1 To NPCChat(.NPCChatIndex).NumLines - 1 '-1 because we are took out the index we already used 'Make sure the number is valid (just in case) If b(j) <> 0 Then 'Don't check the line we just used (yet) If .NPCChatLine <> b(j) Then 'Check the conditions If Engine_NPCChat_MeetsConditions(CharIndex, b(j), ChatTxt) = 1 Then k = b(j) 'Store the successful value in the k variable for below Exit For End If End If End If 'If j is on the last index, and no conditions were met, we try the line we last used If j = NPCChat(.NPCChatIndex).NumLines - 1 Then 'If the For loop is just about to end If b(j) > 0 Then 'If this is the NPC's first line, it'd be 0, so check to make sure its not 0 just in case If Engine_NPCChat_MeetsConditions(CharIndex, .NPCChatLine, ChatTxt) = 1 Then k = b(j) 'Store the successful value in the k variable for below Exit For 'We got the text! Else Exit Function 'None of the lines worked :( End If End If End If Next j End Select 'Return the value Engine_NPCChat_NextLine = k End With End Function Public Function Engine_ClearPath(ByVal UserX As Long, ByVal UserY As Long, ByVal TargetX As Long, ByVal TargetY As Long) As Byte '***************************************************************** 'Check if the path is clear from the user to the target of blocked tiles 'For the line-rect collision, we pretend that each tile is 2 units wide 'so we can give them a width of 1 to center things 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_ClearPath '***************************************************************** Dim X As Long Dim Y As Long '**************************************** '***** Target is on top of the user ***** '**************************************** 'If the target position = user position, we must be targeting ourself, so nothing can be blocking us from us (I hope o.O ) If UserX = TargetX Then If UserY = TargetY Then Engine_ClearPath = 1 Exit Function End If End If '******************************************** '***** Target is right next to the user ***** '******************************************** 'Target is at one of the 4 diagonals of the user If Abs(UserX - TargetX) = 1 Then If Abs(UserY - TargetY) = 1 Then Engine_ClearPath = 1 Exit Function End If End If 'Target is above or below the user If UserX = TargetX Then If Abs(UserY - TargetY) = 1 Then Engine_ClearPath = 1 Exit Function End If End If 'Target is to the left or right of the user If UserY = TargetY Then If Abs(UserX - TargetX) = 1 Then Engine_ClearPath = 1 Exit Function End If End If '******************************************** '***** Target is diagonal from the user ***** '******************************************** 'Check if the target is diagonal from the user - only do the following checks if diagonal from the target If Abs(UserX - TargetX) = Abs(UserY - TargetY) Then If UserX > TargetX Then 'Diagonal to the top-left If UserY > TargetY Then For X = TargetX To UserX - 1 For Y = TargetY To UserY - 1 If MapData(X, Y).BlockedAttack Then Engine_ClearPath = 0 Exit Function End If Next Y Next X 'Diagonal to the bottom-left Else For X = TargetX To UserX - 1 For Y = UserY + 1 To TargetY If MapData(X, Y).BlockedAttack Then Engine_ClearPath = 0 Exit Function End If Next Y Next X End If End If If UserX < TargetX Then 'Diagonal to the top-right If UserY > TargetY Then For X = UserX + 1 To TargetX For Y = TargetY To UserY - 1 If MapData(X, Y).BlockedAttack Then Engine_ClearPath = 0 Exit Function End If Next Y Next X 'Diagonal to the bottom-right Else For X = UserX + 1 To TargetX For Y = UserY + 1 To TargetY If MapData(X, Y).BlockedAttack Then Engine_ClearPath = 0 Exit Function End If Next Y Next X End If End If Engine_ClearPath = 1 Exit Function End If '******************************************************************* '***** Target is directly vertical or horizontal from the user ***** '******************************************************************* 'Check if target is directly above the user If UserX = TargetX Then 'Check if x values are the same (straight line between the two) If UserY > TargetY Then For Y = TargetY + 1 To UserY - 1 If MapData(UserX, Y).BlockedAttack Then Engine_ClearPath = 0 Exit Function End If Next Y Engine_ClearPath = 1 Exit Function End If End If 'Check if the target is directly below the user If UserX = TargetX Then If UserY < TargetY Then For Y = UserY + 1 To TargetY - 1 If MapData(UserX, Y).BlockedAttack Then Engine_ClearPath = 0 Exit Function End If Next Y Engine_ClearPath = 1 Exit Function End If End If 'Check if the target is directly to the left of the user If UserY = TargetY Then If UserX > TargetX Then For X = TargetX + 1 To UserX - 1 If MapData(X, UserY).BlockedAttack Then Engine_ClearPath = 0 Exit Function End If Next X Engine_ClearPath = 1 Exit Function End If End If 'Check if the target is directly to the right of the user If UserY = TargetY Then If UserX < TargetX Then For X = UserX + 1 To TargetX - 1 If MapData(X, UserY).BlockedAttack Then Engine_ClearPath = 0 Exit Function End If Next X Engine_ClearPath = 1 Exit Function End If End If '*************************************************** '***** Target is directly not in a direct path ***** '*************************************************** If UserY > TargetY Then 'Check if the target is to the top-left of the user If UserX > TargetX Then For X = TargetX To UserX For Y = TargetY To UserY 'We must do * 2 on the tiles so we can use +1 to get the center (its like * 32 and + 16 - this does the same affect) If Engine_Collision_LineRect(X * 2, Y * 2, 2, 2, UserX * 2 + 1, UserY * 2 + 1, TargetX * 2 + 1, TargetY * 2 + 1) Then If MapData(X, Y).BlockedAttack Then Engine_ClearPath = 0 Exit Function End If End If Next Y Next X Engine_ClearPath = 1 Exit Function 'Check if the target is to the top-right of the user Else For X = UserX To TargetX For Y = TargetY To UserY If Engine_Collision_LineRect(X * 2, Y * 2, 2, 2, UserX * 2 + 1, UserY * 2 + 1, TargetX * 2 + 1, TargetY * 2 + 1) Then If MapData(X, Y).BlockedAttack Then Engine_ClearPath = 0 Exit Function End If End If Next Y Next X End If Else 'Check if the target is to the bottom-left of the user If UserX > TargetX Then For X = TargetX To UserX For Y = UserY To TargetY If Engine_Collision_LineRect(X * 2, Y * 2, 2, 2, UserX * 2 + 1, UserY * 2 + 1, TargetX * 2 + 1, TargetY * 2 + 1) Then If MapData(X, Y).BlockedAttack Then Engine_ClearPath = 0 Exit Function End If End If Next Y Next X 'Check if the target is to the bottom-right of the user Else For X = UserX To TargetX For Y = UserY To TargetY If Engine_Collision_LineRect(X * 2, Y * 2, 2, 2, UserX * 2 + 1, UserY * 2 + 1, TargetX * 2 + 1, TargetY * 2 + 1) Then If MapData(X, Y).BlockedAttack Then Engine_ClearPath = 0 Exit Function End If End If Next Y Next X End If End If Engine_ClearPath = 1 End Function Public Sub Engine_Render_Skills() '***************************************************************** 'Render the spells list 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Render_Skills '***************************************************************** Dim TempGrh As Grh Dim i As Byte TempGrh.FrameCounter = 1 'Loop through the skills For i = 1 To SkillListSize If SkillList(i).SkillID = 0 Then Exit For 'Render the icon TempGrh.GrhIndex = 106 Engine_Render_Grh TempGrh, SkillList(i).X, SkillList(i).Y, 0, 0, False, GUIColorValue, GUIColorValue, GUIColorValue, GUIColorValue TempGrh.GrhIndex = Engine_SkillIDtoGRHID(SkillList(i).SkillID) Engine_Render_Grh TempGrh, SkillList(i).X, SkillList(i).Y, 0, 0, False Next i End Sub Public Sub Engine_Render_Text(ByRef UseFont As CustomFont, ByVal Text As String, ByVal X As Long, ByVal Y As Long, ByVal Color As Long) '***************************************************************** 'Render text with a custom font 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Render_Text '***************************************************************** Dim TempVA(0 To 3) As TLVERTEX Dim TempStr() As String Dim Count As Integer Dim Ascii() As Byte Dim Row As Integer Dim u As Single Dim v As Single Dim i As Long Dim j As Long Dim KeyPhrase As Byte Dim TempColor As Long Dim ResetColor As Byte Dim SrcRect As RECT Dim v2 As D3DVECTOR2 Dim v3 As D3DVECTOR2 Dim YOffset As Single 'Check if we have the device If D3DDevice.TestCooperativeLevel <> D3D_OK Then Exit Sub 'Check for valid text to render If LenB(Text) = 0 Then Exit Sub 'Assign the alternate rendering value AlternateRender = AlternateRenderText 'Get the text into arrays (split by vbCrLf) TempStr = Split(Text, vbCrLf) 'Set the temp color (or else the first character has no color) TempColor = Color 'Check for alternate rendering If AlternateRender Then 'End the old sprite we had going If SpriteBegun = 1 Then Sprite.End Sprite.Begin End If Else 'Set the texture D3DDevice.SetTexture 0, UseFont.Texture End If 'Clear the LastTexture, letting the rest of the engine know that the texture needs to be changed for next rect render LastTexture = -(Rnd * 10000) 'Loop through each line if there are line breaks (vbCrLf) For i = 0 To UBound(TempStr) If Len(TempStr(i)) > 0 Then YOffset = i * UseFont.CharHeight Count = 0 'Convert the characters to the ascii value Ascii() = StrConv(TempStr(i), vbFromUnicode) 'Loop through the characters For j = 1 To Len(TempStr(i)) 'Check for a key phrase If Ascii(j - 1) = 124 Then 'If Ascii = "|" KeyPhrase = (Not KeyPhrase) 'TempColor = ARGB 255/255/0/0 If KeyPhrase Then TempColor = -65536 Else ResetColor = 1 Else 'Render with triangles If AlternateRender = 0 Then 'Copy from the cached vertex array to the temp vertex array CopyMemory TempVA(0), UseFont.HeaderInfo.CharVA(Ascii(j - 1)).Vertex(0), FVF_Size * 4 'Set up the verticies TempVA(0).X = X + Count TempVA(0).Y = Y + YOffset TempVA(1).X = TempVA(1).X + X + Count TempVA(1).Y = TempVA(0).Y TempVA(2).X = TempVA(0).X TempVA(2).Y = TempVA(2).Y + TempVA(0).Y TempVA(3).X = TempVA(1).X TempVA(3).Y = TempVA(2).Y 'Set the colors TempVA(0).Color = TempColor TempVA(1).Color = TempColor TempVA(2).Color = TempColor TempVA(3).Color = TempColor 'Draw the verticies D3DDevice.DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, TempVA(0), FVF_Size 'Render with D3DXSprite Else 'tU and tV value (basically tU = BitmapXPosition / BitmapWidth, and height for tV) Row = (Ascii(j - 1) - UseFont.HeaderInfo.BaseCharOffset) \ UseFont.RowPitch u = ((Ascii(j - 1) - UseFont.HeaderInfo.BaseCharOffset) - (Row * UseFont.RowPitch)) * UseFont.ColFactor v = Row * UseFont.RowFactor 'Create the source rectangle With SrcRect .Left = u * UseFont.TextureSize.X .Top = v * UseFont.TextureSize.Y .Right = .Left + (UseFont.ColFactor * UseFont.TextureSize.X) .bottom = .Top + (UseFont.RowFactor * UseFont.TextureSize.Y) End With 'Set the translation (location on the screen) v3.X = X + Count v3.Y = Y + (UseFont.CharHeight * i) 'Draw the sprite Sprite.Draw UseFont.Texture, SrcRect, SpriteScaleVector, v2, 0, v3, Color End If 'Shift over the the position to render the next character Count = Count + UseFont.HeaderInfo.CharWidth(Ascii(j - 1)) End If 'Check to reset the color If ResetColor Then ResetColor = 0 TempColor = Color End If Next j End If Next i 'Retreive the default alternate render value AlternateRender = AlternateRenderDefault End Sub Public Sub Engine_SetItemDesc(ByVal Name As String, Optional ByVal Amount As Integer = 0, Optional ByVal Value As Long = 0) '***************************************************************** 'Set item description values 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_SetItemDesc '***************************************************************** Dim i As Byte Dim X As Long 'Set the item values ItemDescLine(1) = Name ItemDescLines = 1 If Amount <> 0 Then ItemDescLines = ItemDescLines + 1 ItemDescLine(ItemDescLines) = "Amount: " & Amount End If If Value <> 0 Then ItemDescLines = ItemDescLines + 1 ItemDescLine(ItemDescLines) = "Value: " & Value End If 'Get the largest size ItemDescWidth = Engine_GetTextWidth(Font_Default, ItemDescLine(1)) If ItemDescLines > 1 Then For i = 2 To ItemDescLines X = Engine_GetTextWidth(Font_Default, ItemDescLine(i)) If X > ItemDescWidth Then ItemDescWidth = X Next i End If End Sub Sub Engine_ShowNextFrame() '***************************************************************** 'Updates and draws next frame to screen 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_ShowNextFrame '***************************************************************** '***** Check if engine is allowed to run ****** If EngineRun Then If UserMoving Then '****** Move screen Left and Right if needed ****** If AddtoUserPos.X <> 0 Then OffsetCounterX = OffsetCounterX - (ScrollPixelsPerFrameX + CharList(UserCharIndex).Speed + (RunningSpeed * CharList(UserCharIndex).Running)) * AddtoUserPos.X * TickPerFrame If Abs(OffsetCounterX) >= Abs(TilePixelWidth * AddtoUserPos.X) Then OffsetCounterX = 0 AddtoUserPos.X = 0 UserMoving = False End If End If '****** Move screen Up and Down if needed ****** If AddtoUserPos.Y <> 0 Then OffsetCounterY = OffsetCounterY - (ScrollPixelsPerFrameY + CharList(UserCharIndex).Speed + (RunningSpeed * CharList(UserCharIndex).Running)) * AddtoUserPos.Y * TickPerFrame If Abs(OffsetCounterY) >= Abs(TilePixelHeight * AddtoUserPos.Y) Then OffsetCounterY = 0 AddtoUserPos.Y = 0 UserMoving = False End If End If End If '****** Update screen ****** Call Engine_Render_Screen(UserPos.X - AddtoUserPos.X, UserPos.Y - AddtoUserPos.Y, OffsetCounterX - 288, OffsetCounterY - 288) 'Get timing info ElapsedTime = Engine_ElapsedTime() If ElapsedTime > 200 Then ElapsedTime = 200 TickPerFrame = (ElapsedTime * EngineBaseSpeed) If FPSLastCheck + 1000 < timeGetTime Then FPS = FramesPerSecCounter FramesPerSecCounter = 1 FPSLastCheck = timeGetTime Else FramesPerSecCounter = FramesPerSecCounter + 1 End If 'Auto-save config every 30 seconds If SaveLastCheck + 30000 < timeGetTime Then SaveLastCheck = timeGetTime Game_Config_Save End If End If End Sub Public Function Engine_SkillIDtoGRHID(ByVal SkillID As Byte) As Integer '***************************************************************** 'Takes in a SkillID and returns the GrhIndex used for that SkillID 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_SkillIDtoGRHID '***************************************************************** Select Case SkillID Case SkID.Bless: Engine_SkillIDtoGRHID = 46 Case SkID.IronSkin: Engine_SkillIDtoGRHID = 47 Case SkID.Strengthen: Engine_SkillIDtoGRHID = 48 Case SkID.Warcry: Engine_SkillIDtoGRHID = 49 Case SkID.Protection: Engine_SkillIDtoGRHID = 50 Case SkID.SpikeField: Engine_SkillIDtoGRHID = 62 Case SkID.Heal: Engine_SkillIDtoGRHID = 63 Case SkID.SummonBandit: Engine_SkillIDtoGRHID = 1 End Select End Function Public Function Engine_SkillIDtoSkillName(ByVal SkillID As Byte) As String '***************************************************************** 'Takes in a SkillID and returns the name of that skill 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_SkillIDtoSkillName '***************************************************************** Select Case SkillID Case SkID.Bless: Engine_SkillIDtoSkillName = "Bless" Case SkID.IronSkin: Engine_SkillIDtoSkillName = "Iron Skin" Case SkID.Strengthen: Engine_SkillIDtoSkillName = "Strengthen" Case SkID.Warcry: Engine_SkillIDtoSkillName = "War Cry" Case SkID.Protection: Engine_SkillIDtoSkillName = "Protection" Case SkID.SpikeField: Engine_SkillIDtoSkillName = "Spike Field" Case SkID.Heal: Engine_SkillIDtoSkillName = "Heal" Case SkID.SummonBandit: Engine_SkillIDtoSkillName = "Summon Bandit" Case Else: Engine_SkillIDtoSkillName = "Unknown Skill" End Select End Function Public Sub Engine_SortIntArray(TheArray() As Integer, TheIndex() As Integer, ByVal LowerBound As Integer, ByVal UpperBound As Integer) '***************************************************************** 'Sort an array of integers 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_SortIntArray '***************************************************************** Dim indxt As Long 'Stored index Dim swp As Integer 'Swap variable Dim i As Integer 'Subarray Low Scan Index Dim j As Integer 'Subarray High Scan Index 'Start the loop For j = LowerBound + 1 To UpperBound indxt = TheIndex(j) swp = TheArray(indxt) For i = j - 1 To LowerBound Step -1 If TheArray(TheIndex(i)) <= swp Then Exit For TheIndex(i + 1) = TheIndex(i) Next i TheIndex(i + 1) = indxt Next j End Sub Sub Engine_UnloadAllForms() '***************************************************************** 'Unloads all forms 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_UnloadAllForms '***************************************************************** Dim frm As Form For Each frm In VB.Forms Unload frm Next End Sub Function Engine_Distance(ByVal x1 As Integer, ByVal Y1 As Integer, ByVal x2 As Integer, ByVal Y2 As Integer) As Single '***************************************************************** 'Finds the distance between two points 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Distance '***************************************************************** Engine_Distance = Sqr(((Y1 - Y2) ^ 2 + (x1 - x2) ^ 2)) End Function Sub Engine_UseQuickBar(ByVal Slot As Byte) '***************************************************************** 'Use the object in the quickbar slot 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_UseQuickBar '***************************************************************** Select Case QuickBarID(Slot).Type 'Use an item Case QuickBarType_Item If QuickBarID(Slot).ID > 0 Then sndBuf.Allocate 2 sndBuf.Put_Byte DataCode.User_Use sndBuf.Put_Byte QuickBarID(Slot).ID End If 'Use a skill Case QuickBarType_Skill If QuickBarID(Slot).ID > 0 Then If LastAttackTime + AttackDelay < timeGetTime Then If CharList(UserCharIndex).CharStatus.Exhausted = 0 Then LastAttackTime = timeGetTime sndBuf.Allocate 5 sndBuf.Put_Byte DataCode.User_CastSkill sndBuf.Put_Byte QuickBarID(Slot).ID sndBuf.Put_Integer TargetCharIndex sndBuf.Put_Byte CharList(UserCharIndex).Heading End If End If End If End Select End Sub Public Function Engine_GetBlinkTime() As Long '***************************************************************** 'Return a value on how long until the next blink happens 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_GetBlinkTime '***************************************************************** Engine_GetBlinkTime = 4000 + Int(Rnd * 5000) End Function Public Function Engine_RectDistance(ByVal x1 As Long, ByVal Y1 As Long, ByVal x2 As Long, ByVal Y2 As Long, ByVal MaxXDist As Long, ByVal MaxYDist As Long) As Byte '***************************************************************** 'Check if two tile points are in the same area 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_RectDistance '***************************************************************** If Abs(x1 - x2) < MaxXDist + 1 Then If Abs(Y1 - Y2) < MaxYDist + 1 Then Engine_RectDistance = True End If End If End Function Public Function Engine_FindDirection(Pos As Position, Target As Position) As Byte '***************************************************************** 'Returns the direction in which the Target is from the Pos, 0 if equal 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_FindDirection '***************************************************************** Dim pX As Integer Dim pY As Integer Dim tX As Integer Dim tY As Integer Dim X As Integer Dim Y As Integer 'Put the bytes into integer variables (causes overflows for negatives, even if the return is an integer) pX = Pos.X pY = Pos.Y tX = Target.X tY = Target.Y 'Find the difference X = pX - tX Y = pY - tY Log "Server_FindDirection: Position difference (X:" & X & " Y:" & Y & ") found", CodeTracker '//\\LOGLINE//\\ 'Same position If X = 0 Then If Y = 0 Then Engine_FindDirection = NORTH Exit Function End If End If 'NE If X <= -1 Then If Y >= 1 Then Engine_FindDirection = NORTHEAST Exit Function End If End If 'NW If X >= 1 Then If Y >= 1 Then Engine_FindDirection = NORTHWEST Exit Function End If End If 'SW If X >= 1 Then If Y <= -1 Then Engine_FindDirection = SOUTHWEST Exit Function End If End If 'SE If X <= -1 Then If Y <= -1 Then Engine_FindDirection = SOUTHEAST Exit Function End If End If 'South If Y <= -1 Then Engine_FindDirection = SOUTH Exit Function End If 'North If Y >= 1 Then Engine_FindDirection = NORTH Exit Function End If 'West If X >= 1 Then Engine_FindDirection = WEST Exit Function End If 'East If X <= -1 Then Engine_FindDirection = EAST Exit Function End If End Function




