[EO 3.0 - DX8 ONLY] Wabbit's Ranged Projectiles!

WARNING: For some reason, the system is causing a very significant drop in CPS! Be aware while I try to sort out the problem!

All credit goes to Wabbit for his system, I just edited it for DX8, and jcsnider for helping fix a few problems that came up, and of course EO 3.0!

If you would like to, for reference, keep this open in another tab: http://www.touchofdeathforums.com/smf2/index.php/topic,73708.0.html

Client

Public Const MAX_WEATHER_PARTICLES As Long = 250

Below that insert:

Public Const MAX_PLAYER_PROJECTILES As Long = 20

Find in loadTextures:

Call CheckFogs

under that insert:

Call CheckProjectiles

SubEditorInit find:

frmEditor_Item.scrlPaperdoll = .Paperdoll

insert directly below it:

If frmEditor_Item.cmbType.ListIndex = ITEM_TYPE_WEAPON Then
    frmEditor_Item.Frame4.Visible = True
    With Item(EditorIndex).ProjecTile
          frmEditor_Item.scrlProjectileDamage.Value = .Damage
          frmEditor_Item.scrlProjectilePic.Value = .Pic
          frmEditor_Item.scrlProjectileRange.Value = .Range
          frmEditor_Item.scrlProjectileSpeed.Value = .Speed
    End With
End If

In the same sub under:

frmEditor_Item.fraEquipment.Visible = False

insert:

frmEditor_Item.Frame4.Visible = False

modGraphics find:

Public Tex_Face() As DX8TextureRec

right under that insert:

Public Tex_Projectile() As DX8TextureRec

Unloadtextures, under the NumFaces For/Next insert:

For i = 1 To NumProjectiles
        Tex_Projectile(i).Texture = 0
    Next

modGraphics, find:

Public NumFogs As Long

insert underneath that:

Public NumProjectiles As Long

In modGraphics at the very bottom place this sub:

' player Projectiles
Public Sub DrawProjectile(ByVal Index As Long, ByVal PlayerProjectile As Long)
Dim x As Long, y As Long, PicNum As Long, i As Long
Dim rec As DxVBLib.RECT

    ' If debug mode, handle error then exit out
    If Options.Debug = 1 Then On Error GoTo errorhandler

    ' check for subscript error
    If Index < 1 Or PlayerProjectile < 1 Or PlayerProjectile > MAX_PLAYER_PROJECTILES Then Exit Sub

    ' check to see if it's time to move the Projectile
    If GetTickCount > Player(Index).ProjecTile(PlayerProjectile).TravelTime Then
        With Player(Index).ProjecTile(PlayerProjectile)
            ' set next travel time and the current position and then set the actual direction based on RMXP arrow tiles.
            Select Case .Direction
                ' down
                Case 0
                    .y = .y + 1
                    ' check if they reached maxrange
                    If .y = (GetPlayerY(Index) + .Range) + 1 Then ClearProjectile Index, PlayerProjectile: Exit Sub
                ' up
                Case 1
                    .y = .y - 1
                    ' check if they reached maxrange
                    If .y = (GetPlayerY(Index) - .Range) - 1 Then ClearProjectile Index, PlayerProjectile: Exit Sub
                ' right
                Case 2
                    .x = .x + 1
                    ' check if they reached max range
                    If .x = (GetPlayerX(Index) + .Range) + 1 Then ClearProjectile Index, PlayerProjectile: Exit Sub
                ' left
                Case 3
                    .x = .x - 1
                    ' check if they reached maxrange
                    If .x = (GetPlayerX(Index) - .Range) - 1 Then ClearProjectile Index, PlayerProjectile: Exit Sub
            End Select
            .TravelTime = GetTickCount + .Speed
        End With
    End If

    ' set the x, y & pic values for future reference
    x = Player(Index).ProjecTile(PlayerProjectile).x
    y = Player(Index).ProjecTile(PlayerProjectile).y
    PicNum = Player(Index).ProjecTile(PlayerProjectile).Pic

    ' check if left map
    If x > Map.MaxX Or y > Map.MaxY Or x < 0 Or y < 0 Then
        ClearProjectile Index, PlayerProjectile
        Exit Sub
    End If

    ' check if we hit a block
    If Map.Tile(x, y).Type = TILE_TYPE_BLOCKED Then
        ClearProjectile Index, PlayerProjectile
        Exit Sub
    End If

    ' check for player hit
    For i = 1 To Player_HighIndex
        If x = GetPlayerX(i) And y = GetPlayerY(i) Then
            ' they're hit, remove it
            If Not x = Player(MyIndex).x Or Not y = GetPlayerY(MyIndex) Then
                ClearProjectile Index, PlayerProjectile
                Exit Sub
            End If
        End If
    Next

    ' check for npc hit
    For i = 1 To MAX_MAP_NPCS
        If x = MapNpc(i).x And y = MapNpc(i).y Then
            ' they're hit, remove it
            ClearProjectile Index, PlayerProjectile
            Exit Sub
        End If
    Next

    ' get positioning in the texture
    With rec
        .Top = 0
        .Bottom = SIZE_Y
        .Left = Player(Index).ProjecTile(PlayerProjectile).Direction * SIZE_X
        .Right = .Left + SIZE_X
    End With

    ' blt the projectile
    RenderTexture Tex_Projectile(PicNum), ConvertMapX(x * PIC_X), ConvertMapY(y * PIC_Y), rec.Left, rec.Top, rec.Right - rec.Left, rec.Bottom - rec.Top, rec.Right - rec.Left, rec.Bottom - rec.Top, D3DColorRGBA(255, 255, 255, 255)
    'Call Engine_BltFast(ConvertMapX(x * PIC_X), ConvertMapY(y * PIC_Y), DDS_Projectile(PicNum), rec, DDBLTFAST_WAIT Or DDBLTFAST_SRCCOLORKEY)

    ' Error handler
    Exit Sub
