Upgrade 1.0.5 to 1.0.6

From VbGORE Visual Basic Online RPG Engine

Contents

This guide will lead you through how to upgrade Version 1.0.5 to Version 1.0.6. For help, please refer to the How to upgrade article. It is highly recommended you read it before ever upgrading.

Add - Client-side attack pre-check

Open GameClient.vbp.

In module TileEngine, add:

<vb> Function Engine_UserIsFacingChar() As Boolean

'***************************************************************** 'Checks if the user is facing a character - used to check if a character ' is at a tile before making a melee attack '***************************************************************** Dim i As Long Dim X As Long Dim Y As Long Dim AddX As Long Dim AddY As Long

   'Get the co-ordinates of the tile the user is facing
   Select Case CharList(UserCharIndex).Heading
   Case NORTH
       AddY = -1
   Case EAST
       AddX = 1
   Case SOUTH
       AddY = 1
   Case WEST
       AddX = -1
   Case NORTHEAST
       AddY = -1
       AddX = 1
   Case SOUTHEAST
       AddY = 1
       AddX = 1
   Case SOUTHWEST
       AddY = 1
       AddX = -1
   Case NORTHWEST
       AddY = -1
       AddX = -1
   End Select
   X = CharList(UserCharIndex).Pos.X + AddX
   Y = CharList(UserCharIndex).Pos.Y + AddY
   
   'Make sure the tile is valid
   If X <= 0 Then Exit Function
   If Y <= 0 Then Exit Function
   If X > MapInfo.Width Then Exit Function
   If Y > MapInfo.Height Then Exit Function
   
   'Loop through all the characters
   For i = 1 To LastChar
       If i <> UserCharIndex Then
           
           'Check if the character is located at the tile
           If CharList(i).Pos.X = X Then
               If CharList(i).Pos.Y = Y Then
                   
                   'We have an character here!
                   Engine_UserIsFacingChar = True
                   Exit Function
                   
               End If
           End If
           
       End If
   Next i

End Function </vb>

Find:

<vb>

               Else
                   sndBuf.Allocate 2
                   sndBuf.Put_Byte DataCode.User_Attack
                   sndBuf.Put_Byte CharList(UserCharIndex).Heading
               End If

</vb>

Replace with:

<vb>

               Else
                   If Engine_UserIsFacingChar Then
                       sndBuf.Allocate 2
                       sndBuf.Put_Byte DataCode.User_Attack
                       sndBuf.Put_Byte CharList(UserCharIndex).Heading
                   End If
               End If

</vb>

Add - Buffer sizing constants

Open GameClient.vbp.

Find:

<vb> Public Const ScreenHeight As Long = 600 'Keep this identical to the value on the server! </vb>

After, add:

<vb> Private Const BufferWidth As Long = 1024 'If ScreenWidth is <= 1024, this will = 1024, else set it as 2048 Private Const BufferHeight As Long = 1024 'Same as the BufferWidth, but with the ScreenHeight </vb>

Find both cases of:

<vb>

       Set BlurStencil = D3DDevice.CreateDepthStencilSurface(1024, 1024, D3DFMT_D16, D3DMULTISAMPLE_NONE)
       Set BlurTexture = D3DX.CreateTexture(D3DDevice, 1024, 1024, 0, D3DUSAGE_RENDERTARGET, DispMode.Format, D3DPOOL_DEFAULT)

</vb>

Replace both with:

<vb>

       Set BlurStencil = D3DDevice.CreateDepthStencilSurface(BufferWidth, BufferHeight, D3DFMT_D16, D3DMULTISAMPLE_NONE)
       Set BlurTexture = D3DX.CreateTexture(D3DDevice, BufferWidth, BufferHeight, 0, D3DUSAGE_RENDERTARGET, DispMode.Format, D3DPOOL_DEFAULT)

</vb>

Change - Integrated manifest files

Open EditorMap.vbp.

