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.
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:
Agora, dentro da "lblArenaAccept" adicione isto:
Agora, dentro da "lblArenaDecline" adicione isto:
Agora, em "ModClientTCP" , no final adicione esta sub:
Agora, em "ModEnumerations", na "Public Enum ServerPackets" logo abaixo ANTES de:
Declare esta enumeração:
Ainda em "ModEnumerations", na "Public Enum ClientPackets" logo abaixo ANTES de:
Declare esta enumeração:
Agora, em "ModHandleData", na "Public Sub InitMessages()", depois de:
Adicione isto:
Ainda em "ModHandleData" , no final adicione isto:
E pronto, cliente completo! Vamos agora ao servidor!
Adicione isto:
Ainda em "ModHandleData", ao final adicione esta sub:
Agora, em "ModPlayer", na "Sub OnDeath(ByVal Index As Long)", procure por esta parte:
E substitua essa parte por esta:
Ainda em "ModPlayer", na "Sub LeftGame(ByVal Index As Long)", e bem no início, substitua essa parte:
Por esta:
Agora, em "ModTypes" , acima de "Public Type TempPlayerRec" , adicione isto:
Ainda em "ModTypes" , na "Public Type TempPlayerRec", ANTES do primeiro "EndType", declare estes tipos:
Agora, em "ModServerTCP" , no final, adicione esta sub:
E pronto, agora você tem um sistema de Arena por convite, teleporte e tudo mais!
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!
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!
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