errorhandler:
    HandleError "BltProjectile", "modDirectDraw7", Err.Number, Err.Description, Err.Source, Err.HelpContext
    Err.Clear
    Exit Sub
End Sub

Render_Graphics under the draw animations code place this:

 ' draw projectiles for each player
    For i = 1 To Player_HighIndex
        For x = 1 To MAX_PLAYER_PROJECTILES
            If Player(i).ProjecTile(x).Pic > 0 Then
                DrawProjectile i, x
            End If
        Next
    Next

In modTypes, above PlayerRec, insert this:

Public Type ProjectileRec
    TravelTime As Long
    Direction As Long
    x As Long
    y As Long
    Pic As Long
    Range As Long
    Damage As Long
    Speed As Long
End Type

At the end of playerRec, before end type, place this:

    ' projectiles
    ProjecTile(1 To MAX_PLAYER_PROJECTILES) As ProjectileRec

ItemRec, before end type, place this:

    ProjecTile As ProjectileRec

At the bottom of modDatabase, add these subs:

' projectiles
Public Sub CheckProjectiles()
Dim i As Long

    ' If debug mode, handle error then exit out
    If Options.Debug = 1 Then On Error GoTo errorhandler

    i = 1
    NumProjectiles = 1

    ReDim Tex_Projectile(1)

    While FileExist(GFX_PATH & "projectiles\" & i & GFX_EXT)
        ReDim Preserve Tex_Projectile(NumProjectiles)
        NumTextures = NumTextures + 1
        ReDim Preserve gTexture(NumTextures)
        Tex_Projectile(NumProjectiles).filepath = App.Path & GFX_PATH & "projectiles\" & i & GFX_EXT
        Tex_Projectile(NumProjectiles).Texture = NumTextures
        NumProjectiles = NumProjectiles + 1
        i = i + 1
    Wend

    NumProjectiles = NumProjectiles - 1

    If NumProjectiles = 0 Then Exit Sub

    For i = 1 To NumProjectiles
        LoadTexture Tex_Projectile(i)
    Next

    ' Error handler
    Exit Sub
errorhandler:
    HandleError "CheckItems", "modDatabase", Err.Number, Err.Description, Err.Source, Err.HelpContext
    Err.Clear
    Exit Sub
End Sub

Sub ClearProjectile(ByVal Index As Long, ByVal PlayerProjectile As Long)
    ' If debug mode, handle error then exit out
    If Options.Debug = 1 Then On Error GoTo errorhandler

    With Player(Index).ProjecTile(PlayerProjectile)
        .Direction = 0
        .Pic = 0
        .TravelTime = 0
        .x = 0
        .y = 0
        .Range = 0
        .Damage = 0
        .Speed = 0
    End With

    ' Error handler
    Exit Sub
errorhandler:
    HandleError "ClearProjectile", "modDatabase", Err.Number, Err.Description, Err.Source, Err.HelpContext
    Err.Clear
    Exit Sub
End Sub

Replace Sub CheckAttack with:

Public Sub CheckAttack()
Dim Buffer As clsBuffer
Dim attackspeed As Long, x As Long, y As Long, i As Long

    ' If debug mode, handle error then exit out
    If Options.Debug = 1 Then On Error GoTo errorhandler

    If ControlDown Then

        Select Case Player(MyIndex).Dir
            Case DIR_UP
                x = GetPlayerX(MyIndex)
                y = GetPlayerY(MyIndex) - 1
            Case DIR_DOWN
                x = GetPlayerX(MyIndex)
                y = GetPlayerY(MyIndex) + 1
            Case DIR_LEFT
                x = GetPlayerX(MyIndex) - 1
                y = GetPlayerY(MyIndex)
            Case DIR_RIGHT
                x = GetPlayerX(MyIndex) + 1
                y = GetPlayerY(MyIndex)
        End Select

        If GetTickCount > Player(MyIndex).EventTimer Then
            For i = 1 To Map.CurrentEvents
                If Map.MapEvents(i).Visible = 1 Then
                    If Map.MapEvents(i).x = x And Map.MapEvents(i).y = y Then
                        Set Buffer = New clsBuffer
                        Buffer.WriteLong CEvent
                        Buffer.WriteLong i
                        SendData Buffer.ToArray()
                        Set Buffer = Nothing
                        Player(MyIndex).EventTimer = GetTickCount + 200
                    End If
                End If
            Next
        End If

        If SpellBuffer > 0 Then Exit Sub ' currently casting a spell, can't attack
        If StunDuration > 0 Then Exit Sub ' stunned, can't attack

        ' speed from weapon
        If GetPlayerEquipment(MyIndex, Weapon) > 0 Then
            attackspeed = Item(GetPlayerEquipment(MyIndex, Weapon)).speed
        Else
            attackspeed = 1000
        End If

        If Player(MyIndex).AttackTimer + attackspeed < GetTickCount Then
            If Player(MyIndex).Attacking = 0 Then

                With Player(MyIndex)
                    .Attacking = 1
                    .AttackTimer = GetTickCount
                End With

                If GetPlayerEquipment(MyIndex, Weapon) > 0 Then
                    If Item(GetPlayerEquipment(MyIndex, Weapon)).ProjecTile.Pic > 0 Then
                        ' projectile
                        Set Buffer = New clsBuffer
                            Buffer.WriteLong CProjecTileAttack
                            SendData Buffer.ToArray()
                            Set Buffer = Nothing
                            Exit Sub
                    End If
                End If

                ' non projectile
                Set Buffer = New clsBuffer
                Buffer.WriteLong CAttack
                SendData Buffer.ToArray()
                Set Buffer = Nothing
            End If
        End If

    End If

    ' Error handler
    Exit Sub
errorhandler:
    HandleError "CheckAttack", "modGameLogic", Err.Number, Err.Description, Err.Source, Err.HelpContext
    Err.Clear
    Exit Sub
End Sub

In Public Enum ServerPackets Before:

SMSG_COUNT

insert:

SHandleProjectile

In Public Enum ClientPackets Before:

CMSG_COUNT

Insert:

CProjecTileAttack

InitMessages after:

HandleDataSub(SPartyVitals) = GetAddress(AddressOf HandlePartyVitals)

Insert:

HandleDataSub(SHandleProjectile) = GetAddress(AddressOf HandleProjectile)

modHandleData insert at the bottom:

Sub HandleProjectile(ByVal Index As Long, ByRef Data() As Byte, ByVal StartAddr As Long, ByVal ExtraVar As Long)
Dim PlayerProjectile As Long
Dim Buffer As clsBuffer

    ' If debug mode, handle error then exit out
    If Options.Debug = 1 Then On Error GoTo errorhandler

    ' create a new instance of the buffer
    Set Buffer = New clsBuffer

    ' read bytes from data()
    Buffer.WriteBytes Data()

    ' recieve projectile number
    PlayerProjectile = Buffer.ReadLong
    Index = Buffer.ReadLong

    ' populate the values
    With Player(Index).ProjecTile(PlayerProjectile)

        ' set the direction
        .Direction = Buffer.ReadLong

        ' set the direction to support file format
        Select Case .Direction
            Case DIR_DOWN
                .Direction = 0
            Case DIR_UP
                .Direction = 1
            Case DIR_RIGHT
                .Direction = 2
            Case DIR_LEFT
                .Direction = 3
        End Select

        ' set the pic
        .Pic = Buffer.ReadLong
        ' set the coordinates
        .x = GetPlayerX(Index)
        .y = GetPlayerY(Index)
        ' get the range
        .Range = Buffer.ReadLong
        ' get the damge
        .Damage = Buffer.ReadLong
        ' get the speed
        .Speed = Buffer.ReadLong

    End With

    ' Error handler
    Exit Sub
errorhandler:
    HandleError "HandleProjectile", "modHandleData", Err.Number, Err.Description, Err.Source, Err.HelpContext
    Err.Clear
    Exit Sub
End Sub

Server Code

After:

Public Const MAX_VARIABLES As Long = 1000

Insert:

Public Const MAX_PLAYER_PROJECTILES As Long = 20

modDatabase at the bottom add:

Sub ClearProjectile(ByVal Index As Long, ByVal PlayerProjectile As Long)
    ' clear the projectile
    With TempPlayer(Index).ProjecTile(PlayerProjectile)
        .Direction = 0
        .Pic = 0
        .TravelTime = 0
        .x = 0
        .y = 0
        .Range = 0
        .Damage = 0
        .Speed = 0
    End With
End Sub

modGameLogic at the bottom add:

Public Sub HandleProjecTile(ByVal Index As Long, ByVal PlayerProjectile As Long)
Dim x As Long, y As Long, i As Long

    ' check for subscript out of range
    If Index < 1 Or Index > MAX_PLAYERS Or PlayerProjectile < 1 Or PlayerProjectile > MAX_PLAYER_PROJECTILES Then Exit Sub

    ' check to see if it's time to move the Projectile
    If GetTickCount > TempPlayer(Index).ProjecTile(PlayerProjectile).TravelTime Then
        With TempPlayer(Index).ProjecTile(PlayerProjectile)
            ' set next travel time and the current position and then set the actual direction based on RMXP arrow tiles.
            Select Case .Direction
                ' down
                Case DIR_DOWN
                    .y = .y + 1
                    ' check if they reached maxrange
                    If .y = (GetPlayerY(Index) + .Range) + 1 Then ClearProjectile Index, PlayerProjectile: Exit Sub
                ' up
                Case DIR_UP
                    .y = .y - 1
                    ' check if they reached maxrange
                    If .y = (GetPlayerY(Index) - .Range) - 1 Then ClearProjectile Index, PlayerProjectile: Exit Sub
                ' right
                Case DIR_RIGHT
                    .x = .x + 1
                    ' check if they reached max range
                    If .x = (GetPlayerX(Index) + .Range) + 1 Then ClearProjectile Index, PlayerProjectile: Exit Sub
                ' left
                Case DIR_LEFT
                    .x = .x - 1
                    ' check if they reached maxrange
                    If .x = (GetPlayerX(Index) - .Range) - 1 Then ClearProjectile Index, PlayerProjectile: Exit Sub
            End Select
            .TravelTime = GetTickCount + .Speed
        End With
    End If

    x = TempPlayer(Index).ProjecTile(PlayerProjectile).x
    y = TempPlayer(Index).ProjecTile(PlayerProjectile).y

    ' check if left map
    If x > Map(GetPlayerMap(Index)).MaxX Or y > Map(GetPlayerMap(Index)).MaxY Or x < 0 Or y < 0 Then
        ClearProjectile Index, PlayerProjectile
        Exit Sub
    End If

    ' check if hit player
    For i = 1 To Player_HighIndex
        ' make sure they're actually playing
        If IsPlaying(i) Then
            ' check coordinates
            If x = Player(i).x And y = GetPlayerY(i) Then
                ' make sure it's not the attacker
                If Not x = Player(Index).x Or Not y = GetPlayerY(Index) Then
                    ' check if player can attack
                    If CanPlayerAttackPlayer(Index, i, False, True) = True Then
                        ' attack the player and kill the project tile
                        PlayerAttackPlayer Index, i, TempPlayer(Index).ProjecTile(PlayerProjectile).Damage
                        ClearProjectile Index, PlayerProjectile
                        Exit Sub
                    Else
                        ClearProjectile Index, PlayerProjectile
                        Exit Sub
                    End If
                End If
            End If
        End If
    Next

    ' check for npc hit
    For i = 1 To MAX_MAP_NPCS
        If x = MapNpc(GetPlayerMap(Index)).Npc(i).x And y = MapNpc(GetPlayerMap(Index)).Npc(i).y Then
            ' they're hit, remove it and deal that damage ;)
            If CanPlayerAttackNpc(Index, i, True) Then
                PlayerAttackNpc Index, i, TempPlayer(Index).ProjecTile(PlayerProjectile).Damage
                ClearProjectile Index, PlayerProjectile
                Exit Sub
            Else
                ClearProjectile Index, PlayerProjectile
                Exit Sub
            End If
        End If
    Next

    ' hit a block
    If Map(GetPlayerMap(Index)).Tile(x, y).Type = TILE_TYPE_BLOCKED Then
        ' hit a block, clear it.
        ClearProjectile Index, PlayerProjectile
        Exit Sub
    End If

