Attribute VB_Name = "modOdyssey"
Option Explicit

Declare Function QueryPerformanceCounter Lib "kernel32" (ByRef X As Currency) As Boolean
Declare Function QueryPerformanceFrequency Lib "kernel32" (ByRef X As Currency) As Boolean

Public Const TitleString = "Odyssey Classic - Modus"

Public Const ClientVer = "Modus"

#Const DEBUGWINDOWPROC = 0
#Const USEGETPROP = 0
#Const CHEATS = 0

#If DEBUGWINDOWPROC Then
Private m_SCHook As WindowProcHook
#End If
Public lastPing As Long

Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

Public Declare Function timeBeginPeriod Lib "winmm.dll" (ByVal uPeriod As Long) As Long
Public Declare Function timeEndPeriod Lib "winmm.dll" (ByVal uPeriod As Long) As Long
Public Declare Function timeGetTime Lib "winmm.dll" () As Long

'INI File Related
Declare Function GetPrivateProfileInt Lib "kernel32" Alias "GetPrivateProfileIntA" (ByVal lpApplicationName As String, ByVal lpKeyName As String, ByVal nDefault As Long, ByVal lpFileName As String) As Long
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
Declare Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lpFileName As String) As Long

Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long
Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long
Declare Function MessageBox Lib "user32" Alias "MessageBoxA" (ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal wType As Long) As Long

Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long

Declare Function LoadImage Lib "user32" Alias "LoadImageA" (ByVal hInst As Long, ByVal lpsz As String, ByVal un1 As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal un2 As Long) As Long
Declare Function RealizePalette Lib "gdi32" (ByVal hdc As Long) As Long
Declare Function CreatePalette Lib "gdi32" (lpLogPalette As LogPalette) As Long
Declare Function SelectPalette Lib "gdi32" (ByVal hdc As Long, ByVal hPalette As Long, ByVal bForceBackground As Long) As Long
Declare Function SetPaletteEntries Lib "gdi32" (ByVal hPalette As Long, ByVal wStartIndex As Long, ByVal wNumEntries As Long, lpPaletteEntries As PaletteEntry) As Long
Declare Function StretchBlt Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long
Declare Function SetBkColor Lib "gdi32" (ByVal hdc As Long, ByVal crColor As Long) As Long
Declare Function SetBkMode Lib "gdi32" (ByVal hdc As Long, ByVal nBkMode As Long) As Long
Declare Function SetTextColor Lib "gdi32" (ByVal hdc As Long, ByVal crColor As Long) As Long
Declare Function TextOut Lib "gdi32" Alias "TextOutA" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal lpString As String, ByVal nCount As Long) As Long
Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Declare Function CreateBitmap Lib "gdi32" (ByVal nWidth As Long, ByVal nHeight As Long, ByVal nPlanes As Long, ByVal nBitCount As Long, lpBits As Any) As Long
Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Declare Function GetObject Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Declare Function DrawText Lib "user32" Alias "DrawTextA" (ByVal hdc As Long, ByVal lpStr As String, ByVal nCount As Long, lpRect As RECT, ByVal wFormat As Long) As Long

'Lighting Effect Related
Public Declare Function SetPixel Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal crColor As Long) As Long
Public 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

'System Registry Related
Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As Long
Private Declare Function RegQueryValueExString Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, ByVal lpData As String, lpcbData As Long) As Long
Private Declare Function RegQueryValueExLong Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, lpData As Long, lpcbData As Long) As Long
Private Declare Function RegQueryValueExNULL Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, ByVal lpData As Long, lpcbData As Long) As Long

'System Registry Constants
Const REG_SZ As Long = 1
Const REG_DWORD As Long = 4

Const HKEY_CLASSES_ROOT = &H80000000
Const HKEY_CURRENT_USER = &H80000001
Const HKEY_LOCAL_MACHINE = &H80000002
Const HKEY_USERS = &H80000003

Const ERROR_NONE = 0
Const ERROR_BADDB = 1
Const ERROR_BADKEY = 2
Const ERROR_CANTOPEN = 3
Const ERROR_CANTREAD = 4
Const ERROR_CANTWRITE = 5
Const ERROR_OUTOFMEMORY = 6
Const ERROR_INVALID_PARAMETER = 7
Const ERROR_ACCESS_DENIED = 8
Const ERROR_INVALID_PARAMETERS = 87
Const ERROR_NO_MORE_ITEMS = 259

Const KEY_ALL_ACCESS = &H3F
Const REG_OPTION_NON_VOLATILE = 0


'SendMessage Constants
Public Const SW_SHOWNORMAL = 1
Public Const EM_LINEINDEX = &HBB
Public Const EM_LINELENGTH = &HC1
Public Const EM_LINEFROMCHAR = &HC9

'EM_SCROLL EM_LINELENGTH EM_SETRECTNP EM_GETPASSWORDCHAR EM_LINEFROMCHAR EM_SETHANDLE EM_UNDO EM_REPLACESEL EM_GETWORDBREAKPROC EM_GETTHUMB

'SetBkMode Constants
Public Const TRANSPARENT = 1

'WaitForTerm
Public Const SYNCHRONIZE = &H100000
Public Const INFINITE = &HFFFFFFFF

' Used for DisableCtrlAltDelete and Minimize
Private Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" (ByVal uAction As Long, ByVal uParam As Long, ByVal lpvParam As Any, ByVal fuWinIni As Long) As Long

'BitBlt Constants
Public Const BLACKNESS = &H42
Public Const WHITENESS = &HFF0062
Public Const SRCCOPY = &HCC0020
Public Const SRCPAINT = &HEE0086
Public Const SRCAND = &H8800C6
Public Const NOTSRCCOPY = &H330008
Public Const SRCINVERT = &H660046
Public Const DSTINVERT = &H550009

'DrawText Constants
Public Const DT_TOP = &H0
Public Const DT_LEFT = &H0
Public Const DT_CENTER = &H1
Public Const DT_RIGHT = &H2
Public Const DT_VCENTER = &H4
Public Const DT_BOTTOM = &H8
Public Const DT_WORDBREAK = &H10
Public Const DT_SINGLELINE = &H20
Public Const DT_EXPANDTABS = &H40
Public Const DT_TABSTOP = &H80
Public Const DT_NOCLIP = &H100
Public Const DT_EXTERNALLEADING = &H200
Public Const DT_CALCRECT = &H400
Public Const DT_NOPREFIX = &H800
Public Const DT_INTERNAL = &H1000

'Hook
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
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Public Const GWL_WNDPROC = -4
Public lpPrevWndProc As Long
Public gHW As Long

Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Declare Function ReleaseCapture Lib "user32" () As Long
Public Const WM_NCLBUTTONDOWN = &HA1
Public Const HTCAPTION = 2

Public hdcTiles As Long, hbmpTiles As Long, obmpTiles As Long
Public hdcTilesMask As Long, hbmpTilesMask As Long, obmpTilesMask As Long

Public hdcObjects As Long, hbmpObjects As Long, obmpObjects As Long
Public hdcObjectsMask As Long, hbmpObjectsMask As Long, obmpObjectsMask As Long

Public hdcSprites As Long, hbmpSprites As Long, obmpSprites As Long
Public hdcSpritesMask As Long, hbmpSpritesMask As Long, obmpSpritesMask As Long

Public hdcEffects As Long, hbmpEffects As Long, obmpEffects As Long
Public hdcEffectsMask As Long, hbmpEffectsMask As Long, obmpEffectsMask As Long

Public hdcWeather As Long, hbmpWeather As Long, obmpWeather As Long
Public hdcWeatherMask As Long, hbmpWeatherMask As Long, obmpWeatherMask As Long

Public hdcTempMask As Long, hbmpTempMask As Long, obmpTempMask As Long

Public hdcBack(0 To 2) As Long, hbmpBack(0 To 2) As Long, obmpBack(0 To 2) As Long

Public hdcBuffer As Long, hbmpBuffer As Long, obmpBuffer As Long

Public hdcFront(0 To 1) As Long, hbmpFront(0 To 1) As Long, obmpFront(0 To 1) As Long
Public hdcFrontMask(0 To 1) As Long, hbmpFrontMask(0 To 1) As Long, obmpFrontMask(0 To 1) As Long
Public hdcDarkness As Long, hbmpDarkness As Long, obmpDarkness As Long
Public hdcDarknessMask As Long, hbmpDarknessMask As Long, obmpDarknessMask As Long
Public hdcHPBar As Long, hbmpHPBar As Long, obmpHPBar As Long
Public hdcHPBarMask As Long, hbmpHPBarMask As Long, obmpHPBarMask As Long
Public hdcViewport As Long, hdcInv As Long
Public hdcGlow As Long, hdcGlowMask As Long
Public hPalette As Long
Public SkillName(1 To 3) As String
Public ClientSocket As Long, SocketData As String

Type Bitmap
    bmType As Long
    bmWidth As Long
    bmHeight As Long
    bmWidthBytes As Long
    bmPlanes As Integer
    bmBitsPixel As Integer
    bmBits As Long
End Type

Private Type PaletteEntry
        peRed As Byte
        peGreen As Byte
        peBlue As Byte
        peFlags As Byte
End Type

Type LogPalette
    palVersion As Integer
    palNumEntries As Integer
    palPalEntry(0 To 255) As PaletteEntry
End Type

Public Palette(0 To 255) As PaletteEntry
Public Bitmap As Bitmap

Type NPCSaleItemData
    GiveObject As Byte
    GiveValue As Long
    TakeObject As Byte
    TakeValue As Long
End Type

Type ProjectileData
    Sprite As Byte
    D As Byte
    Frame As Byte
    TotalFrames As Integer
    TargetType As Byte
    TargetNum As Byte
    TargetX As Long
    TargetY As Long
    SourceX As Long
    SourceY As Long
    X As Long
    Y As Long
    timeStamp As Long
    LoopCount As Integer
    CurLoop As Integer
    Speed As Long
    EndSound As Long
End Type

Type FloatTextData
    Text As String
    Color As Byte
    X As Long
    Y As Long
    D As Long
    Frame As Byte
End Type

Type RainData
    XO As Long
    YO As Long
    Frame As Byte
End Type

Type SnowData
    Sprite As Long
    XO As Long
    YO As Long
    Frame As Byte
End Type

Type StaticTextData
    Text As String
    Color As Byte
    X As Long
    Y As Long
End Type

Public Const pttCharacter = 0
Public Const pttPlayer = 1
Public Const pttMonster = 2
Public Const pttTile = 3
Public Const pttProject = 4

Type PlayerData
    Name As String
    LastMessage As String
    RepCount As Long
    Map As Long
    Sprite As Byte
    Status As Byte
    Dead As Boolean
    HP As Long
    MaxHP As Long
    X As Long
    Y As Long
    XO As Long
    YO As Long
    D As Byte
    A As Byte
    W As Long
    WalkStep As Long
    Guild As Byte
    Color As Long
    Ignore As Boolean
End Type

Type MacroData
    Text As String
    LineFeed As Boolean
End Type

Type ObjectData
    Name As String
    Type As Byte
    Picture As Byte
    Data(0 To 5) As Byte
    ObjClassData As Byte
    Value As Long
End Type

Type MagicData
    Name As String * 15
    Script As String * 15
    Description As String
End Type

Type MonsterData
    Name As String
    Sprite As Byte
    MaxHP As Long
    Exp As Long
End Type

Type MapStartLocationData
    Map As Integer
    X As Byte
    Y As Byte
End Type

Type MapDoorData
    Att As Byte
    BGTile1 As Integer
    X As Long
    Y As Long
End Type

Type TileData
    Ground As Integer
    Ground2 As Integer
    BGTile1 As Integer
    BGTile2 As Integer
    FGTile As Integer
    FGTile2 As Integer
    Att As Byte
    AttData(0 To 3) As Byte
End Type

Type MapMonsterData
    Monster As Byte
    HP As Long
    X As Long
    Y As Long
    XO As Long
    YO As Long
    D As Byte
    A As Byte
    W As Byte
End Type

Type MapObjectData
    Object As Byte
    X As Byte
    Y As Byte
    XOffset As Byte
    YOffset As Byte
    Value As Long
End Type

Type MapMonsterSpawnData
    Monster As Byte
    Rate As Byte
End Type

Type MapData
    Name As String
    ExitUp As Integer
    ExitDown As Integer
    ExitLeft As Integer
    ExitRight As Integer
    Tile(0 To 11, 0 To 11) As TileData
    Object(0 To 79) As MapObjectData
    Monster(0 To 9) As MapMonsterData
    MonsterSpawn(0 To 4) As MapMonsterSpawnData
    Door(0 To 9) As MapDoorData
    BootLocation As MapStartLocationData
    NPC As Byte
    Flags As Byte
    Version As Long
    Snow As Boolean
End Type

Type InvObjData
    Object As Byte
    Value As Long
    Durability As Long
    EquippedNum As Byte
End Type

Type BankData
    Object As Byte
    Value As Long
End Type

Type GuildData
    Name As String
    Sprite As Long
End Type

Type HallData
    Name As String
End Type

Type NPCData
    Name As String
End Type

Type GuildDeclarationData
    Guild As Byte
    Type As Byte
End Type

Type CharacterData
    Name As String
    Class As Byte
    Gender As Byte
    Sprite As Byte
    
    MaxHP As Byte
    MaxEnergy As Byte
    MaxMana As Byte
    HP As Byte
    Energy As Byte
    Mana As Byte
    
    Damage As Byte
    Defense As Byte
    
    Strength As Byte
    Agility As Byte
    Endurance As Byte
    Intelligence As Byte
    Concentration As Byte
    Vitality As Byte
    Stamina As Byte
    Wisdom As Byte
    MaxExperience As Long
    Experience As Long
    level As Byte
    StatPoints As Integer
    
    Status As Byte
    Access As Byte
    Index As Byte
    Guild As Byte
    GuildRank As Byte
    
    GuildDeclaration(0 To 4) As GuildDeclarationData
    
    Desc As String
    Magic(1 To 25) As Byte
    SkillLevel(1 To 4) As Byte
    SkillExp(1 To 4) As Long
    Inv(1 To 20) As InvObjData
    Bank(1 To 30) As BankData
End Type

Type ClassData
    Name As String
    HPChance As Byte
    EnergyChance As Byte
    ManaChance As Byte
    StartHP As Byte
    StartEnergy As Byte
    StartMana As Byte
    StartStrength As Byte
    StartAgility As Byte
    StartEndurance As Byte
    StartIntelligence As Byte
    Picture As Byte
End Type

Type OptionsData
    Wav As Boolean
    Broadcasts As Boolean
    MonsterNames As Boolean
    Weather As Boolean
    WeatherInt As Long
    HPBars As Boolean
End Type

'Vital Constants
Public Const GodSpeed = 32
Public Const WalkSpeed = 2
Public Const RunSpeed = 4
Public Const NumClasses = 4
'End of Constants

Public Section(1 To 30) As String, Suffix As String

Public AutoAttack As Boolean, TargetMonster As Integer 'Temporary
Public AutoAttackSpeed As Integer, AutoAttackWalk As Integer
Public DisableScreen As Boolean

'Info Text
Public InfoText(0 To 3) As String
Public InfoTextTimer As Long

Public FloatTextTimer As Long

Public MapData As String * 2507

Public ServerID As String

Public RandomData As New Collection
Public MovableData As clsMovableData

'Arrays
Public StatusColors(0 To 100) As Long
Public Player(1 To 255) As PlayerData
Public Projectile(1 To 255) As ProjectileData
Public FloatText(1 To 255) As FloatTextData
Public Snow(1 To 255) As SnowData
Public Rain(1 To 255) As RainData
Public StaticText(1 To 255) As StaticTextData
Public Monster(1 To 255) As MonsterData
Public Object(1 To 255) As ObjectData
Public Magic(1 To 255) As MagicData
Public Class(1 To 6) As ClassData
Public Guild(1 To 255) As GuildData
Public Hall(1 To 255) As HallData
Public NPC(1 To 255) As NPCData
Public SaleItem(0 To 9) As NPCSaleItemData
Public CurAttData(0 To 3) As Byte
Public Macro(0 To 9) As MacroData

'Objects
Public Map As MapData, EditMap As MapData, ClipboardMap As MapData
Public Character As CharacterData
Public Options As OptionsData
Public HotKey(1 To 10) As Long

Function BadName(St As String) As Boolean
    Dim A As Long, B As Long
    For A = 1 To Len(St)
        B = Asc(Mid$(St, A, 1))
        If B < 32 Or B > 126 Then
            BadName = True
        End If
    Next A
