Oin turu baum?
Venho trazer um sistemazinho simples.
O que se tem de entender dele é que ele não necessariamente é um Sistema de Reputação, mas sim uma Base Geral de se ter Valores Salvos e de se Enviar tais valores pela comunicação Server <> Cliente.
Esse Pedido foi feito pelo Yashi (Allan) via PM, e aqui estou disponibilizando.
Vai servir como uma Leve Aula para os que ainda não tem conhecimento de como enviar valores, fazer atualização dos mesmos e salva-los.
Qual a Lógica por trás?
Bem, teremos de abrir uma memoria no NPC, onde ela armazenará o valor de "Reputação".
Quando este NPC for derrotado o Player ganhará esse valor de Reputação.
Logo o Player também precisará de uma memoria para salvar este valor de reputação que vamos usar.
Ficha Tecnina
Dificuldade: Fácil
Compatibilidade: Qualquer EO/CS
Necessário:
- Visual Basic 6
- Após o Termino apagar NPC's e Player's nas pastas do Servidor. (Evitar Probleminhas ;3)
Engine Já Modificada: Download (Menos de 2mb)
(Baixe caso queria apenas Ripar o Sistema de Engine - Ou o ver funcionando.)
(Caso queira Ripar, procurar por tudo que tenha "Reputation" ou "Reputação".)
Ao Sistema
[ Parte 1 - Criando as Memórias ]
Vamos estar Indo aos Types para poder adicionar a Variável Type que irá armazenar o Valor que desejamos criar.
No Cliente e no Servidor, procure por:
- Código:
Private Type PlayerRec
Dentro dele, antes do End Type, adicione:
- Código:
Reputation As Long
Colocamos um valor Long na Memória já que em geral esses jogos vão trabalhar na casa de milhões mais..
Com isso a memoria no Player já vai estar lá.
Vamos tratar dos Npc's.
Procure por:
- Código:
Private Type NpcRec
Dentro dele e antes do End Type, adicione:
- Código:
Reputation As Long
O Npc irá armazenar o Valor de reputação a qual ele dará ao morrer.
[ Parte 2 - Preparando o NPC ]
No Cliente,
Acesse a FrmEditor_NPC e prepare os componentes a qual irão nos ajudar na edição do Npc.
Poderá ficar mais o menos assim:
Componentes Principais ai são:
- Label (Sem nome necessário, apenas para ficar indicado que é ali que fica a reputação.)
- textBox (Name = txtReputation)
Apague todo o conteúdo da propriedade "Text" do textBox (txtReputation), deixando ele Limpo.
Dê 2 click's sobre o txtReputation e vamos aos seus códigos:
- Código:
' If debug mode, handle error then exit out
If Options.Debug = 1 Then On Error GoTo errorhandler
If Not Len(txtReputation.text) > 0 Then Exit Sub
If IsNumeric(txtReputation.text) Then Npc(EditorIndex).Reputation = Val(txtReputation.text)
' Error handler
Exit Sub
errorhandler:
HandleError "txtReputation_Change", "frmEditor_NPC", Err.Number, Err.Description, Err.Source, Err.HelpContext
Err.Clear
Exit Sub
Adicionado isso a parte interna do txtReputation, vamos agora garantir que ao Npc ser carregado no Editor, ele carregue também o valor de reputação atual do Npc.
Procure por:
- Código:
Public Sub NpcEditorInit()
Esta sub processa cada carregamento de NPC no Editor. É muito importante que ao fazer componentes novos que usem memória, seja adicionado o carregamento do mesmo no Editor usando essa Sub.
Dentro dela e abaixo de :
- Código:
With frmEditor_NPC
Adicione:
- Código:
.txtReputation.text = Npc(EditorIndex).Reputation
Dessa forma, toda vez que acessar o Editor de Npc's, será posto o valor de Reputação do NPC no TextBox de Reputação.
[ Parte 3 - Packets e Trocas ]
Nessa parte faremos o Pacote que irá transitar a reputação de forma principal. Ele será pequeno já que toda vez que um NPC com Reputação morrer ele será enviado ao Jogador atualizando assim o valor de Reputação do Jogador.
Ainda no cliente procure por:
- Código:
SMSG_COUNT
Acima dele adicione:
- Código:
SPlayerReputation
Estamos aumentando o Limite de Pacotes conhecidos pelo Cliente.
Faremos o mesmo no Servidor.
No servidor procure por:
- Código:
SMSG_COUNT
Acima dele adicione:
- Código:
SPlayerReputation
#É Extremamente Importante que essa parte do modEnumerations esteja de acordo e igual Cliente e Servidor. O Mesmo Numero de Pacotes e de preferencia o Mesmo Nome! Caso contrário você vai começar a ter dores de cabeça >
Tendo isso, quando chamarmos pela Call SendReputation(?), ela pegará o valor de memoria "Reputation" do jogador Alvo e tentará enviar para o Cliente.
Dentro dele, depois de todos os :
Você adiciona:
Não é estritamente necessário que você adicione isso em um "Padrão". Como assim? A ordem ali dentro não é importante, é mais organização. Já que se adicionou um novo pacote, ele "teria" de ficar no final.
Pronto, dessa forma o Servidor já sabe enviar o valor ao Cliente, o Cliente já recebe o Pacote e também já faz a leitura guardando o valor recebido dentro da Memória que criamos para ele.
No Servidor, vamos procurar pela SUB que processa a morte do NPC.
Procure por:
Dentro dela, procure por isso aqui...
Esta parte acima determina e faz o começo da limpeza do NPC, mas queremos que antes dele ser "limpo" entregue a nós a reputação num é mermu?
Então, acima disso adicione:
Em outras palavras o código analisa se o Npc tem reputação para ser entregue, caso tenha, ele adiciona a reputação a memoria do Player, e logo em seguida pede para enviar o Pacote de atualização de Reputação ao Cliente do Player.
De forma simples apenas para mostrar a reputação na tela, eu criei uma Label no FrmMain.
Name da Label: (lblReputation)
Agora procure pelo nosso pacote que recebe a Reputação do Servidor...
Ainda no Cliente procure por:
Abaixo dele adicione:
Dessa forma, toda vez que o Pacote chegar, ele irá atualizar a Propriedade Caption da Label que criamos para mostrar a Reputação.
Esse detalhe se trata de uma atualização vital que se segue pelo cliente<>Server.
É o Nosso PlayerData() que envia muitas vezes boa parte de todas as memorias do Player.
Vamos por nossa memoria de Reputação para ser atualizada também via ele, porque caso contrario.. Ao Você logar no jogo, o Player só receberia a Reputação de 2 Jeitos:
[ 1 ] Caso esteja no PlayerData()
[ 2 ] Caso envie a Reputação via JoinGame()
Como eu estou fazendo esse sistema visando que vocês aprendam e assim modifiquem essa "logica" e memorias para serem usadas de outras maneiras e com outros nomes /o/ para outras diversas finalidades então vou ensinar a mover isso pelo PlayerData(), o que para a Situação Atual seria melhor ser enviada pelo JoinGame (Assim que o Player Logar).
Mas não chega a ser um problema.
Vamos lá.
No Servidor, procure por:
Fique bem atento a isso, entenda que os Buffer's empacotam os valores em ORDEM , no caso Listagem! E o Cliente precisa desempacotar na mesma ORDEM de listagem. Caso contrário você ter dor de cabecinha bb ><
Uma maneira fácil de por é, procure um Buffer de preferencia sem estar dentro de um For/Next
Ex:
Esse Buffer empacota o valor de PK do Player.
Abaixo adicione:
Dentro dela, LEMBRANDO QUE A ESTRUTURA TEM DE SER DESEMPACOTADA EM ORDEM QUE FOI EMPACOTADA!
Abaixo dele, adicionaremos:
Pronto! Agora, o Cliente desempacota com tranquilidade e na ordem correta.
Abaixo disso adicione:
Agora a Label que criamos lá no FrmMain será atualizada assim que o Player Receber a PlayerData também /o/
Vá ao final do modServerTCP (Modulo que é responsável por armazenar os Envios de Pacotes para o Cliente.)
No Final dele adicione:
- Código:
Sub SendReputationTo(ByVal index As Long)
Dim Buffer As clsBuffer, i As Long, partyNum As Long
Set Buffer = New clsBuffer
Buffer.WriteLong SPlayerReputation
Buffer.WriteLong Player(index).Reputation
SendDataTo index, Buffer.ToArray()
Set Buffer = Nothing
End Sub
Tendo isso, quando chamarmos pela Call SendReputation(?), ela pegará o valor de memoria "Reputation" do jogador Alvo e tentará enviar para o Cliente.
Agora vamos fazer o cliente receber.
Voltando ao Cliente, vá ao modHandleData (Modulo responsável por receber os Pacotes que vem do Servidor para o Cliente.)
Procure por:
- Código:
Public Sub InitMessages()
Dentro dele, depois de todos os :
- Código:
HandleDataSub(
Você adiciona:
- Código:
HandleDataSub(SPlayerReputation) = GetAddress(AddressOf HandlePlayerReputation)
Não é estritamente necessário que você adicione isso em um "Padrão". Como assim? A ordem ali dentro não é importante, é mais organização. Já que se adicionou um novo pacote, ele "teria" de ficar no final.
Agora que o Cliente já tem conhecimento do que fazer com o Pacote que criamos, vamos fazer ele ler o pacote.
O Pacote ao chegar será enviado para a "HandlePlayerReputation", sendo assim no final da ModHandleData, coloque:
- Código:
Private Sub HandlePlayerReputation(ByVal Index As Long, ByRef Data() As Byte, ByVal StartAddr As Long, ByVal ExtraVar As Long)
Dim Buffer As clsBuffer, i As Long
Dim Reputation As Long
' If debug mode, handle error then exit out
If Options.Debug = 1 Then On Error GoTo errorhandler
Set Buffer = New clsBuffer
Buffer.WriteBytes Data()
Reputation = Buffer.ReadLong
If Index = MyIndex Then
Player(MyIndex).Reputation = Reputation
End If
' Error handler
Exit Sub
errorhandler:
HandleError "HandlePlayerReputation", "modHandleData", Err.Number, Err.Description, Err.Source, Err.HelpContext
Err.Clear
Exit Sub
End Sub
Pronto, dessa forma o Servidor já sabe enviar o valor ao Cliente, o Cliente já recebe o Pacote e também já faz a leitura guardando o valor recebido dentro da Memória que criamos para ele.
[ Parte 4 - Fazendo o NPC dar Reputação ao ser Abatido ]
No Servidor, vamos procurar pela SUB que processa a morte do NPC.
Procure por:
- Código:
Public Sub PlayerAttackNpc(ByVal attacker As Long
Dentro dela, procure por isso aqui...
- Código:
' 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
Esta parte acima determina e faz o começo da limpeza do NPC, mas queremos que antes dele ser "limpo" entregue a nós a reputação num é mermu?
Então, acima disso adicione:
- Código:
'Get Reputation
If Npc(npcNum).Reputation > 0 Then
Player(attacker).Reputation = Player(attacker).Reputation + Npc(npcNum).Reputation 'Add Reputação
SendReputationTo attacker 'Envia ao Player que Matou
End If
Em outras palavras o código analisa se o Npc tem reputação para ser entregue, caso tenha, ele adiciona a reputação a memoria do Player, e logo em seguida pede para enviar o Pacote de atualização de Reputação ao Cliente do Player.
[ Parte 5 *-* - Mostrando a Reputação no Cliente ]
De forma simples apenas para mostrar a reputação na tela, eu criei uma Label no FrmMain.
Name da Label: (lblReputation)
Agora procure pelo nosso pacote que recebe a Reputação do Servidor...
Ainda no Cliente procure por:
- Código:
Private Sub HandlePlayerReputation(B
Dentro dessa Sub procure por:
- Código:
Player(MyIndex).Reputation = Reputation
Abaixo dele adicione:
- Código:
frmMain.lblReputation.Caption = "Reputação: " & Reputation
Dessa forma, toda vez que o Pacote chegar, ele irá atualizar a Propriedade Caption da Label que criamos para mostrar a Reputação.
Até aqui o sistema está basicamente terminado, faltando apenas mais um detalhe!
[ Parte Ultima - Detalhe! ]
Esse detalhe se trata de uma atualização vital que se segue pelo cliente<>Server.
É o Nosso PlayerData() que envia muitas vezes boa parte de todas as memorias do Player.
Vamos por nossa memoria de Reputação para ser atualizada também via ele, porque caso contrario.. Ao Você logar no jogo, o Player só receberia a Reputação de 2 Jeitos:
[ 1 ] Caso esteja no PlayerData()
[ 2 ] Caso envie a Reputação via JoinGame()
Como eu estou fazendo esse sistema visando que vocês aprendam e assim modifiquem essa "logica" e memorias para serem usadas de outras maneiras e com outros nomes /o/ para outras diversas finalidades então vou ensinar a mover isso pelo PlayerData(), o que para a Situação Atual seria melhor ser enviada pelo JoinGame (Assim que o Player Logar).
Mas não chega a ser um problema.
Vamos lá.
No Servidor, procure por:
- Código:
Function PlayerData(ByVal index As Long) As Byte()
Fique bem atento a isso, entenda que os Buffer's empacotam os valores em ORDEM , no caso Listagem! E o Cliente precisa desempacotar na mesma ORDEM de listagem. Caso contrário você ter dor de cabecinha bb ><
Uma maneira fácil de por é, procure um Buffer de preferencia sem estar dentro de um For/Next
Ex:
- Código:
Buffer.WriteLong GetPlayerPK(index)
Esse Buffer empacota o valor de PK do Player.
Abaixo adicione:
- Código:
Buffer.WriteLong Player(index).Reputation
Agora o PlayerData() vai estar enviando o Reputation do Player.
Vamos ao Cliente,
Iremos agora procurar a Leitura do Pacote do PlayerData() que se chama HandlePlayerData()
Procure por:
- Código:
Private Sub HandlePlayerData(ByVal Index As Long,
Dentro dela, LEMBRANDO QUE A ESTRUTURA TEM DE SER DESEMPACOTADA EM ORDEM QUE FOI EMPACOTADA!
Como botamos o Buffer do Reputation para ser Empacotado embaixo do Buffer de PK, então procuremos pelo de PK Primeiro:
- Código:
Call SetPlayerPK(i, Buffer.ReadLong)
Abaixo dele, adicionaremos:
- Código:
Player(i).Reputation = Buffer.ReadLong
Pronto! Agora, o Cliente desempacota com tranquilidade e na ordem correta.
Caso você ponha em ordem errada, o Valor vai ser Atribuído a outra MEMORIA, e assim Você pode imaginar sua Reputação sendo colocada no HP, ou em diversos outros locais dependendo da ordem de desempacotamento /o/ ~ É uma reação em cadeia que iria lhe dar dores de cabeça não só a você... pq provavelmente iria vir aqui trazer o problema < 3
Para Finalizar...
Ainda na HandlePlayerData, procure por isso aqui:
- Código:
' Check if the player is the client player
If i = MyIndex Then
Abaixo disso adicione:
- Código:
'Refresh Reputation Label
frmMain.lblReputation.Caption = "Reputation: " & Player(MyIndex).Reputation
Agora a Label que criamos lá no FrmMain será atualizada assim que o Player Receber a PlayerData também /o/
FIM * o *
Espero que tenham gostado e que com isso possam pensar em diversas outras memórias,valores e possíveis customizações para a falência de vocês!
Att amores < 3
_________________
"Mistress of shattered hopes and forever broken dreams"