End Sub

InitMessages after:

HandleDataSub(CPartyLeave) = GetAddress(AddressOf HandlePartyLeave)

insert:

HandleDataSub(CProjecTileAttack) = GetAddress(AddressOf HandleProjecTileAttack)

Modhandledata at the bottom insert:

Private Sub HandleProjecTileAttack(ByVal Index As Long, ByRef Data() As Byte, ByVal StartAddr As Long, ByVal ExtraVar As Long)
Dim curProjecTile As Long, i As Long, CurEquipment As Long

    ' prevent subscript
    If Index > MAX_PLAYERS Or Index < 1 Then Exit Sub

    ' get the players current equipment
    CurEquipment = GetPlayerEquipment(Index, Weapon)

    ' check if they've got equipment
    If CurEquipment < 1 Or CurEquipment > MAX_ITEMS Then Exit Sub

    ' set the curprojectile
    For i = 1 To MAX_PLAYER_PROJECTILES
        If TempPlayer(Index).ProjecTile(i).Pic = 0 Then
            ' just incase there is left over data
            ClearProjectile Index, i
            ' set the curprojtile
            curProjecTile = i
            Exit For
        End If
    Next

    ' check for subscript
    If curProjecTile < 1 Then Exit Sub

    ' populate the data in the player rec
    With TempPlayer(Index).ProjecTile(curProjecTile)
        .Damage = Item(CurEquipment).ProjecTile.Damage
        .Direction = GetPlayerDir(Index)
        .Pic = Item(CurEquipment).ProjecTile.Pic
        .Range = Item(CurEquipment).ProjecTile.Range
        .Speed = Item(CurEquipment).ProjecTile.Speed
        .x = GetPlayerX(Index)
        .y = GetPlayerY(Index)
    End With

    ' trololol, they have no more projectile space left
    If curProjecTile < 1 Or curProjecTile > MAX_PLAYER_PROJECTILES Then Exit Sub

    ' update the projectile on the map
    SendProjectileToMap Index, curProjecTile