End Function
Function GetFilename(St As String) As String
    If Exists(ServerID + "\" + St) Then
        GetFilename = ServerID + "\" + St
    Else
        GetFilename = St
    End If
    GetFilename = App.Path & "\" & St
End Function

Function Random(ByVal Max As Long) As Long
    Random = Int(Rnd * Max)
End Function

Sub WaitForTerm(pid As Long)
    Dim phnd As Long
    phnd = OpenProcess(SYNCHRONIZE, 0, pid)
    If phnd <> 0 Then
        Call WaitForSingleObject(phnd, INFINITE)
        Call CloseHandle(phnd)
    End If
End Sub

Sub CreateMapCache()
    Dim St1 As String * 2507, A As Long
    St1 = String$(2507, 0)
    Open MovableData.MapCacheFile For Random As #1 Len = 2507
    For A = 1 To 2000
        Put #1, , St1
    Next A
    Close #1
End Sub

Sub DelItem(lpAppName As String, lpKeyName As String)
    WritePrivateProfileString lpAppName, lpKeyName, 0&, App.Path + "\Modus.ini"
End Sub
Sub LoadMacros()
    Dim A As Long
    For A = 0 To 9
        With Macro(A)
            .Text = ReadString("Macros", "Text" + CStr(A + 1))
            If Len(.Text) > 255 Then .Text = Left$(.Text, 255)
            If ReadInt("Macros", "LineFeed" + CStr(A + 1)) = 0 Then
                .LineFeed = False
            Else
                .LineFeed = True
            End If
        End With
    Next A
End Sub
Sub MonsterDied(Index As Long)
Dim A As Long
    For A = 1 To 100
        With Projectile(A)
            If .Sprite > 0 Then
                If .TargetType = pttMonster Then
                    If .TargetNum = Index Then
                        DestroyEffect (A)
                    End If
                End If
            End If
        End With
    Next A
End Sub
Sub PlayerLeftMap(Index As Long)
    Dim A As Long
    
    For A = 1 To 100
        With Projectile(A)
            If .Sprite > 0 Then
                If .TargetType = pttCharacter Then
                    If .TargetNum = Index Then
                        DestroyEffect (Index)
                    End If
                End If
            End If
        End With
    Next A
    Player(Index).Map = 0
End Sub
Function QuadChar(Num As Long) As String
    QuadChar = Chr$(Int(Num / 16777216) Mod 256) + Chr$(Int(Num / 65536) Mod 256) + Chr$(Int(Num / 256) Mod 256) + Chr$(Num Mod 256)
End Function

Sub CreateClassData()
    With Class(1)
        .Name = "Hero of Valhalla"
        .StartHP = 35
        .StartEnergy = 20
        .StartMana = 15
        .HPChance = 90
        .EnergyChance = 70
        .ManaChance = 50
        .Picture = 93
    End With
    With Class(2)
        .Name = "Storm Archer"
        .StartHP = 20
        .StartEnergy = 35
        .StartMana = 20
        .HPChance = 60
        .EnergyChance = 90
        .ManaChance = 60
        .Picture = 63
    End With
    With Class(3)
        .Name = "Wraith"
        .StartHP = 30
        .StartEnergy = 30
        .StartMana = 25
        .HPChance = 80
        .EnergyChance = 80
        .ManaChance = 70
        .Picture = 51
    End With
    With Class(4)
        .Name = "Druid"
        .StartHP = 15
        .StartEnergy = 25
        .StartMana = 40
        .HPChance = 40
        .EnergyChance = 60
        .ManaChance = 95
        .Picture = 89
    End With
    With Class(5)
        .Name = "Paladin of Freedom"
        .StartHP = 25
        .StartEnergy = 15
        .StartMana = 35
        .HPChance = 75
        .EnergyChance = 50
        .ManaChance = 90
        .Picture = 7
    End With
    With Class(6)
        .Name = "Necromancer"
        .StartHP = 20
        .StartEnergy = 25
        .StartMana = 25
        .HPChance = 65
        .EnergyChance = 80
        .ManaChance = 80
        .Picture = 17
    End With
End Sub
Sub DrawCurInvObj()
Dim A As Long, B As Long, Dura As Long

Dura = Character.Inv(MovableData.CurInvObj).Durability

    frmMain.picObj.Cls
    If MovableData.CurInvObj > 0 Then
        With frmMain
            If Character.Inv(MovableData.CurInvObj).Object > 0 Then
                BitBlt .picObj.hdc, 0, 0, 32, 32, hdcObjects, 0, (CLng(Object(Character.Inv(MovableData.CurInvObj).Object).Picture) - 1) * 32, SRCCOPY
                .lblObjName1.Caption = Object(Character.Inv(MovableData.CurInvObj).Object).Name
                Select Case Object(Character.Inv(MovableData.CurInvObj).Object).Type
                    Case 0 'None
                        For A = 0 To 4
                            .lblData(A) = ""
                        Next A
                    Case 1 'Weapon
                        .lblData(0) = "Weapon: (+" + Trim$(Str(Object(Character.Inv(MovableData.CurInvObj).Object).Data(1))) + " Damage)"
                        If ExamineBit(Object(Character.Inv(MovableData.CurInvObj).Object).Data(5), CByte(0)) Then
                            .lblData(1) = "Condition: Indestructible"
                        Else
                            .lblData(1) = "Condition: " + Str(Dura) + "% Durability"
                        End If
                        If Object(Character.Inv(MovableData.CurInvObj).Object).Data(3) = 1 Then
                            .lblData(2) = "Does not drop on death"
                        Else
                            .lblData(2) = ""
                        End If
                        If Object(Character.Inv(MovableData.CurInvObj).Object).Data(4) > 0 Then
                            .lblData(3) = "Requirements: Level " + Str(Object(Character.Inv(MovableData.CurInvObj).Object).Data(4))
                        Else
                            .lblData(3) = "Requirements: <None>"
                        End If
                        If ExamineBit(Object(Character.Inv(MovableData.CurInvObj).Object).Data(5), CByte(1)) Then
                            .lblData(4) = "Cannot be repaired"
                        Else
                            .lblData(4) = ""
                        End If
                        For A = 0 To 3
                            If ExamineBit(Object(Character.Inv(MovableData.CurInvObj).Object).ObjClassData, CByte(A)) Then
                                .lblClassReq.Visible = True
                                .lblClass(A) = Class(A + 1).Name
                            End If
                        Next A
                        
                    Case 2 'Shield
                        .lblData(0) = "Shield: (+" + Trim$(Str(Object(Character.Inv(MovableData.CurInvObj).Object).Data(1))) + " Defense)"
                        If ExamineBit(Object(Character.Inv(MovableData.CurInvObj).Object).Data(5), CByte(0)) Then
                            .lblData(1) = "Condition: Indestructible"
                        Else
                            .lblData(1) = "Condition: " + Str(Dura) + "% Durability"
                        End If
                        If Object(Character.Inv(MovableData.CurInvObj).Object).Data(3) = 1 Then
                            .lblData(2) = "Does not drop on death"
                        Else
                            .lblData(2) = ""
                        End If
                        If Object(Character.Inv(MovableData.CurInvObj).Object).Data(4) > 0 Then
                            .lblData(3) = "Requirements: Level " + Str(Object(Character.Inv(MovableData.CurInvObj).Object).Data(4))
                        Else
                            .lblData(3) = "Requirements: <None>"
                        End If
                        If ExamineBit(Object(Character.Inv(MovableData.CurInvObj).Object).Data(5), CByte(1)) Then
                            .lblData(4) = "Cannot be repaired"
                        Else
                            .lblData(4) = ""
                        End If
                        For A = 0 To 3
                            If ExamineBit(Object(Character.Inv(MovableData.CurInvObj).Object).ObjClassData, CByte(A)) Then
                                .lblClassReq.Visible = True
                                .lblClass(A) = Class(A + 1).Name
                            End If
                        Next A
                    Case 3 'Armor
                        .lblData(0) = "Armor: (+" + Trim$(Str(Object(Character.Inv(MovableData.CurInvObj).Object).Data(1))) + " Defense)"
                        If ExamineBit(Object(Character.Inv(MovableData.CurInvObj).Object).Data(5), CByte(0)) Then
                            .lblData(1) = "Condition: Indestructible"
                        Else
                            .lblData(1) = "Condition: " + Str(Dura) + "% Durability"
                        End If
                        If Object(Character.Inv(MovableData.CurInvObj).Object).Data(3) = 1 Then
                            .lblData(2) = "Does not drop on death"
                        Else
                            .lblData(2) = ""
                        End If
                        If Object(Character.Inv(MovableData.CurInvObj).Object).Data(4) > 0 Then
                            .lblData(3) = "Requirements: Level " + Str(Object(Character.Inv(MovableData.CurInvObj).Object).Data(4))
                        Else
                            .lblData(3) = "Requirements: <None>"
                        End If
                        If ExamineBit(Object(Character.Inv(MovableData.CurInvObj).Object).Data(5), CByte(1)) Then
                            .lblData(4) = "Cannot be repaired"
                        Else
                            .lblData(4) = ""
                        End If
                        For A = 0 To 3
                            If ExamineBit(Object(Character.Inv(MovableData.CurInvObj).Object).ObjClassData, CByte(A)) Then
                                .lblClassReq.Visible = True
                                .lblClass(A) = Class(A + 1).Name
                            End If
                        Next A
                    Case 4 'Helmet
                        .lblData(0) = "Helmet: (+" + Trim$(Str(Object(Character.Inv(MovableData.CurInvObj).Object).Data(1))) + " Defense)"
                        If ExamineBit(Object(Character.Inv(MovableData.CurInvObj).Object).Data(5), CByte(0)) Then
                            .lblData(1) = "Condition: Indestructible"
                        Else
                            .lblData(1) = "Condition: " + Str(Dura) + "% Durability"
                        End If
                        If Object(Character.Inv(MovableData.CurInvObj).Object).Data(3) = 1 Then
                            .lblData(2) = "Does not drop on death"
                        Else
                            .lblData(2) = ""
                        End If
                        If Object(Character.Inv(MovableData.CurInvObj).Object).Data(4) > 0 Then
                            .lblData(3) = "Requirements: Level " + Str(Object(Character.Inv(MovableData.CurInvObj).Object).Data(4))
                        Else
                            .lblData(3) = "Requirements: <None>"
                        End If
                        If ExamineBit(Object(Character.Inv(MovableData.CurInvObj).Object).Data(5), CByte(1)) Then
                            .lblData(4) = "Cannot be repaired"
                        Else
                            .lblData(4) = ""
                        End If
                        For A = 0 To 3
                            If ExamineBit(Object(Character.Inv(MovableData.CurInvObj).Object).ObjClassData, CByte(A)) Then
                                .lblClassReq.Visible = True
                                .lblClass(A) = Class(A + 1).Name
                            End If
                        Next A
                    Case 5 'Potion
                        .lblData(0) = "Potion"
                        For A = 1 To 4
                            If A <> 3 Then .lblData(A) = ""
                        Next A
                        If Object(Character.Inv(MovableData.CurInvObj).Object).Data(4) > 0 Then
                            .lblData(3) = "Requirements: Level " + Str(Object(Character.Inv(MovableData.CurInvObj).Object).Data(4))
                        Else
                            .lblData(3) = "Requirements: <None>"
                        End If
                    Case 6 'Money
                        .lblData(0) = "Value: " + CStr(Character.Inv(MovableData.CurInvObj).Value)
                        For A = 1 To 4
                            .lblData(A) = ""
                        Next A
                    Case 7 'Key
                        .lblData(0) = "Key"
                        For A = 1 To 4
                            If A <> 3 Then .lblData(A) = ""
                        Next A
                        If Object(Character.Inv(MovableData.CurInvObj).Object).Data(4) > 0 Then
                            .lblData(3) = "Requirements: Level " + Str(Object(Character.Inv(MovableData.CurInvObj).Object).Data(4))
                        Else
                            .lblData(3) = "Requirements: <None>"
                        End If
                    Case 8 'Ring
                        '.lblData(0) = "Ring: (+" + Trim$(Str(Object(Character.Inv(MovableData.CurInvObj).Object).Data(2)))) + " Defense)"
                        If ExamineBit(Object(Character.Inv(MovableData.CurInvObj).Object).Data(5), CByte(0)) Then
                            .lblData(1) = "Condition: Indestructible"
                        Else
                            .lblData(1) = "Condition: " + Str(Dura) + "% Durability"
                        End If
                        If Object(Character.Inv(MovableData.CurInvObj).Object).Data(3) = 1 Then
                            .lblData(2) = "Does not drop on death"
                        Else
                            .lblData(2) = ""
                        End If
                        If Object(Character.Inv(MovableData.CurInvObj).Object).Data(4) > 0 Then
                            .lblData(3) = "Requirements: Level " + Str(Object(Character.Inv(MovableData.CurInvObj).Object).Data(4))
                        Else
                            .lblData(3) = "Requirements: <None>"
                        End If
                        If ExamineBit(Object(Character.Inv(MovableData.CurInvObj).Object).Data(5), CByte(1)) Then
                            .lblData(4) = "Cannot be repaired"
                        Else
                            .lblData(4) = ""
                        End If
                        For A = 0 To 3
                            If ExamineBit(Object(Character.Inv(MovableData.CurInvObj).Object).ObjClassData, CByte(A)) Then
                                .lblClassReq.Visible = True
                                .lblClass(A) = Class(A + 1).Name
                            End If
                        Next A
                    Case 9 'Guild Deed
                        .lblData(0) = "Guild Deed"
                        For A = 1 To 4
                            If A <> 3 Then .lblData(A) = ""
                        Next A
                        If Object(Character.Inv(MovableData.CurInvObj).Object).Data(4) > 0 Then
                            .lblData(3) = "Requirements: Level " + Str(Object(Character.Inv(MovableData.CurInvObj).Object).Data(4))
                        Else
                            .lblData(3) = "Requirements: <None>"
                        End If
                End Select
            Else
                .lblClassReq.Visible = False
                .lblObjName1 = ""
                For A = 0 To 4
                    .lblData(A) = ""
                Next A
                For A = 0 To 3
                    .lblClass(A) = ""
                Next A
            End If
        End With
    End If
End Sub

Sub DrawStaticText()
Dim A As Long, B As Long, R As RECT

For A = 1 To 255
    With StaticText(A)
        If .Text <> "" Then
            R.Left = (.X * 32) - 96
            R.Right = (.X * 32) + 128
            R.Top = (.Y * 32) - 16
            R.Bottom = (.Y * 32) + 16
            Draw3dText hdcBuffer, R, .Text, QBColor(.Color), 2
        End If
    End With
Next A

End Sub

Sub DrawInfoText()
    Dim A As Long
    If InfoTextTimer > 0 Then
        If timeGetTime - InfoTextTimer <= 10000 Then
            For A = 2 To 3
                If InfoText(A) <> "" Then
                    SetTextColor hdcBuffer, QBColor(0)
                    TextOut hdcBuffer, 5, 332 + 12 * A, InfoText(A), Len(InfoText(A))
                    SetTextColor hdcBuffer, QBColor(12)
                    TextOut hdcBuffer, 3, 330 + 12 * A, InfoText(A), Len(InfoText(A))
                End If
            Next A
        Else
            For A = 2 To 3
                InfoText(A) = ""
            Next A
            InfoTextTimer = 0
        End If
    End If
End Sub
Sub DrawTrainBars()
    Dim X1 As Long, X2 As Long, St As String
    frmMain.lblStatPoints = "Free Stat Points: " + CStr(MovableData.TempVar9)
    With frmMain.picStatTrain(0)
        X1 = Int((CSng(Character.Strength) / 50!) * CSng(.ScaleWidth))
        X2 = Int((CSng(Character.Strength + MovableData.TempVar1) / 50!) * CSng(.ScaleWidth))
        If X1 > 0 Then frmMain.picStatTrain(0).Line (0, 0)-(X1, .ScaleHeight), &H44352F, BF
        If X2 > X1 Then frmMain.picStatTrain(0).Line (X1, 0)-(X2, .ScaleHeight), &H808080, BF
        If X2 < .ScaleWidth Then frmMain.picStatTrain(0).Line (X2, 0)-(.ScaleWidth, .ScaleHeight), 0, BF
        If MovableData.TempVar1 > 0 Then
            St = "Strength: " + Str(Character.Strength) + " + " + CStr(MovableData.TempVar1)
        Else
            St = "Strength: " + Str(Character.Strength)
        End If
        TextOut .hdc, 5, (.ScaleHeight - .TextHeight(St)) / 2, St, Len(St)
        .Refresh
    End With
    With frmMain.picStatTrain(1)
        X1 = Int((CSng(Character.Agility) / 50!) * CSng(.ScaleWidth))
        X2 = Int((CSng(Character.Agility + MovableData.TempVar2) / 50!) * CSng(.ScaleWidth))
        If X1 > 0 Then frmMain.picStatTrain(1).Line (0, 0)-(X1, .ScaleHeight), &H44352F, BF
        If X2 > X1 Then frmMain.picStatTrain(1).Line (X1, 0)-(X2, .ScaleHeight), &H808080, BF
        If X2 < .ScaleWidth Then frmMain.picStatTrain(1).Line (X2, 0)-(.ScaleWidth, .ScaleHeight), 0, BF
        If MovableData.TempVar2 > 0 Then
            St = "Agility: " + Str(Character.Agility) + " + " + CStr(MovableData.TempVar2)
        Else
            St = "Agility: " + Str(Character.Agility)
        End If
        TextOut .hdc, 5, (.ScaleHeight - .TextHeight(St)) / 2, St, Len(St)
        .Refresh
    End With
    With frmMain.picStatTrain(2)
        X1 = Int((CSng(Character.Endurance) / 50!) * CSng(.ScaleWidth))
        X2 = Int((CSng(Character.Endurance + MovableData.TempVar3) / 50!) * CSng(.ScaleWidth))
        If X1 > 0 Then frmMain.picStatTrain(2).Line (0, 0)-(X1, .ScaleHeight), &H44352F, BF
        If X2 > X1 Then frmMain.picStatTrain(2).Line (X1, 0)-(X2, .ScaleHeight), &H808080, BF
        If X2 < .ScaleWidth Then frmMain.picStatTrain(2).Line (X2, 0)-(.ScaleWidth, .ScaleHeight), 0, BF
        If MovableData.TempVar3 > 0 Then
            St = "Endurance: " + Str(Character.Endurance) + " + " + CStr(MovableData.TempVar3)
        Else
            St = "Endurance: " + Str(Character.Endurance)
        End If
        TextOut .hdc, 5, (.ScaleHeight - .TextHeight(St)) / 2, St, Len(St)
        .Refresh
    End With
    With frmMain.picStatTrain(3)
        X1 = Int((CSng(Character.Intelligence) / 50!) * CSng(.ScaleWidth))
        X2 = Int((CSng(Character.Intelligence + MovableData.TempVar4) / 50!) * CSng(.ScaleWidth))
        If X1 > 0 Then frmMain.picStatTrain(3).Line (0, 0)-(X1, .ScaleHeight), &H44352F, BF
        If X2 > X1 Then frmMain.picStatTrain(3).Line (X1, 0)-(X2, .ScaleHeight), &H808080, BF
        If X2 < .ScaleWidth Then frmMain.picStatTrain(3).Line (X2, 0)-(.ScaleWidth, .ScaleHeight), 0, BF
        If MovableData.TempVar4 > 0 Then
            St = "Intelligence: " + Str(Character.Intelligence) + " + " + CStr(MovableData.TempVar4)
        Else
            St = "Intelligence: " + Str(Character.Intelligence)
        End If
        TextOut .hdc, 5, (.ScaleHeight - .TextHeight(St)) / 2, St, Len(St)
        .Refresh
    End With
    With frmMain.picStatTrain(4)
        X1 = Int((CSng(Character.Concentration) / 50!) * CSng(.ScaleWidth))
        X2 = Int((CSng(Character.Concentration + MovableData.TempVar5) / 50!) * CSng(.ScaleWidth))
        If X1 > 0 Then frmMain.picStatTrain(4).Line (0, 0)-(X1, .ScaleHeight), &H44352F, BF
        If X2 > X1 Then frmMain.picStatTrain(4).Line (X1, 0)-(X2, .ScaleHeight), &H808080, BF
        If X2 < .ScaleWidth Then frmMain.picStatTrain(4).Line (X2, 0)-(.ScaleWidth, .ScaleHeight), 0, BF
        If MovableData.TempVar5 > 0 Then
            St = "Concentration: " + Str(Character.Concentration) + " + " + CStr(MovableData.TempVar5)
        Else
            St = "Concentration: " + Str(Character.Concentration)
        End If
        TextOut .hdc, 5, (.ScaleHeight - .TextHeight(St)) / 2, St, Len(St)
        .Refresh
    End With
    With frmMain.picStatTrain(5)
        X1 = Int((CSng(Character.Vitality) / 50!) * CSng(.ScaleWidth))
        X2 = Int((CSng(Character.Vitality + MovableData.TempVar6) / 50!) * CSng(.ScaleWidth))
        If X1 > 0 Then frmMain.picStatTrain(5).Line (0, 0)-(X1, .ScaleHeight), &H44352F, BF
        If X2 > X1 Then frmMain.picStatTrain(5).Line (X1, 0)-(X2, .ScaleHeight), &H808080, BF
        If X2 < .ScaleWidth Then frmMain.picStatTrain(5).Line (X2, 0)-(.ScaleWidth, .ScaleHeight), 0, BF
        If MovableData.TempVar6 > 0 Then
            St = "Vitality: " + Str(Character.Vitality) + " + " + CStr(MovableData.TempVar6)
        Else
            St = "Vitality: " + Str(Character.Vitality)
        End If
        TextOut .hdc, 5, (.ScaleHeight - .TextHeight(St)) / 2, St, Len(St)
        .Refresh
    End With
    With frmMain.picStatTrain(6)
        X1 = Int((CSng(Character.Stamina) / 50!) * CSng(.ScaleWidth))
        X2 = Int((CSng(Character.Stamina + MovableData.TempVar7) / 50!) * CSng(.ScaleWidth))
        If X1 > 0 Then frmMain.picStatTrain(6).Line (0, 0)-(X1, .ScaleHeight), &H44352F, BF
        If X2 > X1 Then frmMain.picStatTrain(6).Line (X1, 0)-(X2, .ScaleHeight), &H808080, BF
        If X2 < .ScaleWidth Then frmMain.picStatTrain(6).Line (X2, 0)-(.ScaleWidth, .ScaleHeight), 0, BF
        If MovableData.TempVar7 > 0 Then
            St = "Stamina: " + Str(Character.Stamina) + " + " + CStr(MovableData.TempVar7)
        Else
            St = "Stamina: " + Str(Character.Stamina)
        End If
        TextOut .hdc, 5, (.ScaleHeight - .TextHeight(St)) / 2, St, Len(St)
        .Refresh
    End With
    With frmMain.picStatTrain(7)
        X1 = Int((CSng(Character.Wisdom) / 50!) * CSng(.ScaleWidth))
        X2 = Int((CSng(Character.Wisdom + MovableData.TempVar8) / 50!) * CSng(.ScaleWidth))
        If X1 > 0 Then frmMain.picStatTrain(7).Line (0, 0)-(X1, .ScaleHeight), &H44352F, BF
        If X2 > X1 Then frmMain.picStatTrain(7).Line (X1, 0)-(X2, .ScaleHeight), &H808080, BF
        If X2 < .ScaleWidth Then frmMain.picStatTrain(7).Line (X2, 0)-(.ScaleWidth, .ScaleHeight), 0, BF
        If MovableData.TempVar8 > 0 Then
            St = "Wisdom: " + Str(Character.Wisdom) + " + " + CStr(MovableData.TempVar8)
        Else
            St = "Wisdom: " + Str(Character.Wisdom)
        End If
        TextOut .hdc, 5, (.ScaleHeight - .TextHeight(St)) / 2, St, Len(St)
        .Refresh
    End With
End Sub
Function mmSend(ByVal sCommand As String) As String
    Dim iLen As Long, msReturn As String, Success As Long
    msReturn = Space$(255)
    iLen = Len(msReturn)
    Success = mciSendString(sCommand, msReturn, iLen, 0)
    If Success = 0 Then
        msReturn = Trim$(msReturn)
        msReturn = Left$(msReturn, Len(msReturn) - 1)
    Else
        msReturn = ""
    End If
    mmSend = msReturn
End Function
Sub MoveToTile()
    With MovableData
        SendSocket Chr$(7) + Chr$(.CWalkCode) + Chr$(.cx) + Chr$(.cy) + Chr$(MovableData.CDir) + Chr$(.CWalkStep)
        If .CWalkStep = 4 Then
            'Use Energy
            If Character.Energy > 0 Then
                Character.Energy = Character.Energy - 1
                DrawEnergy
            Else
                .CWalkStep = 2
            End If
        End If
        If Map.Tile(.cx, .cy).Att = 2 Then
            If Character.Access = 0 Or Character.Access <> 0 And .keyAlt = False Then
                If frmMain.MapTimer.Enabled = False Then
                    frmMain.MapTimer.Enabled = True
                    .Freeze = True
                    .NextTransition = 5
                End If
            End If
        End If
    End With
End Sub

Sub PrintInfoText(St As String)
    InfoTextTimer = timeGetTime
    InfoText(2) = InfoText(3)
    InfoText(3) = St
End Sub
Sub PrintFloatText(Text As String, Color As Byte, X As Long, Y As Long, Dir As Long)
Dim A As Long

A = FreeFloatText
With FloatText(A)
    .Text = Text
    .Color = Color
    .X = X
    .Y = Y
    .D = Dir
End With

End Sub
Sub PrintStaticText(Text As String, Color As Byte, X As Long, Y As Long)
Dim A As Long

A = FreeStaticText
With StaticText(A)
    .Text = Text
    .Color = Color
    .X = X
    .Y = Y
End With

End Sub
Function GetTime() As Long
Dim A As Currency, B As Currency
    QueryPerformanceCounter A
    QueryPerformanceFrequency B
    If Int(A * B) <= 60000 Then GetTime = Int(A * B) \ 100
End Function
Sub SaveOptions()
    With Options
        WriteString "Options", "Saved", "1"
        If .Wav = True Then
            WriteString "Options", "Wav", "1"
        Else
            WriteString "Options", "Wav", "0"
        End If
        If .Broadcasts = True Then
            WriteString "Options", "Broadcasts", "1"
        Else
            WriteString "Options", "Broadcasts", "0"
        End If
        If .MonsterNames = True Then
            WriteString "Options", "MonsterNames", "1"
        Else
            WriteString "Options", "MonsterNames", "0"
        End If
        If .HPBars = True Then
            WriteString "Options", "HPBars", "1"
        Else
            WriteString "Options", "HPBars", "0"
        End If
        If .Weather = True Then
            WriteString "Options", "Weather", "1"
        Else
            WriteString "Options", "Weather", "0"
        End If
        
        WriteString "Options", "WeatherInt", .WeatherInt
    End With
End Sub
Sub SaveHotKeys()
Dim A As Long, B As Long
    For A = 1 To 10
        WriteString Character.Name, "HotKey" + CStr(A), HotKey(A)
    Next A
End Sub
Sub LoadHotKeys()
Dim A As Long, B As Long
    For A = 1 To 10
        B = ReadString(Character.Name, "HotKey" + CStr(A))
        If B <> 0 Then HotKey(A) = B
    Next A
End Sub
Sub LoadOptions()
    With Options
        If ReadInt("Options", "Saved") = 1 Then
            If ReadInt("Options", "Wav") = 1 Then
                .Wav = True
            Else
                .Wav = False
            End If
            If ReadInt("Options", "Broadcasts") = 1 Then
                .Broadcasts = True
            Else
                .Broadcasts = False
            End If
            If ReadInt("Options", "MonsterNames") = 1 Then
                .MonsterNames = True
            Else
                .MonsterNames = False
            End If
            If ReadInt("Options", "HPBars") = 1 Then
                .HPBars = True
            Else
                .HPBars = False
            End If
            If ReadInt("Options", "Weather") = 1 Then
                .Weather = True
            Else
                .Weather = False
            End If
            .WeatherInt = CLng(ReadInt("Options", "WeatherInt"))
        Else
            .Wav = True
            .Broadcasts = True
            .MonsterNames = True
            .HPBars = True
            .Weather = True
            .WeatherInt = 5
            SaveOptions
        End If
    End With
End Sub
Sub ShowMap()

    frmMain.lblMapName = "[" + Map.Name + "]"
    If ExamineBit(Map.Flags, 0) Then
        frmMain.lblMapName.ForeColor = QBColor(11)
    ElseIf ExamineBit(Map.Flags, 6) Then
        frmMain.lblMapName.ForeColor = QBColor(12)
    Else
        frmMain.lblMapName.ForeColor = QBColor(15)
    End If
    If ExamineBit(Map.Flags, 2) Then
    End If
    DrawMap
    If MovableData.frmWait_Loaded = True Then
        Unload frmWait
    End If
    If MovableData.frmMain_Showing = False Then
        frmMain.Show
        MovableData.frmMain_Showing = True
    End If
    Transition
    MovableData.Freeze = False
End Sub
Sub ClearBit(bytByte As Byte, Bit As Byte)
      bytByte = bytByte And Not (2 ^ Bit)
End Sub
Sub PlayWav(Number As Long)
    If Options.Wav = True Then
        sndPlaySound GetFilename("\data\sfx\sound" + CStr(Number) + ".wav"), 1
    End If
End Sub
Sub RedrawTile()
    BitBlt frmMain.picTile.hdc, 0, 0, 32, 32, 0, 0, 0, BLACKNESS
    If MovableData.EditMode < 6 Then
        If MovableData.CurTile > 0 Then
            BitBlt frmMain.picTile.hdc, 0, 0, 32, 32, hdcTiles, ((MovableData.CurTile - 1) Mod 7) * 32, Int((MovableData.CurTile - 1) / 7) * 32, SRCCOPY
        End If
    Else
        If MovableData.CurAtt > 0 Then
            BitBlt frmMain.picTile.hdc, 0, 0, 32, 32, frmMain.picAtts.hdc, ((MovableData.CurAtt - 1) Mod 7) * 32, Int((MovableData.CurAtt - 1) / 7) * 32, SRCCOPY
        End If
    End If
    frmMain.picTile.Refresh
End Sub
Sub RedrawTiles()
    BitBlt frmMain.picTiles.hdc, 0, 0, 224, 192, 0, 0, 0, BLACKNESS
    If MovableData.EditMode < 6 Then
        BitBlt frmMain.picTiles.hdc, 0, 0, 224, 192, hdcTiles, 0, MovableData.TopY, SRCCOPY
    Else
        BitBlt frmMain.picTiles.hdc, 0, 0, 224, 192, frmMain.picAtts.hdc, 0, 0, SRCCOPY
    End If
    frmMain.picTiles.Refresh
End Sub
Sub SetBit(bytByte As Byte, Bit As Byte)
    bytByte = bytByte Or (2 ^ Bit)
End Sub
Function ExamineBit(bytByte As Byte, Bit As Byte) As Byte
    ExamineBit = ((bytByte And (2 ^ Bit)) > 0)
End Function

Sub CloseMapEdit()
    MovableData.MapEdit = False
    'frmMain.picInfobar.Visible = True
    frmMain.picMapEdit.Visible = False
    DrawMap
    SendSocket Chr$(77)
End Sub

Sub DrawChatString()
    Dim R As RECT
    
    If MovableData.ChatString <> "" Then
        With R
            .Left = 5
            .Top = 5
            .Right = 379
            .Bottom = 50
        End With
        SetTextColor hdcBuffer, QBColor(15)
        DrawText hdcBuffer, MovableData.ChatString, Len(MovableData.ChatString), R, DT_CENTER Or DT_NOCLIP Or DT_WORDBREAK
    End If
End Sub

Sub GetSections(ByVal St As String, NumSections)
    Dim A As Integer, W As Integer, Q As Boolean
    Dim CurChar As String * 1, LastChar As String * 1
    Erase Section
    Suffix = ""
    If Len(St) = 0 Then Exit Sub
    
    W = 1
    For A = 1 To Len(St)
        CurChar = Mid$(St, A, 1)
        Select Case Asc(CurChar)
            Case 32
                If Q = False Then
                    If Not LastChar = Chr$(32) Then W = W + 1
                    If W > NumSections Then Exit For
                Else
                    Section(W) = Section(W) + CurChar
                End If
            Case 34
                If Q = False Then Q = True Else Q = False
            Case Else
                Section(W) = Section(W) + CurChar
        End Select
        LastChar = CurChar
    Next A
    If A < Len(St) Then
        Suffix = Mid$(St, A + 1)
    Else
        Suffix = ""
    End If
End Sub
Sub GetSections2(St)
    Dim A As Long, B As Long, C As Long
    B = 1
    Erase Section
    For A = 1 To 30
        C = InStr(B, St, Chr$(0))
        If C - B = 0 Then
            Section(A) = ""
        ElseIf C <> 0 Then
            Section(A) = Mid$(St, B, C - B)
        Else
            Section(A) = Mid$(St, B, Len(St) - B + 1)
            Exit For
        End If
        B = C + 1
    Next A
End Sub
Function ClipString(St As String) As String
    Dim A As Long
    For A = Len(St) To 1 Step -1
        If Mid$(St, A, 1) <> Chr$(32) Then
            ClipString = Mid$(St, 1, A)
            Exit Function
        End If
    Next A
End Function

Sub CopyMap(DestMap As MapData, SourceMap As MapData)
    Dim A As Long, X As Long, Y As Long
    
    With DestMap
        .Name = SourceMap.Name
        .NPC = SourceMap.NPC
        .ExitUp = SourceMap.ExitUp
        .ExitDown = SourceMap.ExitDown
        .ExitLeft = SourceMap.ExitLeft
        .ExitRight = SourceMap.ExitRight
        .BootLocation.Map = SourceMap.BootLocation.Map
        .BootLocation.X = SourceMap.BootLocation.X
        .BootLocation.Y = SourceMap.BootLocation.Y
        .Flags = SourceMap.Flags
        For A = 0 To 4
            .MonsterSpawn(A).Monster = SourceMap.MonsterSpawn(A).Monster
            .MonsterSpawn(A).Rate = SourceMap.MonsterSpawn(A).Rate
        Next A
        For Y = 0 To 11
            For X = 0 To 11
                With .Tile(X, Y)
                    .Ground = SourceMap.Tile(X, Y).Ground
                    .Ground2 = SourceMap.Tile(X, Y).Ground2
                    .BGTile1 = SourceMap.Tile(X, Y).BGTile1
                    .BGTile2 = SourceMap.Tile(X, Y).BGTile2
                    .FGTile = SourceMap.Tile(X, Y).FGTile
                    .FGTile2 = SourceMap.Tile(X, Y).FGTile2
                    .Att = SourceMap.Tile(X, Y).Att
                    .AttData(0) = SourceMap.Tile(X, Y).AttData(0)
                    .AttData(1) = SourceMap.Tile(X, Y).AttData(1)
                    .AttData(2) = SourceMap.Tile(X, Y).AttData(2)
                    .AttData(3) = SourceMap.Tile(X, Y).AttData(3)
                End With
            Next X
        Next Y
        For A = 0 To 9
            With SourceMap.Door(A)
                If .Att > 0 Then
                    DestMap.Tile(.X, .Y).BGTile1 = .BGTile1
                    DestMap.Tile(.X, .Y).Att = .Att
                End If
            End With
            .Door(A).Att = 0
            .Door(A).BGTile1 = 0
        Next A
    End With
End Sub
Sub LoadMap(MapData As String)
    Dim A As Long, X As Long, Y As Long
    On Error Resume Next
    If Len(MapData) = 2507 Then
        With Map
            .Name = ClipString$(Mid$(MapData, 1, 30))
            .Version = Asc(Mid$(MapData, 31, 1)) * 16777216 + Asc(Mid$(MapData, 32, 1)) * 65536 + Asc(Mid$(MapData, 33, 1)) * 256& + Asc(Mid$(MapData, 34, 1))
            .NPC = Asc(Mid$(MapData, 35, 1))
            .ExitUp = Asc(Mid$(MapData, 37, 1)) * 256 + Asc(Mid$(MapData, 38, 1))
            .ExitDown = Asc(Mid$(MapData, 39, 1)) * 256 + Asc(Mid$(MapData, 40, 1))
            .ExitLeft = Asc(Mid$(MapData, 41, 1)) * 256 + Asc(Mid$(MapData, 42, 1))
            .ExitRight = Asc(Mid$(MapData, 43, 1)) * 256 + Asc(Mid$(MapData, 44, 1))
            .BootLocation.Map = Asc(Mid$(MapData, 45, 1)) * 256 + Asc(Mid$(MapData, 46, 1))
            .BootLocation.X = Asc(Mid$(MapData, 47, 1))
            .BootLocation.Y = Asc(Mid$(MapData, 48, 1))
            .Flags = Asc(Mid$(MapData, 49, 1))
            For A = 0 To 4 '50 - 59
                .MonsterSpawn(A).Monster = Asc(Mid$(MapData, 50 + A * 2))
                .MonsterSpawn(A).Rate = Asc(Mid$(MapData, 51 + A * 2))
            Next A
            '60
            For Y = 0 To 11
                For X = 0 To 11
                    With .Tile(X, Y)
                        A = 60 + Y * 204 + X * 17
                        .Ground = Asc(Mid$(MapData, A, 1)) * 256 + Asc(Mid$(MapData, A + 1, 1))
                        .Ground2 = Asc(Mid$(MapData, A + 2, 1)) * 256 + Asc(Mid$(MapData, A + 3, 1))
                        .BGTile1 = Asc(Mid$(MapData, A + 4, 1)) * 256 + Asc(Mid$(MapData, A + 5, 1))
                        .BGTile2 = Asc(Mid$(MapData, A + 6, 1)) * 256 + Asc(Mid$(MapData, A + 7, 1))
                        .FGTile = Asc(Mid$(MapData, A + 8, 1)) * 256 + Asc(Mid$(MapData, A + 9, 1))
                        .FGTile2 = Asc(Mid$(MapData, A + 10, 1)) * 256 + Asc(Mid$(MapData, A + 11, 1))
                        .Att = Asc(Mid$(MapData, A + 12, 1))
                        .AttData(0) = Asc(Mid$(MapData, A + 13, 1))
                        .AttData(1) = Asc(Mid$(MapData, A + 14, 1))
                        .AttData(2) = Asc(Mid$(MapData, A + 15, 1))
                        .AttData(3) = Asc(Mid$(MapData, A + 16, 1))
                    End With
                Next X
            Next Y
        End With
    End If
End Sub
Sub Draw3dText(DC As Long, TargetRect As RECT, St As String, lngColor As Long, Height As Integer)
    Dim ShadowRect As RECT
    With ShadowRect
        .Top = TargetRect.Top + Height
        .Left = TargetRect.Left + Height
        .Bottom = TargetRect.Bottom + Height
        .Right = TargetRect.Right + Height
    End With
    SetTextColor DC, RGB(10, 10, 10)
    DrawText DC, St, Len(St), ShadowRect, DT_CENTER Or DT_NOCLIP Or DT_WORDBREAK
    SetTextColor DC, lngColor
    DrawText DC, St, Len(St), TargetRect, DT_CENTER Or DT_NOCLIP Or DT_WORDBREAK
End Sub
Sub DrawBank()
Dim A As Long

For A = 1 To 30
    If Character.Bank(A).Object > 0 Then
        BitBlt frmMain.picBankObj(A).hdc, 0, 0, 32, 32, hdcObjects, 0, CLng(Object(Character.Bank(A).Object).Picture - 1) * 32, SRCCOPY
    Else
        BitBlt frmMain.picBankObj(A).hdc, 0, 0, 32, 32, 0, 0, 0, BLACKNESS
    End If
frmMain.picBankObj(A).Refresh
Next A

End Sub
Sub DrawHP()
    Dim Percent As Single, St As String
    
    If Character.MaxHP > 0 Then
        Percent = Character.HP / Character.MaxHP
    Else
        Percent = 0
    End If

    St = CStr(Int(Percent * 100)) + "% " + CStr(Character.HP) + "/" + CStr(Character.MaxHP)
    With frmMain.picStatHP
        .Cls
        BitBlt .hdc, 0, 0, Int(frmMain.picStatBarHP.Width * Percent), 17, frmMain.picStatBarHP.hdc, 0, 0, SRCCOPY
        TextOut .hdc, 32, 0, St, Len(St)
        .Refresh
    End With
End Sub
Sub DrawEnergy()
    Dim Percent As Single, St As String
    
    If Character.MaxEnergy > 0 Then
        Percent = Character.Energy / Character.MaxEnergy
    Else
        Percent = 0
    End If
    
    St = CStr(Int(Percent * 100)) + "% " + CStr(Character.Energy) + "/" + CStr(Character.MaxEnergy)
    With frmMain.picStatEnergy
        .Cls
        BitBlt .hdc, 0, 0, Int(frmMain.picStatBarEnergy.Width * Percent), 17, frmMain.picStatBarEnergy.hdc, 0, 0, SRCCOPY
        TextOut frmMain.picStatEnergy.hdc, 32, 0, St, Len(St)
        .Refresh
    End With
End Sub
Sub DrawMana()
    Dim Percent As Single, St As String
    
    If Character.MaxMana > 0 Then
        Percent = Character.Mana / Character.MaxMana
    Else
        Percent = 0
    End If
    St = CStr(Int(Percent * 100)) + "% " + CStr(Character.Mana) + "/" + CStr(Character.MaxMana)
    With frmMain.picStatMana
        .Cls
        BitBlt .hdc, 0, 0, Int(frmMain.picStatBarMana.Width * Percent), 17, frmMain.picStatBarMana.hdc, 0, 0, SRCCOPY
        TextOut .hdc, 32, 0, St, Len(St)
        .Refresh
    End With
End Sub
Sub DrawLevel()
Dim Percent As Single, St As String
If Character.MaxExperience > 0 Then
    Percent = Character.Experience / Character.MaxExperience
Else
    Percent = 0
End If
St = CStr(Int(Percent * 100)) + "% " + CStr(Character.Experience) + " / " + CStr(Character.MaxExperience)
With frmMain.picStatLevel
    .Cls
    BitBlt .hdc, 0, 0, Int(frmMain.picStatBarLevel.Width * Percent), 17, frmMain.picStatBarLevel.hdc, 0, 0, SRCCOPY
    TextOut .hdc, 32, 0, St, Len(St)
    .Refresh
End With
End Sub
Sub DrawSkillLevel(Skill As Byte)
Dim Percent As Single, MaxExp As Long, St As String

With Character
    MaxExp = (.SkillLevel(Skill) * 4) + (.SkillLevel(Skill) * .SkillLevel(Skill))

    If MaxExp > 0 Then
        Percent = .SkillExp(Skill) / MaxExp
    Else
        Percent = 0
    End If

    St = CStr(Int(Percent * 100)) + "% " + CStr(.SkillExp(Skill)) + "/" + CStr(MaxExp)
    With frmMain.picSkillStat
        .Cls
        BitBlt .hdc, 0, 0, Int(frmMain.picSkillStatBar.Width * Percent), 17, frmMain.picSkillStatBar.hdc, 0, 0, SRCCOPY
        TextOut .hdc, 36, -2, St, Len(St)
        .Refresh
    End With
End With
End Sub
Sub DrawInvObject(InvNum As Long)
    Dim A As Long, X As Long, Y As Long

    X = 1 + 36 * ((InvNum - 1) Mod 5)
    Y = 1 + 35 * Int((InvNum - 1) / 5)

    With Character.Inv(InvNum)
        If .Object > 0 Then
            A = Object(.Object).Picture
            If A > 0 Then
                If MovableData.CurInvObj = InvNum Then
                    BitBlt hdcInv, X - 1, Y - 1, 34, 34, 0, 0, 0, WHITENESS
                    BitBlt hdcInv, X, Y, 32, 32, 0, 0, 0, BLACKNESS
                    If .EquippedNum > 0 Then
                        TransparentBlt hdcInv, X - 1, Y - 1, 34, 34, hdcGlow, 0, 0, hdcGlowMask
                    End If
                    TransparentBlt hdcInv, X, Y, 32, 32, hdcObjects, 0, CLng(A - 1) * 32, hdcObjectsMask
                Else
                    If .EquippedNum > 0 Then
                        BitBlt hdcInv, X - 1, Y - 1, 34, 34, hdcGlow, 0, 0, SRCCOPY
                        TransparentBlt hdcInv, X, Y, 32, 32, hdcObjects, 0, CLng(A - 1) * 32, hdcObjectsMask
                    Else
                        BitBlt hdcInv, X - 1, Y - 1, 34, 34, 0, 0, 0, BLACKNESS
                        BitBlt hdcInv, X, Y, 32, 32, hdcObjects, 0, CLng(A - 1) * 32, SRCCOPY
                    End If
                End If
            Else
                If MovableData.CurInvObj = InvNum Then
                    BitBlt hdcInv, X - 1, Y - 1, 34, 34, 0, 0, 0, WHITENESS
                Else
                    BitBlt hdcInv, X - 1, Y - 1, 34, 34, 0, 0, 0, BLACKNESS
                End If
            End If
        Else
            If MovableData.CurInvObj = InvNum Then
                BitBlt hdcInv, X - 1, Y - 1, 34, 34, 0, 0, 0, WHITENESS
                BitBlt hdcInv, X, Y, 32, 32, 0, 0, 0, BLACKNESS
            Else
                BitBlt hdcInv, X - 1, Y - 1, 34, 34, 0, 0, 0, BLACKNESS
            End If
        End If
    End With
    
    frmMain.picInv.Refresh
    
    If InvNum = MovableData.CurInvObj Then DrawCurInvObj
End Sub
Sub DrawEquippedArmor()
Dim A As Long

For A = 0 To 4
    frmMain.picEqObj(A).Cls
Next A

For A = 1 To 20
    If Character.Inv(A).EquippedNum > 0 Then
        BitBlt frmMain.picEqObj(Character.Inv(A).EquippedNum - 1).hdc, 0, 0, 32, 32, hdcObjects, 0, CLng(Object(Character.Inv(A).Object).Picture - 1) * 32, SRCCOPY
    End If
Next A
End Sub
Sub OpenMapEdit()
    MovableData.MapEdit = True
    CopyMap EditMap, Map
    frmMain.picMapEdit.Visible = True
    RedrawTiles
    RedrawTile
    DrawMap
End Sub
Sub PrepSourceDC(DC As Long)
    SetBkColor DC, 0
End Sub
Sub PrepTargetDC(DC As Long)
    SetBkColor DC, RGB(255, 255, 255)
    SetTextColor DC, 0
End Sub
Sub FillMap()
Dim MapX As Long, MapY As Long

For MapX = 0 To 11
For MapY = 0 To 11

If MovableData.MapEdit = True Then
        Select Case MovableData.EditMode
            Case 0 'Ground
                EditMap.Tile(MapX, MapY).Ground = MovableData.CurTile
                RedrawMapTile MapX, MapY
            Case 1 'Ground2
                EditMap.Tile(MapX, MapY).Ground2 = MovableData.CurTile
                RedrawMapTile MapX, MapY
            Case 2 'BGTile1
                EditMap.Tile(MapX, MapY).BGTile1 = MovableData.CurTile
                RedrawMapTile MapX, MapY
            Case 3 'BGTile2
                EditMap.Tile(MapX, MapY).BGTile2 = MovableData.CurTile
                RedrawMapTile MapX, MapY
            Case 4 'FGTile
                EditMap.Tile(MapX, MapY).FGTile = MovableData.CurTile
                RedrawMapTile MapX, MapY
            Case 5 'FGTile2
                EditMap.Tile(MapX, MapY).FGTile2 = MovableData.CurTile
                RedrawMapTile MapX, MapY
            Case 6 'Att
                EditMap.Tile(MapX, MapY).Att = MovableData.CurAtt
                EditMap.Tile(MapX, MapY).AttData(0) = CurAttData(0)
                EditMap.Tile(MapX, MapY).AttData(1) = CurAttData(1)
                EditMap.Tile(MapX, MapY).AttData(2) = CurAttData(2)
                EditMap.Tile(MapX, MapY).AttData(3) = CurAttData(3)
                RedrawMapTile MapX, MapY
        End Select
End If

Next MapY
Next MapX

End Sub

Sub ClearMap()
Dim MapX As Long, MapY As Long, A As Long

For MapX = 0 To 11
For MapY = 0 To 11

    Select Case MovableData.EditMode
        Case 0 'Ground
            EditMap.Tile(MapX, MapY).Ground = 0
            RedrawMapTile MapX, MapY
        Case 1 'Ground2
            EditMap.Tile(MapX, MapY).Ground2 = 0
            RedrawMapTile MapX, MapY
        Case 2 'BGTile1
            EditMap.Tile(MapX, MapY).BGTile1 = 0
            RedrawMapTile MapX, MapY
        Case 3 'BGTile1
            EditMap.Tile(MapX, MapY).BGTile2 = 0
            RedrawMapTile MapX, MapY
        Case 4 'FGTile
            EditMap.Tile(MapX, MapY).FGTile = 0
            RedrawMapTile MapX, MapY
        Case 5 'FGTile2
            EditMap.Tile(MapX, MapY).FGTile2 = 0
            RedrawMapTile MapX, MapY
        Case 6 'Att
            EditMap.Tile(MapX, MapY).Att = 0
            EditMap.Tile(MapX, MapY).AttData(0) = 0
            EditMap.Tile(MapX, MapY).AttData(1) = 0
            EditMap.Tile(MapX, MapY).AttData(2) = 0
            EditMap.Tile(MapX, MapY).AttData(3) = 0
            RedrawMapTile MapX, MapY
        End Select
Next MapY
Next MapX

End Sub

Sub DrawGrass()
Dim MapX As Long, MapY As Long

For MapX = 0 To 11
For MapY = 0 To 11

If EditMap.Tile(MapX, MapY).Ground = 0 Then
   EditMap.Tile(MapX, MapY).Ground = Random(24) + 1652
   RedrawMapTile MapX, MapY
End If
        
Next MapY
Next MapX

End Sub
Function RandomTree() As Long
    Select Case Random(7)
        Case 0
            RandomTree = 351
        Case 1
            RandomTree = 352
        Case 2
            RandomTree = 365
        Case 3
            RandomTree = 366
        Case 4
            RandomTree = 379
        Case 5
            RandomTree = 380
        Case 6
            RandomTree = 381
    End Select
End Function

Sub DrawTrees()
Dim A As Long, MapX As Long, MapY As Long

For MapX = 0 To 11
For MapY = 0 To 11

A = RandomTree

If EditMap.Tile(MapX, MapY).Att = 13 Then
    If Map.Tile(MapX, MapY).BGTile1 <> 351 And Map.Tile(MapX, MapY).BGTile1 <> 352 And Map.Tile(MapX, MapY).BGTile1 <> 365 And Map.Tile(MapX, MapY).BGTile1 <> 366 And Map.Tile(MapX, MapY).BGTile1 <> 379 And Map.Tile(MapX, MapY).BGTile1 <> 380 And Map.Tile(MapX, MapY).BGTile1 <> 381 Then
        If EditMap.Tile(MapX, MapY).BGTile1 <> 351 And EditMap.Tile(MapX, MapY).BGTile1 <> 352 And EditMap.Tile(MapX, MapY).BGTile1 <> 365 And EditMap.Tile(MapX, MapY).BGTile1 <> 366 And EditMap.Tile(MapX, MapY).BGTile1 <> 379 And EditMap.Tile(MapX, MapY).BGTile1 <> 380 And EditMap.Tile(MapX, MapY).BGTile1 <> 381 Then
            EditMap.Tile(MapX, MapY).BGTile1 = A
            If MapY > 0 Then EditMap.Tile(MapX, MapY - 1).FGTile2 = A - 7
            If MapY = 11 Then EditMap.Tile(MapX, MapY).FGTile2 = RandomTree - 7
            RedrawMapTile MapX, MapY
            RedrawMapTile MapX, MapY - 1
        End If
    End If
Else
    If EditMap.Tile(MapX, MapY).BGTile1 = 351 Or EditMap.Tile(MapX, MapY).BGTile1 = 352 Or EditMap.Tile(MapX, MapY).BGTile1 = 365 Or EditMap.Tile(MapX, MapY).BGTile1 = 366 Or EditMap.Tile(MapX, MapY).BGTile1 = 379 Or EditMap.Tile(MapX, MapY).BGTile1 = 380 Or EditMap.Tile(MapX, MapY).BGTile1 = 381 Then
        EditMap.Tile(MapX, MapY).BGTile1 = 0
        If MapY > 0 Then EditMap.Tile(MapX, MapY - 1).FGTile2 = 0
        If MapY = 11 Then EditMap.Tile(MapX, MapY).FGTile2 = 0
        RedrawMapTile MapX, MapY
        RedrawMapTile MapX, MapY - 1
    End If
End If
        
Next MapY
Next MapX

End Sub

Sub DrawMap()
    Dim A As Long, B As Long, C As Long, X As Long, Y As Long
    BitBlt hdcBack(0), 0, 0, 384, 384, 0, 0, 0, BLACKNESS
    BitBlt hdcBack(1), 0, 0, 384, 384, 0, 0, 0, BLACKNESS
    BitBlt hdcBack(2), 0, 0, 384, 384, 0, 0, 0, BLACKNESS
    BitBlt hdcFront(0), 0, 0, 384, 384, 0, 0, 0, BLACKNESS
    BitBlt hdcFront(1), 0, 0, 384, 384, 0, 0, 0, BLACKNESS
    BitBlt hdcFrontMask(0), 0, 0, 384, 384, 0, 0, 0, WHITENESS
    BitBlt hdcFrontMask(1), 0, 0, 384, 384, 0, 0, 0, WHITENESS
    
    If MovableData.MapEdit = False Then
        For X = 0 To 11
            For Y = 0 To 11
                With Map.Tile(X, Y)
                    If .Ground > 0 Then
                        For A = 0 To 2
                            BitBlt hdcBack(A), X * 32, Y * 32, 32, 32, hdcTiles, ((.Ground - 1) Mod 7) * 32, Int((.Ground - 1) / 7) * 32, SRCCOPY
                        Next A
                    End If
                    If .Ground2 > 0 Then
                        For A = 0 To 2
                            TransparentBlt hdcBack(A), X * 32, Y * 32, 32, 32, hdcTiles, ((.Ground2 - 1) Mod 7) * 32, Int((.Ground2 - 1) / 7) * 32, hdcTilesMask
                        Next A
                    End If
                    If .BGTile1 > 0 Then
                        For A = 1 To 2
                            If .BGTile2 = 0 Then
                                TransparentBlt hdcBack(A), X * 32, Y * 32, 32, 32, hdcTiles, ((.BGTile1 - 1) Mod 7) * 32, Int((.BGTile1 - 1) / 7) * 32, hdcTilesMask
                            Else
                                TransparentBlt hdcBack(1), X * 32, Y * 32, 32, 32, hdcTiles, ((.BGTile1 - 1) Mod 7) * 32, Int((.BGTile1 - 1) / 7) * 32, hdcTilesMask
                            End If
                        Next A
                    End If
                    If .BGTile2 > 0 Then
                        TransparentBlt hdcBack(2), X * 32, Y * 32, 32, 32, hdcTiles, ((.BGTile2 - 1) Mod 7) * 32, Int((.BGTile2 - 1) / 7) * 32, hdcTilesMask
                    End If
                    If .FGTile > 0 Then
                        BitBlt hdcFront(0), X * 32, Y * 32, 32, 32, hdcTiles, ((.FGTile - 1) Mod 7) * 32, Int((.FGTile - 1) / 7) * 32, SRCCOPY
                        BitBlt hdcFrontMask(0), X * 32, Y * 32, 32, 32, hdcTilesMask, ((.FGTile - 1) Mod 7) * 32, Int((.FGTile - 1) / 7) * 32, SRCCOPY
                    End If
                    If .FGTile2 > 0 Then
                        BitBlt hdcFront(1), X * 32, Y * 32, 32, 32, hdcTiles, ((.FGTile2 - 1) Mod 7) * 32, Int((.FGTile2 - 1) / 7) * 32, SRCCOPY
                        BitBlt hdcFrontMask(1), X * 32, Y * 32, 32, 32, hdcTilesMask, ((.FGTile2 - 1) Mod 7) * 32, Int((.FGTile2 - 1) / 7) * 32, SRCCOPY
                    End If
                End With
            Next Y
        Next X
    Else
        For X = 0 To 11
            For Y = 0 To 11
                With EditMap.Tile(X, Y)
                    If .Ground > 0 Then
                        For A = 0 To 2
                            BitBlt hdcBack(A), X * 32, Y * 32, 32, 32, hdcTiles, ((.Ground - 1) Mod 7) * 32, Int((.Ground - 1) / 7) * 32, SRCCOPY
                        Next A
                    End If
                    If .Ground2 > 0 Then
                        For A = 0 To 2
                            TransparentBlt hdcBack(A), X * 32, Y * 32, 32, 32, hdcTiles, ((.Ground2 - 1) Mod 7) * 32, Int((.Ground2 - 1) / 7) * 32, hdcTilesMask
                        Next A
                    End If
                    If .BGTile1 > 0 Then
                        For A = 0 To 2
                            If .BGTile2 = 0 Then
                                TransparentBlt hdcBack(A), X * 32, Y * 32, 32, 32, hdcTiles, ((.BGTile1 - 1) Mod 7) * 32, Int((.BGTile1 - 1) / 7) * 32, hdcTilesMask
                            Else
                                TransparentBlt hdcBack(1), X * 32, Y * 32, 32, 32, hdcTiles, ((.BGTile1 - 1) Mod 7) * 32, Int((.BGTile1 - 1) / 7) * 32, hdcTilesMask
                            End If
                        Next A
                    End If
                    If .BGTile2 > 0 Then
                        TransparentBlt hdcBack(2), X * 32, Y * 32, 32, 32, hdcTiles, ((.BGTile2 - 1) Mod 7) * 32, Int((.BGTile2 - 1) / 7) * 32, hdcTilesMask
                    End If
                    If .FGTile > 0 Then
                        BitBlt hdcFront(0), X * 32, Y * 32, 32, 32, hdcTiles, ((.FGTile - 1) Mod 7) * 32, Int((.FGTile - 1) / 7) * 32, SRCCOPY
                        BitBlt hdcFrontMask(0), X * 32, Y * 32, 32, 32, hdcTilesMask, ((.FGTile - 1) Mod 7) * 32, Int((.FGTile - 1) / 7) * 32, SRCCOPY
                    End If
                    If .FGTile2 > 0 Then
                        BitBlt hdcFront(1), X * 32, Y * 32, 32, 32, hdcTiles, ((.FGTile2 - 1) Mod 7) * 32, Int((.FGTile2 - 1) / 7) * 32, SRCCOPY
                        BitBlt hdcFrontMask(1), X * 32, Y * 32, 32, 32, hdcTilesMask, ((.FGTile2 - 1) Mod 7) * 32, Int((.FGTile2 - 1) / 7) * 32, SRCCOPY
                    End If
                    If .Att > 0 And MovableData.EditMode = 6 Or .Att > 0 And frmMain.chkAtts Then
                        BitBlt hdcFront(1), X * 32 + 8, Y * 32 + 8, 16, 16, frmMain.picAtts.hdc, ((.Att - 1) Mod 7) * 32 + 8, Int((.Att - 1) / 7) * 32 + 8, SRCCOPY
                        BitBlt hdcFrontMask(1), X * 32 + 7, Y * 32 + 7, 17, 17, 0, 0, 0, BLACKNESS
                    End If
                End With
            Next Y
        Next X
    End If
    For A = 0 To 79
        With Map.Object(A)
            If .Object > 0 Then
                B = Object(.Object).Picture
                If B > 0 Then
                    For C = 0 To 2
                        TransparentBlt hdcBack(C), .X * 32, .Y * 32, 32, 32, hdcObjects, 0, (B - 1) * 32, hdcObjectsMask
                    Next C
                End If
            End If
        End With
    Next A
    If MovableData.MapEdit = False Then
        If ExamineBit(Map.Flags, 2) Then
            TransparentBlt hdcFront(1), 0, 0, 384, 384, hdcDarkness, 0, 0, hdcDarknessMask
            TransparentBlt hdcFrontMask(1), 0, 0, 384, 384, hdcDarkness, 0, 0, hdcDarknessMask
        End If
    End If
End Sub
Function ReadInt(lpAppName, lpKeyName$) As Integer
    ReadInt = GetPrivateProfileInt&(lpAppName, lpKeyName$, 0, App.Path + "\Modus.ini")
End Function
Function ReadString(lpAppName, lpKeyName As String) As String
    Dim lpReturnedString As String, Valid As Long
    lpReturnedString = Space$(256)
    Valid = GetPrivateProfileString&(lpAppName, lpKeyName, "", lpReturnedString, 256, App.Path + "\Modus.ini")
    ReadString = Left$(lpReturnedString, Valid)
End Function
Function Settings(lpAppName, lpKeyName As String) As String
    Dim lpReturnedString As String, Valid As Long
    lpReturnedString = Space$(256)
    Valid = GetPrivateProfileString&(lpAppName, lpKeyName, "", lpReturnedString, 256, App.Path + "\Settings.ini")
    Settings = Left$(lpReturnedString, Valid)
End Function
Sub RedrawMapTile(X As Long, Y As Long)
    Dim A As Long, B As Long, C As Long
    If X >= 0 And X <= 11 And Y >= 0 And Y <= 11 Then
        If MovableData.MapEdit = False Then
            With Map.Tile(X, Y)
                If .Ground > 0 Then
                    For A = 0 To 2
                        BitBlt hdcBack(A), X * 32, Y * 32, 32, 32, hdcTiles, ((.Ground - 1) Mod 7) * 32, Int((.Ground - 1) / 7) * 32, SRCCOPY
                    Next A
                Else
                    For A = 0 To 2
                        BitBlt hdcBack(A), X * 32, Y * 32, 32, 32, 0, 0, 0, BLACKNESS
                    Next A
                End If
                If .Ground2 > 0 Then
                    For A = 0 To 2
                        TransparentBlt hdcBack(A), X * 32, Y * 32, 32, 32, hdcTiles, ((.Ground2 - 1) Mod 7) * 32, Int((.Ground2 - 1) / 7) * 32, hdcTilesMask
                    Next A
                End If
                If .BGTile1 > 0 Then
                    For A = 0 To 2
                        If .BGTile2 = 0 Then
                            TransparentBlt hdcBack(A), X * 32, Y * 32, 32, 32, hdcTiles, ((.BGTile1 - 1) Mod 7) * 32, Int((.BGTile1 - 1) / 7) * 32, hdcTilesMask
                        Else
                            TransparentBlt hdcBack(1), X * 32, Y * 32, 32, 32, hdcTiles, ((.BGTile1 - 1) Mod 7) * 32, Int((.BGTile1 - 1) / 7) * 32, hdcTilesMask
                        End If
                    Next A
                End If
                If .BGTile2 > 0 Then
                    TransparentBlt hdcBack(2), X * 32, Y * 32, 32, 32, hdcTiles, ((.BGTile2 - 1) Mod 7) * 32, Int((.BGTile2 - 1) / 7) * 32, hdcTilesMask
                End If
            End With
        Else
            With EditMap.Tile(X, Y)
                If .Ground > 0 Then
                    For A = 0 To 2
                        BitBlt hdcBack(A), X * 32, Y * 32, 32, 32, hdcTiles, ((.Ground - 1) Mod 7) * 32, Int((.Ground - 1) / 7) * 32, SRCCOPY
                    Next A
                Else
                    For A = 0 To 2
                        BitBlt hdcBack(A), X * 32, Y * 32, 32, 32, 0, 0, 0, BLACKNESS
                    Next A
                End If
                If .Ground2 > 0 Then
                    For A = 0 To 2
                        TransparentBlt hdcBack(A), X * 32, Y * 32, 32, 32, hdcTiles, ((.Ground2 - 1) Mod 7) * 32, Int((.Ground2 - 1) / 7) * 32, hdcTilesMask
                    Next A
                End If
                If .BGTile1 > 0 Then
                    For A = 0 To 2
                        If .BGTile2 = 0 Then
                            TransparentBlt hdcBack(A), X * 32, Y * 32, 32, 32, hdcTiles, ((.BGTile1 - 1) Mod 7) * 32, Int((.BGTile1 - 1) / 7) * 32, hdcTilesMask
                        Else
                            TransparentBlt hdcBack(1), X * 32, Y * 32, 32, 32, hdcTiles, ((.BGTile1 - 1) Mod 7) * 32, Int((.BGTile1 - 1) / 7) * 32, hdcTilesMask
                        End If
                    Next A
                End If
                If .BGTile2 > 0 Then
                    TransparentBlt hdcBack(2), X * 32, Y * 32, 32, 32, hdcTiles, ((.BGTile2 - 1) Mod 7) * 32, Int((.BGTile2 - 1) / 7) * 32, hdcTilesMask
                End If
                If .FGTile > 0 Then
                    BitBlt hdcFront(0), X * 32, Y * 32, 32, 32, hdcTiles, ((.FGTile - 1) Mod 7) * 32, Int((.FGTile - 1) / 7) * 32, SRCCOPY
                    BitBlt hdcFrontMask(0), X * 32, Y * 32, 32, 32, hdcTilesMask, ((.FGTile - 1) Mod 7) * 32, Int((.FGTile - 1) / 7) * 32, SRCCOPY
                Else
                    BitBlt hdcFront(0), X * 32, Y * 32, 32, 32, 0, 0, 0, BLACKNESS
                    BitBlt hdcFrontMask(0), X * 32, Y * 32, 32, 32, 0, 0, 0, WHITENESS
                End If
                If .FGTile2 > 0 Then
                    BitBlt hdcFront(1), X * 32, Y * 32, 32, 32, hdcTiles, ((.FGTile2 - 1) Mod 7) * 32, Int((.FGTile2 - 1) / 7) * 32, SRCCOPY
                    BitBlt hdcFrontMask(1), X * 32, Y * 32, 32, 32, hdcTilesMask, ((.FGTile2 - 1) Mod 7) * 32, Int((.FGTile2 - 1) / 7) * 32, SRCCOPY
                Else
                    BitBlt hdcFront(1), X * 32, Y * 32, 32, 32, 0, 0, 0, BLACKNESS
                    BitBlt hdcFrontMask(1), X * 32, Y * 32, 32, 32, 0, 0, 0, WHITENESS
                End If
                If .Att > 0 And MovableData.EditMode = 6 Or .Att > 0 And frmMain.chkAtts Then
                    BitBlt hdcFront(1), X * 32 + 8, Y * 32 + 8, 16, 16, frmMain.picAtts.hdc, ((.Att - 1) Mod 7) * 32 + 8, Int((.Att - 1) / 7) * 32 + 8, SRCCOPY
                    BitBlt hdcFrontMask(1), X * 32 + 7, Y * 32 + 7, 17, 17, 0, 0, 0, BLACKNESS
                End If
            End With
        End If
        For A = 0 To 79
            With Map.Object(A)
                If .Object > 0 And .X = X And .Y = Y Then
                    B = Object(.Object).Picture
                    If B > 0 Then
                        For C = 0 To 2
                            TransparentBlt hdcBack(C), .X * 32, .Y * 32, 32, 32, hdcObjects, 0, (B - 1) * 32, hdcObjectsMask
                        Next C
                    End If
                End If
            End With
        Next A
    End If
End Sub
Sub Transition()
    Dim A As Long, T As Long
    
    Select Case MovableData.NextTransition
        Case 1
            DrawNextFrame
            PlayWav 1
            For A = 1 To 255
                If FloatText(A).Text <> "" Then DestroyFloatText (A)
                If StaticText(A).Text <> "" Then DestroyStaticText (A)
                If A <= 75 Then Player(A).HP = 0
            Next A
            For A = 0 To 9
                Map.Monster(A).HP = 0
            Next A
            frmMain.picViewport.Refresh

        Case 5 'Warp
            For A = 0 To 192 Step 4
                T = timeGetTime
                BitBlt hdcViewport, A, A, 383 - 2 * A, 4, hdcBuffer, A, A, SRCCOPY
                BitBlt hdcViewport, A, 379 - A, 383 - 2 * A, 4, hdcBuffer, A, 379 - A, SRCCOPY
                BitBlt hdcViewport, A, A, 4, 383 - 2 * A, hdcBuffer, A, A, SRCCOPY
                BitBlt hdcViewport, 379 - A, A, 4, 383 - 2 * A, hdcBuffer, 379 - A, A, SRCCOPY
                While timeGetTime - T < 0
                Wend
                frmMain.picViewport.Refresh
            Next A
            PlayWav 6
            For A = 1 To 255
                If FloatText(A).Text <> "" Then DestroyFloatText (A)
                If StaticText(A).Text <> "" Then DestroyStaticText (A)
                If A <= 75 Then Player(A).HP = 0
            Next A
            For A = 0 To 9
                Map.Monster(A).HP = 0
            Next A
            frmMain.picViewport.Refresh
        Case Else
            PlayWav 6
            For A = 1 To 255
                If FloatText(A).Text <> "" Then DestroyFloatText (A)
                If StaticText(A).Text <> "" Then DestroyStaticText (A)
                If A <= 75 Then Player(A).HP = 0
            Next A
            For A = 0 To 9
                Map.Monster(A).HP = 0
            Next A
        End Select
    MovableData.NextTransition = 0
End Sub
Sub UpdatePlayerColor(Index As Long)
    Dim A As Long
    With Player(Index)
        If .Guild > 0 Then
            If .Guild = Character.Guild Then
                .Color = 11
            Else
                .Color = 15
                If Character.Guild > 0 Then
                    For A = 0 To 4
                        If Character.GuildDeclaration(A).Guild = .Guild Then
                            If Character.GuildDeclaration(A).Type = 0 Then
                                .Color = 10
                            Else
                                .Color = 12
                            End If
                        End If
                    Next A
                End If
            End If
        Else
            .Color = 7
        End If
    End With
End Sub
Sub UpdatePlayersColors()
    Dim A As Long, B As Long, C As Long
    For A = 1 To 255
        UpdatePlayerColor A
    Next A
End Sub
Sub UpdateSaleItem(A As Long)
    Dim St As String
    With SaleItem(A)
        If .GiveObject >= 1 And .TakeObject >= 1 Then
            St = CStr(A) + ": "
            If Object(.GiveObject).Type = 6 Then
                'Money
                St = St + CStr(.GiveValue) + " " + Object(.GiveObject).Name
            Else
                St = St + "1 " + Object(.GiveObject).Name
            End If
            St = St + " in exchange for "
            If Object(.TakeObject).Type = 6 Then
                'Money
                St = St + CStr(.TakeValue) + " " + Object(.TakeObject).Name
            Else
                St = St + "1 " + Object(.TakeObject).Name
            End If
            frmNPC.lstSaleItems.List(A) = St
        Else
            frmNPC.lstSaleItems.List(A) = CStr(A) + ":"
        End If
    End With
End Sub
Sub WriteString(lpAppName, lpKeyName As String, A)
    Dim lpString As String, Valid As Long
    lpString = A
    Valid = WritePrivateProfileString&(lpAppName, lpKeyName, lpString, App.Path + "\Modus.ini")
End Sub

Sub CheckKeys()
    Dim A As Long, B As Long, C As Long, D As Long
    Dim Att As Long
    
    If Character.Access > 0 And MovableData.keyAlt = True Then frmMain.MapTimer.Enabled = False
    
If MovableData.Dead = False Then
    If MovableData.keyCtrl = True Then
        If MovableData.AttackTime <> 999 Then
            DeInitialize
        End If
        
        If timeGetTime - MovableData.AttackTimer >= MovableData.AttackTime Then
            MovableData.AttackTimer = timeGetTime
            Dim TX As Long, TY As Long
            Select Case MovableData.CDir
                Case 0
                    TX = MovableData.cx
                    TY = MovableData.cy - 1
                Case 1
                    TX = MovableData.cx
                    TY = MovableData.cy + 1
                Case 2
                    TX = MovableData.cx - 1
                    TY = MovableData.cy
                Case 3
                    TX = MovableData.cx + 1
                    TY = MovableData.cy
            End Select
            If TX >= 0 And TX <= 11 And TY >= 0 And TY <= 11 Then
            Att = Map.Tile(MovableData.cx, MovableData.cy).Att
                For A = 0 To 9
                    With Map.Monster(A)
                        If .Monster > 0 And .X = TX And .Y = TY Then
                            If Att = 12 Then
                                Select Case MovableData.CDir
                                    Case 0
                                        If ExamineBit(Map.Tile(MovableData.cx, MovableData.cy).AttData(0), CByte(1)) Then
                                            PrintInfoText "There is nobody there to attack!"
                                            Exit For
                                        End If
                                    Case 1
                                        If ExamineBit(Map.Tile(MovableData.cx, MovableData.cy).AttData(0), CByte(3)) Then
                                            PrintInfoText "There is nobody there to attack!"
                                            Exit For
                                        End If
                                    Case 2
                                        If ExamineBit(Map.Tile(MovableData.cx, MovableData.cy).AttData(0), CByte(5)) Then
                                            PrintInfoText "There is nobody there to attack!"
                                            Exit For
                                        End If
                                    Case 3
                                        If ExamineBit(Map.Tile(MovableData.cx, MovableData.cy).AttData(0), CByte(7)) Then
                                            PrintInfoText "There is nobody there to attack!"
                                            Exit For
                                        End If
                                End Select
                            End If
                            SendSocket Chr$(26) + Chr$(A)
                            SendSocket Chr$(76) + Chr$(0) + Chr$(MovableData.CurInvObj)
                            Exit For
                        End If
                    End With
                Next A
                If A = 10 Then
                    For A = 1 To 255
                        With Player(A)
                            If .Dead = False And .Map = MovableData.CMap And .X = TX And .Y = TY Then
                                If Att = 12 Then
                                    Select Case MovableData.CDir
                                        Case 0
                                            If ExamineBit(Map.Tile(MovableData.cx, MovableData.cy).AttData(0), CByte(1)) Then
                                                PrintInfoText "There is nobody there to attack!"
                                                Exit For
                                            End If
                                        Case 1
                                            If ExamineBit(Map.Tile(MovableData.cx, MovableData.cy).AttData(0), CByte(3)) Then
                                                PrintInfoText "There is nobody there to attack!"
                                                Exit For
                                            End If
                                        Case 2
                                            If ExamineBit(Map.Tile(MovableData.cx, MovableData.cy).AttData(0), CByte(5)) Then
                                                PrintInfoText "There is nobody there to attack!"
                                                Exit For
                                            End If
                                        Case 3
                                            If ExamineBit(Map.Tile(MovableData.cx, MovableData.cy).AttData(0), CByte(7)) Then
                                                PrintInfoText "There is nobody there to attack!"
                                                Exit For
                                            End If
                                    End Select
                                ElseIf Att = 16 Or Map.Tile(.X, .Y).Att = 16 Then
                                    PrintChat "This is a friendly area, you cannot attack here!", 7
                                    Exit For
                                End If
                                SendSocket Chr$(25) + Chr$(A)
                                SendSocket Chr$(76) + Chr$(0) + Chr$(MovableData.CurInvObj)
                                Exit For
                            End If
                        End With
                    Next A
                    If A = 256 Then
                        PrintInfoText "There is nobody there to attack!"
                    End If
                End If
            Else
                PrintInfoText "There is nobody there to attack!"
            End If
        End If
    End If
    If MovableData.cx * 32 = MovableData.CXO And MovableData.cy * 32 = MovableData.CYO Then
        #If CHEATS Then
        If AutoAttack = False Then
        #End If
            If MovableData.keyShift = True And Character.Energy > 0 Then
                MovableData.CWalkStep = RunSpeed
            Else
                If MovableData.keyAlt = True And Character.Access <> 0 Then
                    MovableData.CWalkStep = GodSpeed
                ElseIf MovableData.keyAlt = True And Character.Access <> 0 Then
                Else
                    MovableData.CWalkStep = WalkSpeed
                End If
            End If
            
            If MovableData.keyUp = True Then
                If MovableData.CDir = 0 Then
                    If MovableData.cy > 0 Then
                        If Character.Access > 0 And MovableData.keyAlt = True Then
                            MovableData.cy = MovableData.cy - 1
                            MoveToTile
                        Else
                            If Map.Tile(MovableData.cx, MovableData.cy).Att <> 12 Or Map.Tile(MovableData.cx, MovableData.cy).Att = 12 And ExamineBit(Map.Tile(MovableData.cx, MovableData.cy).AttData(0), CByte(1)) = False Then
                                If IsVacant(MovableData.cx, MovableData.cy - 1) Then
                                    MovableData.cy = MovableData.cy - 1
                                    MoveToTile
                                End If
                            End If
                        End If
                    Else
                        If Map.ExitUp > 0 And frmMain.MapTimer.Enabled = False Then
                            SendSocket Chr$(13) + Chr$(0)
                            MovableData.Freeze = True
                            MovableData.NextTransition = 1
                            If Character.Access = 0 Or Character.Access > 0 And MovableData.keyAlt = False Then
                                frmMain.MapTimer.Enabled = True
                            End If
                        End If
                    End If
                Else
                    MovableData.CDir = 0
                    SendSocket Chr$(7) + Chr$(MovableData.CWalkCode) + Chr$(MovableData.cx) + Chr$(MovableData.cy) + Chr$(MovableData.CDir) + Chr$(MovableData.CWalkStep)
                End If
            ElseIf MovableData.keyDown = True Then
                If MovableData.CDir = 1 Then
                    If MovableData.cy < 11 Then
                        If Character.Access > 0 And MovableData.keyAlt = True Then
                            MovableData.cy = MovableData.cy + 1
                            MoveToTile
                        Else
                            If Map.Tile(MovableData.cx, MovableData.cy).Att <> 12 Or Map.Tile(MovableData.cx, MovableData.cy).Att = 12 And ExamineBit(Map.Tile(MovableData.cx, MovableData.cy).AttData(0), CByte(3)) = False Then
                                If IsVacant(MovableData.cx, MovableData.cy + 1) Then
                                    MovableData.cy = MovableData.cy + 1
                                    MoveToTile
                                End If
                            End If
                        End If
                    Else
                        If Map.ExitDown > 0 And frmMain.MapTimer.Enabled = False Then
                            SendSocket Chr$(13) + Chr$(1)
                            MovableData.Freeze = True
                            MovableData.NextTransition = 1
                        If Character.Access = 0 Or Character.Access > 0 And MovableData.keyAlt = False Then
                            frmMain.MapTimer.Enabled = True
                        End If
                        End If
                    End If
                Else
                    MovableData.CDir = 1
                    SendSocket Chr$(7) + Chr$(MovableData.CWalkCode) + Chr$(MovableData.cx) + Chr$(MovableData.cy) + Chr$(MovableData.CDir) + Chr$(MovableData.CWalkStep)
                End If
            ElseIf MovableData.keyLeft = True Then
                If MovableData.CDir = 2 Then
                    If MovableData.cx > 0 Then
                        If Character.Access > 0 And MovableData.keyAlt = True Then
                            MovableData.cx = MovableData.cx - 1
                            MoveToTile
                        Else
                            If Map.Tile(MovableData.cx, MovableData.cy).Att <> 12 Or Map.Tile(MovableData.cx, MovableData.cy).Att = 12 And ExamineBit(Map.Tile(MovableData.cx, MovableData.cy).AttData(0), CByte(5)) = False Then
                                If IsVacant(MovableData.cx - 1, MovableData.cy) Then
                                    MovableData.cx = MovableData.cx - 1
                                    MoveToTile
                                End If
                            End If
                        End If
                    Else
                        If Map.ExitLeft > 0 And frmMain.MapTimer.Enabled = False Then
                            SendSocket Chr$(13) + Chr$(2)
                            MovableData.Freeze = True
                            MovableData.NextTransition = 1
                        If Character.Access = 0 Or Character.Access > 0 And MovableData.keyAlt = False Then
                            frmMain.MapTimer.Enabled = True
                        End If
                        End If
                    End If
                Else
                    MovableData.CDir = 2
                    SendSocket Chr$(7) + Chr$(MovableData.CWalkCode) + Chr$(MovableData.cx) + Chr$(MovableData.cy) + Chr$(MovableData.CDir) + Chr$(MovableData.CWalkStep)
                End If
            ElseIf MovableData.keyRight = True Then
                If MovableData.CDir = 3 Then
                    If MovableData.cx < 11 Then
                        If Character.Access > 0 And MovableData.keyAlt = True Then
                            MovableData.cx = MovableData.cx + 1
                            MoveToTile
                        Else
                            If Map.Tile(MovableData.cx, MovableData.cy).Att <> 12 Or Map.Tile(MovableData.cx, MovableData.cy).Att = 12 And ExamineBit(Map.Tile(MovableData.cx, MovableData.cy).AttData(0), CByte(7)) = False Then
                                If IsVacant(MovableData.cx + 1, MovableData.cy) Then
                                    MovableData.cx = MovableData.cx + 1
                                    MoveToTile
                               End If
                            End If
                        End If
                    Else
                        If Map.ExitRight > 0 And frmMain.MapTimer.Enabled = False Then
                            SendSocket Chr$(13) + Chr$(3)
                            MovableData.Freeze = True
                            MovableData.NextTransition = 1
                        If Character.Access = 0 Or Character.Access > 0 And MovableData.keyAlt = False Then
                            frmMain.MapTimer.Enabled = True
                        End If
                        End If
                    End If
                Else
                    MovableData.CDir = 3
                    SendSocket Chr$(7) + Chr$(MovableData.CWalkCode) + Chr$(MovableData.cx) + Chr$(MovableData.cy) + Chr$(MovableData.CDir) + Chr$(MovableData.CWalkStep)
                End If
            End If
        #If CHEATS Then
        Else
            If TargetMonster >= 0 Then
                With Map.Monster(TargetMonster)
                    If .Monster > 0 Then
                        If (Abs(MovableData.cx - .X) + Abs(MovableData.cy - .Y)) > 1 Then
                            'Pick up any gold
                            For A = 0 To 79
                                With Map.Object(A)
                                    If .Object = 1 And .X = MovableData.cx And .Y = MovableData.cy Then
                                        SendSocket Chr$(8) + Chr$(A)
                                    End If
                                End With
                            Next A
                            
                            'Move
                            CWalkStep = AutoAttackWalk
                            If MovableData.cx < .X Then
                                If IsVacant(MovableData.cx + 1, MovableData.cy) Then
                                    MovableData.cx = MovableData.cx + 1
                                    CDir = 3
                                End If
                            ElseIf MovableData.cx > .X Then
                                If IsVacant(MovableData.cx - 1, MovableData.cy) Then
                                    MovableData.cx = MovableData.cx - 1
                                    CDir = 2
                                End If
                            End If
                            If MovableData.cx * 32 = CXO And MovableData.cy * 32 = CYO Then
                                If MovableData.cy < .Y Then
                                    If IsVacant(MovableData.cx, MovableData.cy + 1) Then
                                        MovableData.cy = MovableData.cy + 1
                                        CDir = 1
                                    End If
                                ElseIf MovableData.cy > .Y Then
                                    If IsVacant(MovableData.cx, MovableData.cy - 1) Then
                                        MovableData.cy = MovableData.cy - 1
                                        CDir = 0
                                    End If
                                End If
                            End If
                            SendSocket Chr$(7) + Chr$(CWalkCode) + Chr$(MovableData.cx) + Chr$(MovableData.cy) + Chr$(CDir) + Chr$(CWalkStep)
                        Else
                            If MovableData.cx < .X Then
                                A = 3
                            ElseIf MovableData.cx > .X Then
                                A = 2
                            ElseIf MovableData.cy < .Y Then
                                A = 1
                            Else
                                A = 0
                            End If
                            
                            If CDir <> A Then
                                CDir = A
                                SendSocket Chr$(7) + Chr$(CWalkCode) + Chr$(MovableData.cx) + Chr$(MovableData.cy) + Chr$(CDir) + Chr$(CWalkStep)
                            End If
                            
                            'Attack
                            If timeGetTime - AttackTimer >= AutoAttackSpeed Then
                                AttackTimer = timeGetTime
                                SendSocket Chr$(26) + Chr$(TargetMonster)
                            End If
                        End If
                    Else
                        TargetMonster = -1
                    End If
                End With
            Else
                B = 99999
                For A = 0 To 9
                    With Map.Monster(A)
                        If .Monster > 0 Then
                            C = (MovableData.cx - .X) ^ 2 + (MovableData.cy - .Y) ^ 2
                            If C < B Then
                                TargetMonster = A
                                B = C
                            End If
                        End If
                    End With
                Next A
            End If
        End If
        #End If
    End If
End If

End Sub
Function FreeRain() As Long
Dim A As Long
    For A = 1 To 255
        If Rain(A).Frame = 0 Then
            FreeRain = A
            Exit Function
        End If
    Next A
End Function
Function FreeSnow() As Long
Dim A As Long
    For A = 1 To 255
        If Snow(A).Frame = 0 Then
            FreeSnow = A
            Exit Function
        End If
    Next A
End Function

Sub DrawRain()
Dim A As Long, B As Long

For B = 0 To 5
    If Int(Rnd * 10) <= Options.WeatherInt Then
        A = FreeRain
        Rain(A).Frame = 1
    End If
Next B
For A = 1 To 255
    With Rain(A)
        If .Frame > 0 And .Frame < 40 Then
            If .Frame = 1 Then
                .XO = Int(Rnd * 384)
                .YO = Int(Rnd * 384)
            End If
            .Frame = .Frame + 1
            TransparentBlt hdcBuffer, .XO - 50 + .Frame * 2, .YO - 150 + .Frame * 4, 15, 15, hdcWeather, 0, 15, hdcWeatherMask
        Else
            If .Frame = 40 Then TransparentBlt hdcBuffer, .XO + 30, .YO + 10, 15, 15, hdcWeather, 15, 15, hdcWeatherMask
            .Frame = 0
        End If
    End With
Next A

End Sub
Sub DrawMonsterHP()
Dim A As Long, B As Long, HP As Long, MaxHP As Long
Dim Percent As Single
    For A = 0 To 9
        With Map.Monster(A)
            If .Monster > 0 Then
                HP = .HP
                MaxHP = Monster(.Monster).MaxHP
                If HP > 0 And MaxHP > 0 Then
                    Percent = HP / MaxHP * 28
                    If Options.MonsterNames = True Then
                        B = .XO - 2
                        If B < 0 Then B = 0
                        TransparentBlt hdcBuffer, B, .YO - 14, 2, 28, hdcHPBar, 0, 0, hdcHPBarMask
                        TransparentBlt hdcBuffer, B, .YO + 14 - Int(Percent), 2, Int(Percent), hdcHPBar, 2, 0, hdcHPBarMask
                    Else
                        TransparentBlt hdcBuffer, .XO + 2, .YO - 19, 28, 2, hdcHPBar, 0, 28, hdcHPBarMask
                        TransparentBlt hdcBuffer, .XO + 2, .YO - 19, Int(Percent), 2, hdcHPBar, 0, 30, hdcHPBarMask
                    End If
                End If
            End If
        End With
    Next A
End Sub
Sub DrawPlayerHP()
Dim A As Long
Dim Percent As Single
    For A = 1 To 75
        With Player(A)
            If .Map = MovableData.CMap Then
                If .HP > 0 And .MaxHP > 0 And .HP <> .MaxHP Then
                    Percent = .HP / .MaxHP * 28
                    A = .XO - 2
                    If A < 0 Then A = 0
                    TransparentBlt hdcBuffer, A, .YO - 14, 2, 28, hdcHPBar, 0, 0, hdcHPBarMask
                    TransparentBlt hdcBuffer, A, .YO + 14 - Int(Percent), 2, Int(Percent), hdcHPBar, 2, 0, hdcHPBarMask
                End If
            End If
        End With
    Next A
End Sub
Sub DrawCharacterHP()
Dim Percent As Single, A As Long
    With Character
        If .HP > 0 And .MaxHP > 0 And .HP <> .MaxHP Then
            Percent = .HP / .MaxHP * 28
            A = MovableData.CXO - 2
            If A < 0 Then A = 0
            TransparentBlt hdcBuffer, A, MovableData.CYO - 14, 2, 28, hdcHPBar, 0, 0, hdcHPBarMask
            TransparentBlt hdcBuffer, A, MovableData.CYO + 14 - Int(Percent), 2, Int(Percent), hdcHPBar, 2, 0, hdcHPBarMask
        End If
    End With
End Sub
Sub DrawSnow()
Dim A As Long, B As Long

For B = 0 To 2
    If Int(Rnd * 10) <= Options.WeatherInt Then
        A = FreeSnow
        Snow(A).Frame = 1
    End If
Next B
    For A = 1 To 255
        With Snow(A)
            If .Frame > 0 And .Frame < 75 Then
                If .Frame = 1 Then
                    .XO = Int(Rnd * 384)
                    .YO = Int(Rnd * 384)
                End If
                .Frame = .Frame + 1
                Select Case Int(Rnd * 3)
                    Case 0
                        .XO = .XO
                    Case 1
                        .XO = .XO + 1
                    Case 2
                        .XO = .XO - 1
                End Select
                If .Sprite = 0 Then
                    .Sprite = 1 + Int(Rnd * 2)
                ElseIf .Sprite = 1 Then
                    TransparentBlt hdcBuffer, .XO, .YO - 75 + .Frame, 16, 16, hdcWeather, 0, 0, hdcWeatherMask
                ElseIf .Sprite = 2 Then
                    SetTextColor hdcBuffer, QBColor(15)
                    TextOut hdcBuffer, .XO, .YO - 75 + .Frame, ".", 1
                End If
            Else
                .Frame = 0
                .Sprite = 0
            End If
        End With
    Next A

End Sub
Sub DrawFloatText()
Dim A As Long, B As Long
Dim R As RECT

For A = 1 To 255
    With FloatText(A)
        If .Frame <= 35 Then
            If .Text <> "" Then
                .Frame = .Frame + 1
                    Select Case .D
                        Case 0 'Up
                            R.Left = (.X * 32) - 64
                            R.Right = (.X * 32) + 96
                            R.Top = (.Y * 32) - 32 - .Frame
                            R.Bottom = (.Y * 32) - 16 - .Frame
                        Case 1 'Down
                            R.Left = (.X * 32) - 64
                            R.Right = (.X * 32) + 96
                            R.Top = (.Y * 32) - 32 + .Frame
                            R.Bottom = (.Y * 32) - 16 + .Frame
                        Case 2 'Left
                            R.Left = (.X * 32) - 64 - .Frame
                            R.Right = (.X * 32) + 96 - .Frame
                            R.Top = (.Y * 32) - 32
                            R.Bottom = (.Y * 32) - 16
                        Case 3 'Right
                            R.Left = (.X * 32) - 64 + .Frame
                            R.Right = (.X * 32) + 96 + .Frame
                            R.Top = (.Y * 32) - 32
                            R.Bottom = (.Y * 32) - 16
                    End Select
                If .Color = 24 Then
                    B = Random(23)
                Else
                    B = .Color
                End If
                If B <> 1 And B <> 25 Then
                    Draw3dText hdcBuffer, R, .Text, StatusColors(B), 2
                Else
                    If B = 1 Then Draw3dText hdcBuffer, R, .Text, QBColor(15), 2
                    If B = 25 Then Draw3dText hdcBuffer, R, .Text, QBColor(11), 2
                End If
            End If
        Else
            DestroyFloatText CLng(A)
        End If
    End With
Next A

End Sub
Sub DrawNextFrame()
    Dim A As Long, B As Long, C As Long, D As Long, R As RECT
    
    'Copy Back Buffer to Viewport
    If DisableScreen = False Then
        BitBlt hdcBuffer, 0, 0, 384, 384, hdcBack(0), 0, 0, SRCCOPY
        If MovableData.CurFrame = 1 Then
            BitBlt hdcBuffer, 0, 0, 384, 384, hdcBack(1), 0, 0, SRCCOPY
        Else
            BitBlt hdcBuffer, 0, 0, 384, 384, hdcBack(2), 0, 0, SRCCOPY
        End If
    End If
    
    'Move You
    If MovableData.CXO < MovableData.cx * 32 Then
        MovableData.CXO = MovableData.CXO + MovableData.CWalkStep
        If Int(MovableData.CXO / 16) * 16 = MovableData.CXO Then
            MovableData.CWalk = 1 - MovableData.CWalk
            If MovableData.CWalk = 0 Then PlayWav 4
        End If
    ElseIf MovableData.CXO > MovableData.cx * 32 Then
        MovableData.CXO = MovableData.CXO - MovableData.CWalkStep
        If Int(MovableData.CXO / 16) * 16 = MovableData.CXO Then
            MovableData.CWalk = 1 - MovableData.CWalk
            If MovableData.CWalk = 0 Then PlayWav 4
        End If
    End If
    If MovableData.CYO < MovableData.cy * 32 Then
        MovableData.CYO = MovableData.CYO + MovableData.CWalkStep
        If Int(MovableData.CYO / 16) * 16 = MovableData.CYO Then
            MovableData.CWalk = 1 - MovableData.CWalk
            If MovableData.CWalk = 0 Then PlayWav 4
        End If
    ElseIf MovableData.CYO > MovableData.cy * 32 Then
        MovableData.CYO = MovableData.CYO - MovableData.CWalkStep
        If Int(MovableData.CYO / 16) * 16 = MovableData.CYO Then
            MovableData.CWalk = 1 - MovableData.CWalk
            If MovableData.CWalk = 0 Then PlayWav 4
        End If
    End If
    
    If DisableScreen = True Then Exit Sub
    
    For A = 1 To 255
        With Player(A)
            If .Dead = True Then .Status = 9

            If .Map = MovableData.CMap Then
                'Move Player
                If .XO < .X * 32 Then
                    .XO = .XO + .WalkStep
                    If Int(.XO / 16) * 16 = .XO Then .W = 1 - .W
                ElseIf .XO > .X * 32 Then
                    .XO = .XO - .WalkStep
                    If Int(.XO / 16) * 16 = .XO Then .W = 1 - .W
                End If
                If .YO < .Y * 32 Then
                    .YO = .YO + .WalkStep
                    If Int(.YO / 16) * 16 = .YO Then .W = 1 - .W
                ElseIf .YO > .Y * 32 Then
                    .YO = .YO - .WalkStep
                    If Int(.YO / 16) * 16 = .YO Then .W = 1 - .W
                End If
                
                'Draw Player
                If .A > 0 Then
                    B = .D * 3 + 2
                    .A = .A - 1
                Else
                    B = .D * 3 + .W
                End If
                
                If .Sprite < 255 Then
                    If .Dead = False Then
                        TransparentBlt hdcBuffer, .XO, .YO - 16, 32, 32, hdcSprites, B * 32, (.Sprite - 1) * 32, hdcSpritesMask
                    Else
                        TransparentBlt hdcBuffer, .XO, .YO, 32, 32, hdcSprites, 0, 202 * 32, hdcSpritesMask
                    End If
                End If
            End If
        End With
    Next A
    
    'Draw You
    If MovableData.CAttack > 0 Then
        B = MovableData.CDir * 3 + 2
        MovableData.CAttack = MovableData.CAttack - 1
    Else
        B = MovableData.CDir * 3 + MovableData.CWalk
    End If
    
    If Character.Sprite < 255 Then
        If MovableData.Dead = False Then
            TransparentBlt hdcBuffer, MovableData.CXO, MovableData.CYO - 16, 32, 32, hdcSprites, B * 32, (Character.Sprite - 1) * 32, hdcSpritesMask
        Else
            TransparentBlt hdcBuffer, MovableData.CXO, MovableData.CYO, 32, 32, hdcSprites, 0, 202 * 32, hdcSpritesMask
        End If
    End If
    
        For A = 0 To 9
        With Map.Monster(A)
            If .Monster > 0 Then
                C = Monster(.Monster).Sprite
                If C > 0 Then
                    If .XO < .X * 32 Then
                        .XO = .XO + 2
                        If Int(.XO / 16) * 16 = .XO Then .W = 1 - .W
                    ElseIf .XO > .X * 32 Then
                        .XO = .XO - 2
                        If Int(.XO / 16) * 16 = .XO Then .W = 1 - .W
                    End If
                    If .YO < .Y * 32 Then
                        .YO = .YO + 2
                        If Int(.YO / 16) * 16 = .YO Then .W = 1 - .W
                    ElseIf .YO > .Y * 32 Then
                        .YO = .YO - 2
                        If Int(.YO / 16) * 16 = .YO Then .W = 1 - .W
                    End If
                    
                    'Draw Monster
                    If .A > 0 Then
                        B = .D * 3 + 2
                        .A = .A - 1
                    Else
                        B = .D * 3 + .W
                    End If
                    
                    If C < 255 Then
                        TransparentBlt hdcBuffer, .XO, .YO - 16, 32, 32, hdcSprites, B * 32, (C - 1) * 32, hdcSpritesMask
                    End If
                End If
            End If
        End With
    Next A
    
    For A = 1 To 255
        With Projectile(A)
            If .Sprite > 0 Then
                Select Case .TargetType
                    Case pttCharacter
                        If .TargetNum = Character.Index Then
                            .X = MovableData.CXO
                            .Y = MovableData.CYO
                        Else
                            .X = Player(.TargetNum).XO
                            .Y = Player(.TargetNum).YO
                        End If
                        
                        If timeGetTime - .timeStamp >= .Speed Then
                            If .Frame < .TotalFrames Then
                                .Frame = .Frame + 1
                            Else
                                If .CurLoop = .LoopCount Then
                                    If .EndSound > 0 Then
                                        PlayWav .EndSound
                                    End If
                                    DestroyEffect (A)
                                Else
                                    .CurLoop = .CurLoop + 1
                                    .Frame = 0
                                End If
                            End If
                            .timeStamp = timeGetTime
                        End If
                    Case pttPlayer
                        If .TargetNum = Character.Index Then
                            .TargetX = MovableData.CXO
                            .TargetY = MovableData.CYO
                        Else
                            .TargetX = Player(.TargetNum).XO
                            .TargetY = Player(.TargetNum).YO
                        End If
                        If .X < .TargetX Then .X = .X + 16
                        If .X > .TargetX Then .X = .X - 16
                        If .Y < .TargetY Then .Y = .Y + 16
                        If .Y > .TargetY Then .Y = .Y - 16
                        
                        If timeGetTime - .timeStamp >= .Speed Then
                            If .X = .TargetX And .Y = .TargetY Then
                                If .Frame < .TotalFrames Then
                                    .Frame = .Frame + 1
                                Else
                                    DestroyEffect (A)
                                End If
                            End If
                            .timeStamp = timeGetTime
                        End If
                    Case pttMonster
                        .TargetX = Map.Monster(.TargetNum).XO
                        .TargetY = Map.Monster(.TargetNum).YO
                        If .X < .TargetX Then .X = .X + 16
                        If .X > .TargetX Then .X = .X - 16
                        If .Y < .TargetY Then .Y = .Y + 16
                        If .Y > .TargetY Then .Y = .Y - 16
                        
                        If timeGetTime - .timeStamp >= .Speed Then
                            If .X = .TargetX And .Y = .TargetY Then
                                If .Frame < .TotalFrames Then
                                    .Frame = .Frame + 1
                                Else
                                    DestroyEffect (A)
                                End If
                            End If
                            .timeStamp = timeGetTime
                        End If
                    Case pttTile
                        If timeGetTime - .timeStamp >= .Speed Then
                            If .Frame < .TotalFrames Then
                                .Frame = .Frame + 1
                            Else
                                If .CurLoop = .LoopCount Then
                                    If .EndSound > 0 Then
                                        PlayWav .EndSound
                                    End If
                                    DestroyEffect (A)
                                Else
                                    .CurLoop = .CurLoop + 1
                                    .Frame = 0
                                End If
                            End If
                            .timeStamp = timeGetTime
                        End If
                    End Select
                TransparentBlt hdcBuffer, .X, .Y - 16, 32, 32, hdcEffects, .Frame * 32, (.Sprite - 1) * 32, hdcEffectsMask
            End If
        End With
    Next A
    
    TransparentBlt hdcBuffer, 0, 0, 384, 384, hdcFront(0), 0, 0, hdcFrontMask(0)
    TransparentBlt hdcBuffer, 0, 0, 384, 384, hdcFront(1), 0, 0, hdcFrontMask(1)
    
    For A = 0 To 9
        With Map.Monster(A)
            If .Monster > 0 Then
                If Options.MonsterNames = True Then
                    R.Left = .XO - 32
                    R.Right = .XO + 64
                    R.Top = .YO - 32
                    R.Bottom = .YO - 16
                    Draw3dText hdcBuffer, R, Monster(.Monster).Name, StatusColors(9), 2
                End If
            End If
        End With
    Next A
    
    With R
        .Left = MovableData.CXO - 32
        .Right = MovableData.CXO + 64
        .Top = MovableData.CYO - 32
        .Bottom = MovableData.CYO - 16
    End With
    
    Select Case Character.Status
        Case 0, 9
            If Character.Guild = 0 Then
                Draw3dText hdcBuffer, R, Character.Name, StatusColors(Character.Status), 2
            Else
                Draw3dText hdcBuffer, R, Character.Name, QBColor(11), 2
            End If
        Case 1
            If MovableData.CurFrame = 1 Then
                Draw3dText hdcBuffer, R, Character.Name, QBColor(4), 2
            Else
                If Character.Guild > 0 Then
                    Draw3dText hdcBuffer, R, Character.Name, QBColor(11), 2
                Else
                    Draw3dText hdcBuffer, R, Character.Name, StatusColors(Character.Status), 2
                End If
            End If
        Case 24 'Rainbow (FUN)
            Draw3dText hdcBuffer, R, Character.Name, StatusColors((Int(Rnd * 23))), 2
        Case 25 'Red/Black Flashy
            If MovableData.CurFrame = 1 Then
                Draw3dText hdcBuffer, R, Character.Name, StatusColors(22), 2
            Else
                Draw3dText hdcBuffer, R, Character.Name, StatusColors(10), 2
            End If
        Case 26 'Green/Black Flashy
            If MovableData.CurFrame = 1 Then
                Draw3dText hdcBuffer, R, Character.Name, StatusColors(21), 2
            Else
                Draw3dText hdcBuffer, R, Character.Name, StatusColors(10), 2
            End If
        Case 27 'White/Black Flashy
            If MovableData.CurFrame = 1 Then
                Draw3dText hdcBuffer, R, Character.Name, QBColor(15), 2
            Else
                Draw3dText hdcBuffer, R, Character.Name, StatusColors(10), 2
            End If
        Case Else
            Draw3dText hdcBuffer, R, Character.Name, StatusColors(Character.Status), 2
    End Select
    
    For A = 1 To 255
        With Player(A)
            If .Map = MovableData.CMap Then
                R.Left = .XO - 32
                R.Right = .XO + 64
                R.Top = .YO - 32
                R.Bottom = .YO - 16
                If .Status = 9 Then  'Invisible Name
                    If Character.Access > 0 Then
                        Draw3dText hdcBuffer, R, .Name, StatusColors(9), 2
                    End If
                Else
                    Select Case .Status
                        Case 1
                            If MovableData.CurFrame = 1 Then
                                Draw3dText hdcBuffer, R, .Name, QBColor(4), 2
                            Else
                                If .Guild > 0 Then
                                    If .Guild = Character.Guild Then
                                        Draw3dText hdcBuffer, R, .Name, QBColor(11), 2
                                    Else
                                        Draw3dText hdcBuffer, R, .Name, QBColor(15), 2
                                    End If
                                Else
                                    Draw3dText hdcBuffer, R, .Name, StatusColors(0), 2
                                End If
                            End If
                        Case 0
                            If .Guild > 0 Then
                                If .Guild = Character.Guild Then
                                    Draw3dText hdcBuffer, R, .Name, QBColor(11), 2
                                Else
                                    Draw3dText hdcBuffer, R, .Name, QBColor(15), 2
                                End If
                            Else
                                Draw3dText hdcBuffer, R, .Name, StatusColors(0), 2
                            End If
                        Case 24 'Rainbow
                            Draw3dText hdcBuffer, R, .Name, StatusColors((Int(Rnd * 23))), 2
                        Case 25 'Red/Black Flashy
                            If MovableData.CurFrame = 1 Then
                                Draw3dText hdcBuffer, R, .Name, StatusColors(22), 2
                            Else
                                Draw3dText hdcBuffer, R, .Name, StatusColors(10), 2
                            End If
                        Case 26 'Green/Black Flashy
                            If MovableData.CurFrame = 1 Then
                                Draw3dText hdcBuffer, R, .Name, StatusColors(21), 2
                            Else
                                Draw3dText hdcBuffer, R, .Name, StatusColors(10), 2
                            End If
                        Case 27 'White/Black Flashy
                            If MovableData.CurFrame = 1 Then
                                Draw3dText hdcBuffer, R, .Name, QBColor(15), 2
                            Else
                                Draw3dText hdcBuffer, R, .Name, StatusColors(10), 2
                            End If
                        Case Else
                            Draw3dText hdcBuffer, R, .Name, StatusColors(.Status), 2
                    End Select
                End If
            End If
        End With
    Next A
    If ExamineBit(Map.Flags, CByte(7)) And Options.Weather = True Then
        DrawRain
    End If
    If ExamineBit(Map.Flags, CByte(1)) And Options.Weather = True Then
        DrawSnow
    End If
    If Options.HPBars = True Then
        DrawMonsterHP
        DrawPlayerHP
        DrawCharacterHP
    End If
    DrawStaticText
    DrawFloatText
    DrawChatString
    DrawInfoText
End Sub
Function Exists(Filename As String) As Boolean
     Exists = (Dir(Filename) <> "")
End Function
Sub Encrypt(ByVal Filename As String)
Dim Data() As Byte
ReDim Data(0 To FileLen(Filename) - 1)
    Open Filename For Binary Access Read As #1
        Get #1, , Data
    Close #1
    Open Filename For Binary Access Write As #1
        Data(1) = Data(1) Xor (1 Mod 186)
        Put #1, , Data
    Close #1
End Sub
Sub CheckFile(Filename As String)
    If Exists(Filename) = False Then
        MsgBox "Error: File " + Chr$(34) + Filename + Chr$(34) + " not found!", vbOKOnly + vbExclamation, TitleString
        End
    End If
End Sub

Sub CloseClientSocket(Action As Byte)

    closesocket ClientSocket
    ClientSocket = INVALID_SOCKET
    
    SaveHotKeys
    
    If MovableData.frmMain_Loaded = True Then Unload frmMain
    If MovableData.frmWait_Loaded = True Then Unload frmWait
    If MovableData.frmNewCharacter_Loaded = True Then Unload frmNewCharacter
    If MovableData.frmNewPass_Loaded = True Then Unload frmNewPass
    If MovableData.frmMonster_Loaded = True Then Unload frmMonster
    If MovableData.frmObject_Loaded = True Then Unload frmObject
    If MovableData.frmList_Loaded = True Then Unload frmList
    If MovableData.frmGuilds_Loaded = True Then Unload frmGuilds
    If MovableData.frmGuild_Loaded = True Then Unload frmGuild
    If MovableData.frmBan_Loaded = True Then Unload frmBan
    If MovableData.frmHall_Loaded = True Then Unload frmHall
    If MovableData.frmOptions_Loaded = True Then Unload frmOptions
    If MovableData.frmNewGuild_Loaded = True Then Unload frmNewGuild
    If MovableData.frmLogin_Loaded = True And Action <> 1 Then Unload frmLogin
    If MovableData.frmAccount_Loaded = True And Action <> 2 Then Unload frmAccount
    
    Select Case Action
        Case 0
            frmMenu.Show
        Case 1
            frmMenu.Show
        Case 2
            frmAccount.Show
        Case 3
            frmMenu.Show
        Case Else
            frmMenu.Show
    End Select
End Sub
Sub DeInitialize()
    
    If ClientSocket <> INVALID_SOCKET Then
        'closesocket ClientSocket
    End If
    
    'Unload Graphics
    If hdcTiles <> 0 Then
        SelectObject hdcTiles, obmpTiles
        DeleteObject hbmpTiles
        DeleteDC hdcTiles
    End If
    
    If hdcTilesMask <> 0 Then
        SelectObject hdcTilesMask, obmpTilesMask
        DeleteObject hbmpTilesMask
        DeleteDC hdcTilesMask
    End If
    
    If hdcObjects <> 0 Then
        SelectObject hdcObjects, obmpObjects
        DeleteObject hbmpObjects
        DeleteDC hdcObjects
    End If
    
    If hdcObjectsMask <> 0 Then
        SelectObject hdcObjectsMask, obmpObjectsMask
        DeleteObject hbmpObjectsMask
        DeleteDC hdcObjectsMask
    End If
    
    If hdcSprites <> 0 Then
        SelectObject hdcSprites, obmpSprites
        DeleteObject hbmpSprites
        DeleteDC hdcSprites
    End If
    
    If hdcSpritesMask <> 0 Then
        SelectObject hdcSpritesMask, obmpSpritesMask
        DeleteObject hbmpSpritesMask
        DeleteDC hdcSpritesMask
    End If
    
    If hdcEffects <> 0 Then
        SelectObject hdcEffects, obmpEffects
        DeleteObject hbmpEffects
        DeleteDC hdcEffects
    End If
    
    If hdcEffectsMask <> 0 Then
        SelectObject hdcEffectsMask, obmpEffectsMask
        DeleteObject hbmpEffectsMask
        DeleteDC hdcEffectsMask
    End If
       
    If hdcBuffer <> 0 Then
        SelectObject hdcBuffer, obmpBuffer
        DeleteObject hbmpBuffer
        DeleteDC hdcBuffer
    End If
    
    If hdcBack(0) <> 0 Then
        SelectObject hdcBack(0), obmpBack(0)
        DeleteObject hbmpBack(0)
        DeleteDC hdcBack(0)
    End If
    
    If hdcBack(1) <> 0 Then
        SelectObject hdcBack(1), obmpBack(1)
        DeleteObject hbmpBack(1)
        DeleteDC hdcBack(1)
    End If
    
    If hdcBack(2) <> 0 Then
        SelectObject hdcBack(2), obmpBack(2)
        DeleteObject hbmpBack(2)
        DeleteDC hdcBack(2)
    End If
    
    If hdcFront(0) <> 0 Then
        SelectObject hdcFront(0), obmpFront(0)
        DeleteObject hbmpFront(0)
        DeleteDC hdcFront(0)
    End If
    
    If hdcFront(1) <> 0 Then
        SelectObject hdcFront(1), obmpFront(1)
        DeleteObject hbmpFront(1)
        DeleteDC hdcFront(1)
    End If
    
    If hdcFrontMask(0) <> 0 Then
        SelectObject hdcFrontMask(0), obmpFrontMask(0)
        DeleteObject hbmpFrontMask(0)
        DeleteDC hdcFrontMask(0)
    End If
    
    If hdcFrontMask(1) <> 0 Then
        SelectObject hdcFrontMask(1), obmpFrontMask(1)
        DeleteObject hbmpFrontMask(1)
        DeleteDC hdcFrontMask(1)
    End If
    
    If hdcDarkness <> 0 Then
        SelectObject hdcDarkness, obmpDarkness
        DeleteObject hbmpDarkness
        DeleteDC hdcDarkness
    End If
    
    If hdcDarknessMask <> 0 Then
        SelectObject hdcDarknessMask, obmpDarknessMask
        DeleteObject hbmpDarknessMask
        DeleteDC hdcDarknessMask
    End If
    
    If hdcHPBar <> 0 Then
        SelectObject hdcHPBar, obmpHPBar
        DeleteObject hbmpHPBar
        DeleteDC hdcHPBar
    End If
    
    If hdcHPBarMask <> 0 Then
        SelectObject hdcHPBarMask, obmpHPBarMask
        DeleteObject hbmpHPBarMask
        DeleteDC hdcHPBarMask
    End If
    
    If hPalette <> 0 Then
        DeleteObject hPalette
    End If
    
    'Unload Winsock
    EndWinsock
    
    'Unhook Form
    Unhook
    
    End

End Sub
Public Sub Hook()
#If DEBUGWINDOWPROC Then
    On Error Resume Next
    Set m_SCHook = CreateWindowProcHook
    If Err Then
        MsgBox Err.Description
        Err.Clear
        Unhook
        Exit Sub
    End If
    On Error GoTo 0
    With m_SCHook
        .SetMainProc AddressOf WindowProc
        lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, .ProcAddress)
        .SetDebugProc lpPrevWndProc
    End With