Replace all of module Manifest with:

<vb> Option Explicit

Private Declare Sub InitCommonControls Lib "comctl32.dll" ()

Public Sub InitManifest()

   'This routine will make sure the application hooks to ComCtrl32.DLL
   'This must be called on the very first line of sub Main (whichever is called first)
   InitCommonControls
  

End Sub </vb>

Copy \Data\XP.Manifest.Res from the latest version to the same location in your version.

Things are a bit trickier for the map editor's resource file because it already contains information, so copy over \GrhMapEditor\MapEditor.RES to the same location in your version, then delete EditorMap.exe.manifest from the root directory.

These next steps must be done for every project using a .manifest file:

  • EditorParticle
  • GameConfig
  • ToolColorCon
  • ToolFileProcessor
  • ToolFreeNumber
  • ToolGrhCategorizer
  • ToolGrhRawAssistant
  • ToolRebooter
  • ToolServerFPSViewer

Delete the .manifest file corresponding to the project (ie ToolFileProcessor.exe.manifest). Open the project and press Ctrl + D to add a new file. Browse to the \Data\XP.Manifest.Res file and add it.

Add - Tons of GM commands

Open GameServer.vbp.

Find:

<vb>

   GM_GiveSkill As Byte

</vb>

After, add:

<vb>

   GM_GiveGold As Byte
   GM_GiveObject As Byte
   GM_KillMap As Byte
   GM_Kill As Byte
   GM_WarpToMap As Byte
   GM_IPInfo As Byte
   GM_BanList As Byte

</vb>

Find:

<vb>

       .GM_GiveSkill = 113

</vb>

After, add:

<vb>

       .GM_GiveGold = 114
       .GM_GiveObject = 115
       .GM_KillMap = 116
       .GM_Kill = 117
       .GM_WarpToMap = 118
       .GM_IPInfo = 119
       .GM_BanList = 120

</vb>

Find:

<vb>

           Case .GM_Warp: Data_GM_Warp rBuf, Index

</vb>

After, add:

<vb>

           Case .GM_GiveGold: Data_GM_GiveGold rBuf, Index
           Case .GM_GiveObject: Data_GM_GiveObject rBuf, Index
           Case .GM_KillMap: Data_GM_KillMap rBuf, Index
           Case .GM_Kill: Data_GM_Kill rBuf, Index
           Case .GM_WarpToMap: Data_GM_WarpToMap rBuf, Index
           Case .GM_IPInfo: Data_GM_IPInfo rBuf, Index
           Case .GM_BanList: Data_GM_BanList rBuf, Index

</vb>

In module TCP, add:

<vb> Sub Data_GM_GiveGold(ByRef rBuf As DataBuffer, ByVal UserIndex As Integer)

'***************************************************************** 'GM gives themself gold '<Amount(L)> '***************************************************************** Dim Amount As Long

   'Get the gold amount
   Amount = rBuf.Get_Long
   
   'Confirm that the user has a high enough GM level
   If UserList(UserIndex).Flags.GMLevel = 0 Then Exit Sub
   
   'Give the GM the gold
   UserList(UserIndex).Stats.BaseStat(SID.Gold) = UserList(UserIndex).Stats.BaseStat(SID.Gold) + Amount
   
   '"You got gold" message
   ConBuf.PreAllocate 5
   ConBuf.Put_Byte DataCode.Server_Message
   ConBuf.Put_Byte 138
   ConBuf.Put_Long Amount
   Data_Send ToIndex, UserIndex, ConBuf.Get_Buffer, , PP_GMMessages

End Sub

Sub Data_GM_GiveObject(ByRef rBuf As DataBuffer, ByVal UserIndex As Integer)