End Sub

modServerTCP insert at the bottom:

Sub SendProjectileToMap(ByVal Index As Long, ByVal PlayerProjectile As Long)
Dim Buffer As clsBuffer

    Set Buffer = New clsBuffer
    Buffer.WriteLong SHandleProjectile
    Buffer.WriteLong PlayerProjectile
    Buffer.WriteLong Index
    With TempPlayer(Index).ProjecTile(PlayerProjectile)
        Buffer.WriteLong .Direction
        Buffer.WriteLong .Pic
        Buffer.WriteLong .Range
        Buffer.WriteLong .Damage
        Buffer.WriteLong .Speed
    End With
    SendDataToMap GetPlayerMap(Index), Buffer.ToArray()
    Set Buffer = Nothing
End Sub

modTypes, before PlayerRec starts, insert:

Public Type ProjectileRec
    TravelTime As Long
    Direction As Long
    x As Long
    y As Long
    Pic As Long
    Range As Long
    Damage As Long
    Speed As Long
End Type

Public type TempPlayerRec at the bottom before End Type insert:

ProjecTile(1 To MAX_PLAYER_PROJECTILES) As ProjectileRec

ItemRec, before endType, insert:

ProjecTile As ProjectileRec

Sub ServerLoop, find:

' Checks to update player vitals every 5 seconds - Can be tweaked