#Else
    lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, AddressOf WindowProc)
#End If
End Sub

Public Sub Unhook()
    SetWindowLong gHW, GWL_WNDPROC, lpPrevWndProc
End Sub
Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim St1 As String
    If uMsg = 1025 Then
        'Client Socket
        Select Case lParam And 255
            Case FD_CLOSE
                CloseClientSocket 1
                MessageBox frmMenu.hwnd, "You have been disconnected from the server!", TitleString, vbOKOnly + vbExclamation
            Case FD_CONNECT
                If lParam = FD_CONNECT Then
                    MovableData.SentPacketCount = 0
                    DisableNagel ClientSocket, soxSO_TCP_NODELAY, True
                    SendSocket Chr$(61) + ClientVer
                    If MovableData.NewAccount = True Then
                        frmWait.lblStatus = "Sending Account Information ..."
                        SendSocket Chr$(0) + MovableData.User + Chr$(0) + EncryptString(MovableData.Pass)
                    Else
                        frmWait.lblStatus = "Sending Login Information ..."
                        SendSocket Chr$(1) + MovableData.User + Chr$(0) + EncryptString(MovableData.Pass)
                    End If
                Else
                    CloseClientSocket 0
                    WaitForConnect "Error Connecting - Waiting"
                End If
            Case FD_READ
                If lParam = FD_READ Then ReceiveData
        End Select
    End If
    WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam)