'***************************************************************** 'GM gives themself an object '<ObjIndex(I)><Amount(I)> '***************************************************************** Dim ObjIndex As Integer Dim Amount As Integer

   'Get the values
   ObjIndex = rBuf.Get_Integer
   Amount = rBuf.Get_Integer
   
   'Confirm that the user has a high enough GM level
   If UserList(UserIndex).Flags.GMLevel = 0 Then Exit Sub
   
   'Let the GiveObj routine handle the rest
   User_GiveObj UserIndex, ObjIndex, Amount
   

End Sub

Sub Data_GM_KillMap(ByRef rBuf As DataBuffer, ByVal UserIndex As Integer)

'***************************************************************** 'GM kills all of the NPCs on the map '<> '***************************************************************** Dim i As Integer

   'Confirm that the user has a high enough GM level
   If UserList(UserIndex).Flags.GMLevel = 0 Then Exit Sub
   
   'Loop through every NPC
   For i = 1 To LastNPC
       
       'Check if the NPC is on the user's map
       If NPCList(i).Pos.Map = UserList(UserIndex).Pos.Map Then
       
           'Check for valid NPC flags
           If NPCList(i).Flags.NPCAlive Then
               If NPCList(i).Flags.NPCActive Then
                   
                   'Kill them!
                   NPC_Kill i
                   
               End If
           End If
       
       End If
       
   Next i
   

End Sub

Sub Data_GM_Kill(ByRef rBuf As DataBuffer, ByVal UserIndex As Integer)

'***************************************************************** 'GM kills their target '<> '***************************************************************** Dim TargetIndex As Integer Dim TargetType As Byte

   'Confirm that the user has a high enough GM level
   If UserList(UserIndex).Flags.GMLevel = 0 Then Exit Sub
   
   'Get the target index and type
   TargetIndex = UserList(UserIndex).Flags.TargetIndex
   TargetType = UserList(UserIndex).Flags.Target
   
   'Check for PC
   If TargetType = CharType_PC Then
   
       'Make sure the GM isn't targeting themself
       If TargetIndex = 0 Then Exit Sub
       If TargetIndex = UserIndex Then Exit Sub
       
       'Check for a valid target
       If TargetIndex <= 0 Then Exit Sub
       If TargetIndex > LastUser Then Exit Sub
       If UserList(TargetIndex).Flags.Disconnecting = 1 Then Exit Sub
       If UserList(TargetIndex).Flags.UserLogged = 0 Then Exit Sub
       
       'Kill the user
       User_Kill TargetIndex
       
   'Check for NPC
   Else
   
       'Check for a valid target
       If TargetIndex <= 0 Then Exit Sub
       If TargetIndex > LastNPC Then Exit Sub
       If NPCList(TargetIndex).Flags.NPCActive = 0 Then Exit Sub
       If NPCList(TargetIndex).Flags.NPCAlive = 0 Then Exit Sub
       
       'Kill the NPC
       NPC_Kill TargetIndex
       
   End If
   

End Sub

Sub Data_GM_WarpToMap(ByRef rBuf As DataBuffer, ByVal UserIndex As Integer)

'***************************************************************** 'GM warps to a map by number '<MapIndex(I)> '***************************************************************** Dim MapIndex As Integer Dim X As Byte Dim Y As Byte

   'Get the map index
   MapIndex = rBuf.Get_Integer
   
   'Confirm that the user has a high enough GM level
   If UserList(UserIndex).Flags.GMLevel = 0 Then Exit Sub
   
   'Check for a valid map
   If MapIndex <= 0 Then Exit Sub
   If MapIndex > NumMaps Then Exit Sub
   
   'Make sure the map is loaded
   Load_Maps_Temp MapIndex
   
   'Warp the user to the very first legal tile
   For Y = 1 To MapInfo(MapIndex).Width
       For X = 1 To MapInfo(MapIndex).Height
           If MapInfo(MapIndex).Data(X, Y).Blocked = 0 Then
               User_WarpChar UserIndex, MapIndex, X, Y
               Exit Sub
           End If
       Next X
   Next Y
           

End Sub