Above that, insert:

        For i = 1 To Player_HighIndex
            If IsPlaying(i) Then
                For x = 1 To MAX_PLAYER_PROJECTILES
                    If TempPlayer(i).ProjecTile(x).Pic > 0 Then
                        ' handle the projec tile
                        HandleProjecTile i, x
                    End If
                Next
            End If
        Next

In Public Enum ServerPackets before:

SMSG_COUNT

Insert:

SHandleProjectile

In Public Enum ClientPackets before:

CMSG_COUNT

Insert:

CProjecTileAttack

In Sub PlayerAttackNpc before:

Name = Trim$(Npc(npcNum).Name)

Insert:

If npcNum < 1 Then Exit Sub

Function CanPlayerAttackPlayer, replace the entire procedure with:

Function CanPlayerAttackPlayer(ByVal attacker As Long, ByVal victim As Long, Optional ByVal IsSpell As Boolean = False, Optional ByVal IsProjectile As Boolean = False) As Boolean

    If Not IsSpell And Not IsProjectile Then
        ' Check attack timer
        If GetPlayerEquipment(attacker, Weapon) > 0 Then
            If GetTickCount < TempPlayer(attacker).AttackTimer + Item(GetPlayerEquipment(attacker, Weapon)).Speed Then Exit Function
        Else
            If GetTickCount < TempPlayer(attacker).AttackTimer + 1000 Then Exit Function
        End If
    End If

    ' Check for subscript out of range
    If Not IsPlaying(victim) Then Exit Function

    ' Make sure they are on the same map
    If Not GetPlayerMap(attacker) = GetPlayerMap(victim) Then Exit Function

    ' Make sure we dont attack the player if they are switching maps
    If TempPlayer(victim).GettingMap = YES Then Exit Function

    If Not IsSpell And Not IsProjectile Then
        ' Check if at same coordinates
        Select Case GetPlayerDir(attacker)
            Case DIR_UP

                If Not ((GetPlayerY(victim) + 1 = GetPlayerY(attacker)) And (GetPlayerX(victim) = GetPlayerX(attacker))) Then Exit Function
            Case DIR_DOWN

                If Not ((GetPlayerY(victim) - 1 = GetPlayerY(attacker)) And (GetPlayerX(victim) = GetPlayerX(attacker))) Then Exit Function
            Case DIR_LEFT

                If Not ((GetPlayerY(victim) = GetPlayerY(attacker)) And (GetPlayerX(victim) + 1 = GetPlayerX(attacker))) Then Exit Function
            Case DIR_RIGHT

                If Not ((GetPlayerY(victim) = GetPlayerY(attacker)) And (GetPlayerX(victim) - 1 = GetPlayerX(attacker))) Then Exit Function
            Case Else
                Exit Function
        End Select
    End If

    ' Check if map is attackable
    If Not Map(GetPlayerMap(attacker)).Moral = MAP_MORAL_NONE Then
        If GetPlayerPK(victim) = NO Then
            Call PlayerMsg(attacker, "This is a safe zone!", BrightRed)
            Exit Function
        End If
    End If

    ' Make sure they have more then 0 hp
    If GetPlayerVital(victim, Vitals.HP) <= 0 Then Exit Function

    ' Check to make sure that they dont have access
    If GetPlayerAccess(attacker) > ADMIN_MONITOR Then
        Call PlayerMsg(attacker, "Admins cannot attack other players.", BrightBlue)
        Exit Function
    End If

    ' Check to make sure the victim isn't an admin
    If GetPlayerAccess(victim) > ADMIN_MONITOR Then
        Call PlayerMsg(attacker, "You cannot attack " & GetPlayerName(victim) & "!", BrightRed)
        Exit Function
    End If

    ' Make sure attacker is high enough level
    If GetPlayerLevel(attacker) < 10 Then
        Call PlayerMsg(attacker, "You are below level 10, you cannot attack another player yet!", BrightRed)
        Exit Function
    End If

    ' Make sure victim is high enough level
    If GetPlayerLevel(victim) < 10 Then
        Call PlayerMsg(attacker, GetPlayerName(victim) & " is below level 10, you cannot attack this player yet!", BrightRed)
        Exit Function
    End If

    CanPlayerAttackPlayer = True