End Function
Sub ReceiveData()
    Dim PacketLength As Integer, PacketID As Integer
    Dim St As String, St1 As String, St2 As String, St3 As String, St4 As String
    Dim A As Long, B As Long, C As Long, D As Long
    
    On Error Resume Next
    
    SocketData = SocketData + Receive(ClientSocket)
LoopRead:
    If Len(SocketData) >= 3 Then
        PacketLength = GetInt(Mid$(SocketData, 1, 2))
        If Len(SocketData) - 2 >= PacketLength Then
            St = Mid$(SocketData, 3, PacketLength)
            SocketData = Mid$(SocketData, PacketLength + 3)
            If PacketLength > 0 Then
                PacketID = Asc(Mid$(St, 1, 1))
                If Len(St) > 1 Then
                    St = Mid$(St, 2)
                Else
                    St = ""
                End If
                Select Case PacketID
                    Case 0 'Error Logging On
                        If Len(St) >= 1 Then
                            Select Case Asc(Mid$(St, 1, 1))
                                Case 0 'Custom Message
                                    If Len(St) >= 2 Then
                                        MessageBox frmMenu.hwnd, Mid$(St, 2), TitleString, vbOKOnly + vbExclamation
                                    End If
                                Case 1 'Invalid User/Pass
                                    MessageBox frmMenu.hwnd, "Invalid user name/password!", TitleString, vbOKOnly + vbExclamation
                                Case 2 'Account already in use
                                    MessageBox frmMenu.hwnd, "Someone is already using that account!", TitleString, vbOKOnly + vbExclamation
                                Case 3 'Banned
                                    If Len(St) >= 5 Then
                                        A = Asc(Mid$(St, 2, 1)) * 16777216 + Asc(Mid$(St, 3, 1)) * 65536 + Asc(Mid$(St, 4, 1)) * 256& + Asc(Mid$(St, 5, 1))
                                        If Len(St) > 5 Then
                                            MessageBox frmMenu.hwnd, "You are banned from The Odyssey Online Classic until " + CStr(CDate(A)) + " (" + Mid$(St, 6) + ")!", TitleString, vbOKOnly
                                        Else
                                            MessageBox frmMenu.hwnd, "You are banned from The Odyssey Online Classic until " + CStr(CDate(A)) + "!", TitleString, vbOKOnly
                                        End If
                                        CloseClientSocket 0
                                    End If
                                Case 4 'Server Full
                                    MessageBox frmMenu.hwnd, "The server is full, please try again in a few minutes!", TitleString, vbOKOnly + vbExclamation
                                Case 5 'Logging in with a god account
                                    MessageBox frmMenu.hwnd, "You are not permitted to use this account!", TitleString, vbOKOnly + vbExclamation
                                    CloseClientSocket 0
                            End Select
                        End If
                        CloseClientSocket 1
                        
                    Case 1 'Error Creating New Account
                        If Len(St) >= 1 Then
                            Select Case Asc(Mid$(St, 1, 1))
                                Case 0 'Custom Message
                                    If Len(St) >= 2 Then
                                        MessageBox frmAccount.hwnd, Mid$(St, 2), TitleString, vbOKOnly + vbExclamation
                                    End If
                                Case 1 'User name already in use
                                    MessageBox frmAccount.hwnd, "That user name is already in use.  Please try another.", TitleString, vbOKOnly + vbExclamation
                            End Select
                        End If
                        CloseClientSocket 2
                        
                    Case 2 'Account Created
                        CloseClientSocket 0
                        MessageBox frmMenu.hwnd, "Your account has been created successfully!  Please write down your user name and password somewhere safe so that you do not loose them.  Click Login to connect to the game server.", TitleString, vbOKOnly + vbExclamation
                    
                    Case 3 'Logged On / Character Data
                        If MovableData.frmWait_Loaded = True Then Unload frmWait
                        If MovableData.frmLogin_Loaded = True Then Unload frmLogin
                        If MovableData.frmNewCharacter_Loaded = True Then Unload frmNewCharacter
                        If Len(St) >= 26 Then
                            With Character
                                .Name = ""
                                .Class = Asc(Mid$(St, 1, 1))
                                .Gender = Asc(Mid$(St, 2, 1))
                                .Sprite = Asc(Mid$(St, 3, 1))
                                .HP = Asc(Mid$(St, 4, 1))
                                .Mana = Asc(Mid$(St, 6, 1))
                                .MaxHP = Asc(Mid$(St, 7, 1))
                                .MaxEnergy = Asc(Mid$(St, 8, 1))
                                .Energy = .MaxEnergy
                                .MaxMana = Asc(Mid$(St, 9, 1))
                                .Strength = Asc(Mid$(St, 10, 1))
                                .Agility = Asc(Mid$(St, 11, 1))
                                .Endurance = Asc(Mid$(St, 12, 1))
                                .Intelligence = Asc(Mid$(St, 13, 1))
                                .Concentration = Asc(Mid$(St, 14, 1))
                                .Vitality = Asc(Mid$(St, 15, 1))
                                .Stamina = Asc(Mid$(St, 16, 1))
                                .Wisdom = Asc(Mid$(St, 17, 1))
                                .level = Asc(Mid$(St, 18, 1))
                                .Status = Asc(Mid$(St, 19, 1))
                                .Guild = Asc(Mid$(St, 20, 1))
                                .GuildRank = Asc(Mid$(St, 21, 1))
                                .Access = Asc(Mid$(St, 22, 1))
                                .Index = Asc(Mid$(St, 23, 1))
                                .MaxExperience = Int(1000 * CLng(.level) ^ 1.3)
                                .Experience = Asc(Mid$(St, 24, 1)) * 16777216 + Asc(Mid$(St, 25, 1)) * 65536 + Asc(Mid$(St, 26, 1)) * 256& + Asc(Mid$(St, 27, 1))
                                .StatPoints = Asc(Mid$(St, 28, 1)) * 256& + Asc(Mid$(St, 29, 1))
                                St = Mid$(St, 30)
                                A = InStr(St, Chr$(0))
                                If A > 1 Then
                                    .Name = Mid$(St, 1, A - 1)
                                    If A < Len(St) Then
                                        .Desc = Mid$(St, A + 1)
                                    End If
                                End If
                                For A = 1 To 20
                                    With .Inv(A)
                                        .Object = 0
                                        .EquippedNum = 0
                                        .Value = 0
                                        DrawInvObject A
                                    End With
                                Next A
                            End With
                            MovableData.CMap = 0
                            For A = 1 To 255
                                Guild(A).Name = ""
                                With Player(A)
                                    .Sprite = 0
                                    .Map = 0
                                End With
                            Next A
                            MovableData.keyLeft = False
                            MovableData.keyRight = False
                            MovableData.keyUp = False
                            MovableData.keyDown = False
                            MovableData.keyCtrl = False
                            MovableData.keyShift = False
                            MovableData.keyAlt = False
                            MovableData.Dead = False
                            LoadHotKeys
                            frmWait.Show
                            frmWait.lblStatus = "Receiving Game Data ..."
                            frmWait.Refresh
                            SendSocket Chr$(5) 'I wanna play
                        Else
                            Character.Class = 0
                            frmNewCharacter.Show
                        End If
                        
                    Case 4 'Guild Sprite
                        If Len(St) = 2 Then
                            A = Asc(Mid$(St, 1, 1))
                            Guild(A).Sprite = Asc(Mid$(St, 2, 1))
                        End If
                        
                    Case 5 'Password Changed
                        PrintChat "Password Changed!", 15
                        
                    Case 6 'Player Joined Game
                        If Len(St) >= 5 Then
                            A = Asc(Mid$(St, 1, 1))
                            With Player(A)
                                .Dead = False
                                .Ignore = False
                                .Sprite = Asc(Mid$(St, 2, 1))
                                .Status = Asc(Mid$(St, 3, 1))
                                .Guild = Asc(Mid$(St, 4, 1))
                                .Name = Mid$(St, 5)
                                If MovableData.CMap > 0 Then
                                    If .Status = 2 Then
                                        PrintChat "All hail " + .Name + ", a new adventurer in this land!", 3
                                    Else
                                        PrintChat .Name + " has joined the game!", 3
                                    End If
                                End If
                                UpdatePlayerColor A
                            End With
                        End If
                        
                    Case 7 'Player Left Game
                        If Len(St) = 1 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                With Player(A)
                                    PlayerLeftMap A
                                    .Sprite = 0
                                    PrintChat .Name + " has left the game!", 3
                                End With
                            End If
                        End If
                    
                    Case 8 'Player joined map
                        If Len(St) = 4 Then
                            A = Asc(Mid$(St, 1, 1))
                            With Player(A)
                                .Map = MovableData.CMap
                                .X = Asc(Mid$(St, 2, 1))
                                .Y = Asc(Mid$(St, 3, 1))
                                .D = Asc(Mid$(St, 4, 1))
                                .XO = .X * 32
                                .YO = .Y * 32
                                .A = 0
                            End With
                        End If
                        
                    Case 9 'Player left map
                        If Len(St) = 1 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                PlayerLeftMap (A)
                            End If
                        End If
                        
                    Case 10 'Player moved
                        If Len(St) = 5 Then
                            With Player(Asc(Mid$(St, 1, 1)))
                                If .X * 32 = .XO And .Y * 32 = .YO Then
                                    .X = Asc(Mid$(St, 2, 1))
                                    .Y = Asc(Mid$(St, 3, 1))
                                Else
                                    .XO = .X * 32
                                    .YO = .Y * 32
                                    .X = Asc(Mid$(St, 2, 1))
                                    .Y = Asc(Mid$(St, 3, 1))
                                End If
                                .D = Asc(Mid$(St, 4, 1))
                                .WalkStep = Asc(Mid$(St, 5, 1))
                            End With
                        End If
                        
                    Case 11 'Say
                        If Len(St) >= 2 Then
                            A = Asc(Mid$(St, 1, 1))
                            PrintChat Player(A).Name + " says, " + Chr$(34) + Mid$(St, 2) + Chr$(34), 7
                        End If
                        
                    Case 12 'You joined map
                        If Len(St) = 14 Then
                            If MovableData.MapEdit = True Then CloseMapEdit
                            'Destroy Projectiles
                            For A = 1 To 100
                                DestroyEffect (A)
                            Next A
                            If MovableData.CMap = 0 Then
                                St1 = ""
                                B = 0
                                For A = 1 To 255
                                    With Player(A)
                                        If .Sprite > 0 And A <> Character.Index Then
                                            B = B + 1
                                            St1 = St1 + ", " + .Name
                                        End If
                                    End With
                                Next A
                                If B > 0 Then
                                    St1 = Mid$(St1, 2)
                                    PrintChat "Welcome to Odyssey Classic - Modus!  There are " + CStr(B) + " other players online:" + St1, 15
                                Else
                                    PrintChat "Welcome to Odyssey Classic - Modus!  There are no other users currently online.", 15
                                End If
                                Load frmMain
                            End If
                            MovableData.CMap = Asc(Mid$(St, 1, 1)) * 256 + Asc(Mid$(St, 2, 1))
                            MovableData.cx = Asc(Mid$(St, 3, 1))
                            MovableData.cy = Asc(Mid$(St, 4, 1))
                            MovableData.CDir = Asc(Mid$(St, 5, 1))
                            MovableData.CWalkCode = Asc(Mid$(St, 6, 1))
                            MovableData.CXO = MovableData.cx * 32
                            MovableData.CYO = MovableData.cy * 32
                            For A = 0 To 9
                                Map.Monster(A).Monster = 0
                            Next A
                            For A = 0 To 79
                                Map.Object(A).Object = 0
                            Next A
                            For A = 0 To 9
                                Map.Door(A).Att = 0
                            Next A
                            For A = 1 To 255
                                Player(A).Map = 0
                            Next A
                            MovableData.Freeze = True
                            Open MovableData.MapCacheFile For Random As #1 Len = 2507
                            Get #1, MovableData.CMap, MapData
                            Close #1
                            LoadMap MapData
                            If Map.Version <> Asc(Mid$(St, 7, 1)) * 16777216 + Asc(Mid$(St, 8, 1)) * 65536 + Asc(Mid$(St, 9, 1)) * 256& + Asc(Mid$(St, 10, 1)) Or CheckSum(MapData) <> Asc(Mid$(St, 11, 1)) * 16777216 + Asc(Mid$(St, 12, 1)) * 65536 + Asc(Mid$(St, 13, 1)) * 256& + Asc(Mid$(St, 14, 1)) Then
                                SendSocket Chr$(45)
                                MovableData.RequestedMap = True
                            Else
                                MovableData.RequestedMap = False
                            End If
                        End If
                        
                    Case 13 'Error creating character
                        If MovableData.frmWait_Loaded = True Then Unload frmWait
                        frmNewCharacter.Show
                        MessageBox frmNewCharacter.hwnd, "That name is already in use, please try another!", TitleString, vbOKOnly + vbExclamation
                        
                    Case 14 'New Map Object
                        If Len(St) = 4 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A <= 79 Then
                                With Map.Object(A)
                                    .Object = Asc(Mid$(St, 2, 1))
                                    .X = Asc(Mid$(St, 3, 1))
                                    .Y = Asc(Mid$(St, 4, 1))
                                    .XOffset = Int(Rnd * 16)
                                    .YOffset = Int(Rnd * 16)
                                    RedrawMapTile CLng(.X), CLng(.Y)
                                End With
                            End If
                        End If
                        
                    Case 15 'Erase Map Object
                        If Len(St) = 1 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A <= 79 Then
                                With Map.Object(A)
                                    .Object = 0
                                    RedrawMapTile CLng(.X), CLng(.Y)
                                End With
                            End If
                        End If
                        
                    Case 16 'Messages
                        If Len(St) >= 1 Then
                            Select Case Asc(Mid$(St, 1, 1))
                                Case 0 'Custom
                                    If Len(St) > 2 Then
                                        PrintChat Mid$(St, 2), 7
                                    End If
                                Case 1 'Inv full
                                    PrintChat "Your inventory is full!", 7
                                Case 2 'Map full
                                    PrintChat "There is too much already on the ground here to drop that.", 7
                                Case 3 'No such object
                                    PrintChat "No such object.", 7
                                Case 4 'No such player
                                    PrintChat "No such player.", 7
                                Case 5 'No such monster
                                    PrintChat "No such monster.", 7
                                Case 6 'Player is too far away
                                    PrintChat "Player is too far away.", 7
                                Case 7 'Monster is too far away
                                    PrintChat "Monster is too far away.", 7
                                Case 8 'You cannot use that
                                    PrintChat "You cannot use that object.", 7
                                Case 9 'Friendly Zone - can't attack
                                    PrintChat "This is a friendly area, you cannot attack here!", 7
                                Case 10 'Too tired to use skill
                                    PrintChat "You are too tired to use this skill!", 14
                                Case 12 'Can't attack monsters here
                                    PrintChat "You cannot attack these monsters!", 7
                                Case 13 'Ban list full
                                    PrintChat "The ban list is full!", 7
                                Case 14 'Not invited to join
                                    PrintChat "You have not been invited to join any guild.", 7
                                Case 15 'Not enough cash
                                    PrintChat "You do not have enough gold to do that!", 7
                                Case 16 'Guild name in use
                                    PrintChat "That name is already used either by another player or guild.  Please try another.", 7
                                Case 17 'Guild full
                                    PrintChat "That guild is full!", 7
                                Case 18 'too many guilds
                                    PrintChat "Too many guilds already exist.  You may join another guild or try again later.", 7
                                Case 19 'cannot attack player -- he is not in guild
                                    PrintChat "That player is not in a guild -- you may not attack non-guild players.", 7
                                Case 20 'cannot attack player -- you are not in guild
                                    PrintChat "You must be a member of a guild to attack other players.", 7
                                Case 21 'not in a hall
                                    PrintChat "You are not in a guild hall!", 7
                                Case 22 'hall already owned
                                    PrintChat "This hall is already owned by another guild.", 7
                                Case 23 'already have hall
                                    PrintChat "Your guild already owns a hall.  You must move out of your old hall before you may purchase a new one.", 7
                                Case 24 'don't have enough money to buy hall
                                    PrintChat "Your guild does not have enough money in its bank account to buy this hall.  Type /guild hallinfo for the price information of this hall.", 7
                                Case 25 'do not own a guild hall
                                    PrintChat "Your guild does not own a hall.", 7
                                Case 26 'need 5 members
                                    PrintChat "You must have atleast 5 members in your guild before you may do that.", 7
                                Case 27 'Can't afford that
                                    PrintChat "You do not have the items required to purchase that!", 7
                                Case 28 'Not in a bank
                                    PrintChat "This is not a Bank!", 14
                                Case 29 'too far away
                                    PrintChat "That player is too far away to hit!", 7
                                Case 30 'must be level 5 to join guild
                                    PrintChat "You must be at least level 5 to join a guild!", 7
                                Case 31 'Invalid Admin Password
                                    PrintChat "Incorrect Administration Password to perform action!", 7
                                Case 32 'Must be in a smithy shop
                                    PrintChat "There is no Blacksmith here!", 14
                                Case 33 'Do not have enough money
                                    PrintChat "You do not have enough Gold Coins to repair this object!", 7
                                Case 34 'Blank
                                Case 35 'Help Request Received
                                    MsgBox "We have received your help request and a staff member will be with you as soon as possible! Please do not submit another request or your most recent one will be canceled!", vbExclamation, "Help Request Received"
                                Case 36 'Help request not received
                                    MsgBox "The help box is full! Please try again shortly.", vbCritical, "Error"
                                Case 37 'God can't perform action
                                    PrintChat "You cannot perform this action!", 14
                                Case 38 'Account Log File not found
                                    PrintChat "The log file you have submitted was not found!", 14
                                Case 40 'Lumberjacking
                                    PrintChat "You hack away at the tree but recieve nothing!", 14
                                Case 41 'Mining
                                    PrintChat "You hack away at the rocks but recieve nothing!", 14
                                Case 42 'Fishing
                                    PrintChat "You throw your hook into the water but recieve nothing!", 14
                            End Select
                        End If
                        
                    Case 17 'New Inv Object
                        If Len(St) <= 6 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 And A <= 20 Then
                                With Character.Inv(A)
                                    .Object = Asc(Mid$(St, 2, 1))
                                    If Len(St) >= 3 Then .Value = Asc(Mid$(St, 3, 1)) * 16777216 + Asc(Mid$(St, 4, 1)) * 65536 + Asc(Mid$(St, 5, 1)) * 256& + Asc(Mid$(St, 6, 1))
                                    .EquippedNum = 0
                                End With
                                DrawInvObject A
                                SendSocket Chr$(76) + Chr$(0) + Chr$(MovableData.CurInvObj)
                            End If
                        End If
                        
                    Case 18 'Erase Inv Object
                        If Len(St) = 1 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 And A <= 20 Then
                                With Character.Inv(A)
                                    .Object = 0
                                    .EquippedNum = 0
                                End With
                            End If
                            DrawInvObject A
                            DrawEquippedArmor
                        End If
                        
                    Case 19 'Use Object
                        If Len(St) = 2 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 And A <= 20 Then
                                Character.Inv(A).EquippedNum = Asc(Mid$(St, 2, 1))
                                DrawEquippedArmor
                                DrawInvObject A
                            End If
                        End If
                        
                    Case 20 'Stop using object
                        If Len(St) = 1 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 And A <= 20 Then
                                Character.Inv(A).EquippedNum = False
                                DrawEquippedArmor
                                DrawInvObject A
                            End If
                        End If
                        
                    Case 21 'Map Data
                        If Len(St) = 2507 Then
                            MapData = St
                            Open MovableData.MapCacheFile For Random As #1 Len = 2507
                            Put #1, MovableData.CMap, MapData
                            Close #1
                            LoadMap MapData
                            ShowMap
                        End If
                        
                    Case 22 'Done Sending Map
                        If MovableData.RequestedMap = False Then
                            ShowMap
                        End If
                        
                    Case 24 'Joined Game
                        If MovableData.frmWait_Loaded = True Then
                            frmWait.lblStatus = "Loading Game ..."
                            frmWait.lblStatus.Refresh
                        End If
                        For A = 1 To 255
                            Player(A).Map = 0
                        Next A
                        lastPing = 0
                        Load frmMain
                        DrawHP
                        DrawEnergy
                        DrawMana
                        DrawLevel
                        DrawMap
                        DrawEquippedArmor
                        MovableData.blnPlaying = True
                        
                    Case 25 'Tell
                        If Len(St) >= 2 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                With Player(A)
                                    If .Ignore = False Then
                                        PrintChat .Name + " tells you, " + Chr$(34) + Mid$(St, 2) + Chr$(34), 10
                                    End If
                                End With
                            End If
                        End If
                        
                    Case 26 'Broadcast
                        If Len(St) >= 2 And Options.Broadcasts = True Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                If Mid$(St, 2) = Player(A).LastMessage Then
                                    Player(A).RepCount = Player(A).RepCount + 1
                                Else
                                    Player(A).RepCount = 0
                                    Player(A).LastMessage = Mid$(St, 2)
                                End If
                                
                                PrintChat Player(A).Name + ": " + Mid$(St, 2), 13
                            End If
                        End If
                        
                    Case 27 'Emote
                        If Len(St) >= 2 Then
                            A = Asc(Mid$(St, 1, 1))
                            PrintChat Player(A).Name + " " + Mid$(St, 2), 11
                        End If
                        
                    Case 28 'Yell
                        If Len(St) >= 2 Then
                            A = Asc(Mid$(St, 1, 1))
                            PrintChat Player(A).Name + " yells, " + Chr$(34) + Mid$(St, 2) + Chr$(34), 7
                        End If
                        
                    Case 29 'Map Changed
                        If Len(St) = 1 Then
                            PrintChat "This map has been altered by " + Player(A).Name + ".", 14
                        End If
                        
                    Case 30 'Server Message
                        If Len(St) > 0 Then
                            PrintChat "Server Message: " + St, 9
                        End If
                        
                    Case 31 'Object Data
                        If Len(St) >= 3 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                With Object(A)
                                    .Picture = Asc(Mid$(St, 2, 1))
                                    .Type = Asc(Mid$(St, 3, 1))
                                    If Len(St) >= 4 Then
                                        .Name = Mid$(St, 4)
                                    Else
                                        .Name = ""
                                    End If
                                    If MovableData.frmMonster_Loaded = True Then
                                        frmMonster.cmbObject(0).List(A) = CStr(A) + ": " + .Name
                                        frmMonster.cmbObject(1).List(A) = CStr(A) + ": " + .Name
                                        frmMonster.cmbObject(2).List(A) = CStr(A) + ": " + .Name
                                    End If
                                    If MovableData.frmNPC_Loaded = True Then
                                        frmNPC.cmbGiveObject.List(A) = CStr(A) + ": " + .Name
                                        frmNPC.cmbTakeObject.List(A) = CStr(A) + ": " + .Name
                                    End If
                                    If MovableData.frmList_Loaded = True Then
                                        frmList.lstObjects.List(A - 1) = CStr(A) + ": " + .Name
                                    End If
                                End With
                                For B = 1 To 20
                                    If Character.Inv(B).Object = A Then
                                        DrawInvObject B
                                    End If
                                Next B
                                For B = 0 To 79
                                    With Map.Object(B)
                                        If .Object = A Then
                                            RedrawMapTile CLng(.X), CLng(.Y)
                                        End If
                                    End With
                                Next B
                                DrawEquippedArmor
                            End If
                        End If
                        
                    Case 32 'Monster Data
                        If Len(St) >= 3 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                With Monster(A)
                                    .Sprite = Asc(Mid$(St, 2, 1))
                                    .MaxHP = Asc(Mid$(St, 3, 1))
                                    If Len(St) >= 4 Then
                                        .Name = Mid$(St, 4)
                                    Else
                                        .Name = ""
                                    End If
                                    If MovableData.frmList_Loaded = True Then
                                        frmList.lstMonsters.List(A - 1) = CStr(A) + ": " + .Name
                                    End If
                                    If MovableData.frmMapProperties_Loaded = True Then
                                        frmMapProperties.cmbMonster(0).List(A) = CStr(A) + ": " + .Name
                                        frmMapProperties.cmbMonster(1).List(A) = CStr(A) + ": " + .Name
                                        frmMapProperties.cmbMonster(2).List(A) = CStr(A) + ": " + .Name
                                        frmMapProperties.cmbMonster(3).List(A) = CStr(A) + ": " + .Name
                                        frmMapProperties.cmbMonster(4).List(A) = CStr(A) + ": " + .Name
                                    End If
                                End With
                            End If
                        End If
                        
                    Case 33 'Edit Object Data
                        If Len(St) = 9 Then
                            A = Asc(Mid$(St, 1, 1))
                            If MovableData.frmObject_Loaded = False Then Load frmObject
                            With frmObject
                                .lblNumber = A
                                .txtName = Object(A).Name
                                If Object(A).Picture > 0 Then
                                    .sclPicture = Object(A).Picture
                                Else
                                    .sclPicture = 1
                                End If
                                For B = 0 To 4
                                    .ObjData(B) = Asc(Mid$(St, B + 3, 1))
                                    .lblData(B) = .ObjData(B)
                                Next B
                                .sclData(4) = .lblData(4)
                                Object(A).Data(5) = Asc(Mid$(St, 8, 1))
                                Object(A).ObjClassData = Asc(Mid$(St, 9, 1))
                                If ExamineBit(Object(A).Data(5), CByte(0)) Then
                                    .chkIndes = 1
                                Else
                                    .chkIndes = 0
                                End If
                                If ExamineBit(Object(A).Data(5), CByte(1)) Then
                                    .chkUnrep = 1
                                Else
                                    .chkUnrep = 0
                                End If
                                For B = 0 To 3
                                    If ExamineBit(Object(A).ObjClassData, CByte(B)) Then
                                        .chkClass(B) = 1
                                    Else
                                        .chkClass(B) = 0
                                    End If
                                Next B
                                If Object(A).Type < .cmbType.ListCount Then
                                    .cmbType.ListIndex = 0
                                    .cmbType.ListIndex = Object(A).Type
                                Else
                                    .cmbType.ListIndex = 0
                                End If
                                .Show 1
                            End With
                        End If
                        
                    Case 34 'Edit Monster Data
                        If Len(St) >= 15 Then
                            A = Asc(Mid$(St, 1, 1))
                            If MovableData.frmMonster_Loaded = False Then Load frmMonster
                            With frmMonster
                                .lblNumber = A
                                .txtName = Monster(A).Name
                                If Monster(A).Sprite > 0 Then
                                    .sclSprite = Monster(A).Sprite
                                Else
                                    .sclSprite = 1
                                End If
                                B = Asc(Mid$(St, 2, 1))
                                If B > 0 Then .sclHP = B Else .sclHP = 1
                                B = Asc(Mid$(St, 3, 1))
                                If B > 0 Then .sclStrength = B Else .sclStrength = 1
                                B = Asc(Mid$(St, 4, 1))
                                .sclArmor = B
                                B = Asc(Mid$(St, 5, 1))
                                If B > 0 Then .sclSpeed = B Else .sclSpeed = 1
                                B = Asc(Mid$(St, 6, 1))
                                If B > 0 Then .sclSight = B Else .sclSight = 1
                                B = Asc(Mid$(St, 7, 1))
                                If B <= 100 Then .sclAgility = B Else .sclAgility = 100
                                B = Asc(Mid$(St, 18, 1)) * 16777216 + Asc(Mid$(St, 19, 1)) * 65536 + Asc(Mid$(St, 20, 1)) * 256& + Asc(Mid$(St, 21, 1))
                                If B <= 1000000 Then .txtExp = B Else .txtExp = "1000000"
                                If Val(.txtExp) <= 30000 Then .sclExp = Val(.txtExp)
                                B = Asc(Mid$(St, 8, 1))
                                For C = 0 To 3
                                    If ExamineBit(CByte(B), CByte(C)) Then
                                        .chkFlag(C) = 1
                                    Else
                                        .chkFlag(C) = 0
                                    End If
                                Next C
                                .cmbObject(0).ListIndex = Asc(Mid$(St, 9, 1))
                                .txtValue(0) = Asc(Mid$(St, 10, 1)) * 256 + Asc(Mid$(St, 11, 1))
                                .cmbObject(1).ListIndex = Asc(Mid$(St, 12, 1))
                                .txtValue(1) = Asc(Mid$(St, 13, 1)) * 256 + Asc(Mid$(St, 14, 1))
                                .cmbObject(2).ListIndex = Asc(Mid$(St, 15, 1))
                                .txtValue(2) = Asc(Mid$(St, 16, 1)) * 256 + Asc(Mid$(St, 17, 1))
                                .Show 1
                            End With
                        End If
                    Case 35 'Repeat
                        If Len(St) >= 1 Then
                            SendSocket St
                        End If
                        
                    Case 36 'Door Open
                        If Len(St) = 3 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A <= 9 Then
                                With Map.Door(A)
                                    .X = Asc(Mid$(St, 2, 1))
                                    .Y = Asc(Mid$(St, 3, 1))
                                    .Att = Map.Tile(.X, .Y).Att
                                    .BGTile1 = Map.Tile(.X, .Y).BGTile1
                                    Map.Tile(.X, .Y).Att = 0
                                    Map.Tile(.X, .Y).BGTile1 = 0
                                    RedrawMapTile .X, .Y
                                End With
                            End If
                        End If
                        
                    Case 37 'Close Door
                        If Len(St) = 1 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A <= 9 Then
                                With Map.Door(A)
                                    Map.Tile(.X, .Y).Att = .Att
                                    Map.Tile(.X, .Y).BGTile1 = .BGTile1
                                    .Att = 0
                                    RedrawMapTile .X, .Y
                                End With
                            End If
                        End If
                        
                    Case 38 'New Map Monster
                        If Len(St) = 5 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A <= 9 Then
                                With Map.Monster(A)
                                    .Monster = Asc(Mid$(St, 2, 1))
                                    .HP = 0
                                    .X = Asc(Mid$(St, 3, 1))
                                    .Y = Asc(Mid$(St, 4, 1))
                                    .D = Asc(Mid$(St, 5, 1))
                                    .XO = .X * 32
                                    .YO = .Y * 32
                                    .A = 0
                                End With
                            End If
                        End If
                        
                    Case 39 'Monster Die
                        If Len(St) = 1 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A <= 9 Then
                                PlayWav 9
                                Map.Monster(A).Monster = 0
                                MonsterDied A
                            End If
                        End If
                        
                    Case 40 'Monster Move
                        If Len(St) = 4 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A <= 9 Then
                                With Map.Monster(A)
                                    If CLng(.X) * 32 <> .XO Or CLng(.Y) * 32 <> .YO Then
                                        .X = Asc(Mid$(St, 2, 1))
                                        .Y = Asc(Mid$(St, 3, 1))
                                        .XO = .X * 32
                                        .YO = .Y * 32
                                    Else
                                        .X = Asc(Mid$(St, 2, 1))
                                        .Y = Asc(Mid$(St, 3, 1))
                                    End If
                                    .D = Asc(Mid$(St, 4, 1))
                                End With
                            End If
                        End If
                        
                    Case 41 'Monster Attack
                        If Len(St) = 1 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A <= 9 Then
                                Map.Monster(A).A = 5
                            End If
                        End If
                        
                    Case 42 'Player Attack
                        If Len(St) = 1 Or Len(St) = 2 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                If A <> Character.Index Then
                                    Player(A).A = 5
                                Else
                                    MovableData.CAttack = 5
                                End If
                            End If
                        End If
                        
                    Case 43 'You hit player
                        If Len(St) = 3 Then
                            A = Asc(Mid$(St, 2, 1))
                            If A >= 1 Then
                                B = Asc(Mid$(St, 3, 1))
                                Select Case Asc(Mid$(St, 1, 1))
                                    Case 0
                                        PlayWav 2
                                        MovableData.CAttack = 5
                                    Case 1
                                        PlayWav 3
                                End Select
                            End If
                        End If
                        
                    Case 44 'You hit monster
                        If Len(St) = 3 Then
                            A = Asc(Mid$(St, 2, 1))
                            If A >= 0 And A <= 9 Then
                                If Map.Monster(A).Monster > 0 Then
                                    B = Asc(Mid$(St, 3, 1))
                                    Select Case Asc(Mid$(St, 1, 1))
                                        Case 0
                                            PlayWav 2
                                            MovableData.CAttack = 5
                                        Case 1
                                            PlayWav 3
                                    End Select
                                End If
                            End If
                        End If
                        
                    Case 45 'You killed player
                        If Len(St) = 5 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                PlayWav 8
                                For C = 1 To 100
                                    If Projectile(C).TargetNum = A Then
                                        DestroyEffect (C)
                                    End If
                                Next C
                                With Player(A)
                                    If .Status = 1 Then
                                        PrintChat "You have put the evil murderer " + .Name + " to justice!", 12
                                        .Status = 0
                                    Else
                                        PrintChat "You have murdered " + .Name + " in cold blood!", 12
                                        Character.Status = 1
                                    End If
                                    B = Asc(Mid$(St, 2, 1)) * 16777216 + Asc(Mid$(St, 3, 1)) * 65536 + Asc(Mid$(St, 4, 1)) * 256& + Asc(Mid$(St, 5, 1))
                                    Character.Experience = Character.Experience + B
                                End With
                            End If
                        End If
                        
                    Case 46 'Change HP
                        If Len(St) = 1 Then
                            Character.HP = Asc(Mid$(St, 1, 1))
                            DrawHP
                        End If
                        
                    Case 47 'Change Energy
                        If Len(St) = 2 Then
                            A = Asc(Mid$(St, 2, 1))
                            Select Case Asc(Mid$(St, 1, 1))
                                Case 0
                                    Character.Energy = Character.Energy + A
                                Case 1
                                    Character.Energy = Character.Energy - A
                            End Select
                            DrawEnergy
                        End If
                        
                    Case 48 'Change Mana
                        If Len(St) = 1 Then
                            Character.Mana = Asc(Mid$(St, 1, 1))
                            DrawMana
                        End If
                        
                    Case 49 'Player Hit You
                        If Len(St) = 3 Then
                            A = Asc(Mid$(St, 2, 1))
                            If A >= 1 Then
                                B = Asc(Mid$(St, 3, 1))
                                Select Case Asc(Mid$(St, 1, 1))
                                    Case 0
                                        PlayWav 2
                                        If Character.HP > B Then
                                            Character.HP = Character.HP - B
                                        Else
                                            Character.HP = 0
                                        End If
                                        DrawHP
                                        Player(A).A = 5
                                        SendSocket Chr$(76) + Chr$(0) + Chr$(MovableData.CurInvObj)
                                    Case 1
                                        PlayWav 3
                                End Select
                            End If
                        End If
                        
                    Case 50 'Monster Hit You
                        If Len(St) = 3 Then
                            A = Asc(Mid$(St, 2, 1))
                            If A <= 9 Then
                                B = Map.Monster(A).Monster
                                C = Asc(Mid$(St, 3, 1))
                                Select Case Asc(Mid$(St, 1, 1))
                                    Case 0
                                        PlayWav 2
                                        If Character.HP > C Then
                                            Character.HP = Character.HP - C
                                        Else
                                            Character.HP = 0
                                        End If
                                        DrawHP
                                        Map.Monster(A).A = 5
                                        SendSocket Chr$(76) + Chr$(0) + Chr$(MovableData.CurInvObj)
                                    Case 1
                                        PlayWav 3
                                End Select
                            End If
                        End If
                        
                    Case 51 'You killed the monster
                        If Len(St) = 5 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A <= 9 Then
                                PlayWav 9
                                Map.Monster(A).Monster = 0
                                B = Asc(Mid$(St, 2, 1)) * 16777216 + Asc(Mid$(St, 3, 1)) * 65536 + Asc(Mid$(St, 4, 1)) * 256& + Asc(Mid$(St, 5, 1))
                                If Character.level < 125 Then Character.Experience = Character.Experience + B
                                MonsterDied (A)
                                DrawLevel
                            End If
                        End If
                        
                    Case 52 'Player Killed You
                        If Len(St) = 1 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                With Player(A)
                                    If Character.Status = 1 Then
                                        PrintChat .Name + " has put you to justice!  You have lost 1/3 of your experience!", 12
                                        Character.Status = 0
                                    Else
                                        PrintChat .Name + " has murdered you in cold blood!  You have lost 1/3 of your experience!", 12
                                        .Status = 1
                                    End If
                                End With
                                frmMain.DeathTimer.Enabled = True
                                YouDied
                            End If
                        End If
                    
                    Case 53 'Monster Killed You
                        If Len(St) = 1 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                MovableData.NextTransition = 5
                                With Monster(A)
                                    PrintChat "The " + .Name + " has killed you!  You have lost 1/3 of your experience!", 12
                                End With
                                If Character.Status = 1 Then Character.Status = 0
                                frmMain.DeathTimer.Enabled = True
                                YouDied
                            End If
                        End If
                        
                    Case 54 'Bank
                        With frmMain
                            .picBank.Visible = True
                            .lblBankName = Map.Name
                        End With
                        DrawBank
                        
                    Case 56 'Text
                        If Len(St) >= 2 Then
                            PrintChat Mid$(St, 2), Asc(Mid$(St, 1, 1))
                        End If
                    
                    Case 57 'Object Breaks
                        If Len(St) = 1 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 And A <= 20 Then
                                With Character.Inv(A)
                                    If .Object > 0 Then
                                        PrintChat "Your " + Object(.Object).Name + " breaks.", 14
                                    End If
                                    .Object = 0
                                    .EquippedNum = 0
                                End With
                                DrawInvObject A
                                DrawEquippedArmor
                            End If
                        End If
                        
                    Case 59 'Level Up
                        If Len(St) = 5 Then
                            With Character
                                .MaxHP = Asc(Mid$(St, 1, 1))
                                .MaxEnergy = Asc(Mid$(St, 2, 1))
                                .MaxMana = Asc(Mid$(St, 3, 1))
                                .StatPoints = Asc(Mid$(St, 4, 1)) * 256 + Asc(Mid$(St, 5, 1))
                                .MaxExperience = Int(1000 * CLng(.level) ^ 1.3)
                                .Experience = 0
                                PrintChat "Level Up!  You are now level " + CStr(.level) + ".  You have " + CStr(.StatPoints) + " stat points.  Click Stats to spend them.", 12
                                If .level = 5 Then
                                    PrintChat "You are no longer protected from other players.", 12
                                End If
                                DrawHP
                                DrawEnergy
                                DrawMana
                                DrawLevel
                            End With
                        End If
                        
                    Case 60 'Experience Change
                        If Len(St) = 4 And Character.level < 125 Then
                            Character.Experience = Asc(Mid$(St, 1, 1)) * 16777216 + Asc(Mid$(St, 2, 1)) * 65536 + Asc(Mid$(St, 3, 1)) * 256& + Asc(Mid$(St, 4, 1))
                            DrawLevel
                        End If
                        
                    Case 61 'Player killed by player
                        If Len(St) = 2 Then
                            A = Asc(Mid$(St, 1, 1))
                            B = Asc(Mid$(St, 2, 1))
                            If A >= 1 And B >= 1 Then
                                With Player(A)
                                    If .Status = 1 Then
                                        PrintChat Player(B).Name + " has put " + .Name + " to justice!", 12
                                        .Status = 0
                                    Else
                                        PrintChat Player(B).Name + " has murdered " + .Name + " in cold blood!", 12
                                        Player(B).Status = 1
                                    End If
                                    If .Map = MovableData.CMap Then PlayWav 8
                                End With
                            End If
                        End If
                        
                    Case 62 'Player killed by monster
                        If Len(St) = 2 Then
                            A = Asc(Mid$(St, 1, 1))
                            B = Asc(Mid$(St, 2, 1))
                            If A >= 1 And B >= 1 Then
                                With Player(A)
                                    If .Map = MovableData.CMap Then PlayWav 8
                                    PrintChat .Name + " has been killed by a " + Monster(B).Name + "!", 12
                                    If .Status = 1 Then .Status = 0
                                End With
                            End If
                        End If
                    
                    Case 63 'Player Sprite Changed
                        If Len(St) >= 2 Then
                            A = Asc(Mid$(St, 2, 1))
                            B = Asc(Mid$(St, 3, 1))
                            Select Case Asc(Mid$(St, 1, 1))
                                Case 0 'Sprite Change
                                    If A >= 1 And B >= 1 Then
                                        If A = Character.Index Then
                                            Character.Sprite = B
                                        Else
                                            If Player(A).Sprite > 0 Then
                                                Player(A).Sprite = B
                                            End If
                                        End If
                                    End If
                                Case 1 'Player Dead
                                    If A >= 1 Then
                                        If A = Character.Index Then
                                            MovableData.Dead = True
                                            frmMain.DeathTimer.Enabled = True
                                        Else
                                            If Player(A).Sprite > 0 Then
                                                Player(A).Dead = True
                                            End If
                                        End If
                                    End If
                            End Select
                        End If
                        
                    Case 64 'Player Name Change
                        If Len(St) >= 2 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                If A = Character.Index Then
                                    Character.Name = Mid$(St, 2)
                                Else
                                    If Player(A).Sprite > 0 Then
                                        Player(A).Name = Mid$(St, 2)
                                    End If
                                End If
                            End If
                        End If
                        
                    Case 65 'Changed access
                        If Len(St) = 1 Then
                            Character.Access = Asc(Mid$(St, 1, 1))
                            If Character.Access > 0 Then
                                Character.Status = 3
                            End If
                        End If
                        
                    Case 66 'Player banned
                        If Len(St) >= 2 Then
                            B = Asc(Mid$(St, 1, 1))
                            C = Asc(Mid$(St, 2, 1))
                            If B >= 1 And C >= 1 Then
                                If C >= 1 Then
                                    If Len(St) > 2 Then
                                        PrintChat Player(B).Name + " has been banned by " + Player(C).Name + " - Reason: " + Mid$(St, 3), 15
                                    Else
                                        PrintChat Player(B).Name + " has been banned by " + Player(C).Name + "!", 15
                                    End If
                                Else
                                    If Len(St) > 2 Then
                                        PrintChat Player(B).Name + " has been banned - Reason: " + Mid$(St, 3), 15
                                    Else
                                        PrintChat Player(B).Name + " has been banned!", 15
                                    End If
                                End If
                            End If
                        End If
                        
                    Case 67 'Booted
                        If Len(St) >= 1 Then
                            A = Asc(Mid$(St, 2, 1))
                            Select Case Asc(Mid$(St, 1, 1))
                                Case 0
                                    If Len(St) > 2 Then
                                        MessageBox frmMenu.hwnd, "You have been booted from The Odyssey by " + Player(A).Name + "! - Reason: " + Mid$(St, 3), TitleString, vbOKOnly + vbExclamation
                                    Else
                                        MessageBox frmMenu.hwnd, "You have been booted from The Odyssey by " + Player(A).Name + "!", TitleString, vbOKOnly + vbExclamation
                                    End If
                                Case 1
                                    If Len(St) > 2 Then
                                        MessageBox frmMenu.hwnd, "You have been banned from The Odyssey Online Classic! - Reason: " + Mid$(St, 3), TitleString, vbOKOnly + vbExclamation
                                    Else
                                        MessageBox frmMenu.hwnd, "You have been booted from The Odyssey Online Classic!", TitleString, vbOKOnly + vbExclamation
                                    End If
                            End Select
                            CloseClientSocket 0
                        End If
                        
                    Case 68 'Player Booted
                        If Len(St) >= 2 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                If Len(St) > 1 Then
                                    PrintChat Player(A).Name + " has been booted - Reason: " + Mid$(St, 2), 15
                                Else
                                    PrintChat Player(A).Name + " has been booted!", 15
                                End If
                            End If
                        End If
                        
                    Case 69 'Ban List
                        If Len(St) >= 2 Then
                            A = Asc(Mid$(St, 1, 1))
                            With frmList.lstBans
                                .AddItem CStr(A) + ": " + Mid$(St, 2)
                                .ItemData(.ListCount - 1) = A
                            End With
                        Else
                            frmList.Show
                        End If
                        
                    Case 70 'Guild Data
                        If Len(St) >= 1 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                If Len(St) > 1 Then
                                    Guild(A).Name = Mid$(St, 2)
                                Else
                                    Guild(A).Name = ""
                                    Guild(A).Sprite = 0
                                End If
                            End If
                            If MovableData.frmGuild_Loaded = True And Character.Guild = A Then frmGuild.lblName = Mid$(St, 2)
                        End If
                        
                    Case 71 'Guild Dec. Data
                        If Len(St) = 3 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A <= 4 Then
                                With Character.GuildDeclaration(A)
                                    .Guild = Asc(Mid$(St, 2, 1))
                                    .Type = Asc(Mid$(St, 3, 1))
                                End With
                                UpdatePlayersColors
                            End If
                        End If
                        
                    Case 72 'Guild Change
                        If Len(St) = 1 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A > 0 Then
                                PrintChat "You are now a member of " + Chr$(34) + Guild(A).Name + Chr$(34), 15
                            Else
                                If Character.Guild > 0 Then
                                    PrintChat "You are no longer a member of " + Chr$(34) + Guild(Character.Guild).Name + Chr$(34), 15
                                End If
                            End If
                            Character.Guild = A
                            Character.GuildRank = 0
                            UpdatePlayersColors
                        End If
                        
                    Case 73 'Player Changed Guild
                        If Len(St) = 2 Then
                            A = Asc(Mid$(St, 1, 1))
                            B = Asc(Mid$(St, 2, 1))
                            If A >= 1 Then
                                If Player(A).Guild = Character.Guild And Character.Guild > 0 Then
                                    PrintChat Player(A).Name + " is no longer a member of your guild.", 15
                                End If
                                Player(A).Guild = B
                                If B > 0 And B = Character.Guild Then
                                    PrintChat Player(A).Name + " is now a member of your guild.", 15
                                End If
                            End If
                            UpdatePlayerColor A
                        End If
                        
                    Case 74 'Guild Account Status
                        If Len(St) = 4 Then
                            A = Asc(Mid$(St, 1, 1)) * 16777216 + Asc(Mid$(St, 2, 1)) * 65536 + Asc(Mid$(St, 3, 1)) * 256& + Asc(Mid$(St, 4, 1))
                            PrintChat "Your guild has " + CStr(A) + " gold in the bank.", 15
                        ElseIf Len(St) = 8 Then
                            A = Asc(Mid$(St, 1, 1)) * 16777216 + Asc(Mid$(St, 2, 1)) * 65536 + Asc(Mid$(St, 3, 1)) * 256& + Asc(Mid$(St, 4, 1))
                            B = Asc(Mid$(St, 5, 1)) * 16777216 + Asc(Mid$(St, 6, 1)) * 65536 + Asc(Mid$(St, 7, 1)) * 256& + Asc(Mid$(St, 8, 1))
                            PrintChat "Your guild owes " + CStr(A) + " gold.  This must be payed before " + CStr(CDate(B)) + " or your guild will be disbanded.  Type '/guild pay <amount>' to pay toward the debt.", 15
                        End If
                        
                    Case 75 'Guild Deleted
                        If Len(St) = 1 Then
                            Select Case Asc(Mid$(St, 1, 1))
                                Case 0
                                    PrintChat "Your guild has failed to pay its debt in time and has been disbanded!", 15
                                Case 1
                                    PrintChat "Your guild member count has fallen below three -- your guild has been disbanded!", 15
                                Case 2
                                    PrintChat "Your guild has been disbanded!", 15
                                Case 3
                                    PrintChat "Your guild has been disbanded by a god!", 15
                            End Select
                            Character.Guild = 0
                            Character.GuildRank = 0
                            UpdatePlayersColors
                        End If
                        
                    Case 76 'Rank Changed
                        If Len(St) = 1 Then
                            Character.GuildRank = Asc(Mid$(St, 1, 1))
                            PrintChat "Your guild rank has been changed to " + Chr$(34) + Choose(Character.GuildRank + 1, "Initiate", "Member", "Lord", "Founder") + Chr$(34) + ".", 15
                        End If
                        
                    Case 77 'Invited to join guild
                        If Len(St) = 2 Then
                            A = Asc(Mid$(St, 1, 1))
                            B = Asc(Mid$(St, 2, 1))
                            If A >= 1 And B >= 1 Then
                                PrintChat "You have been invited to join the guild " + Chr$(34) + Guild(A).Name + Chr$(34) + " by " + Player(B).Name + ".  If you wish to join, type /guild join.  It will cost 10000 gold to join this guild.", 15
                            End If
                        End If
                        
                    Case 78 'View Guild Data
                        If Len(St) >= 12 Then
                            frmMain.picBuy.Visible = False
                            frmMain.picDrop.Visible = False
                            frmMain.picTrain.Visible = False
                            MovableData.TempVar1 = Asc(Mid$(St, 1, 1))
                            If MovableData.frmGuild_Loaded = False Then Load frmGuild
                            With frmGuild
                                A = Asc(Mid$(St, 2, 1))
                                If A > 0 Then
                                    .lblHall = Hall(A).Name
                                Else
                                    .lblHall = "None"
                                End If
                                .lstDeclarations.Clear
                                For A = 0 To 4
                                    B = Asc(Mid$(St, 3 + 2 * A))
                                    If B > 0 Then
                                        If Asc(Mid$(St, 4 + 2 * A)) = 0 Then
                                            .lstDeclarations.AddItem "Declaration of Alliance with " + Guild(B).Name
                                        Else
                                            .lstDeclarations.AddItem "Declaration of War with " + Guild(B).Name
                                        End If
                                        .lstDeclarations.ItemData(.lstDeclarations.ListCount - 1) = A
                                    End If
                                Next A
                                If Len(St) >= 13 Then
                                    GetSections2 Mid$(St, 13)
                                    .lblName = Guild(MovableData.TempVar1).Name
                                    .lstMembers.Clear
                                    For A = 0 To 19
                                        If Len(Section(A + 1)) >= 2 Then
                                            B = Asc(Mid$(Section(A + 1), 1, 1)) - 1
                                            If B <= 3 Then
                                                .lstMembers.AddItem Mid$(Section(A + 1), 2) + " - " + Choose(B + 1, "Initiate", "Member", "Lord", "Founder")
                                                .lstMembers.ItemData(.lstMembers.ListCount - 1) = A
                                            End If
                                        End If
                                    Next A
                                End If
                                If Character.Guild = MovableData.TempVar1 And Character.GuildRank >= 2 Then
                                    If Character.GuildRank = 3 Then
                                        .lblDisband.Enabled = True
                                    Else
                                        .lblDisband.Enabled = False
                                    End If
                                    If .lstDeclarations.ListCount < 5 Then
                                        .lblAddDeclaration.Enabled = True
                                    Else
                                        .lblAddDeclaration.Enabled = False
                                    End If
                                    If .lblHall = "<none>" Then
                                        .lblMoveOut.Enabled = False
                                    Else
                                        .lblMoveOut.Enabled = True
                                    End If
                                    .lblBuySprite.Enabled = True
                                    .lblRemoveSprite.Enabled = True
                                Else
                                    .lblBuySprite.Enabled = False
                                    .lblRemoveSprite.Enabled = False
                                    .lblDisband.Enabled = False
                                    .lblAddDeclaration.Enabled = False
                                    .lblMoveOut.Enabled = False
                                End If
                                .lblRemoveMember.Enabled = False
                                .lblRemoveDeclaration.Enabled = False
                                .lblRank(0).Enabled = False
                                .lblRank(1).Enabled = False
                                .lblRank(2).Enabled = False
                                .lblRank(3).Enabled = False
                                .lblOk.Enabled = True
                                .Show
                                .picSprite.Refresh
                                BitBlt .picSprite.hdc, 0, 0, 32, 32, hdcSprites, 128, 0, SRCCOPY
                            End With
                        End If
                        
                    Case 79 'Guild Chat
                        If Len(St) >= 2 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                PrintChat Player(A).Name + " -> Guild: " + Mid$(St, 2), 15
                            End If
                        End If
                    
                    Case 80 'Created Guild
                        If Len(St) = 1 Then
                            A = Asc(Mid$(St, 1, 1))
                            Character.Guild = A
                            Character.GuildRank = 3
                            If A > 0 Then
                                PrintChat "You have created a new guild called " + Chr$(34) + Guild(A).Name + Chr$(34) + ".  To invite other players to your guild, type '/guild invite <player>'.  You must get atleast two other players to join your guild today or your guild will be disbanded.", 15
                            End If
                        End If
                        
                    Case 81 'Guild hall change
                        If Len(St) = 1 Then
                            If Asc(Mid$(St, 1, 1)) = 0 Then
                                PrintChat "Your guild now owns a hall!", 15
                            Else
                                PrintChat "Your guild no longer owns a hall!", 15
                            End If
                        End If
                    
                    Case 82 'Guild hall data
                        If Len(St) >= 1 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                If Len(St) >= 2 Then
                                    Hall(A).Name = Mid$(St, 2)
                                Else
                                    Hall(A).Name = ""
                                End If
                                If MovableData.frmList_Loaded = True Then
                                    frmList.lstHalls.List(A - 1) = CStr(A) + ": " + Hall(A).Name
                                End If
                            End If
                        End If
                        
                    Case 83 'Guild Hall Edit Data
                        If Len(St) = 13 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                If MovableData.frmHall_Loaded = False Then Load frmHall
                                With frmHall
                                    .lblNumber = A
                                    .txtName = Hall(A).Name
                                    .txtPrice = CStr(Asc(Mid$(St, 2, 1)) * 16777216 + Asc(Mid$(St, 3, 1)) * 65536 + Asc(Mid$(St, 4, 1)) * 256& + Asc(Mid$(St, 5, 1)))
                                    .txtUpkeep = CStr(Asc(Mid$(St, 6, 1)) * 16777216 + Asc(Mid$(St, 7, 1)) * 65536 + Asc(Mid$(St, 8, 1)) * 256& + Asc(Mid$(St, 9, 1)))
                                    B = Asc(Mid$(St, 10, 1)) * 256 + Asc(Mid$(St, 11, 1))
                                    If B < 1 Then B = 1
                                    If B > 2000 Then B = 2000
                                    .sclStartMap = B
                                    B = Asc(Mid$(St, 12, 1))
                                    If B > 11 Then B = 11
                                    .sclStartX = B
                                    B = Asc(Mid$(St, 13, 1))
                                    If B > 11 Then B = 11
                                    .sclStartY = B
                                    .Show
                                End With
                            End If
                        End If
                        
                    Case 84 'Guild Hall Info
                        If Len(St) = 10 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                B = Asc(Mid$(St, 2, 1))
                                If B > 0 Then
                                    PrintChat "Owned By: " + Guild(B).Name, 15
                                Else
                                    PrintChat "This guild hall is not yet owned!", 15
                                End If
                                A = Asc(Mid$(St, 3, 1)) * 16777216 + Asc(Mid$(St, 4, 1)) * 65536 + Asc(Mid$(St, 5, 1)) * 256& + Asc(Mid$(St, 6, 1))
                                PrintChat "Cost: " + CStr(A) + " gold coins", 15
                                A = Asc(Mid$(St, 7, 1)) * 16777216 + Asc(Mid$(St, 8, 1)) * 65536 + Asc(Mid$(St, 9, 1)) * 256& + Asc(Mid$(St, 10, 1))
                                PrintChat "Upkeep: " + CStr(A) + " gold coins per day", 15
                            End If
                        End If
                        
                    Case 85 'NPC Data
                        If Len(St) >= 1 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                With NPC(A)
                                    If Len(St) >= 2 Then
                                        .Name = Mid$(St, 2)
                                    Else
                                        .Name = ""
                                    End If
                                    If MovableData.frmList_Loaded = True Then
                                        frmList.lstNPCs.List(A - 1) = CStr(A) + ": " + .Name
                                    End If
                                    If MovableData.frmMapProperties_Loaded = True Then
                                        frmMapProperties.cmbNPC.List(A) = CStr(A) + ": " + .Name
                                    End If
                                End With
                            End If
                        End If
                        
                    Case 86 'Buy Data
                        If Len(St) = 100 Then
                            For A = 0 To 9
                                With SaleItem(A)
                                    .GiveObject = Asc(Mid$(St, 1 + A * 10, 1))
                                    .GiveValue = Asc(Mid$(St, 2 + A * 10, 1)) * 16777216 + Asc(Mid$(St, 3 + A * 10, 1)) * 65536 + Asc(Mid$(St, 4 + A * 10, 1)) * 256& + Asc(Mid$(St, 5 + A * 10, 1))
                                    .TakeObject = Asc(Mid$(St, 6 + A * 10, 1))
                                    .TakeValue = Asc(Mid$(St, 7 + A * 10, 1)) * 16777216 + Asc(Mid$(St, 8 + A * 10, 1)) * 65536 + Asc(Mid$(St, 9 + A * 10, 1)) * 256& + Asc(Mid$(St, 10 + A * 10, 1))
                                    If .GiveObject >= 1 And .TakeObject >= 1 Then
                                        St1 = ""
                                        If Object(.GiveObject).Type = 6 Then
                                            St1 = CStr(.GiveValue) + " " + Object(.GiveObject).Name
                                        Else
                                            St1 = "1 " + Object(.GiveObject).Name
                                        End If
                                        St1 = St1 + " in exchange for "
                                        If Object(.TakeObject).Type = 6 Then
                                            St1 = St1 + CStr(.TakeValue) + " " + Object(.TakeObject).Name
                                        Else
                                            St1 = St1 + "1 " + Object(.TakeObject).Name
                                        End If
                                        frmMain.lblItem(A) = St1
                                        frmMain.GivObjPic(A).Cls
                                        TransparentBlt frmMain.GivObjPic(A).hdc, 0, 0, 32, 32, hdcObjects, 0, (Object(.GiveObject).Picture - 1) * 32, hdcObjectsMask
                                    Else
                                        frmMain.lblItem(A) = ""
                                        frmMain.GivObjPic(A).Cls
                                    End If
                                End With
                            Next A
                            frmMain.picBuy.Visible = True
                            frmMain.picTrain.Visible = False
                            frmMain.picDrop.Visible = False
                        End If
                    
                    Case 87 'Edit NPC Data
                        If Len(St) >= 108 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                If MovableData.frmNPC_Loaded = False Then Load frmNPC
                                B = Asc(Mid$(St, 2, 1))
                                For C = 0 To 1
                                    If ExamineBit(CByte(B), CByte(C)) Then
                                        frmNPC.chkFlag(C) = 1
                                    Else
                                        frmNPC.chkFlag(C) = 0
                                    End If
                                Next C
                                For B = 0 To 9
                                    With SaleItem(B)
                                        .GiveObject = Asc(Mid$(St, 3 + B * 10, 1))
                                        .GiveValue = Asc(Mid$(St, 4 + B * 10, 1)) * 16777216 + Asc(Mid$(St, 5 + B * 10, 1)) * 65536 + Asc(Mid$(St, 6 + B * 10, 1)) * 256& + Asc(Mid$(St, 7 + B * 10, 1))
                                        .TakeObject = Asc(Mid$(St, 8 + B * 10, 1))
                                        .TakeValue = Asc(Mid$(St, 9 + B * 10, 1)) * 16777216 + Asc(Mid$(St, 10 + B * 10, 1)) * 65536 + Asc(Mid$(St, 11 + B * 10, 1)) * 256& + Asc(Mid$(St, 12 + B * 10, 1))
                                    End With
                                    UpdateSaleItem B
                                Next B
                                '103
                                GetSections2 Mid$(St, 103)
                                With frmNPC
                                    .lblNumber = A
                                    .txtName = NPC(A).Name
                                    .txtJoinText = Section(1)
                                    .txtLeaveText = Section(2)
                                    .txtSayText1 = Section(3)
                                    .txtSayText2 = Section(4)
                                    .txtSayText3 = Section(5)
                                    .txtSayText4 = Section(6)
                                    .txtSayText5 = Section(7)
                                    .Show 1
                                End With
                            End If
                        End If
                    Case 88 'NPC Talks
                        If Len(St) >= 2 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                PrintChat NPC(A).Name + " says, " + Chr$(34) + Mid$(St, 2) + Chr$(34), 7
                            End If
                        End If
                    Case 89 'Monster/Player HP
                        If Len(St) = 3 Or Len(St) = 4 Then
                            A = Asc(Mid$(St, 2, 1))
                            B = Asc(Mid$(St, 3, 1))
                            C = Asc(Mid$(St, 4, 1))
                            Select Case Asc(Mid$(St, 1, 1))
                                Case 0 'Monster HP
                                    Map.Monster(A).HP = B
                                Case 1 'Player HP
                                    Player(A).HP = B
                                    Player(A).MaxHP = C
                            End Select
                        End If
                    Case 90 'God Chat
                        If Len(St) >= 2 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                PrintChat "[" + Player(A).Name + "] - " + Mid$(St, 2), 11
                            End If
                        End If
                        
                    Case 91 'Status Change
                        If Len(St) = 2 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                If A = Character.Index Then
                                    Character.Status = Asc(Mid$(St, 2, 1))
                                Else
                                    Player(A).Status = Asc(Mid$(St, 2, 1))
                                End If
                                UpdatePlayerColor A
                            End If
                        End If
                        
                    Case 92 'Edit Ban Data
                        If Len(St) >= 4 Then
                            If MovableData.frmBan_Loaded = False Then Load frmBan
                            GetSections2 Mid$(St, 3)
                            With frmBan
                                .lblNumber = Asc(Mid$(St, 1, 1))
                                .sclUnban = Asc(Mid$(St, 2, 1))
                                .txtName = Section(1)
                                .txtBanner = Section(2)
                                .txtReason = Section(3)
                                .txtIP = Section(4)
                                .Show
                            End With
                        End If
                        
                    Case 93 'Skill Levelup
                        If Len(St) = 2 Then
                            A = Asc(Mid$(St, 2, 1))
                            Select Case Asc(Mid$(St, 1, 1))
                                Case 1
                                    St1 = "Lumberjacking"
                                Case 2
                                    St1 = "Mining"
                                Case 3
                                    St1 = "Fishing"
                            End Select
                            PrintChat "Your " + St1 + " skill has increased to Level " + CStr(A) + "!", 12
                        End If
                        
                    Case 94 'Edit Script Data
                        If Len(St) >= 3 Then
                            A = InStr(St, Chr$(0))
                            If A >= 1 Then
                                Load frmScript
                                With frmScript
                                    .lblName = Left$(St, A - 1)
                                    .txtCode = Mid$(St, A + 1)
                                    If .txtCode = "" Then
                                        St1 = .lblName
                                        If St1 Like "mapsay*" Then
                                            .txtCode = "Function Main(Player AS LONG, Message AS STRING) AS LONG" + Chr$(13) + Chr$(10) + "" + Chr$(13) + Chr$(10) + "End Function"
                                        ElseIf St1 = "playerkill" Then
                                            .txtCode = "Function Main(Player AS LONG, Target AS LONG) AS LONG" + Chr$(13) + Chr$(10) + "" + Chr$(13) + Chr$(10) + "End Function"
                                        ElseIf St1 = "clickplayer" Then
                                            .txtCode = "Function Main(Player AS LONG, Target AS LONG) AS LONG" + Chr$(13) + Chr$(10) + "" + Chr$(13) + Chr$(10) + "End Function"
                                        ElseIf St1 = "ts" Then
                                            .txtCode = "Function Main(Player AS LONG, TS AS LONG) AS LONG" + Chr$(13) + Chr$(10) + "" + Chr$(13) + Chr$(10) + "End Function"
                                        ElseIf St1 = "joinmap" Then
                                            .txtCode = "Function Main(Player AS LONG, Map AS LONG) AS LONG" + Chr$(13) + Chr$(10) + "" + Chr$(13) + Chr$(10) + "End Function"
                                        ElseIf St1 = "gainexp" Then
                                            .txtCode = "Function Main(Player AS LONG, Exp AS LONG) AS LONG" + Chr$(13) + Chr$(10) + "" + Chr$(13) + Chr$(10) + "End Function"
                                        ElseIf St1 = "levelup" Then
                                            .txtCode = "Function Main(Player AS LONG, NewLevel AS LONG) AS LONG" + Chr$(13) + Chr$(10) + "" + Chr$(13) + Chr$(10) + "End Function"
                                        ElseIf St1 = "broadcast" Then
                                            .txtCode = "Function Main(Player AS LONG, Message AS STRING) AS LONG" + Chr$(13) + Chr$(10) + "" + Chr$(13) + Chr$(10) + "End Function"
                                        ElseIf St1 = "command" Then
                                            .txtCode = "Function Main(Player as LONG, Command as STRING, Parm1 as STRING, Parm2 as STRING, Parm3 as STRING, Parm4 as STRING) AS LONG" + Chr$(13) + Chr$(10) + "Main = Continue" + Chr$(13) + Chr$(10) + "End Function"
                                        Else
                                            .txtCode = "Function Main(Player as LONG) AS LONG" + Chr$(13) + Chr$(10) + "" + Chr$(13) + Chr$(10) + "End Function"
                                        End If
                                    End If
                                    .Show 1
                                End With
                            End If
                        End If
                        
                    Case 95 'Change Player XY
                        If Len(St) = 3 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A = Character.Index Then
                                MovableData.cx = Asc(Mid$(St, 2, 1))
                                MovableData.cy = Asc(Mid$(St, 3, 1))
                                MovableData.CXO = MovableData.cx * 32
                                MovableData.CYO = MovableData.cy * 32
                                MovableData.Freeze = False
                            Else
                                With Player(A)
                                    .X = Asc(Mid$(St, 2, 1))
                                    .Y = Asc(Mid$(St, 3, 1))
                                    .XO = .X * 32
                                    .YO = .Y * 32
                                End With
                            End If
                        End If
                    
                    Case 96 'Custom Wav Play
                    If Len(St) >= 1 Then
                        A = Asc(Mid$(St, 1, 1))
                        If Exists("Sound" + CStr(A) + ".wav") Then
                            PlayWav A
                        End If
                    End If
                    
                    Case 97 'New Guild Info
                    Select Case Asc(Mid$(St, 1, 1))
                        Case 0 'Already in a guild.
                            PrintChat "You are already in a guild.  If you would like to create a new guild, you must first leave this guild by typing '/guild leave'.", 14
                    
                        Case 1 'New Guild Show
                            frmNewGuild.Show
                    
                        Case 2 'Guilds are Disabled
                            PrintChat "Guilds have been disabled.", 14
                    
                        Case 3 'Need to be atleast level 5
                            PrintChat "You must be atleast level 5 to join a guild!", 14
                    End Select
                    
                    Case 98 'Repairing
                        Select Case Asc(Mid$(St, 1, 1))
                            Case 1 'NPC Repair Display
                                A = Asc(Mid$(St, 4, 1)) * 16777216 + Asc(Mid$(St, 5, 1)) * 65536 + Asc(Mid$(St, 6, 1)) * 256& + Asc(Mid$(St, 7, 1)) 'Repair Ammount
                                B = Asc(Mid$(St, 2, 1)) 'Dur
                                C = QBColor(1)
                                D = Asc(Mid$(St, 3, 1))
                                Select Case B
                                    Case Is = 100
                                        St = "Perfect"
                                        C = QBColor(11)
                                    Case Is >= 80
                                        St = "Excellent"
                                        C = QBColor(11)
                                    Case Is >= 60
                                        St = "Fair"
                                        C = QBColor(14)
                                    Case Is >= 40
                                        St = "Average"
                                        C = QBColor(2)
                                    Case Is >= 20
                                        St = "Weak"
                                        C = QBColor(4)
                                    Case Is >= 0
                                        St = "About to Break"
                                        C = QBColor(5)
                                End Select
                                If Object(B).Data(4) = 1 Then
                                    St = "Indestructible"
                                    C = QBColor(11)
                                End If
                                frmMain.lblObjName = Trim$(Object(D).Name)
                                frmMain.lblRepairNPCName = Trim$(NPC(Map.NPC).Name)
                                frmMain.RepairObjPic.Cls
                                TransparentBlt frmMain.RepairObjPic.hdc, 0, 0, 32, 32, hdcObjects, 0, (Object(D).Picture - 1) * 32, hdcObjectsMask
                            If A = 0 Then
                                frmMain.lblRepairCst = "N/A"
                                St1 = "0"
                            Else
                                frmMain.lblRepairCst = Str(A) + " Gold Coins."
                                St1 = Str(A)
                            End If
                            Select Case Object(D).Type
                                Case 1, 2, 3, 4, 8
                                    frmMain.lblObjDur = Str(B) + "%"
                                    frmMain.lblObjCond = St
                                    frmMain.lblObjCond.ForeColor = C
                                    If St = "Perfect" Then
                                        frmMain.lblRepairNpcTalk = "Hail " + Character.Name + "! Your " + Trim$(Object(D).Name) + " does not need repairing as it is already in Perfect Condition."
                                    Else
                                        frmMain.lblRepairNpcTalk = "Hail " + Character.Name + "! I am able to assist you with this. I can repair your " + Trim$(Object(D).Name) + " for " + St1 + " Gold Coins. My efforts are worth for what I charge."
                                    End If
                                Case Else
                                    frmMain.lblObjDur = "N/A"
                                    frmMain.lblObjCond = "N/A"
                                    frmMain.lblObjCond.ForeColor = QBColor(11)
                                    frmMain.lblRepairNpcTalk = "Hail " + Character.Name + "! I am sorry but this is not a repairable item!"
                            End Select
                            frmMain.picRepair.Visible = True
                        
                        Case 2 'Done Repairing Object
                            A = Asc(Mid$(St, 2, 1))
                            PrintChat "Your " + Object(A).Name + " is now at 100% durability. You repaired it successfully.", 14
                            frmMain.lblObjDur = "100%"
                            frmMain.lblObjCond = "Perfect"
                            frmMain.lblObjCond.ForeColor = QBColor(11)
                        End Select
                    
                    Case 99 'Projectiles
                        Select Case Asc(Mid$(St, 1, 1))
                            Case 1 'Tile Effect
                                CreateTileEffect Asc(Mid$(St, 2, 1)), Asc(Mid$(St, 3, 1)), Asc(Mid$(St, 4, 1)), Asc(Mid$(St, 5, 1)) * 256 + Asc(Mid$(St, 6, 1)), Asc(Mid$(St, 7, 1)), Asc(Mid$(St, 8, 1)), Asc(Mid$(St, 9, 1))
                            Case 2 'Character Effect
                                CreateCharacterEffect Asc(Mid$(St, 2, 1)), Asc(Mid$(St, 3, 1)), Asc(Mid$(St, 4, 1)) * 256 + Asc(Mid$(St, 5, 1)), Asc(Mid$(St, 6, 1)), Asc(Mid$(St, 7, 1)), Asc(Mid$(St, 8, 1))
                            Case 3 'Monster Effect
                                If Asc(Mid$(St, 2, 1)) = Character.Index Then
                                    A = MovableData.cx
                                    B = MovableData.cy
                                Else
                                    A = Player(Asc(Mid$(St, 2, 1))).X
                                    B = Player(Asc(Mid$(St, 2, 1))).Y
                                End If
                                CreateMonsterEffect Asc(Mid$(St, 3, 1)), Asc(Mid$(St, 4, 1)), Asc(Mid$(St, 5, 1)) * 256 + Asc(Mid$(St, 6, 1)), Asc(Mid$(St, 6, 1)), A, B, Asc(Mid$(St, 8, 1))
                            Case 4 'Player Effect
                                If Asc(Mid$(St, 2, 1)) = Character.Index Then
                                    A = MovableData.cx
                                    B = MovableData.cy
                                Else
                                    A = Player(Asc(Mid$(St, 2, 1))).X
                                    B = Player(Asc(Mid$(St, 2, 1))).Y
                                End If
                                CreatePlayerEffect Asc(Mid$(St, 3, 1)), Asc(Mid$(St, 4, 1)), Asc(Mid$(St, 5, 1)) * 256 + Asc(Mid$(St, 6, 1)), Asc(Mid$(St, 7, 1)), A, B, Asc(Mid$(St, 8, 1))
                        End Select
                    Case 100 'MapEdit Check
                        OpenMapEdit
                    Case 101 'Static Text
                        If Len(St) >= 4 Then
                            A = Asc(Mid$(St, 1, 1))
                            B = Asc(Mid$(St, 2, 1))
                            C = Asc(Mid$(St, 3, 1))
                            St1 = Mid$(St, 4)
                            PrintStaticText St1, CByte(C), A, B
                        End If
                    Case 102
                        With Character
                            .MaxHP = Asc(Mid$(St, 1, 1))
                            .MaxEnergy = Asc(Mid$(St, 2, 1))
                            .MaxMana = Asc(Mid$(St, 3, 1))
                            .level = Asc(Mid$(St, 4, 1))
                            .Class = Asc(Mid$(St, 5, 1))
                            If .MaxHP < .HP Then
                                .HP = .MaxHP
                            End If
                            If .MaxEnergy < .Energy Then
                                .Energy = .MaxEnergy
                            End If
                            If .MaxMana < .Mana Then
                                .Mana = .MaxMana
                            End If
                            DrawHP
                            DrawEnergy
                            DrawMana
                        End With
                    Case 103
                        With Character
                            .Damage = Asc(Mid$(St, 1, 1))
                            .Defense = Asc(Mid$(St, 2, 1))
                        End With
                        With frmMain
                            If Character.Gender = 0 Then
                                St1 = "Male"
                            Else
                                St1 = "Female"
                            End If
                            .lblStatName = Character.Name
                            .lblStatLevel = Character.level
                            .lblStatClass = Class(Character.Class).Name
                            .lblStatGender = St1
                            .lblStatStrength = Str(Character.Damage)
                            .lblStatDefense = Str(Character.Defense)
                            MovableData.TempVar1 = 0
                            MovableData.TempVar2 = 0
                            MovableData.TempVar3 = 0
                            MovableData.TempVar4 = 0
                            MovableData.TempVar5 = 0
                            MovableData.TempVar6 = 0
                            MovableData.TempVar7 = 0
                            MovableData.TempVar8 = 0
                            MovableData.TempVar9 = Character.StatPoints
                            DrawTrainBars
                            .picTrain.Visible = True
                            .picDrop.Visible = False
                            .picBuy.Visible = False
                        End With
                    Case 104
                        A = Asc(Mid$(St, 1, 1))
                        B = Asc(Mid$(St, 2, 1))
                        Character.Bank(A).Object = B
                        Character.Bank(A).Value = Asc(Mid$(St, 3, 1)) * 16777216 + Asc(Mid$(St, 4, 1)) * 65536 + Asc(Mid$(St, 5, 1)) * 256& + Asc(Mid$(St, 6, 1))
                        DrawBank
                        SendSocket Chr$(76) + Chr$(0) + Chr$(MovableData.CurInvObj)
                    Case 105
                        A = Asc(Mid$(St, 1, 1))
                        If A >= 1 Then
                            If Asc(Mid(St, 11)) > 0 Then
                                Select Case Asc(Mid(St, 12))
                                    Case 0
                                        St1 = "Initiate"
                                    Case 1
                                        St1 = "Member"
                                    Case 2
                                        St1 = "Lord"
                                    Case 3
                                        St1 = "Founder"
                                End Select
                            Else
                                St1 = "N/A"
                            End If
                            frmScan.Show
                            With frmScan
                                .lblData(0) = Player(A).Name
                                .lblData(3) = Asc(Mid(St, 2))
                                .lblData(4) = Str(Asc(Mid(St, 3, 3))) + "/" + Str(Asc(Mid(St, 4, 3)))
                                .lblData(6) = Str(Asc(Mid(St, 7, 3))) + "/" + Str(Asc(Mid(St, 8, 3)))
                                .lblData(7) = Asc(Mid(St, 9))
                                .lblData(8) = Class(Asc(Mid(St, 10))).Name
                                If Asc(Mid(St, 11)) > 0 Then
                                    .lblData(9) = Guild(Asc(Mid(St, 11))).Name
                                Else
                                    .lblData(9) = "None"
                                End If
                                .lblData(10) = St1
                                .lblData(11) = Asc(Mid(St, 13))
                                .lblData(12) = Asc(Mid(St, 14))
                                .lblData(13) = Asc(Mid(St, 15))
                                .lblData(14) = Asc(Mid(St, 16))
                                .lblData(15) = Asc(Mid(St, 17))
                                .lblData(16) = Asc(Mid(St, 18))
                                .lblData(17) = Asc(Mid(St, 19))
                                .lblData(18) = Asc(Mid(St, 20))
                                .lblData(19) = Asc(Mid(St, 21))
                                .lblData(20) = Asc(Mid(St, 22))
                                .lblData(21) = Asc(Mid(St, 23))
                                .lblSprite = Player(A).Sprite
                                BitBlt .picSprite.hdc, 0, 0, 32, 32, hdcSprites, 128, (Player(A).Sprite - 1) * 32, SRCCOPY
                                .lblData(1) = Mid$(St, 26)
                                A = Len(.lblData(1))
                                .lblData(2) = Mid$(St, 27 + A)
                            End With
                        End If
                        
                    Case 106 'Change Stats
                        Select Case Asc(Mid$(St, 1, 1))
                            Case 0 'Strength
                                Character.Strength = Asc(Mid$(St, 2, 1))
                            Case 1 'Agility
                                Character.Agility = Asc(Mid$(St, 2, 1))
                            Case 2 'Endurance
                                Character.Endurance = Asc(Mid$(St, 2, 1))
                            Case 3 'Intelligence
                                Character.Intelligence = Asc(Mid$(St, 2, 1))
                            Case 4 'Concentration
                                Character.Concentration = Asc(Mid$(St, 2, 1))
                            Case 5 'Vitality
                                Character.Vitality = Asc(Mid$(St, 2, 1))
                            Case 6 'Stamina
                                Character.Stamina = Asc(Mid$(St, 2, 1))
                            Case 7 'Wisdom
                                Character.Wisdom = Asc(Mid$(St, 2, 1))
                        End Select
                    Case 107
                        If Len(St) = 8 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                With Object(A)
                                    For B = 0 To 5
                                        .Data(B) = Asc(Mid$(St, B + 2, 1))
                                    Next B
                                    .ObjClassData = Asc(Mid$(St, 8, 1))
                                End With
                            End If
                        End If
                        For B = 1 To 20
                            If Character.Inv(B).Object = A Then
                                DrawInvObject B
                            End If
                        Next B
                    Case 108
                        A = Asc(Mid$(St, 1, 1))
                        B = Asc(Mid$(St, 2, 1))
                        Character.Inv(A).Durability = B
                        DrawCurInvObj
                    Case 109 'Player Dead/Res
                        A = Asc(Mid$(St, 2, 1))
                        Select Case Asc(Mid$(St, 1, 1))
                            Case 0
                                If A = Character.Index Then
                                    MovableData.Dead = False
                                    frmMain.DeathTimer.Enabled = False
                                Else
                                    Player(A).Dead = False
                                End If
                            Case 1
                                If A = Character.Index Then
                                    YouDied
                                Else
                                    Player(A).Dead = True
                                End If
                        End Select
                    Case 110
                        A = Asc(Mid$(St, 2, 1))
                        B = Asc(Mid$(St, 3, 1))
                        C = Asc(Mid$(St, 4, 1)) * 16777216 + Asc(Mid$(St, 5, 1)) * 65536 + Asc(Mid$(St, 6, 1)) * 256& + Asc(Mid$(St, 7, 1))
                        Select Case Asc(Mid$(St, 1, 1))
                            Case 0
                                If Object(B).Type = 6 Then
                                    frmScan.lstInventory.AddItem Str(A) + ": [" + Trim$(Str(B)) + "] " + Object(B).Name + " - Value: [" + Trim$(Str(C)) + "]"
                                Else
                                    frmScan.lstInventory.AddItem Str(A) + ": [" + Trim$(Str(B)) + "] " + Object(B).Name
                                End If
                            Case 1
                                If Object(B).Type = 6 Then
                                    frmScan.lstBank.AddItem Str(A) + ": [" + Trim$(Str(B)) + "] " + Object(B).Name + " - Value: [" + Trim$(Str(C)) + "]"
                                Else
                                    frmScan.lstBank.AddItem Str(A) + ": [" + Trim$(Str(B)) + "] " + Object(B).Name
                                End If
                        End Select
                    Case 111 'FloatText
                        If Len(St) >= 5 Then
                            A = Asc(Mid$(St, 1, 1))
                            B = Asc(Mid$(St, 2, 1))
                            D = Asc(Mid$(St, 3, 1))
                            C = Asc(Mid$(St, 4, 1))
                            St1 = Mid$(St, 5)
                            PrintFloatText St1, CByte(C), A, B, D
                        End If
                    Case 112 'Magic Data
                        If Len(St) >= 31 Then
                            A = Asc(Mid$(St, 1, 1))
                            If A >= 1 Then
                                With Magic(A)
                                    .Name = Mid$(St, 2, 15)
                                    .Script = Mid$(St, 17, 15)
                                    If Len(St) >= 32 Then
                                        .Description = Mid$(St, 32)
                                    Else
                                        .Description = ""
                                    End If
                                    If MovableData.frmList_Loaded = True Then
                                        frmList.lstMagic.List(A - 1) = CStr(A) + ": " + .Name
                                    End If
                                    
                                End With
                            End If
                        End If
                    Case 113 'Magic Data
                        If Len(St) >= 31 Then
                            A = Asc(Mid$(St, 1, 1))
                            If MovableData.frmMagic_Loaded = False Then Load frmMagic
                            With frmMagic
                                .lblNumber = A
                                .txtName = ClipString$(Magic(A).Name)
                                .txtScript = ClipString$(Magic(A).Script)
                                .txtDesc = ClipString$(Magic(A).Description)
                                .Show 1
                            End With
                        End If
                    Case 114 'Recieve Character Magic
                        If Len(St) = 2 Then
                            A = Asc(Mid$(St, 1, 1))
                            B = Asc(Mid$(St, 2, 1))
                            With Character
                                .Magic(A) = B
                                frmMain.lstMagic.List(A - 1) = ClipString$(Magic(B).Name)
                                For D = 1 To 10
                                    If HotKey(D) = A Then
                                        frmMain.lstMagic.List(A - 1) = frmMain.lstMagic.List(A - 1) + " - F" + CStr(D)
                                        Exit For
                                    End If
                                Next D
                            End With
                        End If
                    Case 115 'Recieve Character Skills
                        SkillName(1) = "Lumberjacking"
                        SkillName(2) = "Mining"
                        SkillName(3) = "Fishing"
                        A = Asc(Mid$(St, 1, 1))
                        B = Asc(Mid$(St, 2, 1))
                        C = Asc(Mid$(St, 3, 1)) * 16777216 + Asc(Mid$(St, 4, 1)) * 65536 + Asc(Mid$(St, 5, 1)) * 256& + Asc(Mid$(St, 6, 1))
                        Character.SkillLevel(A) = B
                        Character.SkillExp(A) = C
                        frmMain.lstSkills.List(A - 1) = SkillName(A) + " [Level " + CStr(B) + "]"
                        For D = 1 To 10
                            If HotKey(D) = A + 25 Then
                                frmMain.lstSkills.List(A - 1) = frmMain.lstSkills.List(A - 1) + " - F" + CStr(D)
                                Exit For
                            End If
                        Next D
                        DrawSkillLevel CByte(A)
                    Case 116 'ForceChat
                        MovableData.ChatString = Mid(St, 1)
                        SendChat
                    Case 117 'Death Wav
                        PlayWav 8
                    Case 118 'Ping
                        If Len(St) = 0 Then
                            PrintChat "Ping: " + CStr(timeGetTime() - lastPing) + " Milliseconds", 15
                            lastPing = 0
                        End If
                End Select
            End If
            GoTo LoopRead
        End If
    End If