Sub Data_GM_IPInfo(ByRef rBuf As DataBuffer, ByVal UserIndex As Integer)

'***************************************************************** 'GM requests information on an IP '<IP(S)> '***************************************************************** Dim s() As String Dim IP As String Dim i As Long Dim j As Long

   'Get the IP (we assume it is valid, since it IS a GM, so they shouldn't be trying to crash the server)
   IP = rBuf.Get_String
   
   'Confirm that the user has a high enough GM level
   If UserList(UserIndex).Flags.GMLevel = 0 Then Exit Sub
   
   'Clear the conversion buffer
   ConBuf.Clear
   
   'Make a query to the database that contains the IP in the ban list
   DB_RS.Open "SELECT name,ip FROM users WHERE ip LIKE '%" & IP & "%'", DB_Conn, adOpenStatic, adLockOptimistic
   
   'Check if there are any results
   If Not DB_RS.EOF Then
   
       'Loop through all of the results and return the names
       i = 0
       Do While Not DB_RS.EOF
           
           'Confirm that the IP is really what we wanted since the LIKE operator won't always give us just what we want
           s = Split(DB_RS!IP, vbNewLine)      'Split up the IPs
           If UBound(s) > 0 Then               'Make sure there is more than one IP
               For j = 0 To UBound(s)          'Loop through and check every value of s()
                   If s(j) = IP Then Exit For  'Valid match found
               Next j
               If j = UBound(s) + 1 Then GoTo NextRS   'If no match was found, skip
           End If
               
           'Add the IP to the list
           i = i + 1
           ConBuf.Allocate 5 + Len(DB_RS!Name) + Len(CStr(i))
           ConBuf.Put_Byte DataCode.Comm_Talk
           ConBuf.Put_String i & ". " & DB_RS!Name
           ConBuf.Put_Byte DataCode.Comm_FontType_Info
           'Move to the next recordset

NextRS:

           DB_RS.MoveNext
           
       Loop
       
   End If
   
   'Close the record set
   DB_RS.Close
   
   'Check if the data buffer has anything in it (if so, there are results)
   If ConBuf.HasBuffer = 0 Then
   
       'No results :(
       ConBuf.Allocate 17  'The buffer is already cleared, so no need for PreAllocate
       ConBuf.Put_Byte DataCode.Comm_Talk
       ConBuf.Put_String "No IP matches."
       ConBuf.Put_Byte DataCode.Comm_FontType_Info
       
   End If
   
   'Send whatever we created (either list of names, or "No IP matches") to the user
   Data_Send ToIndex, UserIndex, ConBuf.Get_Buffer, , PP_GMMessages
   

End Sub

Sub Data_GM_BanList(ByRef rBuf As DataBuffer, ByVal UserIndex As Integer)

'***************************************************************** 'GM requests the list of banned IPs '<> '***************************************************************** Dim i As Long

   'Confirm that the user has a high enough GM level
   If UserList(UserIndex).Flags.GMLevel = 0 Then Exit Sub
   
   'Generate the ban list
   DB_RS.Open "SELECT * FROM banned_ips", DB_Conn, adOpenStatic, adLockOptimistic
   
   'Check if the are any IP bans
   If DB_RS.EOF Then
       DB_RS.Close
       ConBuf.PreAllocate 28
       ConBuf.Put_Byte DataCode.Comm_Talk
       ConBuf.Put_String "There are no banned IPs."
       ConBuf.Put_Byte DataCode.Comm_FontType_Info
       Data_Send ToIndex, UserIndex, ConBuf.Get_Buffer, , PP_GMMessages
       Exit Sub
   End If
   
   'Loop through the IP bans
   i = 0
   Do While Not DB_RS.EOF
       i = i + 1
       ConBuf.Allocate 8 + Len(DB_RS!IP) + Len(DB_RS!Reason) + Len(CStr(i))
       ConBuf.Put_Byte DataCode.Comm_Talk
       ConBuf.Put_String i & ". |" & DB_RS!IP & "| " & DB_RS!Reason
       ConBuf.Put_Byte DataCode.Comm_FontType_Info
       DB_RS.MoveNext  'Move to the next IP
   Loop
   
   'Close the record set
   DB_RS.Close
   
   'Send the list to the user
   Data_Send ToIndex, UserIndex, ConBuf.Get_Buffer, , PP_GMMessages
   