End Function

FORM WORK*

In frmEditor_Item create a replica of the highlighted box:

!

name them:

scrlProjectileDamage
scrlProjectileSpeed
scrlProjectileRange
scrlProjectilePic
lblProjectileDamage
lblProjectileSpeed
lblProjectileRange
lblProjectilePic

In frmEditor_Item’s source code insert:

' projectile
Private Sub scrlProjectileDamage_Change()
    ' If debug mode, handle error then exit out
    If Options.Debug = 1 Then On Error GoTo errorhandler

    If EditorIndex = 0 Or EditorIndex > MAX_ITEMS Then Exit Sub
    lblProjectileDamage.Caption = "Damage: " & scrlProjectileDamage.Value
    Item(EditorIndex).ProjecTile.Damage = scrlProjectileDamage.Value

    ' Error handler
    Exit Sub
errorhandler:
    HandleError "scrlProjectilePic_Change", "frmEditor_Item", Err.Number, Err.Description, Err.Source, Err.HelpContext
    Err.Clear
    Exit Sub
End Sub

' projectile
Private Sub scrlProjectilePic_Change()
    ' If debug mode, handle error then exit out
    If Options.Debug = 1 Then On Error GoTo errorhandler

    If EditorIndex = 0 Or EditorIndex > MAX_ITEMS Then Exit Sub
    lblProjectilePiC.Caption = "Pic: " & scrlProjectilePic.Value
    Item(EditorIndex).ProjecTile.Pic = scrlProjectilePic.Value

    ' Error handler
    Exit Sub