End Sub
Function IsVacant(X As Long, Y As Long) As Boolean
    Dim A As Long, Up As Long, Down As Long, Left As Long, Right As Long
    Select Case Map.Tile(X, Y).Att
        Case 1, 3, 13, 14, 15 'Wall, Key, Wood, Fish, Ore
            Exit Function
        Case 2 'Warp
            If AutoAttack = True Or frmMain.MapTimer.Enabled = True Then Exit Function
        Case 12 'Directional Wall
            If MovableData.CDir = 0 And ExamineBit(Map.Tile(X, Y).AttData(0), CByte(2)) Then Exit Function
            If MovableData.CDir = 1 And ExamineBit(Map.Tile(X, Y).AttData(0), CByte(0)) Then Exit Function
            If MovableData.CDir = 2 And ExamineBit(Map.Tile(X, Y).AttData(0), CByte(6)) Then Exit Function
            If MovableData.CDir = 3 And ExamineBit(Map.Tile(X, Y).AttData(0), CByte(4)) Then Exit Function
    End Select
    For A = 0 To 9
        With Map.Monster(A)
            If .Monster > 0 And .X = X And .Y = Y Then
                Exit Function
            End If
        End With
    Next A
    For A = 1 To 255
        With Player(A)
            If .Map = MovableData.CMap And .X = X And .Y = Y And .Dead = False Then
                Exit Function
            End If
        End With
    Next A
    IsVacant = True
