Aldeia RPG

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

Suporte ao desenvolvimento de jogos


    [E.O 2.0] - Sistema de PVP

    Kotol
    Kotol
    Moderador Local
    Moderador Local


    Mensagens : 77
    Créditos : 17

    [E.O 2.0] - Sistema de PVP Empty [E.O 2.0] - Sistema de PVP

    Mensagem por Kotol Qui Abr 27, 2023 1:56 am

    O sistema de luta é entra dois jogadores. Infelizmente (por motivos de sono) não conta com um sistema de 'tempo de aceitar/recusar' , mas inclui muita coisa. (Talvez eu coloque um "Add-On" depois...)
    Sistema PVP:
    - Envio de convite em uma janela diferente da de "Troca";
    - Checagem se o jogador está em uma arena, se possui convite, se está online ou se a si mesmo;
    - Variável de posição do jogador salva antes de entrar na arena e após o resultado, retornam às suas posições;
    - Jogador desloga:
    *Se estiver em arena = perde a arena, retorna para sua posição, o desafiado é teleportado de volta e limpo;
    *Se tem um convite = limpa a si e quem estava desafiando com um convite em espera, além de fechar a janela;
    - Desafio por Target, checando se é válido;

    Agora, vamos ao tutorial que tem um pouco de coisinhas.

    CLIENT~SIDE


    Primeiramente abra seu "Client.vbp" e crie na "FrmMain" : 

    1x CommandButton -> Name: cmdArena / Caption: Desafiar
    1x PictureBox -> Name: PicArena / Visible: False

    DENTRO da PicArena crie:
    1x Label -> Name: lblArenaDesc
    1x Label -> Name: lblArenaAccept
    1x Label -> Name: lblArenaDecline

    Agora, dentro do "cmdArena", adicione isto:
    Código:
    If myTargetType = TARGET_TYPE_PLAYER And myTarget <> MyIndex Then
            SendArenaCommand 0, myTarget
            ' play sound
            PlaySound Sound_ButtonClick
        Else
            AddText "Alvo de batalha inválido", BrightRed
        End If


    Agora, dentro da "lblArenaAccept" adicione isto:
    Código:
    SendArenaCommand 1, 0
        picArena.Visible = False


    Agora, dentro da "lblArenaDecline" adicione isto:
    Código:
    SendArenaCommand 2, 0
        picArena.Visible = False

    Agora, em "ModClientTCP" , no final adicione esta sub:
    Código:
    Sub SendArenaCommand(ByVal CommandNum As Long, ByVal curTarget As Long)
    Dim Buffer As clsBuffer

        ' If debug mode, handle error then exit out
        If Options.Debug = 1 Then On Error GoTo errorhandler
        
        Set Buffer = New clsBuffer
        Buffer.WriteLong CArena
        Buffer.WriteLong CommandNum
        Buffer.WriteLong curTarget
        SendData Buffer.ToArray()
        Set Buffer = Nothing
        
        ' Error handler
        Exit Sub
    errorhandler:
        HandleError "SendArenaCommand", "modClientTCP", Err.Number, Err.Description, Err.Source, Err.HelpContext
        Err.Clear
        Exit Sub
    End Sub

    Agora, em "ModEnumerations", na "Public Enum ServerPackets" logo abaixo ANTES de:
    Código:
    ' Make sure SMSG_COUNT is below everything else
        SMSG_COUNT
    End Enum

    Declare esta enumeração:
    Código:
    SArena

    Ainda em "ModEnumerations", na "Public Enum ClientPackets" logo abaixo ANTES de:
    Código:
    ' Make sure CMSG_COUNT is below everything else
        CMSG_COUNT
    End Enum

    Declare esta enumeração:
    Código:
    CArena

    Agora, em "ModHandleData", na "Public Sub InitMessages()", depois de:
    Código:
    HandleDataSub(SPartyVitals) = GetAddress(AddressOf HandlePartyVitals)

    Adicione isto:
    Código:
    HandleDataSub(SArena) = GetAddress(AddressOf HandleArena)

    Ainda em "ModHandleData" , no final adicione isto:
    Código:
    Private Sub HandleArena(ByVal Index As Long, ByRef Data() As Byte, ByVal StartAddR As Long, ByVal ExtraVar As Long)
        Dim Buffer As clsBuffer
        Dim Name As String, CommandNum As Long

        Set Buffer = New clsBuffer
        Buffer.WriteBytes Data()
        Name = Buffer.ReadString
        CommandNum = Buffer.ReadLong
        Set Buffer = Nothing
        
        Select Case CommandNum
            Case 0
                With frmMain
                    .picArena.Visible = True
                    .lblArenaDesc = "O jogador " & Name & " te desafiou para uma luta. Deseja aceitar?"
                End With
            Case 1
                frmMain.picArena.Visible = False
        End Select
        
        
    End Sub

    E pronto, cliente completo! Vamos agora ao servidor!

    SERVER~SIDE


    Abra seu "Server.Vbp" e em "ModHandleData" na "Public Sub InitMessages()" , após:
    Código:
    HandleDataSub(CPartyLeave) = GetAddress(AddressOf HandlePartyLeave)

    Adicione isto:
    Código:
    HandleDataSub(CArena) = GetAddress(AddressOf HandleArena)

    Ainda em "ModHandleData", ao final adicione esta sub:
    Código:
    Sub HandleArena(ByVal Index As Long, ByRef Data() As Byte, ByVal StartAddr As Long, ByVal ExtraVar As Long)
    Dim n As Long, i As Long
    Dim Buffer As clsBuffer
    Dim QuestSize As Long
    Dim QuestData() As Byte

        Set Buffer = New clsBuffer
        Buffer.WriteBytes Data()
        i = Buffer.ReadLong 'ArenaCommand
        n = Buffer.ReadLong 'Target
        Set Buffer = Nothing
        
        'Invalid command
        If i < 0 Or i > 2 Then Exit Sub
        
        Select Case i
            Case 0 'Send Invite
                
                'Check for a valid n
                If n <= 0 Or n > MAX_PLAYERS Then Exit Sub
            
                'Offline
                If Not IsPlaying(n) Then
                    PlayerMsg Index, "O jogador está offline!", White
                    Exit Sub
                End If
                
                If TempPlayer(n).InArena Then
                    PlayerMsg Index, "O jogador está em uma arena!", White
                    Exit Sub
                End If
                
                If TempPlayer(n).HasChallenge Then
                    PlayerMsg Index, "Já desafiaram este jogador!", White
                    Exit Sub
                End If
                
                If TempPlayer(Index).HasChallenge Then
                    PlayerMsg Index, "Você já enviou um desafio!", White
                    Exit Sub
                End If
                
                'Checar quem é o desafiado
                If n = Index Then
                    PlayerMsg Index, "Você não pode se desafiar!", White
                    Exit Sub
                End If
                
                TempPlayer(n).HasChallenge = True
                TempPlayer(Index).HasChallenge = True
                
                TempPlayer(n).ChallengeOwner = Index 'Index de quem manda o desafio
                TempPlayer(Index).ChallengeInvited = Index 'Index de quem manda o desafio
                
                TempPlayer(n).ChallengeInvited = Index 'Desafiante pega o Index do desafiado
                TempPlayer(Index).ChallengeInvited = n 'Desafiante pega o Index do desafiado
                
                'Envia a janela de desafio!
                SendChallenge Index, n, 0
                
            Case 1 'Accept
                
                'Check for a valid n
                If n <> 0 Then Exit Sub
                
                If TempPlayer(Index).HasChallenge = False Then
                    PlayerMsg Index, "Você não está sendo desafiado...", White
                    Exit Sub
                End If
                
                If TempPlayer(Index).InArena Then
                    PlayerMsg Index, "Você não pode aceitar desafios na arena!", White
                    Exit Sub
                End If
                
                n = TempPlayer(Index).ChallengeOwner
                
                'Offline
                If Not IsPlaying(n) Then
                    PlayerMsg Index, "Quem te desafiou está offline...", White
                    
                    'Jogador off, só limpa e sai
                    TempPlayer(Index).HasChallenge = False
                    TempPlayer(Index).InArena = False
                    TempPlayer(Index).ChallengeOwner = 0
                    TempPlayer(Index).ChallengeInvited = 0
                    Exit Sub
                End If
                
                If TempPlayer(n).InArena Then
                    PlayerMsg Index, "O jogador está em uma arena!", White
                    
                    'Jogador off, só limpa e sai
                    TempPlayer(Index).HasChallenge = False
                    TempPlayer(Index).InArena = False
                    TempPlayer(Index).ChallengeOwner = 0
                    TempPlayer(Index).ChallengeInvited = 0
                    Exit Sub
                End If
                
                'Recusou o desafio que você mesmo fez?
                If n = Index Then
                    PlayerMsg Index, "Você não pode recusar o próprio desafio!", White
                    Exit Sub
                End If
                
                'Guarda as posições Mapa, X e Y
                TempPlayer(Index).ResultPos.MapNum = GetPlayerMap(Index)
                TempPlayer(Index).ResultPos.x = GetPlayerX(Index)
                TempPlayer(Index).ResultPos.y = GetPlayerY(Index)
                
                TempPlayer(n).ResultPos.MapNum = GetPlayerMap(n)
                TempPlayer(n).ResultPos.x = GetPlayerX(n)
                TempPlayer(n).ResultPos.y = GetPlayerY(n)
                
                TempPlayer(Index).InArena = True
                TempPlayer(n).InArena = True
                
                PlayerWarp Index, 1, 2, 3
                PlayerWarp n, 1, 5, 6
                
                'Envia mensagem a ambos
                PlayerMsg Index, "Começe a batalha!", Yellow
                PlayerMsg n, "Começe a batalha!", Yellow
                
            Case 2 'Decline
                
                'Check for a valid n
                If n <> 0 Then Exit Sub
                
                If TempPlayer(Index).HasChallenge = False Then
                    PlayerMsg Index, "Você não está sendo desafiado...", White
                    Exit Sub
                End If
                
                If TempPlayer(Index).InArena Then
                    PlayerMsg Index, "Você não pode aceitar desafios na arena!", White
                    Exit Sub
                End If
                
                n = TempPlayer(Index).ChallengeOwner
                
                'Offline
                If Not IsPlaying(n) Then
                    PlayerMsg Index, "Quem te desafiou está offline...", White
                    
                    'Jogador off, só limpa e sai
                    TempPlayer(Index).HasChallenge = False
                    TempPlayer(Index).InArena = False
                    TempPlayer(Index).ChallengeOwner = 0
                    TempPlayer(Index).ChallengeInvited = 0
                    Exit Sub
                End If
                
                If TempPlayer(n).InArena Then
                    PlayerMsg Index, "O jogador está em uma arena!", White
                    
                    'Jogador off, só limpa e sai
                    TempPlayer(Index).HasChallenge = False
                    TempPlayer(Index).InArena = False
                    TempPlayer(Index).ChallengeOwner = 0
                    TempPlayer(Index).ChallengeInvited = 0
                    Exit Sub
                End If
                
                'Recusou o desafio que você mesmo fez?
                If n = Index Then
                    PlayerMsg Index, "Você não pode recusar o próprio desafio!", White
                    Exit Sub
                End If
                
                'Envia mensagem a ambos
                PlayerMsg Index, "Você recusou o desafio de " & Trim$(GetPlayerName(n)), White
                PlayerMsg n, "O jogador " & Trim$(GetPlayerName(Index)) & " recusou seu desafio!", White
                
                'Agora é hora de limpá-los, limpamos o outro
                TempPlayer(n).HasChallenge = False
                TempPlayer(n).InArena = False
                TempPlayer(n).ChallengeOwner = 0
                TempPlayer(n).ChallengeInvited = 0
                
                'Limpando quem recusou
                TempPlayer(Index).HasChallenge = False
                TempPlayer(Index).InArena = False
                TempPlayer(Index).ChallengeOwner = 0
                TempPlayer(Index).ChallengeInvited = 0
                
        End Select
        
    End Sub

    Agora, em "ModPlayer", na "Sub OnDeath(ByVal Index As Long)", procure por esta parte:
    Código:
    With Map(GetPlayerMap(index))
            ' to the bootmap if it is set
            If .BootMap > 0 Then
                PlayerWarp index, .BootMap, .BootX, .BootY
            Else
                Call PlayerWarp(index, START_MAP, START_X, START_Y)
            End If
        End With

    E substitua essa parte por esta:
    Código:
    'Estavamos em uma arena
        If TempPlayer(Index).InArena Then 'estava em uma arena
            'Se sommos o dono do convite, então o index do outro é o convidado
            n = TempPlayer(Index).ChallengeInvited
            
            PlayerWarp Index, TempPlayer(Index).ResultPos.MapNum, TempPlayer(Index).ResultPos.x, TempPlayer(Index).ResultPos.y
            PlayerMsg Index, "Você perdeu...", BrightRed
            
            TempPlayer(Index).HasChallenge = False
            TempPlayer(Index).InArena = False
            TempPlayer(Index).ChallengeInvited = 0
            TempPlayer(Index).ChallengeOwner = 0
            
            'Checa se ainda está jogando também, apesar que mesmo que desloguem juntos
            'o index será checado por fila e irá limpar, mas é bom checar
            If IsPlaying(n) Then
                PlayerWarp n, TempPlayer(n).ResultPos.MapNum, TempPlayer(n).ResultPos.x, TempPlayer(n).ResultPos.y
                PlayerMsg n, "Você ganhou!", Yellow
                
                TempPlayer(n).HasChallenge = False
                TempPlayer(n).InArena = False
                TempPlayer(n).ChallengeInvited = 0
                TempPlayer(n).ChallengeOwner = 0
            End If
        Else
            With Map(GetPlayerMap(Index))
                    ' to the bootmap if it is set
                    If .BootMap > 0 Then
                        PlayerWarp Index, .BootMap, .BootX, .BootY
                    Else
                        Call PlayerWarp(Index, START_MAP, START_X, START_Y)
                    End If
            End With
        End If

    Ainda em "ModPlayer", na "Sub LeftGame(ByVal Index As Long)",  e bem no início, substitua essa parte:
    Código:
    If TempPlayer(index).InGame Then
            TempPlayer(index).InGame = False

    Por esta:
    Código:
    'Estavamos em uma arena
            If TempPlayer(Index).InArena Then 'estava em uma arena
                n = TempPlayer(Index).ChallengeInvited
                
                'Usemos SET sem update, o jogador já está de saída.
                If TempPlayer(Index).ResultPos.MapNum > 0 Then
                    SetPlayerMap Index, TempPlayer(Index).ResultPos.MapNum
                    SetPlayerX Index, TempPlayer(Index).ResultPos.x
                    SetPlayerY Index, TempPlayer(Index).ResultPos.y
                    
                    TempPlayer(Index).ResultPos.MapNum = 0
                    TempPlayer(Index).ResultPos.x = 0
                    TempPlayer(Index).ResultPos.y = 0
                End If
                
                'Checa se ainda está jogando também, apesar que mesmo que desloguem juntos
                'o index será checado por fila e irá limpar, mas é bom checar
                If IsPlaying(n) Then
                    If TempPlayer(n).ResultPos.MapNum > 0 Then
                        PlayerWarp n, TempPlayer(n).ResultPos.MapNum, TempPlayer(n).ResultPos.x, TempPlayer(n).ResultPos.y
                    End If
                    PlayerMsg n, "O jogador " & Trim$(GetPlayerName(Index)) & " deslogou, você ganhou!", Yellow
                    
                    TempPlayer(n).HasChallenge = False
                    TempPlayer(n).InArena = False
                    TempPlayer(n).ChallengeInvited = 0
                    TempPlayer(n).ChallengeOwner = 0
                End If
            End If
            
            'Tínhamos um convite ativo!
            If TempPlayer(Index).HasChallenge Then  'estava em uma arena
                n = TempPlayer(Index).ChallengeInvited
                
                'Checa se ainda está jogando também, apesar que mesmo que desloguem juntos
                'o index será checado por fila e irá limpar, mas é bom checar
                If IsPlaying(n) Then
                    PlayerMsg n, "O jogador " & Trim$(GetPlayerName(Index)) & " recusou o pedido de desafio!", Yellow
                    
                    TempPlayer(n).HasChallenge = False
                    TempPlayer(Index).InArena = False
                    TempPlayer(Index).ChallengeInvited = 0
                    TempPlayer(Index).ChallengeOwner = 0
                    
                    'Fecha janela de desafio
                    SendChallenge Index, n, 1
                End If
            End If
            TempPlayer(Index).InGame = False

    Agora, em "ModTypes" , acima de "Public Type TempPlayerRec" , adicione isto:
    Código:
    Private Type RecordPosRec
        MapNum As Long
        x As Long
        y As Long
    End Type

    Ainda em "ModTypes" , na "Public Type TempPlayerRec", ANTES do primeiro "EndType", declare estes tipos:
    Código:
    'Arena System
        HasChallenge As Boolean
        InArena As Boolean
        ChallengeOwner As Long
        ChallengeInvited As Long
        ResultPos As RecordPosRec

    Agora, em "ModServerTCP" , no final, adicione esta sub:
    Código:
    Sub SendChallenge(ByVal Index As Long, ByVal ChallengedIndex As Long, ByVal CommandNum As Long)
        Dim Buffer As clsBuffer

        Set Buffer = New clsBuffer
        Buffer.WriteLong SArena
        Buffer.WriteString Trim$(GetPlayerName(ChallengedIndex))
        Buffer.WriteLong CommandNum
        SendDataTo ChallengedIndex, Buffer.ToArray()
        Set Buffer = Nothing
       
    End Sub



    E pronto, agora você tem um sistema de Arena por convite, teleporte e tudo mais!  Very Happy

    Dica: Caso você queira mudar "para onde os jogadores vão", basta você entra em "ModHandleData" na "Sub HandleArena" e modificar a parte:
    Código:
    PlayerWarp Index, 1, 2, 3
                PlayerWarp n, 1, 5, 6

    Para as coordenadas que você preferir! Lembrando que nesse caso:
    Index = quem aceitou o desafio;
    n = o desafiante.

    No mais é isso, boa criação! Qualquer dúvida, sugestão ou erro, manda aí que damos um suporte!

    Edit1: Adicionado "SendChallenge" esquecido de colocar no tutorial do fórum.
    Créditos


    Kotol

    Valentine gosta desta mensagem


      Data/hora atual: Sáb Nov 23, 2024 4:51 am