errorhandler:
    HandleError "scrlProjectilePic_Change", "frmEditor_Item", Err.Number, Err.Description, Err.Source, Err.HelpContext
    Err.Clear
    Exit Sub
End Sub

' ProjecTile
Private Sub scrlProjectileRange_Change()
    ' If debug mode, handle error then exit out
    If Options.Debug = 1 Then On Error GoTo errorhandler

    If EditorIndex = 0 Or EditorIndex > MAX_ITEMS Then Exit Sub
    lblProjectileRange.Caption = "Range: " & scrlProjectileRange.Value
    Item(EditorIndex).ProjecTile.Range = scrlProjectileRange.Value

    ' Error handler
    Exit Sub
errorhandler:
    HandleError "scrlProjectileRange_Change", "frmEditor_Item", Err.Number, Err.Description, Err.Source, Err.HelpContext
    Err.Clear
    Exit Sub
End Sub

' projectile
Private Sub scrlProjectileSpeed_Change()
    ' If debug mode, handle error then exit out
    If Options.Debug = 1 Then On Error GoTo errorhandler

    If EditorIndex = 0 Or EditorIndex > MAX_ITEMS Then Exit Sub
    lblProjectileSpeed.Caption = "Speed: " & scrlProjectileSpeed.Value
    Item(EditorIndex).ProjecTile.Speed = scrlProjectileSpeed.Value

    ' Error handler
    Exit Sub
errorhandler:
    HandleError "scrlRarity_Change", "frmEditor_Item", Err.Number, Err.Description, Err.Source, Err.HelpContext
    Err.Clear
    Exit Sub
End Sub

Replace cmbType_click() code with:

Private Sub cmbType_Click()
    ' If debug mode, handle error then exit out
    If Options.Debug = 1 Then On Error GoTo errorhandler

    If EditorIndex = 0 Or EditorIndex > MAX_ITEMS Then Exit Sub

    If (cmbType.ListIndex >= ITEM_TYPE_WEAPON) And (cmbType.ListIndex <= ITEM_TYPE_SHIELD) Then
        fraEquipment.Visible = True
        'scrlDamage_Change
        If cmbType.ListIndex = ITEM_TYPE_WEAPON Then
            frame4.Visible = True
        End If
    Else
        fraEquipment.Visible = False
        frame4.Visible = False
    End If

    If cmbType.ListIndex = ITEM_TYPE_CONSUME Then
        fraVitals.Visible = True
        'scrlVitalMod_Change
    Else
        fraVitals.Visible = False
    End If

    If (cmbType.ListIndex = ITEM_TYPE_SPELL) Then
        fraSpell.Visible = True
    Else
        fraSpell.Visible = False
    End If

    Item(EditorIndex).Type = cmbType.ListIndex

    ' Error handler
    Exit Sub
errorhandler:
    HandleError "cmbType_Click", "frmEditor_Item", Err.Number, Err.Description, Err.Source, Err.HelpContext
    Err.Clear
    Exit Sub
End Sub

If you find any mistakes in this tutorial, or bugs/problems, let me know. I do know there was a little lag when attacking enemies, but it went away when I TV’d with jcsnider…weird AF. Anyways, probably will need a fix for bullets going through events that are not walk through, I’ll get to that sometime.

Also, most of this tutorial is the same exact as Wabbits for 2.0, it’s just I changed the blting and such for DX8, and also some other minor problems.

excelent! i’ll make some transparent projectiles and i’ll upload here for use 😉

note: when i compile the server i have a compile error and highlight this: PlayerAttackPlayer i’m looking if i do something wrong, but if you can check that it’ll be great too (my vb skills are not so good :P)

UPDATE: I added my Item editor form if you want to use is 🙂

@Eragon2589:

excelent! i’ll make some transparent projectiles and i’ll upload here for use 😉

note: when i compile the server i have a compile error and highlight this: PlayerAttackPlayer i’m looking if i do something wrong, but if you can check that it’ll be great too (my vb skills are not so good :P)

What does it highlight in PlayerAttackPlayer? Hover over it and take a screenshot for meh

in public sub handle projectile (mod GameLogic)

