Aldeia RPG

Gostaria de reagir a esta mensagem? Crie uma conta em poucos cliques ou inicie sessão para continuar.

Suporte no desenvolvimento de jogos


    [E.O 2.0] - Spell no Clique no mapa (v1.0)

    lucas100vzs
    lucas100vzs
    Iniciante
    Iniciante

    Mensagens : 34
    Créditos : 8

    [E.O 2.0] - Spell no Clique no mapa (v1.0) Empty [E.O 2.0] - Spell no Clique no mapa (v1.0)

    Mensagem por lucas100vzs Ter Jun 08, 2021 4:04 pm

    Bem, este tutorial, vai basicamente permitir que você conjure magias com clique no mapa, na posição do mouse, claro, com um alcance editado por você no editor. Sem mais delongas, vamos ao tutorial. 

    Primeiramente, abra a pasta do cliente, e em "data files > graphics" , adicione esta imagem, ou uma de tamanho similar a esta: 

    [E.O 2.0] - Spell no Clique no mapa (v1.0) Spellx10

    Nome: "spellxy.bmp"


    -CLIENT~SIDE-


    Agora vamos ao código, então abra seu Cliente.vbp , e no final de "ModGlobals" , adicione isto:

    Spoiler:

    Public MemSpell As Long


    Agora, em "ModGameLogic" , procure por:

    Spoiler:

    Public Sub CastSpell(ByVal spellslot As Long)

    E substitua esta linha por esta:

    Spoiler:

    Public Sub CastSpell(ByVal spellslot As Long, ByVal X As Long, ByVal Y As Long)

    Ainda nesta SUB "CastSpell" , abaixo de :

    Spoiler:

    If SpellCD(spellslot) > 0 Then
            AddText "Spell has not cooled down yet!", BrightRed
            Exit Sub
        End If

    Adicione isto: 

    Spoiler:

        If SpellBuffer > 0 Then Exit Sub
        
        If X < 0 Or X > Map.MaxX Then Exit Sub
        If Y < 0 Or Y > Map.MaxY Then Exit Sub
       

    Ainda nesta SUB "CastSpell" , procure por:

    Spoiler:

    If PlayerSpells(spellslot) > 0 Then
            If GetTickCount > Player(MyIndex).AttackTimer + 1000 Then
                If Player(MyIndex).Moving = 0 Then
                    Set Buffer = New clsBuffer
                    Buffer.WriteLong CCast
                    Buffer.WriteLong spellslot
                    SendData Buffer.ToArray()
                    Set Buffer = Nothing
                    SpellBuffer = spellslot
                    SpellBufferTimer = GetTickCount
                Else
                    Call AddText("Cannot cast while walking!", BrightRed)
                End If
            End If
        Else
            Call AddText("No spell here.", BrightRed)
        End If

    E substitua por:

    Spoiler:

    If PlayerSpells(spellslot) > 0 Then
            If GetTickCount > Player(MyIndex).AttackTimer + 1000 Then
                If Player(MyIndex).Moving = 0 Then
                    Set Buffer = New clsBuffer
                    Buffer.WriteLong CCast
                    Buffer.WriteLong spellslot
                    Buffer.WriteLong X
                    Buffer.WriteLong Y
                    SendData Buffer.ToArray()
                    Set Buffer = Nothing
                    SpellBuffer = spellslot
                    SpellBufferTimer = GetTickCount
                Else
                    Call AddText("Cannot cast while walking!", BrightRed)
                End If
            End If
        Else
            Call AddText("No spell here.", BrightRed)
        End If
    Então, procure por :

    Spoiler:

    ' render the decals
        For i = 1 To MAX_BYTE
            Call BltBlood(i)
        Next

    E acima disto, adicione isto: 

    Spoiler:

    'Draw current memSpell on mouse pointer
        If MemSpell > 0 And MemSpell < MAX_SPELLS Then
            If isInRange(Spell(MemSpell).Range, GetPlayerX(MyIndex), GetPlayerY(MyIndex), CurX, CurY) Then
                BltSpellXY CurX * 32, CurY * 32
            Else
                BltSpellXYOutRange CurX * 32, CurY * 32
            End If
        End If

    Agora, no final de "ModDirectX7" , adicione isto:

    Spoiler:

    Public Function isInRange(ByVal Range As Long, ByVal x1 As Long, ByVal y1 As Long, ByVal x2 As Long, ByVal y2 As Long) As Boolean
    Dim nVal As Long
        isInRange = False
        nVal = Sqr((x1 - x2) ^ 2 + (y1 - y2) ^ 2)
        If nVal <= Range Then isInRange = True
    End Function

    Public Sub BltSpellXY(ByVal X As Long, ByVal Y As Long)
    Dim sRECT As DxVBLib.RECT
    Dim width As Long, height As Long
        
        ' If debug mode, handle error then exit out
        If Options.Debug = 1 Then On Error GoTo errorhandler

        If DDS_SpellXY Is Nothing Then Exit Sub
        
        width = DDSD_SpellXY.lWidth / 2
        height = DDSD_SpellXY.lHeight

        With sRECT
            .top = 0
            .Bottom = height
            .Left = 0
            .Right = width
        End With
        
        X = X - ((width - 32) / 2)
        Y = Y - ((height - 32) / 2)
        
        X = ConvertMapX(X)
        Y = ConvertMapY(Y)
        
        ' clipping
        If Y < 0 Then
            With sRECT
                .top = .top - Y
            End With
            Y = 0
        End If

        If X < 0 Then
            With sRECT
                .Left = .Left - X
            End With
            X = 0
        End If

        If Y + height > DDSD_BackBuffer.lHeight Then
            sRECT.Bottom = sRECT.Bottom - (Y + height - DDSD_BackBuffer.lHeight)
        End If

        If X + width > DDSD_BackBuffer.lWidth Then
            sRECT.Right = sRECT.Right - (X + width - DDSD_BackBuffer.lWidth)
        End If
        ' /clipping
        
        Call Engine_BltFast(X, Y, DDS_SpellXY, sRECT, DDBLTFAST_WAIT Or DDBLTFAST_SRCCOLORKEY)
        
        ' Error handler
        Exit Sub
    errorhandler:
        HandleError "BltSpellXY", "modDirectDraw7", Err.Number, Err.Description, Err.Source, Err.HelpContext
        Err.Clear
        Exit Sub
    End Sub
    Public Sub BltSpellXYOutRange(ByVal X As Long, ByVal Y As Long)
    Dim sRECT As DxVBLib.RECT
    Dim width As Long, height As Long
        
        ' If debug mode, handle error then exit out
        If Options.Debug = 1 Then On Error GoTo errorhandler

        If DDS_SpellXY Is Nothing Then Exit Sub
        
        width = DDSD_SpellXY.lWidth / 2
        height = DDSD_SpellXY.lHeight

        With sRECT
            .top = 0
            .Bottom = height
            .Left = width
            .Right = .Left + width
        End With
        
        X = X - ((width - 32) / 2)
        Y = Y - ((height - 32) / 2)

        X = ConvertMapX(X)
        Y = ConvertMapY(Y)
        
        ' clipping
        If Y < 0 Then
            With sRECT
                .top = .top - Y
            End With
            Y = 0
        End If

        If X < 0 Then
            With sRECT
                .Left = .Left - X
            End With
            X = 0
        End If

        If Y + height > DDSD_BackBuffer.lHeight Then
            sRECT.Bottom = sRECT.Bottom - (Y + height - DDSD_BackBuffer.lHeight)
        End If

        If X + width > DDSD_BackBuffer.lWidth Then
            sRECT.Right = sRECT.Right - (X + width - DDSD_BackBuffer.lWidth)
        End If
        ' /clipping
        
        Call Engine_BltFast(X, Y, DDS_SpellXY, sRECT, DDBLTFAST_WAIT Or DDBLTFAST_SRCCOLORKEY)
        
        ' Error handler
        Exit Sub
    errorhandler:
        HandleError "BltSpellXYOutRange", "modDirectDraw7", Err.Number, Err.Description, Err.Source, Err.HelpContext
        Err.Clear
        Exit Sub
    End Sub


    Agora procure pela SUB "picScreen_MouseDown" , e abaixo de :

    Spoiler:

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

    Adicione isto:

    Spoiler:

    'Right mouse click, cancel
        If Button = vbRightButton Then
            MemSpell = 0
        End If
        
        'Check for mouse spell
        If MemSpell > 0 Then
            CastSpell MemSpell, CurX, CurY
            MemSpell = 0
        End If

    Agora procure pela SUB "picSpells_DblClick()" , e troque isto:

    Spoiler:

    If spellnum <> 0 Then
            Call CastSpell(spellnum)
            Exit Sub
        End If

    Por isto:

    Spoiler:

    If spellnum <> 0 Then
            If Spell(spellnum).IsMouse = True Then
                MemSpell = spellnum
            Else
                Call CastSpell(spellnum, 0, 0)
            End If
            Exit Sub
        End If

    Agora procure pela SUB "SendHotbarUse(ByVal Slot As Long)" , e troque essa parte:

    Spoiler:

    ' check if spell
        If Hotbar(Slot).sType = 2 Then ' spell
            Call CastSpell(PlayerSpells(Hotbar(Slot).Slot))
            Exit Sub
        End If

    Por isto:

    Spoiler:

    ' check if spell
        If Hotbar(Slot).sType = 2 Then ' spell
            For X = 1 To MAX_PLAYER_SPELLS
                ' is the spell matching the hotbar?
                If PlayerSpells(X) = Hotbar(Slot).Slot Then
                    If Spell(X).IsMouse Then
                        MemSpell = X
                    Else
                        ' found it, cast it
                        CastSpell X, 0, 0
                    End If
                    Exit Sub
                End If
            Next
            ' can't find the spell, exit out
            Exit Sub
        End If


    Agora, em "ModTypes" , no tipo "Private Type SpellRec" , acima de "End Type" , adicione isto:

    Spoiler:

    IsMouse As Boolean

    Agora, em "ModGameEditors" , na SUB "SpellEditorInit()" , procure por:

    Spoiler:

    .scrlStun.Value = Spell(EditorIndex).StunDuration

    E abaixo disto, adicione isto:

    Spoiler:

    If Spell(EditorIndex).IsMouse Then
                .chkSpellMouse.Value = 1
            Else
                .chkSpellMouse.Value = 0
            End If

    Pra finalizar o cliente, abra seu Editor de Magias de "forms" , e adicione: 

    1x CheckBox 
    Caption: Is mouse-pointer
    Name: chkSpellMouse 

    Então, dê duplo clique para abrir o código do "CheckBox" , e adicione isto dentro: 

    Spoiler:

    Spell(EditorIndex).IsMouse = chkSpellMouse.Value


    -SERVER~SIDE-


    Agora, abra seu "server.vbp" , e em "ModTypes" , no tipo "Private Type SpellRec" , acima de "End Type" , adicione isto:

    Spoiler:

    IsMouse As Boolean

    Ainda em "ModTypes" , no tipo "Public Type TempPlayerRec" , acima de "End Type" , adicione isto:

    Spoiler:

    mouseX As Long
    mouseY As Long

    Agora, em "ModServerLoop", na "Sub ServerLoop()" procure por isto: 

    Spoiler:

    If GetTickCount > TempPlayer(i).spellBuffer.Timer + (Spell(Player(i).Spell(TempPlayer(i).spellBuffer.Spell)).CastTime * 1000) Then
                                    CastSpell i, TempPlayer(i).spellBuffer.Spell, TempPlayer(i).spellBuffer.Target, TempPlayer(i).spellBuffer.tType
                                TempPlayer(i).spellBuffer.Spell = 0
                                TempPlayer(i).spellBuffer.Timer = 0
                                TempPlayer(i).spellBuffer.Target = 0
                                TempPlayer(i).spellBuffer.tType = 0
                            End If

    E substitua por isto:


    Spoiler:

    If GetTickCount > TempPlayer(i).spellBuffer.Timer + (Spell(Player(i).Spell(TempPlayer(i).spellBuffer.Spell)).CastTime * 1000) Then
                                If Spell(TempPlayer(i).spellBuffer.Spell).IsMouse Then
                                    CastMouseSpell i, TempPlayer(i).spellBuffer.Spell, TempPlayer(i).spellBuffer.Target, TempPlayer(i).spellBuffer.tType
                                Else
                                    CastSpell i, TempPlayer(i).spellBuffer.Spell, TempPlayer(i).spellBuffer.Target, TempPlayer(i).spellBuffer.tType
                                End If
                                TempPlayer(i).spellBuffer.Spell = 0
                                TempPlayer(i).spellBuffer.Timer = 0
                                TempPlayer(i).spellBuffer.Target = 0
                                TempPlayer(i).spellBuffer.tType = 0
                            End If



    Agora, em "ModHandleData" , substitua sua "Sub HandleCast" , por esta: 



    Spoiler:

    Sub HandleCast(ByVal Index As Long, ByRef Data() As Byte, ByVal StartAddr As Long, ByVal ExtraVar As Long)
        Dim n As Long
        Dim X As Long, Y As Long
        Dim Buffer As clsBuffer
        
        If Index <= 0 Or Index > MAX_PLAYERS Then Exit Sub
        If TempPlayer(Index).InGame = False Then Exit Sub
        
        Set Buffer = New clsBuffer
        Buffer.WriteBytes Data()
        ' Spell slot
        n = Buffer.ReadLong 'CLng(Parse(1))
        X = Buffer.ReadLong
        Y = Buffer.ReadLong
        Set Buffer = Nothing
        
        If n <= 0 Or n > MAX_PLAYER_SPELLS Then Exit Sub
        
        'Check for validate coordinates
        If X < 0 Or X > Map(GetPlayerMap(Index)).MaxX Then Exit Sub
        If Y < 0 Or Y > Map(GetPlayerMap(Index)).MaxY Then Exit Sub
        
        'Check if is a mouse spell type
        If Spell(n).IsMouse = True Then
            TempPlayer(Index).mouseX = X
            TempPlayer(Index).mouseY = Y
            
            'Set the spell and coordinates
            Call BufferSpell(Index, n)
            
        Else
            TempPlayer(Index).mouseX = 0
            TempPlayer(Index).mouseY = 0
            
            'Even if client send us coordinates without right spell, we zero it
            Call BufferSpell(Index, n)
            
        End If
        
    End Sub

    Ainda em "ModHandleData" , na "Sub HandleHotbarUse", substitua isto:


    Spoiler:

    Case 2 ' spell
                For i = 1 To MAX_PLAYER_SPELLS
                    If Player(Index).Spell(i) > 0 Then
                        If Player(Index).Spell(i) = Player(Index).Hotbar(Slot).Slot Then
                            BufferSpell Index, i
                            Exit Sub
                        End If
                    End If
                Next



    Por isto:


    Spoiler:

    Case 2 ' spell
                For i = 1 To MAX_PLAYER_SPELLS
                    If Player(Index).Spell(i) > 0 Then
                        If Player(Index).Spell(i) = Player(Index).Hotbar(Slot).Slot Then
                            If Spell(Player(Index).Spell(i)).IsMouse Then
                                PlayerMsg Index, "Click spell...", White
                            Else
                                BufferSpell Index, i
                            End If
                            Exit Sub
                        End If
                    End If
                Next


    Agora, em "ModCombat" , na "Public Sub BufferSpell" , abaixo de :

    Spoiler:

    Dim TargetType As Byte
        Dim Target As Long

    Adicione isto:

    Spoiler:

    Dim X As Long, Y As Long


    E substitua isto:


    Spoiler:
    HasBuffered = False


    Por isso: 

    Spoiler:

    X = TempPlayer(Index).mouseX
        Y = TempPlayer(Index).mouseY
        HasBuffered = False
        
        If Spell(SpellNum).IsMouse Then
            
            If X < 0 Or X > Map(GetPlayerMap(Index)).MaxX Then
                    PlayerMsg Index, "X inválido", White
                Exit Sub
            End If
            
            If Y < 0 Or Y > Map(GetPlayerMap(Index)).MaxY Then
                    PlayerMsg Index, "Y inválido", White
                Exit Sub
            End If
            
            If Not isInRange(Range, GetPlayerX(Index), GetPlayerY(Index), X, Y) Then
                PlayerMsg Index, "Spell click too far from range:" & Range, BrightRed
            Else
                HasBuffered = True
            End If
        
        Else

    E acima disto: 

    Spoiler:

    If HasBuffered Then
            SendAnimation MapNum, Spell(SpellNum).CastAnim, 0, 0, TARGET_TYPE_PLAYER, Index
            SendActionMsg MapNum, "Casting " & Trim$(Spell(SpellNum).Name) & "!", BrightRed, ACTIONMSG_SCROLL, GetPlayerX(Index) * 32, GetPlayerY(Index) * 32
            TempPlayer(Index).spellBuffer.Spell = spellslot
            TempPlayer(Index).spellBuffer.Timer = GetTickCount
            TempPlayer(Index).spellBuffer.Target = TempPlayer(Index).Target
            TempPlayer(Index).spellBuffer.tType = TempPlayer(Index).TargetType
            Exit Sub
        Else
            SendClearSpellBuffer Index
        End If

    Adicione isto:

    Spoiler:

    End If

    Agora, no final de "ModCombat" , adicione isto: 

    Spoiler:

    Public Sub CastMouseSpell(ByVal Index As Long, ByVal spellslot As Long, ByVal Target As Long, ByVal TargetType As Byte)
        Dim SpellNum As Long
        Dim MPCost As Long
        Dim LevelReq As Long
        Dim MapNum As Long
        Dim Vital As Long
        Dim DidCast As Boolean
        Dim ClassReq As Long
        Dim AccessReq As Long
        Dim i As Long
        Dim AoE As Long
        Dim Range As Long
        Dim VitalType As Byte
        Dim increment As Boolean
        Dim X As Long, Y As Long
        Dim mX As Long, mY As Long
        
        Dim Buffer As clsBuffer
        Dim SpellCastType As Long
        
        DidCast = False

        ' Prevent subscript out of range
        If spellslot <= 0 Or spellslot > MAX_PLAYER_SPELLS Then Exit Sub

        SpellNum = GetPlayerSpell(Index, spellslot)
        MapNum = GetPlayerMap(Index)

        ' Make sure player has the spell
        If Not HasSpell(Index, SpellNum) Then Exit Sub

        MPCost = Spell(SpellNum).MPCost

        ' Check if they have enough MP
        If GetPlayerVital(Index, Vitals.MP) < MPCost Then
            Call PlayerMsg(Index, "Not enough mana!", BrightRed)
            Exit Sub
        End If
        
        LevelReq = Spell(SpellNum).LevelReq

        ' Make sure they are the right level
        If LevelReq > GetPlayerLevel(Index) Then
            Call PlayerMsg(Index, "You must be level " & LevelReq & " to cast this spell.", BrightRed)
            Exit Sub
        End If
        
        AccessReq = Spell(SpellNum).AccessReq
        
        ' make sure they have the right access
        If AccessReq > GetPlayerAccess(Index) Then
            Call PlayerMsg(Index, "You must be an administrator to cast this spell.", BrightRed)
            Exit Sub
        End If
        
        ClassReq = Spell(SpellNum).ClassReq
        
        ' make sure the classreq > 0
        If ClassReq > 0 Then ' 0 = no req
            If ClassReq <> GetPlayerClass(Index) Then
                Call PlayerMsg(Index, "Only " & CheckGrammar(Trim$(Class(ClassReq).Name)) & " can use this spell.", BrightRed)
                Exit Sub
            End If
        End If
        
        
        
        ' find out what kind of spell it is! self cast, target or AOE
        If Spell(SpellNum).Range > 0 Then
            ' ranged attack, single target or aoe?
            If Not Spell(SpellNum).IsAoE Then
                SpellCastType = 2 ' targetted
            Else
                SpellCastType = 3 ' targetted aoe
            End If
        Else
            If Not Spell(SpellNum).IsAoE Then
                SpellCastType = 0 ' self-cast
            Else
                SpellCastType = 1 ' self-cast AoE
            End If
        End If
        
        ' set the vital
        Vital = Spell(SpellNum).Vital
        AoE = Spell(SpellNum).AoE
        Range = Spell(SpellNum).Range
        mX = TempPlayer(Index).mouseX
        mY = TempPlayer(Index).mouseY
        
        If Spell(SpellNum).IsMouse = True Then
            
            If mX < 0 Or mX > Map(GetPlayerMap(Index)).MaxX Then
                    PlayerMsg Index, "X inválido", White
                Exit Sub
            End If
            
            If mY < 0 Or mY > Map(GetPlayerMap(Index)).MaxY Then
                    PlayerMsg Index, "Y inválido", White
                Exit Sub
            End If
            
            
            'Check for range in mouse
            If Not isInRange(Range, GetPlayerX(Index), GetPlayerY(Index), mX, mY) Then
                PlayerMsg Index, "Spell click too far from range:" & Range, BrightRed
                
            Else
            
                
        Select Case SpellCastType
            Case 0 ' self-cast target
            
                Select Case Spell(SpellNum).Type
                    Case SPELL_TYPE_HEALHP
                        SpellPlayer_Effect Vitals.HP, True, Index, Vital, SpellNum
                        DidCast = True
                    Case SPELL_TYPE_HEALMP
                        SpellPlayer_Effect Vitals.MP, True, Index, Vital, SpellNum
                        DidCast = True
                    Case SPELL_TYPE_WARP
                        SendAnimation MapNum, Spell(SpellNum).SpellAnim, 0, 0, TARGET_TYPE_PLAYER, Index
                        PlayerWarp Index, Spell(SpellNum).Map, Spell(SpellNum).X, Spell(SpellNum).Y
                        SendAnimation GetPlayerMap(Index), Spell(SpellNum).SpellAnim, 0, 0, TARGET_TYPE_PLAYER, Index
                        DidCast = True
                End Select
                
            Case 1, 3 ' self-cast AOE & targetted AOE
                   
                Select Case Spell(SpellNum).Type
                    Case SPELL_TYPE_DAMAGEHP
                        DidCast = True
                        
                        'Check Hit
                        SpellOnCoordinate Index, GetPlayerMap(Index), SpellNum, mX, mY, Vital
                        
                    Case SPELL_TYPE_HEALHP, SPELL_TYPE_HEALMP, SPELL_TYPE_DAMAGEMP
                        If Spell(SpellNum).Type = SPELL_TYPE_HEALHP Then
                            VitalType = Vitals.HP
                            increment = True
                        ElseIf Spell(SpellNum).Type = SPELL_TYPE_HEALMP Then
                            VitalType = Vitals.MP
                            increment = True
                        ElseIf Spell(SpellNum).Type = SPELL_TYPE_DAMAGEMP Then
                            VitalType = Vitals.MP
                            increment = False
                        End If
                        
                        DidCast = True
                        
                        For i = 1 To Player_HighIndex
                            If IsPlaying(i) Then
                                If GetPlayerMap(i) = GetPlayerMap(Index) Then
                                    If isInRange(AoE, mX, mY, GetPlayerX(i), GetPlayerY(i)) Then
                                        SpellPlayer_Effect VitalType, increment, i, Vital, SpellNum
                                    End If
                                End If
                            End If
                        Next
                        For i = 1 To MAX_MAP_NPCS
                            If MapNpc(MapNum).Npc(i).Num > 0 Then
                                If MapNpc(MapNum).Npc(i).Vital(HP) > 0 Then
                                    If isInRange(AoE, mX, mY, MapNpc(MapNum).Npc(i).X, MapNpc(MapNum).Npc(i).Y) Then
                                        SpellNpc_Effect VitalType, increment, i, Vital, SpellNum, MapNum
                                    End If
                                End If
                            End If
                        Next
                        
                End Select
                
                
                
            Case 2 ' targetted
                'It's clicked, we don't need target :)
                
            End Select
            
            End If
        
        Else 'is not a mouse-type one
            PlayerMsg Index, "This is not a mouse spell", Red
            SendClearSpellBuffer Index
            Exit Sub
        End If
        
        If DidCast Then
            Call SetPlayerVital(Index, Vitals.MP, GetPlayerVital(Index, Vitals.MP) - MPCost)
            Call SendVital(Index, Vitals.MP)
            ' send vitals to party if in one
            If TempPlayer(Index).inParty > 0 Then SendPartyVitals TempPlayer(Index).inParty, Index
            
            TempPlayer(Index).SpellCD(spellslot) = GetTickCount + (Spell(SpellNum).CDTime * 1000)
            Call SendCooldown(Index, spellslot)
            SendActionMsg MapNum, Trim$(Spell(SpellNum).Name) & "!", BrightRed, ACTIONMSG_SCROLL, GetPlayerX(Index) * 32, GetPlayerY(Index) * 32
        End If
    End Sub
    Public Sub SpellOnCoordinate(ByVal Index As Long, ByVal MapNum As Long, ByVal SpellNum As Long, ByVal X As Long, ByVal Y As Long, ByVal Damage As Long)
    Dim Area As Long, Range As Long
    Dim i As Long
        
        
        If Index <= 0 Or Index > MAX_PLAYERS Then Exit Sub
        If MapNum <= 0 Or MapNum > MAX_MAPS Then Exit Sub
            
        If X < 0 Or X > Map(MapNum).MaxX Then Exit Sub
        If Y < 0 Or Y > Map(MapNum).MaxY Then Exit Sub
        
        If SpellNum <= 0 Or SpellNum > MAX_SPELLS Then Exit Sub
        
        Area = Spell(SpellNum).AoE
        Range = Spell(SpellNum).Range
        
        'Check if we want to hit in area
        If Area > 0 Then
        
        '//AREA//
        
        For i = 1 To MAX_PLAYERS
            If IsPlaying(i) And Index <> i And GetPlayerMap(i) = MapNum Then
                If isInRange(Range, X, Y, GetPlayerX(i), GetPlayerY(i)) Then
                    PlayerDamagePlayer Index, i, Damage
                End If
            End If
        Next
        For i = 1 To MAX_MAP_NPCS
            If MapNpc(MapNum).Npc(i).Num > 0 And GetPlayerMap(Index) = MapNum Then
                If isInRange(Range, X, Y, MapNpc(MapNum).Npc(i).X, MapNpc(MapNum).Npc(i).Y) Then
                    PlayerDamageNpc Index, MapNum, i, Damage
                End If
            End If
        Next
        
        
        Else
        
        
        '//ON TILE X,Y ONLY//
        
        For i = 1 To MAX_PLAYERS
            If IsPlaying(i) And Index <> i Then
                If GetPlayerMap(i) = MapNum And GetPlayerX(i) = X And GetPlayerY(i) = Y Then
                    PlayerDamagePlayer Index, i, Damage
                End If
            End If
        Next
        For i = 1 To MAX_MAP_NPCS
            If MapNpc(MapNum).Npc(i).Num > 0 Then
                If GetPlayerMap(Index) = MapNum And MapNpc(MapNum).Npc(i).X = X And MapNpc(MapNum).Npc(i).Y = Y Then
                    PlayerDamageNpc Index, MapNum, i, Damage
                End If
            End If
        Next
        
        
        End If
        
        
        If Spell(SpellNum).SpellAnim > 0 Then
            SendAnimation MapNum, Spell(SpellNum).SpellAnim, X, Y
        End If
        
    End Sub
    Public Sub PlayerDamagePlayer(ByVal Attacker As Long, ByVal Victim As Long, ByVal Damage As Long)

           If Attacker <= 0 Or Attacker > MAX_PLAYERS Then Exit Sub
           If Victim <= 0 Or Victim > MAX_PLAYERS Then Exit Sub
            
            
        If Damage >= GetPlayerVital(Victim, Vitals.HP) Then
            
            OnDeath Victim
            
        Else
            
            SendActionMsg GetPlayerMap(Victim), "-" & Damage, BrightRed, 1, (GetPlayerX(Victim) * 32), (GetPlayerY(Victim) * 32)
            SendBlood GetPlayerMap(Victim), GetPlayerX(Victim), GetPlayerY(Victim)
            
            Call SetPlayerVital(Victim, Vitals.HP, GetPlayerVital(Victim, Vitals.HP) - Damage)
            Call SendVital(Attacker, Vitals.HP)
        End If

    End Sub

    Public Sub PlayerDamageNpc(ByVal Index As Long, ByVal MapNum As Long, ByVal MapNpcNum As Long, ByVal Damage As Long)
    Dim Exp As Long
    Dim NpcNum As Long
    Dim d As Long
    Dim n As Long
    Dim i As Long
    Dim Buffer As clsBuffer

        If Index <= 0 Or Index > MAX_PLAYERS Then Exit Sub
        If MapNpcNum <= 0 Or MapNpcNum > MAX_MAP_NPCS Then Exit Sub
        If MapNum <= 0 Or MapNum > MAX_MAPS Then Exit Sub
        
        NpcNum = Map(MapNum).Npc(MapNpcNum)
        
        If NpcNum <= 0 Or NpcNum > MAX_NPCS Then Exit Sub
            
        If Damage >= MapNpc(MapNum).Npc(MapNpcNum).Vital(Vitals.HP) Then
            
            SendActionMsg MapNum, "-" & MapNpc(MapNum).Npc(MapNpcNum).Vital(Vitals.HP), BrightRed, 1, (MapNpc(MapNum).Npc(MapNpcNum).X * 32), (MapNpc(MapNum).Npc(MapNpcNum).Y * 32)
            SendBlood MapNum, MapNpc(MapNum).Npc(MapNpcNum).X, MapNpc(MapNum).Npc(MapNpcNum).Y

            ' Calculate exp to give attacker
            Exp = Npc(NpcNum).Exp

            ' Make sure we dont get less then 0
            If Exp < 0 Then
                Exp = 1
            End If

            ' in party?
            If TempPlayer(Index).inParty > 0 Then
                ' pass through party sharing function
                Party_ShareExp TempPlayer(Index).inParty, Exp, Index
            Else
                ' no party - keep exp for self
                GivePlayerEXP Index, Exp
            End If
            
            
            'Drop the goods if they get it
            n = Int(Rnd * Npc(npcNum).DropChance) + 1

            If n = 1 Then
                Call SpawnItem(Npc(npcNum).DropItem, Npc(npcNum).DropItemValue, MapNum, MapNpc(MapNum).Npc(MapNpcNum).x, MapNpc(MapNum).Npc(MapNpcNum).y)
            End If

            ' Now set HP to 0 so we know to actually kill them in the server loop (this prevents subscript out of range)
            MapNpc(MapNum).Npc(MapNpcNum).Num = 0
            MapNpc(MapNum).Npc(MapNpcNum).SpawnWait = GetTickCount
            MapNpc(MapNum).Npc(MapNpcNum).Vital(Vitals.HP) = 0
            
            ' clear DoTs and HoTs
            For i = 1 To MAX_DOTS
                With MapNpc(MapNum).Npc(MapNpcNum).DoT(i)
                    .Spell = 0
                    .Timer = 0
                    .Caster = 0
                    .StartTime = 0
                    .Used = False
                End With
                
                With MapNpc(MapNum).Npc(MapNpcNum).HoT(i)
                    .Spell = 0
                    .Timer = 0
                    .Caster = 0
                    .StartTime = 0
                    .Used = False
                End With
            Next
            
            ' send death to the map
            Set Buffer = New clsBuffer
            Buffer.WriteLong SNpcDead
            Buffer.WriteLong MapNpcNum
            SendDataToMap MapNum, Buffer.ToArray()
            Set Buffer = Nothing
            
            'Loop through entire map and purge NPC from targets
            For i = 1 To Player_HighIndex
                If IsPlaying(i) And IsConnected(i) Then
                    If Player(i).Map = MapNum Then
                        If TempPlayer(i).TargetType = TARGET_TYPE_NPC Then
                            If TempPlayer(i).Target = MapNpcNum Then
                                TempPlayer(i).Target = 0
                                TempPlayer(i).TargetType = TARGET_TYPE_NONE
                                SendTarget i
                            End If
                        End If
                    End If
                End If
            Next
            
            
        Else
            ' NPC not dead, just do the damage
            MapNpc(MapNum).Npc(MapNpcNum).Vital(Vitals.HP) = MapNpc(MapNum).Npc(MapNpcNum).Vital(Vitals.HP) - Damage

            ' Check for a weapon and say damage
            SendActionMsg MapNum, "-" & Damage, BrightRed, 1, (MapNpc(MapNum).Npc(MapNpcNum).X * 32), (MapNpc(MapNum).Npc(MapNpcNum).Y * 32)
            SendBlood MapNum, MapNpc(MapNum).Npc(MapNpcNum).X, MapNpc(MapNum).Npc(MapNpcNum).Y

            ' Set the NPC target to the player
            MapNpc(MapNum).Npc(MapNpcNum).TargetType = 1 ' player
            MapNpc(MapNum).Npc(MapNpcNum).Target = Index

            ' Now check for guard ai and if so have all onmap guards come after'm
            If Npc(MapNpc(MapNum).Npc(MapNpcNum).Num).Behaviour = NPC_BEHAVIOUR_GUARD Then
                For i = 1 To MAX_MAP_NPCS
                    If MapNpc(MapNum).Npc(i).Num = MapNpc(MapNum).Npc(MapNpcNum).Num Then
                        MapNpc(MapNum).Npc(i).Target = Index
                        MapNpc(MapNum).Npc(i).TargetType = 1 ' player
                    End If
                Next
            End If
            
            ' set the regen timer
            MapNpc(MapNum).Npc(MapNpcNum).stopRegen = True
            MapNpc(MapNum).Npc(MapNpcNum).stopRegenTimer = GetTickCount
            
            
            SendMapNpcVitals MapNum, MapNpcNum
            
        End If

    End Sub


    E pronto, agora você faz magias com um clique!  Indignity

    Pontos a considerar: 
    -Por mais que esteja em 1.0 , não foram encontrados bugs;
    -Pra conforto do jogador, lembre de impedir no cliente "BltTargetHover" e captura de alvos, quando estiver com "MemSpell" , evita que a imagem de alvo mostre quando você não quer; 
    - Funcional com as magias da versão 2.0 do E.O (Dano HP/MP e Cura HP/MP); 
    - Explicando valores do editor: Range = Distância que o mouse pode se afastar do jogador e AOE = Área do efeito e da animação onde for clicado; 
    - Cliente: X = Pode castar , X = Não pode castar
    - Foi bem extenso, então qualquer erro, 99% de chance de ser algo que esqueci, então só perguntar, que atualizo o tópico quando disponível; 


    ~Créditos~
    Eu - lucas100vzs/Kotol

    WillMaiaBR e Sonart gostam desta mensagem


      Data/hora atual: Sex Jun 18, 2021 12:07 pm