End Function
Function CheckSum(St As String) As Long
    Dim A As Long, B As Long
    For A = 1 To Len(St)
        B = B + Asc(Mid$(St, A, 1))
    Next A
    CheckSum = B
End Function
Function FreeFloatText() As Long
Dim A As Long
    For A = 1 To 255
        If FloatText(A).Text = "" Then
            FreeFloatText = A
            Exit Function
        End If
    Next A
End Function
Function FreeStaticText() As Long
Dim A As Long
    For A = 1 To 255
        If StaticText(A).Text = "" Then
            FreeStaticText = A
            Exit Function
        End If
    Next A
End Function

Function FindMagic(ByVal Name As String) As Long
    Dim A As Long
    For A = 1 To 255
        If ClipString$(Magic(A).Name) = Name Then
            FindMagic = A
            Exit Function
        End If
    Next A
End Function
Function FindPlayer(ByVal St As String) As Long
    Dim A As Long, StLen As Long
    St = UCase$(St)
    
    'Search for exact match
    For A = 1 To 255
        With Player(A)
            If .Sprite > 0 And UCase$(.Name) = St Then
                FindPlayer = A
                Exit Function
            End If
        End With
    Next A
    
    'Search for partial match
    StLen = Len(St)
    For A = 1 To 255
        With Player(A)
            If .Sprite > 0 Then
                If Len(.Name) >= StLen Then
                    If UCase$(Left$(.Name, StLen)) = St Then
                        FindPlayer = A
                        Exit Function
                    End If
                End If
            End If
        End With
    Next A