' check if player can attack
                    If CanPlayerAttackPlayer(Index, i, False, True) = True Then
                        ' attack the player and kill the project tile
                        PlayerAttackPlayer Index, i, TempPlayer(Index).ProjecTile(PlayerProjectile).Damage
                        ClearProjectile Index, PlayerProjectile
                        Exit Sub
                    Else

well, actually all the PlayerAttackPlayer shows that error too

P.S: in the other message i added an item editor form that you can use for this if you want, i’ll make the projectiles later

@Eragon2589:

in public sub handle projectile (mod GameLogic)

' check if player can attack
                    If CanPlayerAttackPlayer(Index, i, False, True) = True Then
                        ' attack the player and kill the project tile
                        PlayerAttackPlayer Index, i, TempPlayer(Index).ProjecTile(PlayerProjectile).Damage
                        ClearProjectile Index, PlayerProjectile
                        Exit Sub
                    Else

well, actually all the PlayerAttackPlayer shows that error too

P.S: in the other message i added an item editor form that you can use for this if you want, i’ll make the projectiles later

When does it show that error?

when i compile the server. I’m using a clean version of Nighty Eclipse

@Eragon2589:

when i compile the server. I’m using a clean version of Nighty Eclipse

delete all accounts and items first. I forgot to say that!

Edit: forgot to edit CheckAttack with events, fixed in OP.

ok, i’ll test later

thanks for the last info

Very good, functioned normally.

in the attachments are 4 arrows that you can use.

Forget i posted fixed the problem, 😃  😛

@Exxsamuari:

i had an error when compiling the client. and i have no idea why, i did everthing as told, ried twice amd same error

Control + F for “TempPlayerRec” and "TempPlayer(1 " (no quotes). Are they there?

figured it out i was missing Sub HandleProjectile, i feel stupid lol

i noticed something odd, when i have 2 games open an have a character shoot, the player shooting cannot see the arrow sometimes but the other character can see it fine. anyone aware of this?
also it seems the pic screen dosnt load actions done by the player fast enough, like droping and picking up items
*edit: I have been testing and it seems the lastplayer to login dosnt get the weird slow loading lag, but anyone before the last person to login gets the lag, i havent tested yet using multiple computers

Nice. I’ll try and add this and test it out. I was hoping some tutorials would get updated.

@Exxsamuari:

*edit: I have been testing and it seems the lastplayer to login dosnt get the weird slow loading lag, but anyone before the last person to login gets the lag, i havent tested yet using multiple computers

I tested the same way, and I see what you mean. I think it’s only the first player who gets lag, and usually it’s the server host. Like I said, this really fucks with your CPS for some reason. If you want to use this system I suggest you have a very nice server.

ya i have a amd 8 core 3.2ghz server with 16gb ram, used to use it with minecraft. ill keep testing out what might cause this weird lag

I have tried this 4+ times and keep getting a compiling error.
It highlights the Frame4… in the below code and also the Frame4 in the code following it.

! If frmEditor_Item.cmbType.ListIndex = ITEM_TYPE_WEAPON Then
    frmEditor_Item.Frame4.Visible = True
    With Item(EditorIndex).ProjecTile
          frmEditor_Item.scrlProjectileDamage.Value = .Damage
          frmEditor_Item.scrlProjectilePic.Value = .Pic
          frmEditor_Item.scrlProjectileRange.Value = .Range
          frmEditor_Item.scrlProjectileSpeed.Value = .Speed
    End With
End If

I am implementing  this in a clean Eclipse 3.0

Can anyone upload Eclipse 3.0 with this already inserted?

Thanks,
nneader

@nneader:

I have tried this 4+ times and keep getting a compiling error.
It highlights the Frame4… in the below code and also the Frame4 in the code following it.

! If frmEditor_Item.cmbType.ListIndex = ITEM_TYPE_WEAPON Then
    frmEditor_Item.Frame4.Visible = True
    With Item(EditorIndex).ProjecTile
          frmEditor_Item.scrlProjectileDamage.Value = .Damage
          frmEditor_Item.scrlProjectilePic.Value = .Pic
          frmEditor_Item.scrlProjectileRange.Value = .Range
          frmEditor_Item.scrlProjectileSpeed.Value = .Speed
    End With
End If

I am implementing  this in a clean Eclipse 3.0

Can anyone upload Eclipse 3.0 with this already inserted?

Thanks,
nneader

Is your frame called Frame4?

probably not.

I am guessing the “projectile” frame on the item form needs to be called, Frame 4? 😕

could you explain this to me…I am not sure what exactly I need to do. :embarrassed:

nneader

Log in to reply