End Sub </vb>

Open GameClient.vbp.

Find:

<vb>

   ElseIf Input_GetCommand("/RAISE") Then

</vb>

Before, add:

<vb>

   ElseIf Input_GetCommand("/KILLMAP") Then
       sndBuf.Put_Byte DataCode.GM_KillMap
   ElseIf Input_GetCommand("/KILL") Then
       If TargetCharIndex = UserCharIndex Or TargetCharIndex = 0 Then
           Engine_AddToChatTextBuffer "Suicide is not the answer...", FontColor_Info
       Else
           sndBuf.Put_Byte DataCode.GM_Kill
       End If
       
   ElseIf Input_GetCommand("/GIVEGO") Then
       s = Input_GetBufferArgs
       If Val(s) <= 0 Or Val(s) > MAXLONG Then
           Engine_AddToChatTextBuffer "Please enter an amount greater than 0.", FontColor_Info
           GoTo CleanUp
       End If
       sndBuf.Put_Byte DataCode.GM_GiveGold
       sndBuf.Put_Long Val(s)
       
   ElseIf Input_GetCommand("/GIVEOBJ") Then
       s = Input_GetBufferArgs
       If s = vbNullString Then GoTo CleanUp
       TempS = Split(s, " ")
       If UBound(TempS) <> 1 Then
           Engine_AddToChatTextBuffer "Please use the format: <ObjIndex> <Amount>", FontColor_Info
           GoTo CleanUp
       End If
       If Val(TempS(0)) <= 0 Or Val(TempS(0)) > MAXINT Then
           Engine_AddToChatTextBuffer "Invalid ObjIndex parameter - enter a value between 1 and " & MAXINT & ".", FontColor_Info
           GoTo CleanUp
       End If
       If Val(TempS(1)) <= 0 Or Val(TempS(1)) > MAXINT Then
           Engine_AddToChatTextBuffer "Invalid Amount parameter - enter a value between 1 and " & MAXINT & ".", FontColor_Info
           GoTo CleanUp
       End If
       sndBuf.Put_Byte DataCode.GM_GiveObject
       sndBuf.Put_Integer Val(TempS(0))
       sndBuf.Put_Integer Val(TempS(1))
       
   ElseIf Input_GetCommand("/WARP") Then
       i = Val(Input_GetBufferArgs)
       If Not Engine_FileExist(MapPath & i & ".map", vbNormal) Then
           Engine_AddToChatTextBuffer "Please enter a valid map number.", FontColor_Info
           GoTo CleanUp
       End If
       sndBuf.Put_Byte DataCode.GM_WarpToMap
       sndBuf.Put_Integer i
   
   ElseIf Input_GetCommand("/IPINFO") Then
       s = Input_GetBufferArgs
       If s = vbNullString Then GoTo CleanUp
       TempS = Split(s, ".")   'All of this is just a check for a valid IP
       If UBound(TempS) <> 3 Then  'Check for 3 periods
           Engine_AddToChatTextBuffer Message(92), FontColor_Info
           GoTo CleanUp
       End If
       For j = 0 To 3  'Check for values between 0 and 255
           If Val(TempS(j)) < 0 Or Val(TempS(j)) > 255 Then
               Engine_AddToChatTextBuffer Message(92), FontColor_Info
               GoTo CleanUp
           End If
       Next j
       sndBuf.Put_Byte DataCode.GM_IPInfo
       sndBuf.Put_String s
       
   ElseIf Input_GetCommand("/BANLIST") Then
       sndBuf.Put_Byte DataCode.GM_BanList