End Function

Function FindGuild(ByVal St As String) As Long
    Dim A As Long, StLen As Long
    St = UCase$(St)
    
    'Search for exact match
    For A = 1 To 255
        With Guild(A)
            If UCase$(.Name) = St Then
                FindGuild = A
                Exit Function
            End If
        End With
    Next A
    
    'Search for partial match
    StLen = Len(St)
    For A = 1 To 255
        With Guild(A)
            If Len(.Name) >= StLen Then
                If UCase$(Left$(.Name, StLen)) = St Then
                    FindGuild = A
                    Exit Function
                End If
            End If
        End With
    Next A
End Function
Function GetInt(Chars As String) As Long
    GetInt = Asc(Mid$(Chars, 1, 1)) * 256 + Asc(Mid$(Chars, 2, 1))
End Function

Sub SendSocket(ByVal St As String)
    If SendData(ClientSocket, DoubleChar(Len(St) + 1) + Chr$(MovableData.SentPacketCount) + St) = SOCKET_ERROR Then
        CloseClientSocket 0
    End If
    
    MovableData.SentPacketCount = (MovableData.SentPacketCount + 1) Mod 256
End Sub
Sub SendChat()
Dim A As Long, B As Long, C As Long, X As Long, Y As Long
Dim St1 As String, MaxExperience As Long
With frmMain
    If Left$(MovableData.ChatString, 1) = "/" Then
        If Len(MovableData.ChatString) > 1 Then
            GetSections Mid$(MovableData.ChatString, 2), 1
                Select Case UCase$(Section(1))
                    Case "HELP"
                        PrintChat "Available Commands: BALANCE BROADCAST DEPOSIT DESCRIBE EMOTE GUILD GUILDS HELP MACROS OPTIONS SAY STATS TELL TRADE TRAIN WHERE WITHDRAW WHO YELL HELPME CHANGEPASSWORD REPAIR", 14
                    Case "OPTIONS"
                        frmOptions.Show
                    Case "CHANGEPASSWORD"
                        frmNewPass.Show
                    Case "MACROS"
                        frmMacros.Show
                    Case "BUY", "TRADE", "SELL", "SHOP"
                        If Map.NPC > 0 Then
                            SendSocket Chr$(52)
                            .lblShopName = Map.Name
                        Else
                            PrintChat "There is no NPC here!", 14
                        End If
                    Case "REPAIR"
                        If Map.NPC > 0 Then
                            If Character.Inv(MovableData.CurInvObj).Object > 0 Then
                                SendSocket Chr$(65) + Chr$(1) + Chr$(MovableData.CurInvObj)
                            Else
                                .lblRepairNPCName = Trim$(NPC(Map.NPC).Name)
                                .lblRepairNpcTalk = "Hail! " + Character.Name + ", Please select a repairable item."
                                .lblObjName = "N/A"
                                .lblObjDur = "N/A"
                                .lblRepairCst = "N/A"
                                .lblObjCond = "N/A"
                                .lblObjCond.ForeColor = QBColor(11)
                                .RepairObjPic.Cls
                                .picRepair.Visible = True
                            End If
                        Else
                            PrintChat "There is no NPC here!", 14
                        End If
                    Case "BROADCAST", "BROADCAS", "BROADCA", "BROADC", "BROAD", "BROA", "BRO", "BR", "B"
                        If Suffix <> "" Then
                            If Character.Mana >= 5 Then
                                SendSocket Chr$(15) + Suffix
                                PrintChat Character.Name + ": " + Suffix, 13
                            Else
                                PrintChat "You do not have enough mana to broadcast!", 14
                            End If
                        Else
                            PrintChat "What do you want to broadcast?", 14
                        End If
                    Case "DESCRIBE", "DESCRIB", "DESCRI", "DESCR", "DESC", "DES", "DE", "D"
                        If Len(Suffix) > 0 Then
                            SendSocket Chr$(28) + Suffix
                            PrintChat "Your description has been changed.", 14
                        Else
                            PrintChat "You must enter a description.", 14
                        End If
                    Case "EMOTE", "EMOT", "EMO", "EM", "E"
                        If Suffix <> "" Then
                            SendSocket Chr$(16) + Suffix
                            PrintChat Character.Name + " " + Suffix, 11
                        Else
                            PrintChat "What do you want to do?", 14
                        End If
                    Case "SAY", "SA", "S"
                        If Suffix <> "" Then
                            SendSocket Chr$(6) + Suffix
                            PrintChat "You say, " + Chr$(34) + Suffix + Chr$(34), 7
                        Else
                            PrintChat "What do you want to say?", 14
                        End If
                    Case "BANK"
                        If Map.NPC > 0 Then
                            If .picBank.Visible = False Then SendSocket Chr$(54)
                        Else
                            PrintChat "There is no NPC here!", 14
                        End If
                    Case "PING"
                        If lastPing = 0 Then
                            lastPing = timeGetTime()
                            SendSocket Chr$(87)
                        End If
                    Case "STATS", "STAT", "STA", "ST"
                        SendSocket Chr$(73)
                    Case "IGNORE"
                        If Suffix <> "" Then
                            A = FindPlayer(Suffix)
                            If A > 0 Then
                                With Player(A)
                                    If .Ignore = True Then
                                        .Ignore = False
                                        PrintChat "You are no longer ignoring " + .Name + ".", 14
                                    Else
                                        .Ignore = True
                                        PrintChat "You are now ignoring " + .Name + ".", 14
                                    End If
                                End With
                            Else
                                PrintChat "No such player!", 14
                            End If
                        Else
                            St1 = ""
                            B = 0
                            For A = 1 To 255
                                With Player(A)
                                    If .Sprite > 0 And .Ignore = True Then
                                        B = B + 1
                                        St1 = St1 + ", " + .Name
                                    End If
                                End With
                            Next A
                            If B > 0 Then
                                St1 = Mid$(St1, 2)
                                PrintChat "You are currently ignoring " + CStr(B) + " people:" + St1, 14
                            Else
                                PrintChat "You are not ignoring anybody!", 14
                            End If
                        End If
                    Case "TELL", "TEL", "TE", "T"
                        If Suffix <> "" Then
                            GetSections Suffix, 1
                            A = FindPlayer(Section(1))
                            If A > 0 Then
                                If Suffix <> "" Then
                                    If Character.Mana >= 2 Then
                                        SendSocket Chr$(14) + Chr$(A) + Suffix
                                        PrintChat "You tell " + Player(A).Name + ", " + Chr$(34) + Suffix + Chr$(34), 10
                                    Else
                                        PrintChat "You do not have enough mana to tell!", 14
                                    End If
                                Else
                                    PrintChat "What do you want to tell " + Player(A).Name + "?", 14
                                End If
                            Else
                                PrintChat "No such player!", 14
                            End If
                        Else
                            PrintChat "What, and to whom, do you want to tell?", 14
                        End If
                    Case "WHERE", "WHER", "WHE"
                        PrintChat "You are at location [" + CStr(MovableData.CMap) + ", " + CStr(MovableData.cx) + ", " + CStr(MovableData.cy) + "]", 14
                    Case "WHO", "WH", "W"
                        St1 = ""
                        B = 0
                        For A = 1 To 255
                            With Player(A)
                                If .Sprite > 0 And A <> Character.Index Then
                                    B = B + 1
                                    St1 = St1 + ", " + .Name
                                End If
                            End With
                        Next A
                        If B > 0 Then
                            St1 = Mid$(St1, 2)
                            PrintChat "There are " + CStr(B) + " other players online: " + St1, 14
                        Else
                            PrintChat "There are no other players online.", 14
                        End If
                    Case "YELL", "YEL", "YE", "Y"
                        If Suffix <> "" Then
                            SendSocket Chr$(17) + Suffix
                            PrintChat "You yell, " + Chr$(34) + Suffix + Chr$(34), 7
                        Else
                            PrintChat "What do you want to yell?", 14
                        End If
                    Case "FRAMERATE", "FRAMERAT", "FRAMERA", "FRAMER", "FRAME", "FRAM", "FRA", "FR", "F"
                        PrintChat "Current Frame Rate: " + CStr(MovableData.FrameRate), 14
                    Case "GUILDS"
                        frmGuilds.Show
                    Case "GUILD"
                        GetSections Suffix, 1
                        Select Case UCase$(Section(1))
                            Case "NEW"
                                SendSocket Chr$(70)
                            Case "BUY"
                                If Character.Guild > 0 And Character.GuildRank >= 2 Then
                                    SendSocket Chr$(43)
                                Else
                                    PrintChat "You must be the Lord of a guild to use that command.", 14
                                End If
                            Case "WHO", "WH", "W"
                                If Character.Guild > 0 Then
                                    St1 = ""
                                    B = 0
                                    For A = 1 To 255
                                        With Player(A)
                                            If .Sprite > 0 And A <> Character.Index And .Guild = Character.Guild Then
                                                B = B + 1
                                                St1 = St1 + ", " + .Name
                                            End If
                                        End With
                                    Next A
                                    If B > 0 Then
                                        St1 = Mid$(St1, 2)
                                        PrintChat "There are " + CStr(B) + " other guild members online: " + St1, 14
                                    Else
                                        PrintChat "There are no other guild members online.", 14
                                    End If
                                Else
                                    PrintChat "You are not in a guild!", 14
                                End If
                            Case "CHAT"
                                If Character.Guild > 0 Then
                                    If Suffix <> "" Then
                                        SendSocket Chr$(41) + Suffix 'Guild Chat
                                        PrintChat Character.Name + " -> Guild: " + Suffix, 15
                                    Else
                                        PrintChat "You must specify a message!", 14
                                    End If
                                Else
                                    PrintChat "You are not in a guild!", 14
                                End If
                            Case "INVITE"
                                If Character.Guild > 0 And Character.GuildRank >= 2 Then
                                    GetSections Suffix, 1
                                    If Section(1) <> "" Then
                                        A = FindPlayer(Section(1))
                                        If A > 0 Then
                                            If Character.Mana >= 15 Then
                                                SendSocket Chr$(34) + Chr$(A)
                                                PrintChat Player(A).Name + " has been invited to join your guild.", 15
                                            Else
                                                PrintChat "This task requires 15 or more mana to use.", 15
                                            End If
                                        Else
                                            PrintChat "No such player!", 14
                                        End If
                                    Else
                                        PrintChat "Must specify a name.", 14
                                    End If
                                Else
                                    PrintChat "You must be the Lord of a guild to use that command.", 14
                                End If
                            Case "JOIN"
                                If Character.Guild = 0 Then
                                    If Character.level >= 25 Then
                                        SendSocket Chr$(31) 'Join Guild
                                    Else
                                        PrintChat "You must be at least Level 25 to join a Guild!", 15
                                    End If
                                Else
                                    PrintChat "You are already in a guild.  If you would like to join a new guild, you must first leave this guild by typing '/guild leave'.", 14
                                End If
                            Case "LEAVE"
                                If Character.Guild > 0 Then
                                    SendSocket Chr$(32) 'Leave Guild
                                Else
                                    PrintChat "You are not in a guild!", 14
                                End If
                            Case "PAY"
                                If Character.Guild > 0 Then
                                    GetSections Suffix, 1
                                    If Section(1) <> "" Then
                                        If CDbl(Int(Val(Section(1)))) <= 2147483647# Then
                                            A = Int(Val(Section(1)))
                                            If A >= 0 Then
                                                SendSocket Chr$(40) + QuadChar(A) 'Pay balance
                                            Else
                                                PrintChat "Invalid value.", 14
                                            End If
                                        Else
                                            PrintChat "Invalid value.", 14
                                        End If
                                    Else
                                        PrintChat "You must specify an amount!", 14
                                    End If
                                Else
                                    PrintChat "You are not in a guild!", 14
                                End If
                            Case "SPRITE"
                                If Character.Guild > 0 Then
                                    SendSocket Chr$(87)
                                    Character.Sprite = Guild(Character.Guild).Sprite
                                    PrintChat "Your guild sprite has been restored!", 14
                                Else
                                    PrintChat "You are not in a guild!", 14
                                End If
                            Case "EDIT"
                                If Character.Guild > 0 Then
                                    SendSocket Chr$(39) + Chr$(Character.Guild)
                                Else
                                    PrintChat "You are not in a guild!", 14
                                End If
                            Case "HALLINFO"
                                SendSocket Chr$(47)
                            Case "BALANCE"
                                If Character.Guild > 0 Then
                                    SendSocket Chr$(46)
                                Else
                                    PrintChat "You are not in a guild!", 14
                                End If
                            Case "HELP"
                                PrintChat "Guild commands: BALANCE BUY CHAT HALLINFO INVITE JOIN LEAVE NEW PAY EDIT", 14
                            Case Else
                                PrintChat "Invalid guild command.", 14
                        End Select
                    Case "GOD"
                        'If Character.Access > 0 Then
                            GetSections Suffix, 1
                            Select Case UCase$(Section(1))
                                Case "CHAT"
                                    If Suffix <> "" Then
                                        SendSocket Chr$(18) + Chr$(14) + Suffix
                                        PrintChat "<" + Character.Name + ">: " + Suffix, 11
                                    End If
                                Case "BOOT"
                                    If Character.Access >= 2 Then
                                        GetSections Suffix, 1
                                        If Section(1) <> "" Then
                                            A = FindPlayer(Section(1))
                                            If A >= 1 Then
                                                SendSocket Chr$(18) + Chr$(9) + Chr$(A) + Suffix
                                            Else
                                                PrintChat "Boot: No such player", 14
                                            End If
                                        Else
                                            PrintChat "Boot: Not enough parameters", 14
                                        End If
                                    Else
                                        PrintChat "You do not have access to that command!", 14
                                    End If
                                Case "BAN"
                                    If Character.Access >= 3 Then
                                        GetSections Suffix, 2
                                        If Section(2) <> "" Then
                                            A = FindPlayer(Section(1))
                                            If A >= 1 Then
                                                B = Int(Val(Section(2)))
                                                If B >= 1 And B <= 255 Then
                                                    SendSocket Chr$(18) + Chr$(10) + Chr$(A) + Chr$(B) + Suffix
                                                Else
                                                    PrintChat "Ban: Unnacceptable number of days", 14
                                                End If
                                            Else
                                                PrintChat "Ban: No such player", 14
                                            End If
                                        Else
                                            PrintChat "Ban: Not enough parameters", 14
                                        End If
                                    Else
                                        PrintChat "You do not have access to that command!", 14
                                    End If
                                Case "DISBAND", "DELETE", "REMOVE"
                                    If Character.Access >= 3 Then
                                        GetSections Suffix, 1
                                        A = FindGuild(Section(1))
                                        If A >= 1 Then
                                            SendSocket Chr$(18) + Chr$(5) + Chr$(A)
                                            PrintChat "Guild " + Guild(A).Name + " disbanded!", 14
                                        Else
                                            PrintChat "No such guild!", 14
                                        End If
                                    Else
                                        PrintChat "You do not have access to that command!", 14
                                    End If
                                Case "RESETMAP"
                                    If Character.Access >= 3 Then
                                        SendSocket Chr$(18) + Chr$(8)
                                    Else
                                        PrintChat "You do not have access to that command!", 14
                                    End If
                                Case "SCAN"
                                    If Character.Access >= 2 Then
                                        GetSections Suffix, 1
                                        If Section(1) <> "" Then
                                            A = FindPlayer(Section(1))
                                            If A >= 1 Then
                                                frmScan.lstInventory.Clear
                                                SendSocket Chr$(72) + Chr$(A)
                                            Else
                                                PrintChat "Scan: No such player", 14
                                            End If
                                        Else
                                            PrintChat "Scan: Not enough parameters", 14
                                        End If
                                    Else
                                        PrintChat "You do not have access to that command!", 14
                                    End If
                                Case "NAME", "NAM", "NA", "N"
                                    If Character.Access >= 3 Then
                                        If Len(Suffix) > 0 Then
                                            If Len(Suffix) <= 15 Then
                                                SendSocket Chr$(18) + Chr$(7) + Chr$(Character.Index) + Suffix
                                                PrintChat "Name changed.", 14
                                            Else
                                                PrintChat "Name may be no longer than 15 characters!", 14
                                            End If
                                        Else
                                            PrintChat "You must specify a new name!", 14
                                        End If
                                    Else
                                        PrintChat "You do not have access to that command!", 14
                                    End If
                                Case "SETPLAYERSPRITE"
                                    If Character.Access >= 2 Then
                                        GetSections Suffix, 2
                                        A = FindPlayer(Section(1))
                                        If A >= 1 Then
                                            B = Int(Val(Section(2)))
                                            If B >= 0 And B <= 255 Then
                                                SendSocket Chr$(18) + Chr$(6) + Chr$(A) + Chr$(B)
                                                PrintChat Player(A).Name + "'s sprite has been changed.", 14
                                            Else
                                                PrintChat "Invalid sprite number!", 14
                                            End If
                                        Else
                                            PrintChat "No such player!", 14
                                        End If
                                    Else
                                        PrintChat "You do not have access to that command!", 14
                                    End If
                                Case "SPRITE"
                                    If Character.Access >= 2 Then
                                        If Val(Suffix) > 0 Then
                                            A = Int(Val(Suffix))
                                            If A > 202 Then A = 202
                                            SendSocket Chr$(18) + Chr$(6) + Chr$(Character.Index) + Chr$(A)
                                            PrintChat "Sprite changed.", 14
                                        Else
                                            PrintChat "You must specify a Sprite number!", 14
                                        End If
                                    Else
                                        PrintChat "You do not have access to that command!", 14
                                    End If
                                Case "STATUS"
                                    If Character.Access >= 2 Then
                                        If Val(Suffix) >= 0 Then
                                            A = Int(Val(Suffix))
                                            If A > 27 Then A = 27
                                            SendSocket Chr$(18) + Chr$(11) + Chr$(Character.Index) + Chr$(A)
                                            PrintChat "Status changed.", 14
                                        Else
                                            PrintChat "You must specify a Status number!", 14
                                        End If
                                    Else
                                        PrintChat "You do not have access to that command!", 14
                                    End If
                                Case "GLOBAL", "GLOBA", "GLOB", "GLO", "GL", "G"
                                    If Suffix <> "" Then
                                        SendSocket Chr$(18) + Chr$(0) + Suffix
                                    Else
                                        PrintChat "You must specify a message!", 14
                                    End If
                                    Case "WARP", "WAR", "WA", "W"
                                        If Character.Access > 2 Then
                                            GetSections Suffix, 1
                                            If Val(Section(1)) >= 1 Then
                                                If Section(1) >= 1 And Section(1) <= 2000 Then
                                                    A = Val(Section(1))
                                                    SendSocket Chr$(18) + Chr$(1) + DoubleChar(A)
                                                    PrintChat "You have been warped to Map " + Str(A), 14
                                                Else
                                                    PrintChat "No such warp location.", 14
                                                End If
                                            Else
                                                PrintChat "You must specify a Map number!", 14
                                            End If
                                        Else
                                            PrintChat "You do not have access to this command!", 14
                                        End If
                                        
                                    Case "WARPMETO", "WARPME", "WARPM"
                                        If Character.Access >= 2 Then
                                            GetSections Suffix, 1
                                            If Section(1) <> "" Then
                                                A = FindPlayer(Section(1))
                                                If A > 0 Then
                                                    SendSocket Chr$(18) + Chr$(2) + Chr$(A)
                                                    PrintChat "You have been warped to " + Player(A).Name + ".", 14
                                                Else
                                                    PrintChat "No such player", 14
                                                End If
                                            Else
                                                PrintChat "You must specify a player to warp to.", 14
                                            End If
                                        Else
                                            PrintChat "You do not have access to that command!", 14
                                        End If
                                        
                                    Case "WARPTOME", "WARPTOM", "WARPTO", "WARPT"
                                        If Character.Access >= 2 Then
                                            GetSections Suffix, 1
                                            If Section(1) <> "" Then
                                                A = FindPlayer(Section(1))
                                                If A > 0 Then
                                                    SendSocket Chr$(18) + Chr$(3) + Chr$(A) + DoubleChar(MovableData.CMap) + Chr$(MovableData.cx) + Chr$(MovableData.cy)
                                                    PrintChat Player(A).Name + " has been warped to you.", 14
                                                Else
                                                    PrintChat "No such player", 14
                                                End If
                                            Else
                                                PrintChat "You must specify a player to warp to.", 14
                                            End If
                                        Else
                                            PrintChat "You do not have access to that command!", 14
                                        End If
                                        
                                    Case "EDITMAP"
                                        If Character.Access >= 3 Then
                                            If MovableData.MapEdit = False Then
                                                SendSocket Chr$(64) + Chr$(2)
                                            Else
                                                PrintChat "The map editor is already open!", 14
                                            End If
                                        Else
                                            PrintChat "You do not have access to that command!", 14
                                        End If
                                        
                                    Case "BANS"
                                        If Character.Access >= 3 Then
                                            If MovableData.frmList_Loaded = False Then Load frmList
                                            With frmList
                                                .lstBans.Clear
                                                .lstBans.Visible = True
                                                .lblList = "Bans:"
                                                .lstMonsters.Visible = False
                                                .lstObjects.Visible = False
                                                .lstNPCs.Visible = False
                                                .lstHalls.Visible = False
                                                .lstMagic.Visible = False
                                            End With
                                            SendSocket Chr$(18) + Chr$(12)
                                        Else
                                            PrintChat "You do not have access to that command!", 14
                                        End If
                                        
                                    Case "EDITHALL"
                                        If Character.Access >= 2 Then
                                            GetSections Suffix, 1
                                            If Section(1) <> "" And Val(Section(1)) >= 1 And Val(Section(1)) <= 255 Then
                                                SendSocket Chr$(48) + Chr$(Val(Section(1)))
                                            Else
                                                If MovableData.frmList_Loaded = False Then Load frmList
                                                With frmList
                                                    .lstHalls.Visible = True
                                                    .lblList = "Halls:"
                                                    .lstObjects.Visible = False
                                                    .lstMonsters.Visible = False
                                                    .lstNPCs.Visible = False
                                                    .lstBans.Visible = False
                                                    .lstMagic.Visible = False
                                                    .btnOk.Caption = "Edit"
                                                    .Show
                                                End With
                                            End If
                                        Else
                                            PrintChat "You do not have access to that command!", 14
                                        End If
                                    Case "EDITSCRIPT"
                                        'If Character.Access >= 3 Then
                                            GetSections Suffix, 1
                                            If Section(1) <> "" Then
                                                If Len(Section(1)) <= 15 Then
                                                    SendSocket Chr$(59) + Section(1)
                                                Else
                                                    PrintChat "Error: Script name too long!", 14
                                                End If
                                            Else
                                                PrintChat "Must specify a script name!", 14
                                            End If
                                        'Else
                                        '    PrintChat "You do not have access to that command!", 14
                                        'End If
                                    Case "EDITMAGIC"
                                        If Character.Access >= 2 Then
                                            GetSections Suffix, 1
                                            If Section(1) <> "" And Val(Section(1)) >= 1 And Val(Section(1)) <= 255 Then
                                                SendSocket Chr$(19) + Chr$(Val(Section(1)))
                                            Else
                                                If MovableData.frmList_Loaded = False Then Load frmList
                                                With frmList
                                                    .lstMagic.Visible = True
                                                    .lblList = "Magic:"
                                                    .lstObjects.Visible = False
                                                    .lstMonsters.Visible = False
                                                    .lstNPCs.Visible = False
                                                    .lstBans.Visible = False
                                                    .lstHalls.Visible = False
                                                    .btnOk.Caption = "Edit"
                                                    .Show
                                                End With
                                            End If
                                        Else
                                            PrintChat "You do not have access to that command!", 14
                                        End If
                                    Case "EDITOBJECT"
                                        If Character.Access >= 2 Then
                                            GetSections Suffix, 1
                                            If Section(1) <> "" And Val(Section(1)) >= 1 And Val(Section(1)) <= 255 Then
                                                SendSocket Chr$(19) + Chr$(Val(Section(1)))
                                            Else
                                                If MovableData.frmList_Loaded = False Then Load frmList
                                                With frmList
                                                    .lstObjects.Visible = True
                                                    .lblList = "Objects:"
                                                    .lstMonsters.Visible = False
                                                    .lstNPCs.Visible = False
                                                    .lstBans.Visible = False
                                                    .lstHalls.Visible = False
                                                    .lstMagic.Visible = False
                                                    .btnOk.Caption = "Edit"
                                                    .Show
                                                End With
                                            End If
                                        Else
                                            PrintChat "You do not have access to that command!", 14
                                        End If
                                    Case "EDITMONSTER"
                                        If Character.Access >= 2 Then
                                            GetSections Suffix, 1
                                            If Section(1) <> "" And Val(Section(1)) >= 1 And Val(Section(1)) <= 255 Then
                                                SendSocket Chr$(20) + Chr$(Val(Section(1)))
                                            Else
                                                If MovableData.frmList_Loaded = False Then Load frmList
                                                With frmList
                                                    .lstMonsters.Visible = True
                                                    .lblList = "Monsters:"
                                                    .lstObjects.Visible = False
                                                    .lstNPCs.Visible = False
                                                    .lstBans.Visible = False
                                                    .lstHalls.Visible = False
                                                    .lstMagic.Visible = False
                                                    .btnOk.Caption = "Edit"
                                                    .Show
                                                End With
                                            End If
                                        Else
                                            PrintChat "You do not have access to that command!", 14
                                        End If
                                    Case "EDITNPC"
                                        If Character.Access >= 2 Then
                                            GetSections Suffix, 1
                                            If Section(1) <> "" And Val(Section(1)) >= 1 And Val(Section(1)) <= 255 Then
                                                SendSocket Chr$(50) + Chr$(Val(Section(1)))
                                            Else
                                                If MovableData.frmList_Loaded = False Then Load frmList
                                                With frmList
                                                    .lstNPCs.Visible = True
                                                    .lblList = "NPCs:"
                                                    .lstObjects.Visible = False
                                                    .lstMonsters.Visible = False
                                                    .lstBans.Visible = False
                                                    .lstHalls.Visible = False
                                                    .lstMagic.Visible = False
                                                    .btnOk.Caption = "Edit"
                                                    .Show
                                                End With
                                            End If
                                        Else
                                            PrintChat "You do not have access to that command!", 14
                                        End If
                                    Case "HELP"
                                        PrintChat "Available God Commands: BAN BANS BOOT EDITMAP EDITOBJECT EDITHALL EDITMONSTER EDITNPC GLOBAL RESETMAP WARP WARPME WARPTOME SPRITE SETPLAYERSPRITE", 14
                                    Case Else
                                        PrintChat "No such god command!", 14
                                End Select
                            'Else
                                'PrintChat "You do not have god access!", 14
                            'End If
                        Case Else
                            St1 = UCase$(Section(1))
                            GetSections Suffix, 3
                            SendSocket Chr$(62) + St1 + Chr$(0) + Section(1) + Chr$(0) + Section(2) + Chr$(0) + Section(3)
                    End Select
                End If
            Else
                SendSocket Chr$(6) + MovableData.ChatString
                PrintChat "You say, " + Chr$(34) + MovableData.ChatString + Chr$(34), 7
            End If
        MovableData.ChatString = ""
    End With
End Sub
Function DoubleChar(Num As Long) As String
    DoubleChar = Chr$(Int(Num / 256)) + Chr$(Num Mod 256)
End Function
Sub UploadMap()
    Dim MapData As String, St1 As String * 30
    Dim X As Long, Y As Long
    With EditMap
        If .Version < 2147483647 Then
            .Version = .Version + 1
        Else
            .Version = 1
        End If
        St1 = .Name
        MapData = St1 + QuadChar(.Version) + Chr$(.NPC) + Chr$(0) + DoubleChar$(CLng(.ExitUp)) + DoubleChar$(CLng(.ExitDown)) + DoubleChar$(CLng(.ExitLeft)) + DoubleChar$(CLng(.ExitRight)) + DoubleChar(CLng(.BootLocation.Map)) + Chr$(.BootLocation.X) + Chr$(.BootLocation.Y) + Chr$(.Flags) + Chr$(.MonsterSpawn(0).Monster) + Chr$(.MonsterSpawn(0).Rate) + Chr$(.MonsterSpawn(1).Monster) + Chr$(.MonsterSpawn(1).Rate) + Chr$(.MonsterSpawn(2).Monster) + Chr$(.MonsterSpawn(2).Rate) + Chr$(.MonsterSpawn(3).Monster) + Chr$(.MonsterSpawn(3).Rate) + Chr$(.MonsterSpawn(4).Monster) + Chr$(.MonsterSpawn(4).Rate)
        For Y = 0 To 11
            For X = 0 To 11
                With .Tile(X, Y)
                    MapData = MapData + DoubleChar(CLng(.Ground)) + DoubleChar(CLng(.Ground2)) + DoubleChar(CLng(.BGTile1)) + DoubleChar(CLng(.BGTile2)) + DoubleChar(CLng(.FGTile)) + DoubleChar(CLng(.FGTile2)) + Chr$(.Att) + Chr$(.AttData(0)) + Chr$(.AttData(1)) + Chr$(.AttData(2)) + Chr$(.AttData(3))
                End With
            Next X
        Next Y
    End With
    SendSocket Chr$(12) + MapData
End Sub
Sub UseSkill(ByVal Skill As Byte)
Dim A, X, Y As Long
Dim St1 As String

X = MovableData.cx
Y = MovableData.cy

Select Case Skill
    Case 1
        St1 = "You cannot lumberjack here!"
    Case 2
        St1 = "You cannot mine here!"
    Case 3
        St1 = "You cannot fish here!"
    Case 4
        St1 = "You cannot smith here!"
End Select
Select Case MovableData.CDir
    Case 0
        If Y = 0 Then
            PrintChat St1, 7
            Exit Sub
        End If
    Case 1
        If Y = 11 Then
            PrintChat St1, 7
            Exit Sub
        End If
    Case 2
        If X = 0 Then
            PrintChat St1, 7
            Exit Sub
        End If
    Case 3
        If X = 11 Then
            PrintChat St1, 7
            Exit Sub
        End If
End Select
If Character.Energy >= 5 Then
    Select Case Skill
        Case 1 'Lumberjacking
            Select Case MovableData.CDir
                Case 0 'Up
                    If Map.Tile(X, Y - 1).Att = 13 Then
                        SendSocket Chr$(85) + Chr$(Skill)
                    Else
                        PrintChat St1, 7
                        Exit Sub
                    End If
                Case 1 'Down
                    If Map.Tile(X, Y + 1).Att = 13 Then
                        SendSocket Chr$(85) + Chr$(Skill)
                    Else
                        PrintChat St1, 7
                        Exit Sub
                    End If
                Case 2 'Left
                    If Map.Tile(X - 1, Y).Att = 13 Then
                        SendSocket Chr$(85) + Chr$(Skill)
                    Else
                        PrintChat St1, 7
                        Exit Sub
                    End If
                Case 3 'Right
                    If Map.Tile(X + 1, Y).Att = 13 Then
                        SendSocket Chr$(85) + Chr$(Skill)
                    Else
                        PrintChat St1, 7
                        Exit Sub
                    End If
            End Select
        Case 2 'Mining
            Select Case MovableData.CDir
                Case 0 'Up
                    If Map.Tile(X, Y - 1).Att = 15 Then
                        SendSocket Chr$(85) + Chr$(Skill)
                    Else
                        PrintChat St1, 7
                        Exit Sub
                    End If
                Case 1 'Down
                    If Map.Tile(X, Y + 1).Att = 15 Then
                        SendSocket Chr$(85) + Chr$(Skill)
                    Else
                        PrintChat St1, 7
                        Exit Sub
                    End If
                Case 2 'Left
                    If Map.Tile(X - 1, Y).Att = 15 Then
                        SendSocket Chr$(85) + Chr$(Skill)
                    Else
                        PrintChat St1, 7
                        Exit Sub
                    End If
                Case 3 'Right
                    If Map.Tile(X + 1, Y).Att = 15 Then
                        SendSocket Chr$(85) + Chr$(Skill)
                    Else
                        PrintChat St1, 7
                        Exit Sub
                    End If
            End Select
        Case 3 'Fishing
            Select Case MovableData.CDir
                Case 0 'Up
                    If Map.Tile(X, Y - 1).Att = 14 Then
                        SendSocket Chr$(85) + Chr$(Skill)
                    Else
                        PrintChat St1, 7
                        Exit Sub
                    End If
                Case 1 'Down
                    If Map.Tile(X, Y + 1).Att = 14 Then
                        SendSocket Chr$(85) + Chr$(Skill)
                    Else
                        PrintChat St1, 7
                        Exit Sub
                    End If
                Case 2 'Left
                    If Map.Tile(X - 1, Y).Att = 14 Then
                        SendSocket Chr$(85) + Chr$(Skill)
                    Else
                        PrintChat St1, 7
                        Exit Sub
                    End If
                Case 3 'Right
                    If Map.Tile(X + 1, Y).Att = 14 Then
                        SendSocket Chr$(85) + Chr$(Skill)
                    Else
                        PrintChat St1, 7
                        Exit Sub
                    End If
            End Select
        End Select
        Character.Energy = Character.Energy - 5
        DrawEnergy
    Else
        PrintChat "You are too tired!", 14
    End If
End Sub

Sub Main()
    Dim freq As Currency, curTime As Currency, timeStamp As Currency
    Dim A As Long, B As Long, C As String
    Dim LogPalette As LogPalette
    Dim RData As clsRandomData
    
    On Error Resume Next
    timeBeginPeriod 1
    
    QueryPerformanceFrequency freq
    
    Randomize Timer
     
    'Fill random amount of memory
    B = Rnd * 200
    For A = 1 To B
        Set RData = New clsRandomData
        RandomData.Add RData
    Next A
    
    'Create new instance of game data
    Set MovableData = New clsMovableData
    
    'ChDir ("c:\odyssey")

    If Exists("odyssey.tmp") Then
        On Error Resume Next
        Do
            DoEvents
            Err.Clear
            FileCopy "odyssey.tmp", "odyssey.exe"
        Loop While Err.Number > 0
        Kill "odyssey.tmp"
        On Error GoTo 0
    End If
    
    GetSections Command$, 3
    
    If Section(1) <> "" Then
        ServerID = Section(1)
        On Error Resume Next
        MkDir (ServerID)
        On Error GoTo 0
    Else
        ServerID = "DEFAULT"
    End If

    If Dir(ServerID & "\mcache.dat") = vbNullString Then
        If Dir(ServerID, vbDirectory) = vbNullString Then MkDir (ServerID)
    End If
    MovableData.MapCacheFile = ServerID + "\mcache.dat"
    If Dir(MovableData.MapCacheFile) = vbNullString Then CreateMapCache
    'Get Computer ID
    'MovableData.ComputerID = Trim$(GetWindowsKey())
    
    LoadOptions
    LoadMacros
    
    CreateClassData

    Dim St As String
    Dim Pic As StdPicture
    Dim T As Long
    
    C = "Data\GFX\"
    
    'Check Files
    CheckFile GetFilename(C + "tiles.rsc")
    CheckFile GetFilename(C + "tilesm.rsc")
    CheckFile GetFilename(C + "objects.rsc")
    CheckFile GetFilename(C + "objectsm.rsc")
    CheckFile GetFilename(C + "sprites.rsc")
    CheckFile GetFilename(C + "spritesm.rsc")
    CheckFile GetFilename(C + "darkness.rsc")
    CheckFile GetFilename(C + "darknessm.rsc")
    CheckFile GetFilename(C + "weather.rsc")
    CheckFile GetFilename(C + "weatherm.rsc")
    CheckFile GetFilename(C + "hpbar.rsc")
    CheckFile GetFilename(C + "hpbarm.rsc")

    frmWait.Show
    frmWait.Refresh
    
    If Exists(MovableData.MapCacheFile) = False Then
        frmWait.lblStatus = "Creating Map Cache .."
        frmWait.Refresh
        CreateMapCache
    Else
    End If
    
    frmWait.lblStatus = "Creating Buffers .."
    frmWait.Refresh
    
    hdcBuffer = CreateCompatibleDC(0&)
    hbmpBuffer = CreateCompatibleBitmap(frmWait.hdc, 384, 384)
    obmpBuffer = SelectObject(hdcBuffer, hbmpBuffer)
    
    SetBkMode hdcBuffer, TRANSPARENT
    
    hdcBack(0) = CreateCompatibleDC(0&)
    hbmpBack(0) = CreateCompatibleBitmap(frmWait.hdc, 384, 384)
    obmpBack(0) = SelectObject(hdcBack(0), hbmpBack(0))
    
    hdcBack(1) = CreateCompatibleDC(0&)
    hbmpBack(1) = CreateCompatibleBitmap(frmWait.hdc, 384, 384)
    obmpBack(1) = SelectObject(hdcBack(1), hbmpBack(1))
    
    hdcBack(2) = CreateCompatibleDC(0&)
    hbmpBack(2) = CreateCompatibleBitmap(frmWait.hdc, 384, 384)
    obmpBack(2) = SelectObject(hdcBack(2), hbmpBack(2))
    
    hdcFront(0) = CreateCompatibleDC(0&)
    hbmpFront(0) = CreateCompatibleBitmap(frmWait.hdc, 384, 384)
    obmpFront(0) = SelectObject(hdcFront(0), hbmpFront(0))
    
    hdcFront(1) = CreateCompatibleDC(0&)
    hbmpFront(1) = CreateCompatibleBitmap(frmWait.hdc, 384, 384)
    obmpFront(1) = SelectObject(hdcFront(1), hbmpFront(1))
    
    hdcFrontMask(0) = CreateCompatibleDC(0&)
    hbmpFrontMask(0) = CreateCompatibleBitmap(frmWait.hdc, 384, 384)
    obmpFrontMask(0) = SelectObject(hdcFrontMask(0), hbmpFrontMask(0))
    
    hdcFrontMask(1) = CreateCompatibleDC(0&)
    hbmpFrontMask(1) = CreateCompatibleBitmap(frmWait.hdc, 384, 384)
    obmpFrontMask(1) = SelectObject(hdcFrontMask(1), hbmpFrontMask(1))
    
    GetObject hbmpBack(0), Len(Bitmap), Bitmap
    
    frmWait.lblStatus = "Loading Weather Effects .."
    frmWait.Refresh
    
    hdcWeather = CreateCompatibleDC(0&)
    Encrypt GetFilename(C + "weather.rsc")
    Set Pic = LoadPicture(GetFilename(C + "weather.rsc"))
    Encrypt GetFilename(C + "weather.rsc")
    hbmpWeather = Pic.Handle
    obmpWeather = SelectObject(hdcWeather, hbmpWeather)
    
    hdcWeatherMask = CreateCompatibleDC(0&)
    Set Pic = LoadPicture(GetFilename(C + "weatherm.rsc"))
    hbmpWeatherMask = Pic.Handle
    obmpWeatherMask = SelectObject(hdcWeatherMask, hbmpWeatherMask)
    
    frmWait.lblStatus = "Loading Misc Data .."
    frmWait.Refresh
    
    hdcHPBar = CreateCompatibleDC(0&)
    Encrypt GetFilename(C + "hpbar.rsc")
    Set Pic = LoadPicture(GetFilename(C + "hpbar.rsc"))
    Encrypt GetFilename(C + "hpbar.rsc")
    hbmpHPBar = Pic.Handle
    obmpHPBar = SelectObject(hdcHPBar, hbmpHPBar)
    
    hdcHPBarMask = CreateCompatibleDC(0&)
    Set Pic = LoadPicture(GetFilename(C + "hpbarm.rsc"))
    hbmpHPBarMask = Pic.Handle
    obmpHPBarMask = SelectObject(hdcHPBarMask, hbmpHPBarMask)
    
    hdcDarkness = CreateCompatibleDC(0&)
    Encrypt GetFilename(C + "darkness.rsc")
    Set Pic = LoadPicture(GetFilename(C + "darkness.rsc"))
    Encrypt GetFilename(C + "darkness.rsc")
    hbmpDarkness = Pic.Handle
    obmpDarkness = SelectObject(hdcDarkness, hbmpDarkness)
    
    hdcDarknessMask = CreateCompatibleDC(0&)
    Set Pic = LoadPicture(GetFilename(C + "darknessm.rsc"))
    hbmpDarknessMask = Pic.Handle
    obmpDarknessMask = SelectObject(hdcDarknessMask, hbmpDarknessMask)
    
    frmWait.lblStatus = "Loading Map Tiles .."
    frmWait.Refresh
    
    hdcTiles = CreateCompatibleDC(0&)
    Encrypt GetFilename(C + "tiles.rsc")
    Set Pic = LoadPicture(GetFilename(C + "tiles.rsc"))
    Encrypt GetFilename(C + "tiles.rsc")
    hbmpTiles = Pic.Handle
    obmpTiles = SelectObject(hdcTiles, hbmpTiles)
    
    hdcTilesMask = CreateCompatibleDC(0&)
    Set Pic = LoadPicture(GetFilename(C + "tilesm.rsc"))
    hbmpTilesMask = Pic.Handle
    obmpTilesMask = SelectObject(hdcTilesMask, hbmpTilesMask)
    
    frmWait.lblStatus = "Loading Object Tiles .."
    frmWait.Refresh
    
    hdcObjects = CreateCompatibleDC(0&)
    Encrypt GetFilename(C + "objects.rsc")
    Set Pic = LoadPicture(GetFilename(C + "objects.rsc"))
    Encrypt GetFilename(C + "objects.rsc")
    hbmpObjects = Pic.Handle
    obmpObjects = SelectObject(hdcObjects, hbmpObjects)
    
    hdcObjectsMask = CreateCompatibleDC(0&)
    Set Pic = LoadPicture(GetFilename(C + "objectsm.rsc"))
    hbmpObjectsMask = Pic.Handle
    obmpObjectsMask = SelectObject(hdcObjectsMask, hbmpObjectsMask)
    
    frmWait.lblStatus = "Loading Sprites .."
    frmWait.Refresh
    
    'Load Sprites
    hdcSprites = CreateCompatibleDC(0&)
    Encrypt GetFilename(C + "sprites.rsc")
    Set Pic = LoadPicture(GetFilename(C + "sprites.rsc"))
    Encrypt GetFilename(C + "sprites.rsc")
    hbmpSprites = Pic.Handle
    obmpSprites = SelectObject(hdcSprites, hbmpSprites)
   
    hdcSpritesMask = CreateCompatibleDC(0&)
    Set Pic = LoadPicture(GetFilename(C + "spritesm.rsc"))
    hbmpSpritesMask = Pic.Handle
    obmpSpritesMask = SelectObject(hdcSpritesMask, hbmpSpritesMask)

    frmWait.lblStatus = "Loading Spell Effects..."
    frmWait.Refresh
    
    hdcEffects = CreateCompatibleDC(0&)
    Encrypt GetFilename(C + "effects.rsc")
    Set Pic = LoadPicture(GetFilename(C + "Effects.rsc"))
    Encrypt GetFilename(C + "effects.rsc")
    hbmpEffects = Pic.Handle
    obmpEffects = SelectObject(hdcEffects, hbmpEffects)
   
    hdcEffectsMask = CreateCompatibleDC(0&)
    Set Pic = LoadPicture(GetFilename(C + "Effectsm.rsc"))
    hbmpEffectsMask = Pic.Handle
    obmpEffectsMask = SelectObject(hdcEffectsMask, hbmpEffectsMask)

    'Create Colors
    CreateStatusColors

    frmWait.Refresh
    
    Unload frmWait
    
    Load frmMenu
    
    'Hook Form
    Hook
    
    'Load Winsock
    StartWinsock (St)
    frmMenu.Show
    
    MovableData.AttackTime = 672
    MovableData.AttackTime = MovableData.AttackTime + 327
    MovableData.FrameCounter = 0
    MovableData.FrameTimer = timeGetTime
    MovableData.blnEnd = False
    frmMain.picViewport.Refresh
    While MovableData.blnEnd = False
        QueryPerformanceCounter curTime
        If curTime - timeStamp >= 0.025 * freq Then
            timeStamp = curTime
            MovableData.FrameCounter = MovableData.FrameCounter + 1
            If MovableData.FrameCounter >= 10 Then
                MovableData.FrameCounter = 0
                If MovableData.CurFrame = 1 Then
                    MovableData.CurFrame = 2
                Else
                    MovableData.CurFrame = 1
                End If
            End If
            MovableData.SecondCounter = MovableData.SecondCounter + 1
            If MovableData.SecondCounter >= 20 Then
                If timeGetTime - MovableData.FrameTimer > 0 Then
                    MovableData.FrameRate = 20000 / (timeGetTime - MovableData.FrameTimer)
                    MovableData.FrameTimer = timeGetTime
                End If
                MovableData.SecondCounter = 0
            End If
            If MovableData.blnPlaying = True Then
                T = timeGetTime
                If MovableData.Freeze = False Then
                    CheckKeys
                    DrawNextFrame
                    If DisableScreen = False Then BitBlt hdcViewport, 0, 0, 384, 384, hdcBuffer, 0, 0, SRCCOPY
                    frmMain.picViewport.Refresh
                End If
            End If
            
        End If
        DoEvents
    Wend
    DeInitialize
End Sub
Sub TransparentBlt(hdc As Long, ByVal destX As Long, ByVal destY As Long, destWidth As Long, destHeight As Long, srcDC As Long, srcX As Long, srcY As Long, maskDC As Long)
    BitBlt hdc, destX, destY, destWidth, destHeight, maskDC, srcX, srcY, SRCAND
    BitBlt hdc, destX, destY, destWidth, destHeight, srcDC, srcX, srcY, SRCPAINT
End Sub
Sub PrintChat(ByVal St As String, Color As Byte)
    Dim A As Long, B As Long, FoundLine As Boolean
    Dim Text As String, TextHeight As Long, TextWidth As Long
    
    With frmMain.picChat
        .ForeColor = QBColor(Color)
        TextHeight = .TextHeight("A")
        MoveUp
        While St <> ""
            B = 0
            FoundLine = False
            For A = 1 To Len(St)
                If .TextWidth(Left$(St, A)) > .ScaleWidth - .CurrentX Then
                    FoundLine = True
                    If B = 0 Then
                        B = A - 1
                    End If
                    If B > 0 Then
                        Text = Left$(St, B)
                        St = Mid$(St, B + 1)
                    Else
                        Text = ""
                    End If
                    Exit For
                End If
                If Mid$(St, A, 1) = " " Then B = A
            Next A
            If FoundLine = False Then
                Text = St
                St = ""
            End If
            If Text <> "" Then
                TextWidth = .TextWidth(Text)
                TextOut .hdc, .CurrentX, .ScaleHeight - TextHeight, Text, Len(Text)
                If FoundLine = True Then
                    MoveUp
                Else
                    .CurrentX = .CurrentX + TextWidth
                End If
            Else
                If St <> "" Then
                    MoveUp
                End If
            End If
        Wend
    End With
    frmMain.picChat.Refresh
End Sub
Sub MoveUp()
    Dim TextHeight As Long
    Dim A As Long
    With frmMain.picChat
        A = .TextHeight("A")
        .CurrentX = 0
        BitBlt .hdc, 0, 0, .ScaleWidth, .ScaleHeight - A, .hdc, 0, A, SRCCOPY
        BitBlt .hdc, 0, .ScaleHeight - A, .ScaleWidth, A, 0, 0, 0, 0
    End With
End Sub
Sub YouDied()
    With Character
        'Reset Stat Bars
        .HP = .MaxHP
        .Energy = .MaxEnergy
        .Mana = .MaxMana
        DrawHP
        DrawEnergy
        DrawMana
        DrawLevel
    End With
    MovableData.Dead = True
    PlayWav 8
End Sub
Sub ConnectClient()
Dim St As String

frmWait.Show
frmWait.lblStatus = "Connecting ..."
frmWait.btnCancel.Visible = True
frmWait.Refresh
ClientSocket = ConnectSock(MovableData.ServerIP, MovableData.ServerPort, St, gHW, True)
    
End Sub
Sub WaitForConnect(Message As String)
    frmWait.Show
    frmWait.lblStatus.Caption = Message
    frmWait.btnCancel.Visible = True
    frmWait.Refresh
    
    frmWait.ConnectTimer.Enabled = True
End Sub

Function EncryptString(St As String) As String
Dim TempStr As String, TempStr2 As String
Dim A As Integer, TmpNum As Integer

TempStr = ""
TempStr2 = ""

For A = 1 To Len(St)
    TempStr = Mid$(St, A, 1)
    TmpNum = Asc(TempStr)
    TempStr2 = TempStr2 + Chr$(TmpNum - 7)
Next A

EncryptString = Trim$(TempStr2)
End Function
Function DecipherString(St As String) As String
Dim TempStr As String, TempStr2 As String
Dim A As Integer, TmpNum As Integer

TempStr = ""
TempStr2 = ""

For A = 1 To Len(St)
    TempStr = Mid$(St, A, 1)
    TmpNum = Asc(TempStr)
    TempStr2 = TempStr2 + Chr$(TmpNum + 7)
Next A

DecipherString = Trim$(TempStr2)
End Function
Sub CreateStatusColors()
Dim A As Long

StatusColors(0) = QBColor(7)
StatusColors(1) = QBColor(7)
StatusColors(2) = QBColor(14)
StatusColors(3) = QBColor(9)
StatusColors(4) = &HC0C0FF
StatusColors(5) = &H404000
StatusColors(6) = &H400000
StatusColors(7) = QBColor(6)
StatusColors(8) = &H503F1D
StatusColors(9) = &H808080
StatusColors(10) = QBColor(0)
StatusColors(11) = &H4000&
StatusColors(12) = &H808000
StatusColors(13) = &HFFC0C0
StatusColors(14) = &H404080
StatusColors(15) = &H80FF&
StatusColors(16) = &HC0FFC0
StatusColors(17) = &HC0&
StatusColors(18) = &H404000
StatusColors(19) = &H800080
StatusColors(20) = &HC0FFFF
StatusColors(21) = &HFF00&
StatusColors(22) = &HFF&
StatusColors(23) = &HFF00FF

For A = 24 To 100
    StatusColors(A) = QBColor(7)
Next A
End Sub
Function QueryValueEx(ByVal lhKey As Long, ByVal szValueName As String, vValue As Variant) As Long
    'This Function Copied from MS Knowledge Base
    'Reads a value from the registry
    Dim cch As Long
    Dim lrc As Long
    Dim lType As Long
    Dim lValue As Long
    Dim sValue As String

    On Error GoTo QueryValueExError

    ' Determine the size and type of data to be read
    lrc = RegQueryValueExNULL(lhKey, szValueName, 0&, lType, 0&, cch)
    If lrc <> ERROR_NONE Then Error 5

    Select Case lType
        Case REG_SZ: ' For strings
            sValue = String(cch, 0)
            lrc = RegQueryValueExString(lhKey, szValueName, 0&, lType, sValue, cch)
            If lrc = ERROR_NONE Then
                vValue = Left$(sValue, cch - 1)
            Else
                vValue = Empty
            End If
        Case REG_DWORD: ' For DWORDS
            lrc = RegQueryValueExLong(lhKey, szValueName, 0&, lType, lValue, cch)
            If lrc = ERROR_NONE Then vValue = lValue
        Case Else 'all other data types not supported
            lrc = -1
        End Select

QueryValueExExit:
    QueryValueEx = lrc
    Exit Function
QueryValueExError:
    Resume QueryValueExExit
End Function
Function GetWindowsKey() As String
    Dim lRetVal As Long, hKey As Long, KeyValue As Variant
    Dim A As Integer, ExecString As String
    
    lRetVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\Microsoft\Windows\CurrentVersion", 0, KEY_ALL_ACCESS, hKey)
    If lRetVal = 0 Then
        lRetVal = QueryValueEx(hKey, "ProductKey", KeyValue)
        If lRetVal = 0 Then
            GetWindowsKey = KeyValue
        Else
            'Error Finding Windows Key
        End If
        RegCloseKey (hKey)
    Else
        'Error Finding Windows Key
    End If
End Function
Sub CreateTileEffect(X As Long, Y As Long, Sprite As Long, Speed As Long, TotalFrames As Long, LoopCount As Integer, EndSound As Long)
Dim A As Long

For A = 1 To 255
    With Projectile(A)
        If .Sprite = 0 Then
            .Sprite = Sprite
            .TargetType = 3
            .Frame = 0
            .TotalFrames = TotalFrames
            .Speed = Speed
            .EndSound = EndSound
            .LoopCount = LoopCount
            .X = X * 32
            .Y = Y * 32
            Exit For
        End If
    End With
Next A
End Sub
Sub CreateMonsterEffect(TargetNum As Byte, Sprite As Long, Speed As Long, TotalFrames As Long, SourceX As Long, SourceY As Long, EndSound As Long)
Dim A As Long

For A = 1 To 255
    With Projectile(A)
        If .Sprite = 0 Then
            .Sprite = Sprite
            .TargetType = 2
            .TargetNum = TargetNum
            .Frame = 0
            .TotalFrames = TotalFrames
            .Speed = Speed
            .EndSound = EndSound
            .SourceX = SourceX
            .SourceY = SourceY
            .X = SourceX * 32
            .Y = SourceY * 32
            Exit For
        End If
    End With
Next A
End Sub
Sub CreatePlayerEffect(TargetNum As Byte, Sprite As Long, Speed As Long, TotalFrames As Long, SourceX As Long, SourceY As Long, EndSound As Long)
Dim A As Long

For A = 1 To 255
    With Projectile(A)
        If .Sprite = 0 Then
            .Sprite = Sprite
            .TargetType = 1
            .TargetNum = TargetNum
            .Frame = 0
            .TotalFrames = TotalFrames
            .Speed = Speed
            .EndSound = EndSound
            .SourceX = SourceX
            .SourceY = SourceY
            .X = SourceX * 32
            .Y = SourceY * 32
            Exit For
        End If
    End With
Next A
End Sub
Sub CreateCharacterEffect(TargetNum As Long, Sprite As Long, Speed As Long, TotalFrames As Long, LoopCount As Integer, EndSound As Long)
Dim A As Long

For A = 1 To 255
    With Projectile(A)
        If .Sprite = 0 Then
            .Sprite = Sprite
            .TargetType = 0
            .Frame = 0
            .TotalFrames = TotalFrames
            .Speed = Speed
            .EndSound = EndSound
            .LoopCount = LoopCount
            .TargetNum = TargetNum
            Exit For
        End If
    End With
Next A
End Sub
Sub DestroyEffect(Number As Integer)
With Projectile(Number)
    .CurLoop = 0
    .D = 0
    .EndSound = 0
    .Frame = 0
    .LoopCount = 0
    .SourceX = 0
    .SourceY = 0
    .Speed = 0
    .Sprite = 0
    .TargetNum = 0
    .TargetType = 0
    .TargetX = 0
    .TargetY = 0
    .timeStamp = 0
    .TotalFrames = 0
    .X = 0
    .Y = 0
End With
End Sub
Sub DestroyFloatText(Val As Integer)
    With FloatText(Val)
        .Text = ""
        .Frame = 0
        .Color = 0
        .X = 0
        .Y = 0
        .D = 0
    End With
End Sub
Sub DestroyStaticText(Val As Integer)
    With StaticText(Val)
        .Text = ""
        .Color = 0
        .X = 0
        .Y = 0
    End With
End Sub
Sub DestroyWeather(Val As Integer)
    With Snow(Val)
        .Frame = 0
        .XO = 0
        .YO = 0
    End With
End Sub
Sub DisableCtrlAltDelete(bDisabled As Boolean)
    ' Disables Control Alt Delete Breaking as well as Ctrl-Escape
    Dim X As Long
    
    X = SystemParametersInfo(97, bDisabled, CStr(1), 0)
End Sub