</vb>

Fix - Needless MipMap level

Open GameClient.vbp.

Find both cases of:

<vb>

       Set BlurTexture = D3DX.CreateTexture(D3DDevice, 1024, 1024, 1, D3DUSAGE_RENDERTARGET, DispMode.Format, D3DPOOL_DEFAULT)

</vb>

Replace with:

<vb>

       Set BlurTexture = D3DX.CreateTexture(D3DDevice, 1024, 1024, 0, D3DUSAGE_RENDERTARGET, DispMode.Format, D3DPOOL_DEFAULT)</vb>

Fix - Motion blur rendering

Open GameClient.vbp.

Find:

<vb>

   With D3DDevice
   
       'Check if using motion blur / zooming
       If UseMotionBlur Then
           
           'Perform the zooming calculations
           ' * 1.333... maintains the aspect ratio
           ' ... / 1024 is to factor in the buffer size
           BlurTA(0).tU = ZoomLevel * 1.333333333
           BlurTA(0).tV = ZoomLevel
           BlurTA(1).tU = ((ScreenWidth + 1) / 1024) - (ZoomLevel * 1.333333333)
           BlurTA(1).tV = ZoomLevel
           BlurTA(2).tU = ZoomLevel * 1.333333333
           BlurTA(2).tV = ((ScreenHeight + 1) / 1024) - ZoomLevel
           BlurTA(3).tU = BlurTA(1).tU
           BlurTA(3).tV = BlurTA(2).tV
           
           'Draw what we have drawn thus far since the last .Clear
           LastTexture = -100
           .SetRenderTarget DeviceBuffer, DeviceStencil, 0
           .SetTexture 0, BlurTexture
           .SetRenderState D3DRS_TEXTUREFACTOR, D3DColorARGB(BlurIntensity, 255, 255, 255)
           .SetTextureStageState 0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR
           .DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, BlurTA(0), FVF_Size
           .SetTextureStageState 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE
       End If
       
   End With

</vb>

Move it to the very bottom of sub Engine_Render_Screen, after:

<vb>

   'Show FPS
   Engine_Render_Text "FPS: " & FPS, ScreenWidth - 80, 2, -1

</vb>

Add - Client object grab check

Open GameClient.vbp.

Find:

<vb>

   'Get object off ground (alt)
   If Input_Keys_IsPressed(KeyDefinitions.PickUpObj, KeyCode) Then
       If LastLootTime < timeGetTime Then
           LastLootTime = timeGetTime + LootDelay
           sndBuf.Put_Byte DataCode.User_Get
       End If
   End If

</vb>

Replace with:

<vb>

   'Get object off ground (alt)
   If Input_Keys_IsPressed(KeyDefinitions.PickUpObj, KeyCode) Then
       If Engine_OBJ_AtTile(CharList(UserCharIndex).Pos.X, CharList(UserCharIndex).Pos.Y) Then
           If LastLootTime < timeGetTime Then
               LastLootTime = timeGetTime + LootDelay
               sndBuf.Put_Byte DataCode.User_Get
           End If
       End If
   End If

</vb>

In sub TileEngine, add:

<vb> Function Engine_OBJ_AtTile(ByVal X As Byte, ByVal Y As Byte) As Boolean

'***************************************************************** 'Checks for an object at tile (X,Y) '***************************************************************** Dim i As Long

   'Check if any objects exist
   If LastObj = 0 Then Exit Function
   'Loop through all the objects
   For i = 1 To LastObj
       
       'Check if the object is located at the tile
       If OBJList(i).Pos.X = X Then
           If OBJList(i).Pos.Y = Y Then
               
               'We have an object here!
               Engine_OBJ_AtTile = True
               Exit Function
               
           End If
       End If
       
   Next i

End Function </vb>

Add - ToolGrhRawAssistant

Copy over ToolGrhRawAssistant from Version 1.0.6.

Fix - NPC spawning

Open GameServer.vbp.

Find:

<vb>

   'Close down the NPC
   NPCList(NPCIndex).Flags.NPCActive = 0
   CharList(NPCList(NPCIndex).Char.CharIndex).Index = 0
   CharList(NPCList(NPCIndex).Char.CharIndex).CharType = 0

</vb>

Replace with:

<vb>

   'Close down the NPC
   CharList(NPCList(NPCIndex).Char.CharIndex).Index = 0
   CharList(NPCList(NPCIndex).Char.CharIndex).CharType = 0

</vb>

Find:

<vb>

   'Clear the variables
   NPCList(NPCIndex).Char.CharIndex = 0
   NPCList(NPCIndex).Flags.NPCAlive = 0
   NPCList(NPCIndex).Flags.NPCActive = 0

</vb>

Replace with:

<vb>

   'Clear the variables
   NPCList(NPCIndex).Char.CharIndex = 0
   NPCList(NPCIndex).Flags.NPCAlive = 0

</vb>

Fix - Map object erasing

Open GameServer.vbp.

Find:

<vb> Public Sub Obj_Erase(ByVal Num As Integer, ByVal ObjSlot As Byte, ByVal Map As Byte, ByVal X As Integer, ByVal Y As Integer) </vb>

Replace the whole sub with:

<vb> Public Sub Obj_Erase(ByVal Num As Integer, ByVal ObjSlot As Byte, ByVal Map As Byte, ByVal X As Integer, ByVal Y As Integer)

'***************************************************************** 'Erase a object '*****************************************************************

   Log "Call Obj_Erase(" & Num & "," & ObjSlot & "," & Map & "," & X & "," & Y & ")", CodeTracker '//\\LOGLINE//\\
   'Check for a valid index
   If ObjSlot > MapInfo(Map).ObjTile(X, Y).NumObjs Then
       Log "Obj_Erase: Invalid ObjSlot specified (" & ObjSlot & ")", CriticalError '//\\LOGLINE//\\
       Exit Sub
   End If
   
   'Check to erase every object
   If Num = -1 Then Num = MapInfo(Map).ObjTile(X, Y).ObjInfo(ObjSlot).Amount
   'Remove the amount
   Log "Obj_Erase: Removing " & Num & " objects from (" & Map & "," & X & "," & Y & ") - current amount = " & MapInfo(Map).ObjTile(X, Y).ObjInfo(ObjSlot).Amount, CodeTracker '//\\LOGLINE//\\
   MapInfo(Map).ObjTile(X, Y).ObjInfo(ObjSlot).Amount = MapInfo(Map).ObjTile(X, Y).ObjInfo(ObjSlot).Amount - Num
   
   'Check if they are all gone
   If MapInfo(Map).ObjTile(X, Y).ObjInfo(ObjSlot).Amount <= 0 Then
       Log "Obj_Erase: Erasing object from client screens at (" & Map & "," & X & "," & Y & ")", CodeTracker '//\\LOGLINE//\\
       ConBuf.PreAllocate 7
       ConBuf.Put_Byte DataCode.Server_EraseObject
       ConBuf.Put_Byte CByte(X)
       ConBuf.Put_Byte CByte(Y)
       ConBuf.Put_Long ObjData.GrhIndex(MapInfo(Map).ObjTile(X, Y).ObjInfo(ObjSlot).ObjIndex)
       Data_Send ToMap, 0, ConBuf.Get_Buffer, Map, PP_GroundObjects
       With MapInfo(Map).ObjTile(X, Y)
           .ObjInfo(ObjSlot).ObjIndex = 0
           .ObjInfo(ObjSlot).Amount = 0
           .ObjLife(ObjSlot) = 0
       End With
   End If

End Sub </vb>

Personal tools