quarta-feira, 26 de novembro de 2008

Linux pOOOde em Ragnarok!!!

Basta instalar o cedega (o pacote DEB serviu bem) e colocar as seguintes linhas no final do arquivo ~/.transgaming/config

;; Ragnarok
[AppDefaults\\Ragnarok.exe\\transgaming]
"cmdline" = ""
"bigexe" = "N"
"doscwd" = ""
"force_pthreads" = "Auto"
"winexversion" = "default"
"renice_wineserver" = "N"

[AppDefaults\\Ragnarok.exe\\x11drv]
"Managed" = "Y"
"Desktop" = "No"
"UseXVidMode" = "Y"
"UseXRandR" = "N"
"DXGrab" = "N"
"ShowFPS" = "N"
"ShowMem" = "N"
"VideoRam" = "32"
"AGPVertexRam" = "16"
"NV_VAR" = "Y"
"ARB_VBO" = "Y"

[AppDefaults\\Ragnarok.exe\\WinMM]
"Drivers" = "wineoss.drv"

[AppDefaults\\Ragnarok.exe\\wineoss]
"dsp0" = "/dev/dsp"
"mixer0" = "/dev/mixer"
"UseMMap" = "Y"
"FullDuplex" = "N"

[AppDefaults\\Ragnarok.exe\\winealsa]
"pcm0" = "hw"
"ctl0" = "hw"
"UseMMap" = "Y"
"FullDuplex" = "N"

[AppDefaults\\Ragnarok.exe\\version]
"windows" = "win98"

[AppDefaults\\Ragnarok.exe\\d3dgl]
"AnisotropicTextureFiltering" = "N"
"VertexShaders" = "Y"
"PixelShaders" = "N"
"PixelShadersLevel" = "1.3"
"ClipSpaceFix" = "Y"

[AppDefaults\\Ragnarok.exe\\font]
"FreeType" = "Y"

[AppDefaults\\Ragnarok.exe\\wine]
"Browser" = ""

[AppDefaults\\Ragnarok.exe\\Wineserver]
"SHMWineserver" = "Y"


PS: Tem que mandar rodar o jogo em tela cheia e com a MESMA resolução que você usa no desktop senão fica super lento! Abra o jogo com o WINE pra que ele faça todos os updates pois no cedega num funciona. Depois de atualizado, feche a tela de atualização e abra de novo via cedega.
Autor: LedStyle
Fonte: Forum Ubuntu

Caso queira atualizar o servidor de Ragnarok no BRO, isso serve para Windows e Linux... Basta você ir no site da LUG

ftp://fpatch.levelupgames.com.br/patch/ Atravez dele você podera fazer download das atualizações


DICA BOA EIM ???


comenta vocês aew

segunda-feira, 24 de novembro de 2008

GM defenda seu PC ele é Alvo


Proteja seu PC

Introdução

Uma pergunta muito freqüente entre vários usuários é: "Como proteger meu computador?" Não existe uma fórmula mágica, mas existem várias coisas que podem te ajudar a se proteger e amenizar as conseqüências de certos problemas que possam ocorrer.

Firewall

Um firewall serve para proteger o seu computador de tentativas de invasão através da Internet e gerenciar quais programas no seu computador podem acessar os recursos na rede.

Isso se prova útil na prevenção, onde um firewall pode bloquear uma tentativa de invasão do seu sistema ou um worm de atacar o seu computador. Mas firewalls também servem para que certos tipos de trojans não causem muito estrago.

É comum a prática onde um trojan é instalado no seu computador e este se encarrega de instalar outros trojans, muitas vezes mais de 20 trojans podem ser instalados por aquele um. Com um firewall você pode bloquear aquele trojan de acessar a internet para instalar os outros.

Se você não possui um firewall, instale um agora mesmo. Vários firewalls podem ser baixados e instalados sem custo algum. Se não quiser instalar um firewall, pelo ative o que acompanha o Windows XP seguindo estas instruções.
Modo de Segurança



Para iniciar o computador no Modo de Segurança, tudo que você precisa fazer é apertar a tecla F8 quando o Windows começar a iniciar. Geralmente você pode ficar apertando F8 logo após ligar o computador até aparecer um menu.

Nesse menu, você vai poder escolher Modo de Segurança ou Modo Seguro, dependendo da sua versão do Windows.

Algumas placas-mãe utilizam o F8 para o menu de boot. Se esse for o seu caso, você pode tentar utilizar a tecla F5 ao invés da F8. Se ainda não funcionar, você terá que executar o MSConfig, conforme as instruções abaixo:

1. Clique em Iniciar -> Executar

2. Digite msconfig e clique em OK.

3. Selecione a aba BOOT.INI e marque a opção /SAFEBOOT

4. Clique em OK

Quando você estiver no Modo de Segurança, você deverá reverter o processo e desmarcar a opção /SAFEBOOT. Se você deixá-la marcada, o sistema continuará iniciando apenas em Modo de Segurança até que a opção seja desmarcada.

Rodando o Firewall do Windows XP Por Renato de Moraes

1. Iniciar -> Conectar-se -> Mostrar todas as conexões

2. Clique com o botão direito na conexão que você quer habilitar/desabilitar o firewall e clique em Propriedades

3. Agora clique na aba Avançado

4. Deixe marcado/marque a opção Proteger esse computador e a rede, limitando ou impedindo o acesso a este computador através da Internet. — ScreenShot

5. Clique em OK

Você também pode desmarcar a caixa para desabilitar o firewall, o que não é recomedado a não ser que você saiba o que está fazendo!

Rodando o Prompt de Comando

Windows 95/98/ME

Iniciar -> Executar, digite command e clique em OK.

Windows NT/2000/XP/2003

Iniciar -> Executar, digite cmd e clique em OK.


E-mail e mensagem instantânea

Não execute qualquer arquivo que você recebeu por e-mail. Isso inclui supostos "cartões", anexos e outros arquivos. Se o e-mail do remetente parece ser de alguém que você conhece e o e-mail possui um arquivo anexado ou algo do tipo, confirme com essa pessoa se ela lhe enviou tais arquivos.

Existem pessoas forjando e-mails, utilizando engenharia social para lhe convencer a instalar os programas maliciosos. Se o e-mail lhe pedir para desativar o antivírus, suspeite ainda mais. Em comunicadores instantâneos, verifique qualquer arquivo que você recebe se você não o esperava. Se você receber um link para um site que pede o download de algum arquivo estranho, confirme com a pessoa se ela lhe enviou este link. Se ela disser que não enviou o link, provavelmente é porque ela está infectada com algum worm que está enviando mensagens por ela. É melhor você prevenir os problemas de formas simples como uma verificação dos arquivos que você recebe do que se arrepender por ter sido infectado.

Cuidados com Programas

Tome extremo cuidado com os softwares que você instala. Embora seja uma prática muito comum em softwares P2P, é possível encontrar outros programas — como o popular Add-on Messenger Plus! Para o MSN Messenger — que instalam spyware. Tente se informar antes de instalar algum programa e preste muita atenção em todas as opções do programa de instalação. Alguns deles permitem que você selecione se quer ou não instalar o spyware — e essa opção geralmente vem com um 'Sim' por padrão, portanto fique atento.

Atualizações do Sistema

Atualizar o seu sistema e seus programas é outro passo importante para conseguir uma segurança maior. Softwares atuais possuem menos bugs que softwares mais antigos e, portanto são mais seguros.

Se você utiliza Windows, visite o Windows Update mensalmente para obter as atualizações. Você pode ficar de olho nas notícias aqui do site para saber quando novas falhas forem publicadas e as atualizações estiverem disponíveis. Informação é a sua maior fonte de proteção.

Fonte: http://www.linhadefensiva.org

Servidor sem leg ? (adm veja aqui )

Muitas das vezes, você esta com um lag danado e não sabe o porque vou fazer esse tutorial basico para retirada de programas indesejáveis que abusam da sua conexão deixando sua net mais lenta.

* Nota: Esses Macetes so são para quem não tem problemas de provedor comprovado.

Passo 1: sabendo se sua conexão esta na velocidade ideal

Teste nesse link

http://tools.sisgel.com/

Veja se esta de acordo com sua velocidade.





Se esta tudo normal, aqui o básico do básico:

1º: você pode ter um spyware no seu computador.
2º: Sua conexão esta pulando hora sim hora não.
3º: Veja se existe algum outro programa aberto que mecha com internet.
4º: Veja se e seu computador que esta lagado.
5º: Libere memória se você tiver pouca.


1º Como eliminar os Spywares.

Baixe esse programa http://baixaki.ig.com.br/site/detail7127.htm

Execute ele atualize antes, tudo o que ele localizar e nocivo delete tudo o que ele achar mais deixa ele procurar por todos. Os spywares sao arquivos ou trojans que fazem abrir outrar janelas ou ficam usando sua conecção deixando lento com muito lag sua internet.



2º Como aumentar sua estabilidade.

Baixe esse programa http://baixaki.ig.com.br/site/detail7343.htm




Veja se o windows que esta organizando sua internet, se ele esta e mesmo assim esta lento coloque em conexão LAN, isdn ou o que for, o que ele vai fazer e estabilizar a conexão, vamos supor que sua net seja de 600k e ta legando quando lega ela cai pra 100 50 60, o que esse programa vai fazer e "FAZER ELA FIKAR CONSTANTE NA MESMA VELOCIDADE, isso diminui e muito o lag.

3º: Programas como emule, kazaa e outros compartilhadores pesam a net.




No exemplo acima esta marcado o internet Explorer mais ele não esta aberto aqui, isso e um spyware. os outros programas também não estão abertos.

4º: Computadores largados podem ser resolvidos baixando os drivers mais recentes de vídeos e abaixando a resolução no setup.exe do RO.



Lembrando que. quanto menor a resolução mais rápido o computador fara os sprites.

Usar /effect no jogo também ajuda.

Execute um desfraguimentador de disco pelo menos 1 vez por mês.

Se você e um daqueles que formata o pc direto tente ligar pra prestadora de serviço.


5º: Liberando memória que estava sendo usada por outro programa.

Baixe esse programa http://baixaki.ig.com.br/site/detail41953.htm

Antes de entrar no jogo execute ele, ele libera memória que foi usada e deixa ela mais limpa e mais rápida. Recomendada pra quem tem menos de 128 de memória.



Esse programa e muito bom, ajuda bastante mesmo mais se você tem mais de 128 e quiser usar ele melhora também.


Espero que isso seja util.

Este post foi editado por Strider Hyriu: Aug 28 2006, 12:09 PM

Bot ou não !?


A primeira coisa que acontece quando o servidor consegue uma fama no TOP é aparecer bot's, o bot vem da palavra Robot, como uma expressão de “aquilo que faz sozinho”
... ele é uma inteligência artificial capaz de se passar por um humano dentro do jogo, mas agora vem a pergunta:
"como eu, bot Hunter irei reconhecer o bot?"
já existe alguns aplicativos que ajudam no servidor contra bot's, mas esses aplicativos são chatos, pois interrompe o jogo do player e o faz perder tempo.
O Gm deve ser atento a muitas coisas, o Bot passa por uma configuração, os mestres desse software (openkore) programam as Macros para que o bot se pareça com um humano, ele pode fazer o bot responder a palavras como:

"Ei você é um bot ?"

apenas por algumas palavras "chaves"

nunca jamais tente descobrir um bot pela conversa, isso transmite ao jogador (caso seja o jogador) que você é imaturo e que não tem um comando de GM para descobrir tal coisa: É isso mesmo, a maioria dos players acreditam que o GM pode conhecer o bot com um clique. Em minhas recentes pesquisas descobri que os bot's tem suas fraquezas e a mais intrigante delas é o Chat.
Desconfiou que um player é bot ? siga o procedimento:

"(nome do player) Fomos notificados de uma denuncia a sua pessoa, e por conta disso estamos fazendo uma averiguação
Poderia abrir o chat para mim, e escreva no titulo a cor da roupa de seu personagem por favor."

Bem isso certamente pegaria um bot corajoso, os mestres na arte do bot costumam não por para seus char saírem na presença de um GM, esses contem uma macro perfeita, os bot’s oferecidos pelo openkore vem fornecendo informações para ativar um comando que reconhece um GM no mapa, não sei dizer se esse comando só funciona quando o GM da o @hide e fica visível no mapa, pois segundo algumas configurações da Gravity o hide é uma invisibilidade perfeita reconhecida somente pelo Server que esta rodando.

Para casos desse tipo, peça auxilio aos própios jogadores, eles tem um forte senso de justiça, tipo “ EU UPO AQUI TODO DIA, VEM UM FDP DE UM BOT, NÃO NO MEU SERVER NÃOOOOO” eles ajudarão bastante, peça SS avalie os log’s (ou se isso não tiver ao seu alcance peça para os que podem), banir contas é um risco grande para o servidor, caso você faça isso indevidamente poderá por o servidor em crise.

Exemplo: no meu Server teve uma denuncia de Gm corrupto, o ADM banio muitos players e o servidor afundou, pois os players revoltados fizeram campanha contra o servidor. Sempre avalie tudo,
Se você der um @clone vera um bot mau programado correndo atrás do clone sem poder bater, em uma conversa normal com um bot pessimamente programado você já descobre tudo.


Então sempre vá por etapas:

1° Notificação por mensagem pessoal (nessa você pega bot’s não programados)
2° Faça pergunta como: “Estamos fazendo uma notificação sobre uma denuncia, sabe do que se trata?” ( a pergunta pegara bot meio programados
3° O Bot respondeu ? peça o chat, e avalie (isso pegara bots muito bem programados)

Bem espero que tenhão gostado da Dica !!!

Tutorial Meu ^^

domingo, 23 de novembro de 2008

Shemale ou não ?!


Como identificar uma shemale



Se deu bem e desencalhou no ragnarök? Tá quase casando?

Vem aquela dúvida: SERÁ QUE ELA É SHEMALE?

Shemale: Homem que usa char feminino. Normalmente se passam por mulher para arranjar companheiros/maridos que lhe deem itens/zeny/up. Juram que são mulheres e se ofendem se alguem diz que é shemale.

Obs.: Hoje em dia é muito comum homens que usam char femininos por brincadeira, não para dar golpes.

Tipos Comuns de Shemales:

Shemale Comum:Aquela Dancer/SinX/Sacer, que vive em gef_fild10, usando Asa do Dia Dos Namorados, e um hat qualquer que provavelmente ganhou de um dos Sr. Troxa's da vida. Ela viu aquele elmo em sua cabeça e logo dispara a mandar PMs pedindo ajuda e elogiando o visual.

Shemale Pobre:Parece com a Shemale Comum, mas dá golpe até naqueles pobres coitados. Usa um nick suspeito, mas mesmo assim os caras acham que é mulher de verdade. Pede V.Set, DW, VH, Kage, Sinx card, WS card, Thanatos card etc..., pede se você nao pode ajuda-la, e assim que você faz o que ela pediu, some do mapa, você manda pm e ela nao responde (calma, ela ta passando os itens pra conta de homem dela!!).

Shemale Travecão:Idem as de cima, mas ela entra "no papel", desmunheca geral.

Shemale Enrustida: Tem donates. Vive no PVP. Tem namorado, mas você nunca ve eles juntos, nem nenhuma minima demonstração de afeto. Ela despreza o namorado. Ela pede uma Coroa do Deus Sol, ele diz que não tem, ela começa a fazer chantagem. Algum tempo depois até admite que é homem ou é descoberto.

Shemale Macho:Usa char feminino, mas todo mundo sabe que é homem. Pode ser uma evolução da Shemale Enrustida.

Dicas para descobrir shemales:

Ela no Team Speak


*Ela diz que não tem Team Speak
*Ela diz que tem Team Speak, mas o microfone tá estragado.
*Ela diz que tem TS, mas que ta sem microfone e seu pai vai comprar semana que vem. Semana que vem chega, e ela repete a desculpa.

P.S.: Hoje em dia existem programas que modificam a voz da pessoa, então fique atento:


*Ela fala muito palavrão?
*Ela não age no TS como sua namorada? (obs.: Isso aqui não é determinante, pois não dá mesmo de ficar falando "Eu Te Amo Querido" no microfone com pai, mãe, tia, cachorro e papagaio por perto.)
*Você pega ela de surpresa na sala do clã, falando como um garoto e ela fica quieta derrepente.
* "Sr Fodones" sai do TS quando você loga, logo depois chega "Fulana Gatinha". Quando você sai, seus amigos veem o "Sr Fodones" logar e a "Fulana Gatinha" sair.
*Se ele/ela estiver usando programas de modificação de voz, uma hora a mascara cai, ele/ela se confunde e fala com voz de homem com o loguin de "Fulana Gatinha" ou com voz de mulher no "Sr Fodones".

Ela na Internet


*Ela não tem orkut, fotolog, acc no fórum nem nenhum rastro na internet.
*Você pede pra ver uma foto dela. Ela fala: perai. Derrepente ela manda uma foto estilo "Atriz da Globo".
*Ela quase nunca entra no MSN, isso quando ela diz que não tem (OMG dificil alguem que jogue rag não ter Messenger hoje em dia)
*Ela tem orkut, mas nunca muda a foto, e só tem 1 ou 2 no album, isso quando nem tem.
*No MSN,toda vez que você pergunta se ela tem Web Can, microfone e etc, e pede para ela mostrar, ou ela muda de assunto, ou fica muda por alguns minutos e só depois que continua a conversa.


Ela IN-GAME


*Você pediu ela em casamento, ela aceitou, mando um kis e nenhuma reação a mais.
*Você anuncia todo feliz no canal CASEI!!!! e ela nao diz nada.
*Ela sempre te pede ajuda pra upa, pede pra ajuda nakela quest dificil, ou akela card que você economizo desde o ano passado pra comprar.
*Ela desconversa se você comenta sobre o Orkut, Team Speak, Msn dela.
*Tem atitudes estranhas pra uma garota (leve isso em conta apenas se já suspeitar).
Se apesar de todas as dicas acima, você ainda desconfiar, tire a prova:


TECNICAS EFETIVA PRA DESCOBRIR SHEMALES

1º(Não muito eficas, mas vale a pena tentar) Peça para ela tire uma foto, com um papel e uma coisa escrita.Fale para ela escrever qualquer coisa num papel e tirar uma foto juntamente com o papel.


2º-Peça para ver ela na Web Can ( se ele(a) tiver claro, caso não tenha, muito dificil não ter), desconfie de qualquer movimento dela, pois ele(a) pode ter colocado um video de uma garota para desfarçar(existem programas que fazem isso), ou então coloco a irmã ou a amiga, desconfie do modo como ele(a) fala e como age.


3º(só não funciona se ela leu esse tópico ou se ela trabalha numa empresa fabricante de Absorventes):

1.Pergunta pra ela que absorvente ela usa.
2.Se ela responder Sempre Livre, e você pedir pra ela especificar qual, e ela nao souber, É SHEMALE NA CERTA!
3.Se você perguntar, e ela demorar pra responder, ele/ela deve estar procurando no Google ou perguntando pra irmã.É SHEMALE.
4.Se ela dizer que não usa, É SHEMALE OU É PIRRALHA.

Agora, se ela responder ¹Sempre Livre ²Malha Seca ³Com Abas ¹²Fluxo Regular, NÃO É SHEMALE(A não ser que ele(a) seja muito esperto(a)).

*Variações:
¹- Always, Intimus Gel, OB.
²- Malha Seca/Algodão/Coton, extra-fino, noturno.
³- Com/Sem Abas
¹²- Fluxo Leve, Regular, Regular-Intenso, Intenso

OBS.: Nao dê as opções pra ela. Pergunte apenas pra especificar. E pergunte a cor do pacote e quantos vem em cada pacote.

Lembrando que para todas as regras existem excessões. Avalie a conduta dela com você e com as outras pessoas.

Isso são dicas, e ela se enquadrou em quase todas as dicas, se ela nao leu esse topico, faça o teste do absorvente, é tiro e queda, isso nem traveco assumido deve saber (tecnica testada em shemales e garotas de verdade).

Os creditos desse TuTor eu não achei o autor original ainda !!!

Construindo seu server (para testes)


ATENÇÃO:
Este Guia te ensina a criar um servidor SOMENTE em SQL!
------------------
[ Sumário ]



Capítulo 1- Programas Necessários

Capítulo 2- Instalando e Configurando o No-IP

Capítulo 3- Instalando e Configurando o Xampp

Capítulo 4- Configurando seu Servidor

Capítulo 5- Adicionando NPCs

Capítulo 6- Criando sua conta de GM

Capítulo 7- Configurações Adicionais

------------------

[ Capítulo 1 ]

Programas Necessários:

No-IP: http://www.no-ip.com/downloads.php
eAthena SQL: http://www.eathena.ws/board/index.php?showtopic=111584
Xampp: Mirror 1 _ http://prdownloads.sourceforge.net/xampp/xampplite-win32-1.5.1.exe?download
Mirror 2 _ http://prdownloads.sourceforge.net/xampp/xampplite-win32-1.5.1.exe?download

[ Capítulo 2 ]

Instalando e Configurando o No-IP.

O que é o No-IP ?

No-IP é um serviço de redirecionamento de IP no qual você cria um endereçoo pelo qual as pessoas poderão se conectar a sua maquina mais facilmente (por se tratar de um "IP" com nome de host, fica mais fácil de lembrar).

Fazendo um cadastro no No-IP:
Clique em "Sig-up!" e preencha o formulário com seus dados. O Email é altamente necessário e tem que ser VERDADEIRO caso queira realmente fazer o cadastro, pois apos clicar no botão de confirmação, será enviado ao respectivo email um link no qual você devera clicar para ativar sua conta.

Apos validar seu cadastro, você vai ser enviado para a pagina de configuração de sua conta
você se verá fronte a uma pagina dividida em 4 partes básicas:
Topo = Acesso Rápido a suas opções, ajuda, serviços alternativos (e pagos), downloads e por ultimo as informações sobre o No-IP.

Agora visualize o menu a sua esquerda e clique no menu de Hosts / Redirects, após ter feito isso clique em “Add”

Ira aparecer na sua tela agora um formulário o qual está:
Hostname: nomedoseuservirdor

Não preencha mais nada do formulário.

Agora aperte em Create Host e pronto ;D

Agora que você criou o seu host vamos instalar e Configurar o seu No-IP.

Clique no ducsetup.exe e apenas clique em Next > Next > Sim > Next > Next e espere terminar de instalar.

Quando a instalação estiver concluída essa imagem irá aparecer:

http://img477.imageshack.us/img477/2709/tutosql7og.png

Na janela você coloca o seu email e a sua senha e uma janela assim irá aparecer:

http://img468.imageshack.us/img468/6209/tutosql4oc.jpg

Clique na janelinha do lado da carinha, e espere ele a fazer o Update do seu host.

Se tudo estiver correto uma mensagem assim irá aparecer:

seuserver.no-ip.info: DNS update successful

[ Capítulo 3 ]

Instalando e Configurando o Xampp.

Clique no Zip OU no Exe.
Após clicar, selecione um dos mirrors e clique em Download.

Quando terminar de fazer o download, extraia os arquivos em C:\ (Ou qualquer outro lugar que você queira.)
Uma vez que a instalação estiver finalizada, vá até C:\ (Ou na pasta que você extraiu o Xampp) e abra a pasta chamada xampplite.

Abrindo esta pasta, procure por setup_xampp.bat e dê um clique duplo.

Imagem do Arquivo:
http://img413.imageshack.us/img413/8954/setupxampppic4ms.png

Quando você iniciar o setup_xampp.bat, algo parecido com isso deve aparecer:

http://img107.imageshack.us/img107/7880/openingsetup3tk.png

Espere carregar até aparecer a mensagem "Press any key to continue".
Logo após, pressione qualquer tecla para fechar a janelinha.

Após tudo isso, vá até a pasta xampplite denovo, e clique em xampp_control.exe

Algo parecido com isso vai aparecer:

http://img107.imageshack.us/img107/5922/controlpanel9mg.png

Agora clique nos Botões de Start do Apache do MySQL, circulados em vermelho.

Após ter clicado, algo assim vai aparecer:

http://img413.imageshack.us/img413/9071/controlpanel23lj.png
Agora clique no "X" para fechar esta janela, mas observer bem, isso NÃO irá finalizar o xampp, olhe na barra de tarefas e você vera um ícone laranja, o xampp está lá, rodando perfeitamente.
Agora, vamos registrar o seu xampp.

Vá até http://127.0.0.1
Agora selecione uma língua, de preferencia uma que você entenda xP
Após isso, clique em "Security" painel esquerdo e algo como isso irá aparecer:

http://img401.imageshack.us/img401/5308/nextlink5cb.png

Está vendo está imagem? Sim, é claro, agora veja lá em baixo dela, um link circulado.
Pois é, viu? Clique nele e algo assim irá aparecer:

http://img127.imageshack.us/img127/3015/xampphs6.jpg

ATENÇÃO: Selecione o seu Root password ANTES de selecionar o diretório de Proteção do Xampp, assegure-se de usar senhas LONGAS e SEGURAS.

*Dica:

Adicione aos seus favoritos:
http://127.0.0.1/xampp como "Xampp CP"
http://127.0.0.1 acomo "Website"
http://127.0.0.1/phpmyadmin como "MySQL CP".
Use seu Root password que você escolheu antes para logar no pmA.

Agora faça o seguinte, faça o download do seu eAthena, e coloque ele DENTRO da pasta do Xampp.

Ex: C:\xampplite\eAthena\

Agora, vá até a pasta C:\xampplite\eAthena\conf

E abra o arquivo inter_athena.conf e procure por isso:
Obs: Não modifique a parte do TXT -> SQL Convertors ao menos que você saiba oque está fazendo.

Agora vamos a parte mais chata e complicada.

No campo "Cria novo banco de dados" escreva ragnarok e clique em "CRIA"

Obs.: COM A INICIAL EM MINÚSCULO, SENÃO ISSO IRÁ ACARRETAR UM ERRO !

Se tudo ocorrer bem isso irá aparecer:

http://img439.imageshack.us/img439/6673/tutosql28on.jpg

Agora vamos importar as tabelas.

Para importar as tabelas você tem que fazer o seguinte:

Verifique se o seu banco de dados está vazio onde aparece ragnarok (-)o sinal de "-" significa que ele está Intacto.

Agora clique no botão "SQL".

Na janela Pop-Up clique em "Import files". e depois clique em procurar.

Vá até a pasta SQL-files do seu eAthena e selecione o arquivo MAIN.SQL e clique em executa...
Se você fez correto, devera aparecer essa janela:

http://img421.imageshack.us/img421/8287/tutosql36qn.jpg

"db_tables.sql", "item_db.sql" "mob_db.sql", "mob_db2.sql", "MAIL.sql", "logs.sql" e "convert_engine"*

*Convert Engine é usado para transformar as tabelas de InnoDB para MYISAM.

FAÇA TUDO NESTA MESMA ORDEM !!

Não confunda MAIN.sql com MAIL.sql, isso vai causar um grande problema.

OBS: Apenas a tabela do MAIN.sql é necessária para rodar o servidor, as tabelas acima são usadas como tabelas complementares pra quem usa as tabelas do SQL e não os TXTs.

Mas espere, você ainda não terminou.

De um F5 no seu Browser e verifique se no banco de dados “ragnarok” aparece o numero 79.

Se não apareceu ou se der um numero menor, NÃO FAZ MAL, mas se você quer usar as tabelas do SQL ao invés dos TXTs, faça tudo denovo.

Digite denovo:

http://127.0.0.1/phpmyadmin

Coloque seu login se necessário e depois clique em "privilégios".

Não selecione o item ROUTER, e clique em executar.

Agora clique em "Adicionar Novo Usuario".

No campo "Nome De Usuario" escreva: ragnarok
No campo "Servidor" selecione na aba o item: Local (LocalHost)
No campo "Senha" digite: ragnarok
E no campo "Re-Digite" re-digite: ragnarok

Apos isto clique em "Marcar All" e clique em executar no final da página.

E o seu servidor está pronto, mas NÃO RODE ELE AINDA!
Agora vamos configurar seu servidor!

[ Capítulo 4 ]

Configurando seu Servidor

Primeiro vou apresentar uma simples FAQ.

Battle.conf

É onde você defini algumas das penalidades e delay de algumas Skills.

-------------------------------------------------------------------------------------
Client.conf

É onde você defini coisas dos players como Max Level e Max Stats.

-------------------------------------------------------------------------------------

Drops.conf

É onde você defini as configurações para os Itens.

-------------------------------------------------------------------------------------

Exp.conf

É onde você defini as rates do seu servidor e tipo de experiência para casos especiais.

-------------------------------------------------------------------------------------

GM.conf

É onde as configurações para os chars dos GMs são ativadas.

-------------------------------------------------------------------------------------

Guild.conf

É onde você defini as configurações para sua WoE e para as Guilds.

-------------------------------------------------------------------------------------

Homunc.conf

É onde você defini as configurações para seus homunculus

-------------------------------------------------------------------------------------

Items.conf

É onde você defini as configurações para uns itens especiais.

-------------------------------------------------------------------------------------

Misc.conf

É onde você defini as coisas básicas do servidor, como o tempo de duração do dia e da noite.

-------------------------------------------------------------------------------------

Monster.conf

É onde você defini as configurações para os mobs.

-------------------------------------------------------------------------------------

Party.conf

É onde você defini as Configurações para as partys do seu servidor.

-------------------------------------------------------------------------------------

Pet.conf

É onde você configura os pets do seu servidor para atacar e etc...

-------------------------------------------------------------------------------------

Player.conf

É onde você configura coisas básicas para os players como rate do HP e SP.

-------------------------------------------------------------------------------------

Skill.conf

É onde você defini as configurações que influenciarão as skills como Delay e etc..

-------------------------------------------------------------------------------------

Status.conf

É onde você defini as configurações que influenciarão nas skills, como efeitos causados e etc..

-------------------------------------------------------------------------------------
Pronto ! Após esse mini FAQ vamos configurar o seu servidor !

Agora iremos definir as rates, o Level Máximo, Máximo de Stats etc...

Configurando o Client !

Abra a pasta eAthena\conf\battle e prossiga todos os passos seguintes.

Obs.: Se não tiver uma pasta CONF e sim uma CONF-tmpl é só renomear.

Abra o Client.conf e procure por:
Troque por 255, com isso seu servidor terá 255 como level máximo e não se preocupe com a descrição acima, lembre-se de editar sua Exp Table, confira o Guia de como Mudar a Exp table no Capitulo 6 onde tem as Configs Adicionais.
Aqui você defini o número máximo de pallets.

Obs.: Apenas mude max_hair_style e o max_cloth_color e certifique-se que você tem o mesmo número de pallets que você colocar nas configurações !

Agora feche e salve as modificações e abra o player.conf e procure por isso:
Mude de 99 & 80 para o número que você quiser

Obs.: Não recomendo mais do que 999 de Stats.

Agora feche e salve as modificações e abra o drops.conf e procure por isso:
Mude as Rates de todas as coisas que você quiser, como drop de cards equips e etc...

Lembrando que 100 = 1x || 1000 = 10x || 10000 = 100x || 100000 = 10000x e assim por diante...
Agora feche e salve as modificações e abra o exp.conf e procure por isso:
Aqui você muda as rates de Base e Job Level do seu servidor.

Lembrando que 100 = 1x || 1000 = 10x || 10000 = 100x || 100000 = 10000x e assim por diante...

Agora para você não upar 1 level por vez ache isso:

e mude para YES, assim ele upara mais de um level por vez.

Agora feche e salve as modificações e abra o skill.conf e procure por isso:
Aqui você defini o mínimo de dex para ter Instant Cast, e para cancelar o delay procure por isso:

e Mude para Yes.

Agora vamos a algumas configurações adicionais:

Quer o seu servidor PK ?

Abra o arquivo MISC.conf e procure por:
Mude para YES para abilitar.

Mude para NO para desativar o MUTE dos players.
Ajuste o level mínimo para que ele possar participar do PK.

Quer que mostre o HP dos monstros ?

Abra o arquivo MONSTER.conf e procure por isso:

Mude para YES que o HP do monstro aparecerá.
Pronto, após fazer isso tudo, vamos configurar os IPs do servidor.

Saia da pasta eAthena\conf\battle e vá para pasta eAthena\conf

Abra o char_athena.conf.

Mude o nome do seu servidor logo acima e depois procure por isso:
Agora mude os IPs em vermelho para o seu host no No-IP, então ficaria:
Obs.: NÃO ESQUEÇA DE RETIRAR AS BARRINHAS DUPLAS // OU A CONFIGURAÇÃO NÃO IRÁ FUNCIONAR.

Agora abra o arquivo map_athena.conf.

E mude os IPS em vermelho denovo para o seu host no No-IP.
Então ficaria:
Obs.: NÃO ESQUEÇA DE RETIRAR AS BARRINHAS DUPLAS // OU A CONFIGURAÇÃO NÃO IRÁ FUNCIONAR.

Agora abra o arquivo subnet_athena.conf e ache isto:

Aqui você coloca a sua máscara de rede e o host do No-IP, então ficaria:
Agora abra o arquivo GRF-Files.txt e ache isto:
Geralmente ficaria assim:
E veja se você colocou o caminho das GRFs corretamente, senão o seu eAthena não carregará nenhum mapa.

Pronto o seu Emulador está configurado!

Agora é só ir ajustando de acordo com o pedido dos usuários... xD

[ Capítulo 5 ]

Adicionando NPCs

Como adicionar NPCs ?

Se você quer inserir NPCs como Reset Girl e Etc... Abra o arquivo scripts_custom.conf.
Ache isto:

E apenas retire as // assim:
Agora se você quiser adicionar scripts feitos por você salve os NPCs na sua pasta npc\custom.

Agora vá até a sua pasta NPC e abra scripts_custom.conf.

Ache isto:
E adicione assim:
E você adicionou seus NPCs !!

[ Capítulo 6 ]

Criando sua Conta de GM.

1º Abra seu pmA.

2º Selecione seu Banco de Dados "ragnarok"

3º Abra A tabela Login..

http://img224.imageshack.us/img224/3170/gmacc4fn1to.png

4º Clique em visualizar e essa janela ira abrir:

http://img209.imageshack.us/img209/3605/gmacc13tc.png

5º Encontre a conta que você quer editar

6º Clique no lapizinho ^^

7º Na tag level edite para o número correspondente ao level de GM

8º Depois é só clicar em executar no final da página !!!

[ Adicionando a Roupa GM ]

Agora essa é a parte Mais Fácil...
Você Tem que ir na pasta DATA no Diretorio do seu Ragnarok..ache o sclientinfo.xml e abra com o bloco de notas.

Vai aparecer algo assim:
Em Azul é o lugar para você colocar o ID que você axou na tabela Login no seu pmA.

Supondo que o ID seja 2000000, então ficaria assim:
[ Capítulo 7 ]

[ Configurações Adicionais ]


Instalando o ROCP by Cadinho

Instalando o Ceres CP by Cadinho [ Alternativo e Recomendado ]

Configurando Firewall by newtcv

Fazendo seu Hexed by Banned

Criando Custom Itens by dex

Editando sua Exp Table by Mr. Sapphire

Importante: Os Paineis de Controle devem ser adicionados na pasta C:\xampplite\htdocs para que eles possam funcionar!


Notas Adicionais:

Se o Emulador disser que tem um erro com a senha s1/p1, você pode alterar na tabela Login a senha e o login da conta do servidor facilmente.

Clique no Banco de Dados “ragnarok” e depois em visualizar na tabela login.

Na tag de login e senha, mude para algo fácil de se lembrar e difícil de hackear.

Então feito isso, Abra o arquivo char_athena.conf e o arquivo map_athena.conf ache isso:
E mude para a MESMA coisa que você colocou na tabela login e a mesma coisa nos dois arquivos.

Obs.: O Tutorial foi criado com a Versão eAthena SQL SVN TRUNK 9930


©2006 Banned Network®.
Créditos: Jaguar, Snails, Saory, MaN..., Mr. Sapphire, don'tBR, newtcv, dex, Cadinho, CuraX e Banned.
Este Tutorial está Protegido Sobre a licensa da Creative Commons.
Se Copiar Ponha Créditos e Copie Direito.
É totalmente proibida a reprodução deste tutorial sem autorização do dono.

MVP's (criaturinhas de GM)



Índice:
. Por que Caçar um MvP.
. Regras do Jogo.
. O Que é um MvP.
. Esteja Bem Equipado.
. Convenções
. Lista de MvP´s .

. Por que caçar um MvP:

Porque matar um MvP é bastante compensatório, ele te dá um nível bem alto de experiência, quanto mais o MvP sofrer dano mais será a experiência que o ganhador do MvP ganhará (ganha o MvP que der mais dano nele) e somente o ganhador tem direito aos itens deixados pelo MvP, itens que também costumam ser raros e valiosos. /no1

. Regras do Jogo:

Um MvP é considerado FFA (ou Free for all que em português seria livre pra todos, ou seja não é considerado Kill Steal ataca-lo se outro grupo já o estiver fazendo).
O que acontece é que muitas pessoas substituem FFA por FA ou seja Tudo liberado e é aí que mora o perigo e faz com que muitos jogadores se tornem mau vistos, por interpretarem a regra desse jeito, jogando por exemplo o mob ou o MvP no grupo Rival com skills que lançam o MvP para trás, ou então usando skills que simplesmente anulam o ataque do outro grupo como a skill pneuma do noviço.
Lembro mais uma vez que o ÚNICO dono dos itens deixados pelo MvP eh o ganhador do mesmo! Ou seja, os itens não são FFA .

.O que é um MvP:

MvP é um monstro que poderia ser considerado um “Boss”, ou chefe de fase ou mapa se preferir, ele está presente em alguns mapas e renasce normalmente a cada 1h e apenas 1 em cada mapa onde estão presentes, sempre trazem com ele seguidores ou MOB´s de monstros normalmente fortes.
Como já foi dito todos podem atacá-lo, mas o Loot (ou itens que o MvP deixa depois de morrer) é apenas do vencedor, ou seja o personagem que deu mais dano no MvP, Mas como eu descubro isso?
Aparecerá em sua tela, que você é o ganhador de MvP e o que você ganhou em itens ai é só pegar rapidamente os itens no chão e comemorar a experiência ganha e os itens. /no1

. Esteja Bem Equipado:

Para ir Caçar um MvP você deve estar ciente qual a fraqueza dele, qual o tamanho dele e qual a raça dele.
Por quê?
Simples! Porque caçadores podem se aproveitar da combinação: Arco com as cartas certas (cardeado) + flecha elemental, ninguém mais pode fazer isso a não ser os caçadores. (armas elementais não vem com slot logo mercenários e cavaleiros não podem se beneficiar do mesmo ).
Além de estar bem equipado, espera-se que esteja bem preparado também, um bom personagem pra MvP deve masterizar “Flagelo das Feras” (habilidade de caçador) pois ela te permite masterizar o dano em monstros tipo inseto e Bruto, que aliás é o tipo de vários MvP. /no1

Algumas cartas boas contra MvP são:
Minorous +15% de dano em Monstro tamanho Grande.
Goblin +20% de dano em monstros do tipo Bruto (muitos MvP são desse tipo).
Caramelo +20% de dano em monstros tipo inseto.
Carta Poring Noel +20% de dano em monstros com a propriedade Sombrio
Carta Esqueleto Soldado +15% de dano contra monstros do tipo médio (bom contra alguns mobs dos MvP´s).
Carta Vadon +20% de dano em monstros da propriedade fogo
Carta Hidra: +20% de dano em monstros do tipo Humanóide

Enfim outras cartas que sigam a mesma análise, ou seja, cartas que façam a combinação com a flecha elemental que explore sua fraqueza.
Cartas que devem ser consideradas também são cartas parar se “segurar” mais o MvP, ou seja, cartas que te protegem contra o dano elemental do monstro, cartas como:
Carta Dokebi encanta a armadura com a propriedade vento.
Carta Peixe Espada encanta a armadura com a propriedade água .
Etc.

Cartas que também são recomendadas são cartas que lhe protegem de status como:
Carta Cavalo Marinho torna o usuário imune a congelamento.
Etc.

. Lista de MvP´s:

- BESOURO LADRÃO DOURADO (GTB)

Level: 64
HP: 86000
Elemento: Fogo - 2
Tamanho: Grande
Tipo: Inseto
Flecha recomenda: Flecha de cristal (175% de dano) [produzida a partir do item cristal azul]
Pontos de experiência: 14300
Pontos de classe: 7150

Ataque: 870~1145

HIT: 159
FLEE: 224

MOB: Besouro Ladrão Macho (mob fácil senão ridículo)
Habilidades:
• Lv 1 Teleport
• Lv 8 Summon Monster
• Lv 5 Fire Attack
• Lv 10 Two Hand Quicken
• Lv 8 Summon Slave
• Lv 1 Hiding
• Lv 1 Guide Attack
• Lv 7 Fire Wall
• Lv 10 Fire Bolt
• Lv 1 Critical Slash
• Lv 7 Magnum Break
• Lv 10 Mammonite
• Lv 1 Increase AGI
• Lv 10 Heal

Itens:Oridecon(15%), Elunium(20%), Emperium(3%), Golden Bell (Não sei a tradução) (5%), Ouro(10%), Peça Dourada(2.5%), Maçã Dourada(1.5%), Carta Besouro Ladrão Dourado (0.01%)
Ora Ora(10%), Anel de Ouro(20%).

Encontra-se em: prt_sewb4(1) ou em língua de gente /heh quarto andar do esgoto de prontera.

Comentários:
O Mais fácil dos MvP´s na minha concepção, não é agressivo e tem baixo HP, a única coisa que dá medo mesmo é o ataque dele conhecido como mammonita level 10 esse machuca muito. Dá pra você solar ele com um bom arco cardeado pra ele com minorous e caramelo por exemplo /no1

- GARM ou HATI

Nível: 73
HP: 197000
Tamanho: Grande
Elemento: Agua-4
Tipo: Bruto
Flecha recomendada: Flecha de Vento (200% de dano) [é produzida a partir do item vento Bruto]
Pontos De Experiência: 50050
Pontos De Classe: 20020

Ataque: 1700 ~ 1900

HIT: 219
FLEE: 243

MOB: Sasquatch
Habilidades:
• Lv 1 Blood Drain
• Lv 4 Summon Monster
• Lv 5 Adrenaline Rush
• Lv 10 Cold Bolt
• Lv 5 Water Attack
• Lv 10 Two Hand Quicken
• Lv 4 Summon Slave
• Lv 1 Guide Attack
• Lv 8 Frost Driver
• Lv 8 Frost Nova
• Lv 1 Critical Slash
• Lv 7 Endure
• Lv 1 Decrease AGI
• Lv 1 Increase AGI

Itens:Oridecon(29%), Elunium(41%), Presa*(55%), Presa De Hatii*(90%),
Katar Gélida(%), Ice Falshichion(1.5%), Velha Caixa Azul(30%), Presa De Hatii(55%), Gelo Mistico(30%).

Aparece em : xmas_fild01(1) ou em linguagem de gente Arrendores de Lutie 01

Comentários: o Hatii é muito lerdo sendo um dos mais fáceis pra Mvpar com uma boa estratégia, um arco com as cartas minorous e goblin faz um ótimo trabalho com ele e seu mob, uma vestimenta com carta Cavalo Marinho ou peixe espada é uma boa pedida também.

- PHREEONI

Nível: 69
HP: 188000
Tamanho: Grande
Elemento: Normal - 3
Tipo: Bruto
Pontos de experiência: 32175
Pontos de classe: 16445

Ataque: 880~1530
HIT: 174
FLEE: 274
MOBS: Hodes
Skills:
• Lv 1 Teleport
• Lv 5 Summon Monster
• Lv 5 Earth Spike
• Lv 7 Stone curse
• Lv 5 Mental Breaker
• Lv 5 Earth Attack
• Lv 10 Two Hand Quicken
• Lv 5 Summon Slave
• Lv 1 Hiding
• Lv 5 Brandish Spear
• Lv 5 Heaven's Drive
• Lv 1 Critical Slash
• Lv 1 Increase AGI
• Lv 1 Guide Attack

Items: Oridecon(21%), Elunium(29%), Lingua(100%), Ant Jaw*(50%), Mascara assuatadora(5%)
Adaga Da Boa Ventura(5%), Sucsamad(1.5%), Carta Phreeoni(0.01%),
Diamante de 1 Quilate(10%), Star Crumb(40%).

encontra-se em: moc_fild15(1) ou em linguagem de gente: Formigueiro Infernal Level 1
Comentários: É um Mvp bem fácil com o porém de não possuir fraquezas a elemento algum então use flecha de fogo em seu Mob que pode até ser mais perigoso que ele e nele use flecha normal ou prata mesmo. Com um arco com carta para monstros brutos e grandes (minorous e goblin).
- EDDGA
Nível: 65
HP: 152000
Tamanho: Grande
Elemento: Fogo - 1
Tipo: Bruto
Pontos De Experiência: 25025
Pontos De Classe: 12870

Ataque: 1215~1565

HIT: 155
FLEE: 230
MOB: Pé Grande (Não causa medo não e o mesmo arco usado contra o MvP pode ser aproveitado aqui)

Habilades:
• Lv 1 Teleport
• Lv 5 Summon Monster
• Lv 7 Spear Stab
• Lv 5 Fire Attack
• Lv 10 Two Hand Quicken
• Lv 5 Summon Slave
• Lv 1 Guide Attack
• Lv 10 Fire Ball
• Lv 1 Critical Slash
• Lv 7 Magnum Break
• Lv 7 Endure
• Lv 1 Increase AGI

Itens:
Oridecon(17%), Elunium(23%), Mel(100%), Katar of Raging Blaze(5%),
Caximbo(2.5%), Linguá De Fogo(1.5%), Carta Eddga (0.01%),Pele De Tigre(50%), Coração Flamejante(30%), Pata De Tigre*(10%)

Aparece em: Pay_Fild10 ou em linguagem de gente, o mapa onde Se vira Caçador
Comentários: MvP bem fácil, com o porem que seu Fireball dói um pouco, mas se estiver bem equipado e com um sacerdote você ganha fácil esse MvP o mesmo arco usado pro Hatii eh recomendado aqui, seu dano será bem alto com o mesmo, combinando com a flecha certa /no1

-FLOR DO LUAR
Nível: 67
HP: 120000
Tamanho: Médio
Elemento: Fogo - 3
Tipo: Demonio
Pontos De Experiência: 27500
Pontos de Classe: 14300

Ataque: 1200~1700
HIT: 186
FLEE: 237

Monstros que vem com ele: Nove Caldas
Habilidades:
• Lv 10 Heal
• Lv 1 Teleport
• Lv 5 Summon Monster
• Lv 5 Earth Spike
• Lv 1 Cloaking
• Lv 5 Cold Bolt
• Lv 10 Two Hand Quicken
• Lv 5 Summon Slave
• Lv 1 Guide Attack
• Lv 5 Fire Bolt
• Lv 1 Critical Slash
• Lv 7 Mammonite
• Lv 5 Lightning Bolt
• Lv 5 Random Attack
• Lv 7 Endure
• Lv 1 Increase AGI

Itens:
Oridecon(19%), Elunium(26%), Puppy Love*(10%), Punisher*(5%),
Adaga prata de catidade(6.5%), Maça Longa(1.5%), Walgwanggum(1%),
CartaMoonlight Flower (0.01%), Nove Caldas(50%), Poção Branca(15%), Topaz(5%)

Encontra-se em : pay_dun04(1) ou em língua de gente: quinto level da Caverna De Payon

Comentários: A facilidade com esse MvP vem de sua imensa frakesa à propriedade água, o maior perigo vem de seu MOB que ataca muito rápido, recomenda-se ir com um sacerdote ou se for sozinho, tente matar o mob antes e o mais rápido possível, aproveite das frakesas e propriedades do Moonlight para mata-lo rapidamente /no1

- ABELHA RAINHA ou MISTRESS

Nível: 74
HP: 212000
Tamanho: Pequeno
Elemento: Vento-4
Tipo: Inseto
Pontos De Experiência: 39325
Pontos De Classe : 27170

Ataque: 880~1100
HIT: 259
FLEE: 219
MOB: Petite Azul

Habilidades:
• Lv 1 Teleport
• Lv 10 Heal
• Lv 4 Summon Monster
• Lv 5 Wind Attack
• Lv 10 Two Hand Quicken
• Lv 4 Summon Slave
• Lv 1 Pneuma
• Lv 1 Guide Attack
• Lv 1 Critical Slash
• Lv 8 Jupitel Thunder
• Lv 8 Lex Divina
• Lv 3 Combo Attack
• Lv 1 Increase AGI

Itens:
Oridecon(33%), Elunium(44%), Mel(100%), Velho Album De Carta*(10%), Gungnir(1.5%),
Coroa Menor(2.5%), Toung Twig*(0.1%), Carta Mistress (0.01%),Geléia Real(40%), Vento Bruto(15%), Perola(30%)

Encontra-se em: mjolnir_04(1) ou em linguagem de gente: No monte Mijhonir acima do mapa dos argiopes.

Comentários: Mais um MvP que o Mob é mais perigoso que ele mesmo, mas seu maior problema é a Skill Pneuma, para poder se aproveitar da mesma utilize um bom arco cardeado (carta Lobo do deserto e caramelo) e as flechas corretas, a estratégia eh ao usar pneuma acione chuva de flechas e a retire da pneuma e volte aos ataques /no1
HEROI ORC

Nível: 77
HP: 290000
Tamanho: Grande
Elemento: Terra - 2
Tipo: Humanóide
Flecha recomendada: Fogo (175% de dano) [flecha produzida a partir de sangue escarlate ou comprada em Alberta]
Pontos De Experiência: 58630
Pontos De Classe: 32890

Ataque: 2257~2542

HIT: 188
FLEE: 257

MOB: Grande Orc / Orc Azul
Habilidades:
• Lv 1 Teleport
• Lv 5 Summon Monster
• Lv 5 Adrenaline Rush
• Lv 10 Thunder Storm
• Lv 5 Earth Attack
• Lv 10 Two Hand Quicken
• Lv 5 Summon Slave
• Lv 1 Guide Attack
• Lv 1 Critical Slash
• Lv 1 Maximize Power
• Lv 7 Endure
• Lv 1 Increase AGI

Itens:
Oridecon(37%), Elunium(47%), Orcish Sword*(10%), Monkey Circlet*(5%),
Escudo[1](2.5%), Light Epsilon*(1.5%), Carta Orc Hero (0.005%),Aço(50%), Sardonyx(20%), Fruto Yggdrasil (15%)

Aparece em: gef_fild14(1) ou em linguagem de gente: Arrendores De Geffen 14 (sul do mapa dos castelos de geffen ou esquerda da vila orc)
Comentários: o MOB dele dá muito trabalho, mas ele eh bem fácil, dah pra aproveitar-se de outro tanker pra matar ele ou sozinhu no hit and run ele tem cast time demorado, recomendo ir com sacerdote pois ele ataca bem rápido. Combinação pra arco: minorous e Hidra.

ORC LORD

Nível: 74
HP: 333000
Tamanho: Grande
Elemento: Terra-4
Tipo: Humanóide
Pontos De Experiência: 62205
Pontos De Classe: 8580

Ataque: 2700~3150

HIT: 176
FLEE: 259
MOB: Orc Arqueiro
Habilidades:
• Lv 1 Teleport
• Lv 4 Summon Monster
• Lv 10 Cold Bolt
• Lv 8 Spear Stab
• Lv 5 Earth Attack
• Lv 10 Two Hand Quicken
• Lv 4 Summon Slave
• Lv 1 Guide Attack
• Lv 10 Fire Bolt
• Lv 8 Provoke
• Lv 1 Critical Slash
• Lv 8 Lex Divina
• Lv 7 Endure
• Lv 1 Increase AGI

Itens:

Oridecon(31%), Elunium(44%), Cinto[1](10%), Anel(5%), Machado Sangrento(2%),
Grand Circlet(1.5%), Insignia Do Herói(55%), Caixa Velha Roxa(20%)

Aparece em : gef_fild10(1), ou em lingua de gente: Calabouço Dos Orcs Level 2

Comentários: MvP muito forte só recomendado com um tanker, ele tem um ataque muito forte é muito rápido e seu MOB é difícil, um bom arco as flechas certas e um tanker garantem um bom trabalho /no1


-Cavaleiro Da Tempestade

Nível: 77
HP: 240000
Tamanho: Grande
Elemento: Vento-4
Tipo: Sem forma
Pontos De Experiência: 64350
Pontos De Classe: 21450

Ataque: 1425~1585

HIT: 282
FLEE: 282

MOB: Hatii x2
Habilidades:
• Lv 1 Teleport
• Lv 4 Summon Monster
• Lv 5 Hallucination
• Lv 10 Storm Gust
• Lv 10 Safety Wall
• Lv 5 Wind Attack
• Lv 10 Two Hand Quicken
• Lv 4 Summon Slave
• Lv 1 Guide Attack
• Lv 1 Critical Slash
• Lv 1 Maximize Power
• Lv 8 Lightning Bolt
• Lv 1 Increase AGI

Itens: Oridecon(35%), Elunium(47%), Caixa Velha Azul(30%), Caixa Velha Roxa(40%), Manteau[1](5%), Anel[1](2%), Zephyrus(1.5%), Grand Circlet(0.02%), Aquamarine(45%), Gelo Mistico(30%), Botas[1](5%)

Enocntra-se: xmas_dun02(1), ou em linguagem de gente:Fábrica de Brinquedos level 2*
Comentários: MvP bastante forte com um mob muito Forte e com golpes muito fortes um tanker eh necessário aqui também, arco com carta ovo de peco peco eh bom contra ele /no1

OSIRIS

Nível: 78
HP: 415400
Tamanho: Médio
Elemento: Morto-Vivo - 4
Tipo: Morto-Vivo
Pontos de Experiência: 71500
Pontos De Classe: 28600

Ataque: 780~2880

HIT: 173
FLEE: 239

Vem com: Isis
Habilidades:
• Lv 1 Teleport
• Lv 5 Summon Monster
• Lv 5 Earth Spike
• Lv 5 Quagmire
• Lv 8 Stone curse
• Lv 5 Poison Attack
• Lv 10 Two Hand Quicken
• Lv 5 Summon Slave
• Lv 10 Bash
• Lv 8 Venom Dust
• Lv 1 Critical Slash
• Lv 1 Increase AGI
• Lv 1 Guide Attack
• Lv 1 Curse Attack

Itens: Oridecon(39%), Caixa Velha Roxa(20%) Mão De Deus*(10%), Sphinx Helm*(1.5%),
Coroa(2%), Adaga de Assassino*(1.5%), Jamadhar(6%), Carta Osiris (0.01%),
Caixa Velha Azul(20%), Boneco De Osiris(5%), Semente de Yggdrasil (30%)

Aparece em: moc_pryd04(1), ou em linguagem de gente: Piramide Level 4 (mapa das múmias, isis, matyr, etc)
Comentários: MvP Bastante concorrido, principalemnte pelos drops, um sacerdote segura ele fácil, ou mesmo você sozinho solando pode pegar esse mvp.

MAYA


Nível: 81
HP: 169000
Tamanho: Grande
Elemento: Terra-4
Tipo: Inseto
Flecha Recomendada: Flecha de Fogo (200% de dano) [Flecha obtida com o uso de um sangue escarlate]
Pontos De Experiência: 42900
Pontos De Classe: 17875

Ataque: 1800~2070

HIT: 198
FLEE: 239
Vem com: Arclose
Habilidades:
• Lv 10 Heal
• Lv 1 Teleport
• Lv 5 Summon Monster
• Lv 10 Safety Wall
• Lv 5 Earth Attack
• Lv 10 Two Hand Quicken
• Lv 5 Summon Slave
• Lv 8 Pierce
• Lv 1 Guide Attack
• Lv 5 Brandish Spear
• Lv 5 Heaven's Drive
• Lv 1 Critical Slash
• Lv 1 Maximize Power
• Lv 1 Increase AGI

Itens:Oridecon(25%), Elunium(35%), Ornamento Da Rainha(5%), Anel De Defesa(2%), Armlet of Obediance*(5%), Tiara[1](2%), Mother's Nightmare*(0.02%),
Carta Maya(0,01), Caixa Velha Azul(30%), Caixa Velha Roxa(20%), Diamante de 1 quilate(20%)

Encontra-se em: anthell02(1), gld_dun03(1) ou em linguagem de gente: Formigueiro Infernal 2

Comentários: Maya é como o Osíris um MvP muito Disputado como se pode perceber toda vez que se passa por ela, e isto se deve pricipalmente pelo seu loot, Para matar ela eh bom ter um tanker no Grupo, pois suas skills são bem fortes e seu atake tmbm /no1 (mas com um sacerdote e poções tudo eh possível pra um caçador com a vestimenta correta).Arco com Minorous e caramelo eh uma boa escolha /no1

DRAKE

Nível: 70
HP: 276666
Tamanho: Médio
Elemento: Morto-Vivo-1 / Aguá - 3
Tipo: Morto-Vivo 1
Flecha Recomendada: Flecha de Prata (150% de dano) [Obtida atraves de qualquer NPC que venda flechas]
Pontos De Experiência: 28600
Pontos De Classe: 22880

Ataque: 1800~2100

HIT: 170
FLEE: 224

MOB: Alma Penada
Habilidades:
• Lv 5 Summon Monster
• Lv 10 Waterball
• Lv 5 Water Attack
• Lv 10 Two Hand Quicken
• Lv 5 Summon Slave
• Lv 1 Guide Attack
• Lv 1 Critical Slash
• Lv 1 Maximize Power
• Lv 1 Change Water
• Lv 8 Endure
• Lv 4 Spear Boomerang
• Lv 1 Decrease AGI

Itens:Oridecon(23%), Elunium(32%), Sabre[3](9.5%), Sabre De Impacto(6%), Cutelo(1.5%),Haedonggum[2](4%), Chapéu De Corsário(3.5%), Carta Drake (0.01%), Amethyst(5%), Poção Branca(50%)

Aparece em: treasure02(1), ou em bom português: Navio Fantasma Level 2
Comentários: Apesar de forte ataque rápido, e boas skills é bastante simples mata-lo como caçador um pouco de poção e o arco certo você leva ele fácil o problema aqui é o Water ball dos bruxos, que tira um dano bem alto e no mapa tem água, mas sem esse porém o caçador leva fácil esse /no1 .


SENHOR DAS TREVAS

Nível: 80
HP: 340000
Tamanho: Grande
Elemento: Morto-Vivo -4
Tipo: Demonio
Flecha Recomendada: Prata ou Fogo (200% de dano) [Ambas compradas em NPC]
Pontos De Experiência: 65780
Pontos De Classe: 45045

Ataque: 2800~3320

HIT: 220
FLEE: 254

Vem com: Senhor Das Ilusões
Habilidades:
• Lv 1 Teleport
• Lv 1 Energy Drain
• Lv 4 Summon Monster
• Lv 5 Wind Attack
• Lv 10 Two Hand Quicken
• Lv 4 Summon Slave
• Lv 1 Guide Attack
• Lv 7 Fire Wall
• Lv 1 Critical Slash
• Lv 1 Magical Attack
• Lv 9 Meteor Storm
• Lv 1 Curse Attack
• Lv 1 Increase AGI

Items: Oridecon(41%), Elunium(53%), Bastão Arcano(8%), Elmo De Osso(5.5%) (5.5%), Anel De Caveira(10%),
Adaga Sinistra(3%), Vestimenta Arcana (3%), Capa velha de Marquês (1%),
Crânio(60%), Caixa Velha Roxa (20%) .

Aparece em: gef_dun03(1), gld_dun04(1), gl_chyard(1) mas atualmente apenas (pelo que sei) em: Cemitério de Glast Helm
Comentários: Considerado um dos MvP´s mais difíceis junto com o Bafomeh e o Pharaoh que ainda não tem no Bro. Sem chance de solar ele, muito difícil de ter alguém para tanka-lo o negocio em minha opinião é estar na hora certa com ele e o MOB dele é muito difícil, eu recomendaria ir acompanhado de um bom grupo, sacerdotes e mais de um caçador para suporte tanker e mata-lo mais rápido, (é o meu MvP predileto).

DOPPELGANGER

(o “Doppel” tem respawn de duas horas, ou seja nasce de duas em duas horas)
Nível: 72
HP: 149000
Tamanho: Médio
Elemento: Sombrio-3
Tipo: Demônio
Flecha Recomendada: Flecha de Prata (dano 150%) [Comprada em Qualquer NPC]
Pontos de Experiência: 51480
Pontos De Classe: 10725

Ataque: 1340~1590

HIIT: 182
FLEE: 272
MOB: Pesadelo e Raydriks
Habilidades:
• Lv 1 Teleport
• Lv 10 Heal
• Lv 5 Summon Monster
• Lv 5 Counter Attack
• Lv 5 Shadow Attack
• Lv 10 Two Hand Quicken
• Lv 5 Summon Slave
• Lv 8 Pierce
• Lv 1 Guide Attack
• Lv 10 Frost Driver
• Lv 1 Critical Slash
• Lv 1 Maximize Power
• Lv 1 Blind Attack
• Lv 7 Endure
• Lv 1 Increase AGI

Items: Oridecon(27%), Elunium(38%), Armadura Metálica[1](2.5%),Espada Bastarda*[2] (2.2%), Zwehander(3%), Spiky Band*(3.5%), Lança(5.5%),
Carta Doppleganger (0.01%), Poção Azul(60%), Ruby Amaldiçoado*(15%)
Encontra-se em: gef_dun03(1) ou em bom português: Torre de Gefen Level 3

Comentários: Este MvP especialmente precisa de um bom tanker com carta Khalitzburg pra agüentar o ataque rápido e poderoso que este MvP tem, (possuidor da carta dos meus sonhos) pra vence-lo é necessária uma tática concisa, pois suas skills são muito boas e ele é muito rápido. Um arco com Esqueleto Operário, Poring Noel e/ou Strouf eh Bastante Recomendado /no1 (sacerdote dando aspersio é de grande valia) Seu MOB de pesadelos pode dar algum trabalho.

DRÁCULA

(até onde eu sei esse MvP ainda não existe no Bro, até porque nunca trombei com ele por aqui)
Nível: 85
HP 320096
Propriedade: Sombrio- 4
Raça Demônio
Flecha Recomendada: Prata (200% de dano) [Comprada em qualquer NPC que venda flechas]
Pontos de Experiência 120157
Pontos de Classe 38870 Size Large

Ataque 1625 ~ 1891

Flee:245
Hit: 200

MOB: Sucubus

Habilidades:
• Lv 1 Teleport
• Lv 5 Blood Drain
• Lv 5 Mental Breaker
• Lv 1 Cloaking
• Lv 6 Summon Monster
• Lv 6 Summon Slave
• Lv 1 Decrease AGI
• Lv 7 Combo Attack
• Lv 10 Two Hand Quicken
• Lv 5 Grimtoot

Itens: Balista (0.05%), Fruto de Yggdrasil (47%), Capa Antiga (0.15%) Anel[1] (0.04%), Bastão de Bruxo (0.05%), Livro do Apocalipse (0.04%), Carta Dracula (0.01%), Diamante 3 quilates (30%) e Fruta Mastela(10%)
Encontra-se em: gl_knt02, ou em bom portugues Cavalaria de Glast Helm, no Segundo andar.

Comentários: O MvP que possui um ataque alto, pode ser vencido com uma boa combinação de cartas como Strouf ou Poring Noel, seu MOB eh bem chato. (Um tanker no grupo com carta khalitzburg é recomendado)


AMON RA

Nível: 88
HP: 1214138
Propriedade: terra- 3
Tamanho: Grande
Raça: Humanóide
Flecha Recomendada: Fogo (200% de dano [Item feito com Sangue Escarlate ou comprada em NPC em Alberta]
Pontos de Experiencia 87264
Pontos de classe 35891

Ataque 1647 ~ 2576
Flee: 237
Hit: 109

MOB:

Encontra-se em: moc_pryd06(1) ou em língua de gente: sexto level da pirâmide (logo depois dos minorous e veryts)

Pharaoh


Nível: 93
HP : 445997
Tamanho: Grande
Raça: Humanóide
Propriedade:Sombrio - 3
Flecha Recomendada: Prata (175% de dano) [Comprada em qualquer NPC de flechas]
Pontos de Experiência:
Pontos de Classe:
Ataque: 2267 ~ 3015

Flee: 262
HIT: 206

MOB: Medusas e Pasanas

Habildidades:
• Lv 1 Teleport
• Lv 10 Two Hand Quicken
• Lv 3 Summon Monster
• Lv 3 Summon Slave
• Lv 1 Arrow Repel
• Lv 1 Dark Blessing

Itens: Iggdrasil berry(60%), Geléia Real (20%), Diamante três Quilates (10%), Oridrecon (45%), Manto Sagrado (1.5%), Máscara de Tuntakamon (25%), Jewel Crown (5%), Carta Pharaoh (0.01%), Espada Solar (1%) e Tablet[1] (3%)
Localização: in_sphinx5 ou Esfinge, Quinto andar.

Considerações: MvP Humanóide, um Tanker com carta sapo de thara no Escudo eh recomendado.Um arco com as cartas cartas Poring Noel e Minouros é indispensável. Seu Mob eh bem difícil, mas contra medusa use flecha de cristal e contra Pasana use um arco com cartas Esqueleto Operário.

GENERAL TARTARUGA

Nível: 97
HP: 320700
Propriedade: terra- 2
Raça: Bruto
Tamanho: Grande
Flecha Recomendada: Fogo (175% de dano) [flecha comprada no NPC em alberta, ou obtida através do item sangue escarlate]
Pontos de Experiência18202
Pontos de Classe 9800

Ataque: 2438 ~ 3479
Flee: 277
Hit: 162

MOB: Turtle
Habilidades:
• Lv 1 Teleport
• Lv 5 Summon Monster
• Lv 5 Waterball
• Lv 5 Stun Attack
• Lv 5 Earth Attack
• Lv 10 Sonic Blow
• Lv 10 Two Hand Quicken
• Lv 2 Summon Slave
• Lv 1 Guide Attack
• Lv 10 Brandish Spear
• Lv 1 Critical Slash
• Lv 1 Maximize Power
• Lv 7 Endure
• Lv 1 Increase AGI

Itens: Iron Driver (0.08%), Casca Quebrada (55%), Machado de guerra[1] (0.05%), Zargônio (55%), Poll Axe [1] (0.09%), Solidariedade Tribal (0.01%), Casca de tartaruga (55%), Fruto Yggdrasil (15%), velha caixa Roxa (20%)

Encontra-se em: Tur_dun04(1)

Comentários: um MvP muito Difcil, um bom tanker equipado com carta orc e um arco com carta minorous e goblin ajudam contra esse difícil MvP.

Baphomet

Nível: 81
HP: 568000
Tamanho: Grande
Elemento: Sombrio-3*
Tipo: Demônio
Flecha Recomendada:
Pontos De Experiência: 107250
Pontos de Classe: 37895

Ataque: 3220~4040

HIT: 253
FLEE: 276

MOB: Bafomet Jr.
Habilidades:
• Lv 1 Teleport
• Lv 4 Summon Monster
• Lv 5 Wind Attack
• Lv 10 Two Hand Quicken
• Lv 4 Summon Slave
• Lv 1 Guide Attack
• Lv 5 Brandish Spear
• Lv 1 Critical Slash
• Lv 1 Maximize Power
• Lv 10 Lord of Vermilion
• Lv 1 Curse Attack
• Lv 1 Increase AGI

Itens:Oridecon(43%), Elunium(56%), Presilha[1](8%), Caixa Velha Roxa(30%),
Emperium(5%), Foice(2%), Chifres Magestoso*(2%), Carta Bafomé (0.005%),
Chifre maligno(50%), Boneco De Bafomé(5%), Fruto Yggdrasil (20%)

enontra-se em: Castelo de Ghast Helm2 e Hidden Temple
Comentários: Um MvP bem difcil, seus skills são muito fortes e seu mob eh chato, um arco bem cardeado, um sacerdote e um bom tanker são necessários, além de um grupo de apoio.


Créditos ao Flavio do mmokidz!!!

Dicas para EM de eventos

Bem tive muitos anos de conhecimento na arte de criar eventos, sempre busquei inovar e acabou saindo algo legal que chama muita atenção hoje em dia.
Eu uso o sistema unico de RPG
onde todos os jogadores devem contar suas Historias e interpreta-las de maneira estupenda, para os melhores ... PRÊMIOS... certeza vocês terem um grande show em mãos

Bem em primeiro lugar, crie uma História para seu servidor
Exemplo:

1 Rainha de Amatsu começa a agir de maneira estranha, o rei Tristan resolve mandar um grupo de heróis confiáveis para analisar e eles desaparecem misteriosamente

"Ah mas Ferdinand essa Historia ta simples, como faço evento com isso para durar 6 meses ou a vida toda?"

é so uma questão de por a cabeça em funcionamento.. sente só

Mas a rainha era controlado por Freya, que nesse instante buscava trair os Deuses do Panteão fazendo o Ragnarok se aproximar

Olha só desse lugar ja sai muito evento ... um Deusa em fúria lembra essa caixinha


GM= DEUS Deusa em fúria = Gm sumonando mobs (criando eventos)


É fácil criar essas História !!!


Minha segunda dica é você conhecer o Emulador Cronus, ter um server próprio onde você sozinho cria seus eventos, faça os players criarem metas em suas Historias, caso seu servidor não tenha um acompanhamento de um analista de sistemas para por a informação no ato do cadastro “Historico” faça você mesmo no fórum de seu Server. Com a Historia dos Players ficaria bem legal você criar eventos personalizados e em casos onde o Server cresceu bastante, poderia organizar grupos de RPG, entre os clans existentes, onde esse grupos cuidariam de suas Historias, e a Woe seria uma opção.
Com essa estratégia, fiz os players acharem que à mais atrativos no Ragnarok do que o PvP ou a WoE, ele apreciam e acabam chamando os amigos com esse diferencial
“Galera meu servidor é muito rox!!!”
(o que tem nele ?)
“Muita Historia sobre as civilizações e seus mitos, eventos individuais e toda a nossa Historia e contada no Fórum, é uma verdadeira mesa de RPG online”

Notou uma certa diferença? É isso que os jogadores querem, DIVERSÂO !!!


Use sua Criatividade, e faça seu servidor ser diferente do normal!!!

sábado, 22 de novembro de 2008

@go @warp (Gm tem que ser mestre)


Estou escrevendo esse mini-guia pois percebi que tem muita gente que está começando com RO/PS’s e também para não ter mais tópicos do tipo: Socorro! A Teleportadora sumiu, o que vou fazer?

Antes de começar, gostaria de pedir ao Ralsj que caso essa não seja a seção própria para esse tipo de guia, que não o feche-o e sim, mova-o ao local certo.

Vamos ao guia:


- O que são comandos @go e @warp?
Os comandos @go e @warp são comandos de teleporte exclusivos de PS’s (Private Servers). Ao entrar com um desses comandos você será teleportado para o mapa que o comando indica. Ao dominar isso a Teleportadora se tornará bem inutil. ;D
Vou começar com o mais simples, os @go.

- O Comando @go
Os comandos @go são exclusivos para cidades, ou seja, para se telportar para dungeons ou campos você terá que usar o @warp. Para usar esse comando é necessário ter o conhecimento da cidade em que quer ir, cada cidade tem um “Numero Go”, esse comando não é nada mais nada menos do que um numero de 0 a 16 (acho).
Para usar o codigo é simples:
Digite o @go (somente isso pode ser digitado) e em seguida o numero do mapa.
Ex: Para ir para Prontera deve se digitar @go 0 (o 0 é o Numero Go para prontera) e apertar Enter.
Pronto, você está em prontera!

Dica: Para saber todos os Numeros Go, digite apenas @go e aperte Enter, esse comando faz com que a lista dos numeros aparece indicando cada cidade de RO.

- O Comando @warp
Antes de usar o @wap deve se conhecer outro comando fundamental para o dominio dele, o /where.

- O /where
Where sigfica Onde em inglês. Isso não vem ao caso, mas esse comando é uma especie de mapa ou bussula ou guia, chame-o como quiser, ele lhe fala detalhadamente onde você está, com o Código do Mapa e Coordenadas (veja a seguir). Ao explorar uma cave nova ou estar no lugar para aquela quest isso pode quebrar seu galho. Sempre o use quando estiver perdido ou ganho quiser voltar para o lugar onde você está. ;D

- (Agora sim!) O Comando @warp
Alguns meses atrás, alguns PS’s não possuiam o sistema @go. Era usado então os @warp. Esse comando pode te teleportar para qualquer mapa do jogo em qualquer célula do mapa que você quiser! É bem complexo e no começo pode ser dificil de usar.
Para usar esse comando é necessário saber o Código do Mapa, esse código é obtido quando se usa o comando /where (tá vendo como é útil?) no mapa em que você que saber o código. O cógio está entre parenteses e sempre é algo do tipo prt_fild00 ou pay_dun00).
Obs: ‘fild’ vem de Field que em Ingles siginfica Campo. E ‘dun’ vem de Dungeon que em Ingles significa Caverna. ‘prt’ e ‘pay’ vem de Prontera e Payon, cidades do jogo. Ou seja, “prt_fild00” é o código para um campo de prontera e “pay_dun00” é o código para a caverna de payon.
Os números no fim do código indicam o andar ou o numero do campo. Em certas cave (como a de payon) o primero andar não é 01, e sim 00. Isso as vezes pode confundir. Já que o segundo seria o 01 e não 02 e assim por diante.
Para saber os códigos dos campos veja algum mapa do jogo, geralmente tem os códigos, mas vou quebrar o galho se vocês de novo:

Link para o mapa com códigos: http://games.levelupgames.com.br/ragnaro...l_novo.php

Obs: A LevelUp! Games (distribuidores do bRO) não atualizou o mapa depois de Heritage. Então ai os códigos novos:

Campos de Loyang:
Lou_fild01

Campos de Ayothaya:
Ayo_fild01
Ayo_fild02

Para as cidades: procure no @go

Antes que você pense que ao chegar Einbroch e outras o cógido será as 3 primeiras letras na cidade ai vai um aviso, esses códigos são da versão coreana, as vezes os nomes podem mudar, po exemplo: Kunlun em outros RO’s se chama Gonryun, por isso o código de seu campo é “gon_fild01” e não “kun_fild01”. Sempre é bom verificar. ;D

- Coordenadas

Ao utilizar o comando /where você verá um pouco depois do código do mapa, algo do tipo “23, 91” (números meramente ilustrativos). Isso se chama Coordenada, adicionando isso ao comando @warp você será teleportado para a celula que essa coordenada indica. Como não uso @warp com coordenadas faz séculos não me lembro direito, mas acho que para coordenadas tinha que se colocar da seguinte maneira:
“@warp prt_fild05 34 65” (Mapa ao lado de prontera, numero de coordenadas meramente ilustrativos)
Se não for tentem colocar virgula entre os dois numeros, mas tenho quase certeza que é separado.

Com isso eu concluo esse mini-guia quebra-galho para inciantes em PS's. É preciso lembrar que certos servers não possuem esses sistemas e isso são códigos exclusivos de PS's, não tentem fazer isso em servidores oficiais (bRO, iRO) pois pagaram um mico brabo!

- Cógidos das Dungeons

Aqui vai os códigos para as dungeons, sempre que lançar novas dungeons ou atualizo aqui, se possivel. Se tiver algum código errado me avisem!

Navio Fantasma:
treasure01~02
Formigueiro Infernal:
anthell01~02
Túnel Submarino de Byalan:
iz_dun00~04
Torre do Relógio:
A-) Torre:
c_tower1~4
B-) Subterrânio:
alde_dun01~04
Cavernas de Comodo:
beach_dun
beach_dun2~3
Torre de Geffen (Geffen Dungeon):
gef_dun00~04
Floresta do Labirinto:
prt_maze01~03
Fabrica de Brinquedos de Lutie:
xmas_dun01~02
Caverna de Magma:
mag_dun01~02
Minas de Carvão:
mjo_dun01~03
Calabouço dos Orcs:
orcsdun01~02
Caverna de Payon:
pay_dun00~04
Esgotos de Prontera:
prt_sewb01~04
Pirâmides:
moc_pryd01~04
A-)Guilda dos Gatunos:
moc_prydb1
B-)Porão:
moc_pryd05~06
Esfinge:
in_sphinix1~5
Ilha das Tartarugas:
A-) Campo:
tur_dun01
B-) Caverna:
tur_dun02~04
Calabouço de Amatsu:
ama_dun01~03
Calabouço de Kunlun:
gon_dun01~03
Caverna de Umbala:
um_dun01~02
Árvore de Yggdrasil:
yggdrasil01

Até mais! o

Postado por Andun (achado no forum revolution)

Progamação da AI do homunculo

Indice:
[0.00] Introdução
[0.10] Log de Alterações
[0.30] Comandos in-game Úteis
--------
Quando ouvi que os novos pets de alquimistas, os homunculos, teriam uma AI programavel, eu fiquei animada com a idéia de usar minhas habilidades na area de programação para fazer minha experencia de jogo mais divertida[0.10]
(Não pretendo incluir o change log, sorry)
[0.20]
Muitas pessoas que começarem a ler esse guia mas não tiverem experiencia prévia em programação poderão ter dificuldades em entender o que estou dizendo.
[0.30]
ALT+Clique Direito no chão: Seu homunculo se moverá para a celula que voce clicou.
ALT+Clique Direito em um monstro: Seu homunculo marcará aquele monstro como alvo. É nescessário um segundo clique para seu homunculo começar a atacar.
Digite "/hoai": Esse é o coração da AI customizavel - ele faz o homunculo trocara terrivel AI padrão pela sua AI editada.

Índice:
[1.00] Desvendando Const.lua

[1.10] Funções Client-Side

[1.11] Trace AI
[1.12] MoveToOwner
[1.13] Move
[1.14] Attack
[1.15] GetV
[1.16] GetActors
[1.17] GetTick
[1.18] GetMsg
[1.19] GetResMsg
[1.1A] SkillObject
[1.1B] SkillGround
[1.1C] IsMonster

[1.20] Skill ID para os skills ativos de homunculus

[1.21] Lif
[1.22] Amistir
[1.23] Filir
[1.24] Vanilmirth

[1.30] Constantes usadas em GetV

[1.31] V_OWNER
[1.32] V_POSITION
[1.33] V_TYPE
[1.34] V_MOTION
[1.35] V_ATTACKRANGE
[1.36] V_TARGET
[1.37] V_SKILLATTACKRANGE
[1.38] V_HOMUNTYPE
[1.39] V_HP, V_SP
[1.3A] V_MAXHP, V_MAXSP

[1.40] Constantes usadas para representar tipos de Homunculos.
[1.50] Constantes usadas para representar tipos de Movimento.
[1.60] Constantes usadas para representar tipos de Comandos.

-------------------------

[1.00]
Vou começar essa festa pelo mais basicos dos scripts, Const.lua, no qual veremos a definição de muitas constantes e funções que permitirão o resto dos scripts funcionarem, e também permitirá que nós façamos modificações nos scripts quando chegar a hora.

[1.10]
O primeiro texto no arquivo Const.lua dá o nome e parametros de diversas funções client-side pré-definidas que serão usadas no script. Aqui está a lista e em seguida a descrição de para que serve cada função.

CODE
function TraceAI (string) end
function MoveToOwner (id) end
function Move (id,x,y) end
function Attack (id,id) end
function GetV (V_,id) end
function GetActors () end
function GetTick () end
function GetMsg (id) end
function GetResMsg (id) end
function SkillObject (id,level,skill,target) end
function SkillGround (id,level,skill,x,y) end
function IsMonster (id) end


[1.11]
TraceAI (string): essa função mostra uma string (variavel formada por letras, numeros e/ou simbolos) e mostra-a no chat. Você pode ler essas strings in-game digitando "/traceai". Sua principal função é para debuggar o script, acompanhando mudanças de estado e variaveis.
[1.12]
MoveToOwner (id): essa função pega o ID do homunculo e o faz mover-se até seu dono. Auto-explicativa o bastante.
[1.13]
MoveTo (id,x,y): essa função também pega o ID do homunculo, mas também pega dois valores numericos para as coordenadas x e y. O homunculo então se move para as coordenadas x e y do mapa.
[1.14]
Attack (id, id): essa função pega dois valores de ID, o primeiro é o do homunculo, o segundo é o da criatura que o homunculo deve atacar. Naturalmente, essa função faz o homunculo atacar o alvo especificado.
[1.15]
GetV (V_, id): essa função pega um parametro e um ID, e retorna o parametro daquele ID. Na proxima sessão eu irei a fundo nos diferentes valores que GetV pode retornar. Visto que essa é uma das funções mais uteis para criar seus scripts, é importante saber usa-la bem.
[1.16]
GetActors (): essa função retorna uma lista de objetos mostrando todos objetos que aparecem na tela. Essa lista é usada quando procuramos por alvos em potencial.
[1.17]
GetTick (): essa função retorna o numero de milesimos de segundo que se passou desde um tempo, provavelmente meia-noite PST. Calcular a diferença entre dois ticks é um bom jeito de se saber quanto tempo se passou in-game, mas lembre-se que esse valor se dá em milesimos de segundo, então você precisa dividi-lo por 1000 para compara-lo com segundos ou mutiplicar os segundos por 1000.
[1.18]
GetMsg (id): essa função pega o ID do homunculo e retorna uma mensagem representando um comando que foi passado para o homunculo por seu dono. Já que os scripts de AI estarão processando comandos, eles precisam dessa função para pega-los.
[1.19]
GetResMsg (id): pega o ID do homunculo e retorna uma mensagem represantando um comando passado pelo client ou um comando em espera passado pelo dono. A mensagem reservada é outro tipo de mensagem que será processada pelos scripts de AI, então essa função é nescessária para pega-las.
[1.1A]
SkillObject (id,level,skill,target): Pega o ID do homunculo, o level do skill a ser usado, um número que represanta qual skill ser usado, o ID do alvo e usa o skill no alvo.

[1.20]
Valores conhecidos para skills de Homunculos são os seguintes (agradecimentos à Hahseckh por vários desses valores):
[1.21]
Lif:
Healing Touch = "8001"
Urgent Escape = "8002"
[1.22]
Amistr:
Castling = "8005"
Amistr Bulwark = "8006"
[1.23]
Filir:
Moonlight = "8009"
Flitting = "8010"
Accelerated Flight = "8011"
[1.24]
Vanilmirth:
Caprice = "8013"
Chaotic Blessing = "8014"

[1.1B]
SkillGround (id,level,skill,x,y): Mesmo processo da função anterior, mas ao invés de usar um ID para um objeto-alvo são usadas coordenadas x e y para se usar a skill no chão. Entretanto, até onde eu saiba não há nenhuma skill de efeito de area entre os homunculos.
[1.1C]
IsMonster (id): Pega o ID de um objeto e retorna 1 se o objeto for um monstro, 0 se não for. Isso pode ser usado para diferenciar monstros de jogadores, apesar de não ser muito util em situações de PvP (a não se que plantas invocadas e outros homunculos contem como monstros, ao menos).

[1.30]
A proxima parte do código pré-define os possiveis retornos da função GetV. O parametro V_ pedido pela função GetV é somente um número comum, mas aqui há a lista do que esse número pode representar:

CODE
V_OWNER = 0
V_POSITION = 1
V_TYPE = 2
V_MOTION = 3
V_ATTACKRANGE = 4
V_TARGET = 5
V_SKILLATTACKRANGE = 6
V_HOMUNTYPE = 7
V_HP = 8
V_SP = 9
V_MAXHP = 10
V_MAXSP = 11


[1.31]
V_OWNER, que é representado na função GetV pelo valor 0, irá fazer com que a função GetV retorne o número de ID do dono do ID especificado na função GetV. Esse valor, obviamente, só se aplica a homunculos.
[1.32]
V_POSITION fará com que a função GetV retorne as coordenadas x,y do ID em que lhe foi especificado. Esse valor pode ser usado em qualquer objeto.
[1.33]
V_TYPE fará com que a função GetV retorne o tipo do ID especificado. Não estou certo de como usar isso, visto que não é usado no script e os tipos de homunculo estão especificados em V_HOMUNTYPE.
[1.34]
V_MOTION fará com que a função GetV retorne o tipo de movimento do ID que lhe foi especificado. Os valores para isso estão definidos após os valores de tipos de homunculos, em breve chegaremos a isso.
[1.35]
V_ATTACKRANGE fará com que a função GetV retorne a distancia máxima que os ataques do ID especificado podem atingir. Útil para determinar se seu homunculo está perto o bastante para atingir o inimigo.
[1.36]
V_TARGET fará com que a função GetV retorne o alvo atual do ID especificado. Útil para determinar quando o homcunulo ou seu dono está sendo atacado por um monstro.
[1.37]
V_SKILLATTACKRANGE fará com que a função GetV retorne um número representando a distancia máxima que o skill selecionado do ID especificado pode alcançar. Útil para determinar se o homunculo está na distancia apropriada de um inimigo para usar algum skill.
[1.38]
V_HOMUNTYPE fará com que GetV retorne um valor representando o tipo de homunculo que teve seu ID especificado na função. Obviamente, só funciona em homunculos. Os valores retornados por essa função serão especificados na proxima sessão.
[1.39]
V_HP e V_SP fazem que GetV retorne o HP e o SP atual do ID especificado. A documentação da Gravity diz que esse valor só funciona para o homunculo e seu dono, ou seja, você não pode descobrir quanto de HP seu inimigo tem.
V_MAXHP e V_MAXSP fazem com que GetV retorne o valor maximo de HP e SP do ID especificado. A observação para os valores anteriores também se aplica aqui.

[1.40]
A proxima parte do código define os valores para os tipos de homunculos.

CODE
LIF = 1
AMISTR = 2
FILIR = 3
VANILMIRTH = 4
LIF2 = 5
AMISTR2 = 6
FILIR2 = 7
VANILMIRTH2 = 8
LIF_H = 9
AMISTR_H = 10
FILIR_H = 11
VANILMIRTH_H = 12
LIF_H2 = 13
AMISTR_H2 = 14
FILIR_H2 = 15
VANILMIRTH_H2 = 16

[1.50]
A seguir se encontra uma lista dos tipos de movimento, retornados pelo V_MOTION. Novamente, não são nescessários comentários, visto que só é preciso comparar os valores de GetV (V_MOTION, id).

CODE
MOTION_STAND = 0
MOTION_MOVE = 1
MOTION_ATTACK = 2
MOTION_DEAD = 3
MOTION_ATTACK2 = 9



[1.60]
Finalmente, aqui estão os números que representam os comandos que o dono pode passar para o homunculo. Esses valores sao pré-definidos aqui de forma a que os numeros retornados pelas mensagens possam ser lidados também com seu nome de variavel.

CODE
NONE_CMD = 0
MOVE_CMD = 1
STOP_CMD = 2
ATTACK_OBJECT_CMD = 3
ATTACK_AREA_CMD = 4
PATROL_CMD = 5
HOLD_CMD = 6
SKILL_OBJECT_CMD = 7
SKILL_AREA_CMD = 8
FOLLOW_CMD = 9

Indice:
[2.00] Desvendando Util.lua
[2.10] A utilidade de listas e pilhas
[2.20] Funções úteis
[2.21] GetDistance
[2.22] GetDistance2
[2.23] GetOwnerPosition
[2.24] GetDistanceFromOwner
[2.25] IsOutOfSight
[2.26] IsInAttackSight
---------------------
[2.00]
Agora que já vimos o basico das funções de scripts e como algumas variaveis fazem valores númericos mais faceis de se lidar, prosseguiremos para o próximo arquivo importante: o Util.lua. Nesse arquivo nós temos a maioria das funções de utilidades, que fazem tarefas matematicas semi-complexas e tarefas uteis que serão utilizadas no arquivo final de script.

CODE
require "./AI/Const.lua"


Essa linha do código mostra que o Util.lua depende do arquivo Const.lua para funcionar. Isso é devido ao fato de que aqui são usadas muitas das variaveis pré-definidas e funções client-side definidas no Const.lua.
[2.10]

CODE
List = {}

function List.new ()
return { first = 0, last = -1}
end

function List.pushleft (list, value)
local first = list.first-1
list.first = first
list[first] = value;
end

function List.pushright (list, value)
local last = list.last + 1
list.last = last
list[last] = value
end

function List.popleft (list)
local first = list.first
if first > list.last then
return nil
end
local value = list[first]
list[first] = nil -- to allow garbage collection
list.first = first+1
return value
end

function List.popright (list)
local last = list.last
if list.first > last then
return nil
end
local value = list[last]
list[last] = nil
list.last = last-1
return value
end

function List.clear (list)
for i,v in ipairs(list) do
list[i] = nil
end
--[[
if List.size(list) == 0 then
return
end
local first = list.first
local last = list.last
for i=first, last do
list[i] = nil
end
--]]
list.first = 0
list.last = -1
end

function List.size (list)
local size = list.last - list.first + 1
return size
end


A função acima são todas as utilidades de listas que são geralmente usadas em estruturas de dados conhecidas como Stacks (pilhas). Em uma pilha,, voce adiciona valores ao seu topo, e quando você chega a um ponto em que um dos valores precisa ser processado, você retira ele do topo da pilha, o que irá remove-lo da lista e retornar o valor a ser processado. Isso é exatamente o que essas funções fazem; List.new() cria uma nova lista de tamanho 0. As funções List.pushleft e List.pushright adicionam valores à esquerda ou à direita da pilha, respectivamente. List.popleft e List.popright retorna os valores destes mesmos lados e os removem desta posição na lista. List.Clear() remove todos valores na lista, e List.Size() retorna o tamanho da lista. Ao todo, essas funções não são muito importantes para alterar sua AI, mas elas são importantes no que se diz respeito a como o sistema lida com comandos enfileirados.

[2.20]
Seguindo em frente, aqui encontraremos funções que nos darão valores uteis para o script final.
[2.21]

CODE
function GetDistance (x1,y1,x2,y2)
return math.floor(math.sqrt((x1-x2)^2+(y1-y2)^2))
end


Essa função retorna a distancia entre x1,y1 e x2,y2 usando a formula matematica de calculo de distancias. Útil para calcular a distancia entre o homunculo e um inimigo ou para comparar a distancia maxima do ataque do homunculo com sua distancia do inimigo.
[2.22]

CODE
function GetDistance2 (id1, id2)
local x1, y1 = GetV (V_POSITION,id1)
local x2, y2 = GetV (V_POSITION,id2)
if (x1 == -1 or x2 == -1) then
return -1
end
return GetDistance (x1,y1,x2,y2)
end


Essa função faz o mesmo que a anterior, entretanto nela você especifica dois IDs ao invés de dois pares de coordenadas. Note que, após ela pegar os pares de coordenadas de cada objeto, ela utiliza a função anterior para calcular a distancia.
[2.23]

CODE
function GetOwnerPosition (id)
return GetV (V_POSITION,GetV(V_OWNER,id))
end


Essa função retorna a posição atual do dono do homunculo. Útil se o homunculo quiser voltar para perto do dono.
[2.24]

CODE
function GetDistanceFromOwner (id)
local x1, y1 = GetOwnerPosition (id)
local x2, y2 = GetV (V_POSITION,id)
if (x1 == -1 or x2 == -1) then
return -1
end
return GetDistance (x1,y1,x2,y2)
end


Outra função de distancias, essa retorna a distancia entre o dono do homunculo e um ID. Util para saber qual o inimigo mais proximo do dono ou para verificar se o homunculo não se afastou demais.
[2.25]

CODE
function IsOutOfSight (id1,id2)
local x1,y1 = GetV (V_POSITION,id1)
local x2,y2 = GetV (V_POSITION,id2)
if (x1 == -1 or x2 == -1) then
return true
end
local d = GetDistance (x1,y1,x2,y2)
if d > 20 then
return true
else
return false
end
end

Essa função retorna "true" se o objeto represando por ID2 estiver a mais de 20 celulas de distancia do objeto represantado por ID1, e "false" se estiverem menos de 20 celulas de distancia. O nome sugere que deveria ser uma checagem para quando um objeto está fora do alcance visual do outro, mas o uso de 20 celulas é estranho, visto que o campo visual no jogo é algo em torno de 10 a 15 celulas. Isso pode resultar em homunculos agressivos saindo do campo visual de seu dono se este não for cuidadoso. Pode ser util modificar essa função para corrigir isso, discutiremos sobre isso depois.
[2.26]

CODE
function IsInAttackSight (id1,id2)
local x1,y1 = GetV (V_POSITION,id1)
local x2,y2 = GetV (V_POSITION,id2)
if (x1 == -1 or x2 == -1) then
return false
end
local d = GetDistance (x1,y1,x2,y2)
local a = 0
if (MySkill == 0) then
a = GetV (V_ATTACKRANGE,id1)
else
a = GetV (V_SKILLATTACKRANGE,id1,MySkill)
end

if a >= d then
return true;
else
return false;
end
end

Essa função retorna "true" se o objeto represantado por id2 estiver dentro da distancia maxima de ataque do objeto representado por id1. Normalmente, id1 representa o homunculo. Se o objeto estiver tentando usar um skill, a distancia maxima do skill será levada em conta.

Índice: (lembrando que dividirei em 3 o indice 3 pois o forum num suporta)
[3.00] Desvendando AI.lua

[3.10] Constantes usadas para representar estados

[3.20] Variaveis Globais
[3.21] MyState
[3.22] MyEnemy
[3.23] MyDestX, MyDestY
[3.24] MyPatrolX, MyPatrolY
[3.25] ResCmdList
[3.26] MyID
[3.27] MySkill, MySkillLevel

[3.30] Processamento de Comandos
[3.31] OnMOVE_CMD
[3.32] OnSTOP_CMD
[3.33] OnATTACK_OBJECT_CMD
[3.34] OnATTACK_AREA_CMD
[3.35] OnPATROL_CMD
[3.36] OnHOLD_CMD
[3.37] OnSKILL_OBJECT_CMD
[3.38] OnSKILL_AREA_CMD
[3.39] OnFOLLOW_CMD
[3.3A] ProcessCommand

[3.40] Processamento de Estados
[3.41] OnIDLE_ST
[3.42] OnFOLLOW_ST
[3.43] OnCHASE_ST
[3.44] OnATTACK_ST
[3.45] OnMOVE_CMD_ST
[3.46] OnSTOP_CMD_ST, OnATTACK_OBJECT_CMD_ST
[3.47] OnATTACK_AREA_CMD_ST
[3.48] OnPATROL_CMD_ST
[3.49] OnHOLD_CMD_ST
[3.4A] OnSKILL_OBJECT_CMD_ST
[3.4B] OnSKILL_AREA_CMD_ST
[3.4C] OnFOLLOW_CMD_ST

[3.50] Funções de Seleção de Inimigos
[3.51] GetOwnerEnemy
[3.52] GetMyEnemy
[3.52] GetMyEnemyA
[3.53] GetMyEnemyB

[3.60] A Função AI
------------
[3.00]
Agora que já vimos todos nossos valores de constantes, nossas funções client-side e nossas funções de utilidades, só nos resta uma coisa a fazer: usar todo esse conhecimento adquirido para debulhar o arquivo AI.lua

CODE
require "./AI/Const.lua"
require "./AI/Util.lua"


Novamente, o arquivo de AI nescessita de outros arquivos na mesma pasta para rodar, pois usa funções de utilidades do Util.lua e valores definidos no Const.lua.
[3.10]

CODE
IDLE_ST = 0
FOLLOW_ST = 1
CHASE_ST = 2
ATTACK_ST = 3
MOVE_CMD_ST = 4
STOP_CMD_ST = 5
ATTACK_OBJECT_CMD_ST = 6
ATTACK_AREA_CMD_ST = 7
PATROL_CMD_ST = 8
HOLD_CMD_ST = 9
SKILL_OBJECT_CMD_ST = 10
SKILL_AREA_CMD_ST = 11
FOLLOW_CMD_ST = 12


Assim como os valores definidos em Const.lua, esses valores estão aqui para que lidar com os estados seja mais facil. Esses valores serão usados para alterar o valor da variavel MyState, que será discutido brevemente, assim como para comparar o estado atual do homunculo com outros estados.
[3.20]

CODE
MyState = IDLE_ST
MyEnemy = 0
MyDestX = 0
MyDestY = 0
MyPatrolX = 0
MyPatrolY = 0
ResCmdList = List.new()
MyID = 0
MySkill = 0
MySkillLevel = 0


[3.21]
MyState representa o estado atual do Homunculo. Ele guarda um valor númerico, mas esses valores serão lidados no arquivo de acordo com o que foi definido acima. O valor padrão de MyState é 0, portanto o homunculo inicializa em IDLE_ST.
[3.22]
MyEnemy guarda o ID do objeto que o homunculo tem atualmente como alvo. Esse valor é usado para saber o que o homunculo está visando, tanto para propositos de ataques como perseguições.
[3.23]
MyDestX e MyDestY são usadas para guardar a destinação atual do homunculo. Usadas para move ro homunculo ou para perseguir um inimigo.
[3.24]
MyPatrolX e MyPatrolY são usadas para armazenas as coordenadas da patrulha do homunculo. Na função de patrulha, o homunculo alterna entre (MyDestX,MyDestY) e (MyPatrolX,MyPatrolY).
[3.25]
ResCmdList é a lista em que os comandos do client e os comandos enfileirados são armazenados. Note que ele usa a função List.new() do Util.lua para criar uma nova lista de comandos.
MyID é usada para guardar a ID do homunculo para uso facil. O unico momento em que a ID do homunculo é passada para o programa é na função AI (id), que é a ultima função nesse arquivo, e esse número de ID é usado para obter todas outras informações nescessárias (como o ID do dono, que é nescessário para a posição do dono, inimigo do dono, etc.), portanto é uma variavel extremamente importante.
MySkill e MySkillLevel são usados para armazenar o ID do skill selecionado do homunculo e seu level, para uso na função SkillObject do Const.lua.
[3.30]
Agora passemos para o processamento de comandos, que define as respostas do homunculo aos comandos que seu dono pode lhe passar. Esses são todos chamados pela função Process (msg), que por sua vez é chamada pela função AI. Ou seja, essas são as funções que defininem cada comando que pode ser passado para o homunculo.
[3.31]

CODE
function OnMOVE_CMD (x,y)

TraceAI ("OnMOVE_CMD")

if ( x == MyDestX and y == MyDestY and MOTION_MOVE == GetV(V_MOTION,MyID)) then
return
end

local curX, curY = GetV (V_POSITION,MyID)
if (math.abs(x-curX)+math.abs(y-curY) > 15) then
List.pushleft (ResCmdList,{MOVE_CMD,x,y})
x = math.floor((x+curX)/2)
y = math.floor((y+curY)/2)
end

Move (MyID,x,y)

MyState = MOVE_CMD_ST
MyDestX = x
MyDestY = y
MyEnemy = 0
MySkill = 0

end


Essa função tenta mover o homunculo até o ponto (x,y). Se o ponto for muito longe, o homunculo irá se mover até metade do caminho e então marcar a destinação final como seu destino atual, fazendo na pratica dois movimentos para seguir a rota inteira. Comandar o homunculo para se mover faz com que ele desselecione quaisquer skills e alvos que havia selecionado e mude seu estado para MOVE_CMD_ST, o estado em que ele é comandado para se mover. Simples, não?
[3.32]

CODE
function OnSTOP_CMD ()

TraceAI ("OnSTOP_CMD")

if (GetV(V_MOTION,MyID) ~= MOTION_STAND) then
Move (MyID,GetV(V_POSITION,MyID))
end
MyState = IDLE_ST
MyDestX = 0
MyDestY = 0
MyEnemy = 0
MySkill = 0

end


Essa função faz o homunculo parar de se mover, entrar em estado IDLE_ST (estado Idle, "standby") e desselecionar quaisquer skills e alvos. Se o homunculo estiver fazendo algo além de estar parado, essa função o fará mover para sua posição atual (ou seja, parar) e então mudar seu estado para Idle.
[3.33]

CODE
function OnATTACK_OBJECT_CMD (id)

TraceAI ("OnATTACK_OBJECT_CMD")

MySkill = 0
MyEnemy = id
MyState = CHASE_ST

end


Essa função pega o ID de um inimigo e marca-o como alvo do homunculo. Então o homunculo muda para o estado de perseguição, no qual ele irá perseguir o inimigo. Também faz com que o homunculo desselecione qualquer skill, ou seja, ele irá atacar o alvo normalmente.
[3.34]

CODE
function OnATTACK_AREA_CMD (x,y)

TraceAI ("OnATTACK_AREA_CMD")

if (x ~= MyDestX or y ~= MyDestY or MOTION_MOVE ~= GetV(V_MOTION,MyID)) then
Move (MyID,x,y)
end
MyDestX = x
MyDestY = y
MyEnemy = 0
MyState = ATTACK_AREA_CMD_ST

end


Essa função pega uma posição (x,y) e manda o homunculo "atacar" aquela celula. Basicamente, o homunculo se moverá até o local e então procurará por inimigos proximos para começar a atacar (o que é parte do ATTACK_AREA_CMD_ST que será observado mais adiante).
[3.35]

CODE
function OnPATROL_CMD (x,y)

TraceAI ("OnPATROL_CMD")

MyPatrolX , MyPatrolY = GetV (V_POSITION,MyID)
MyDestX = x
MyDestY = y
Move (MyID,x,y)
MyState = PATROL_CMD_ST

end


Essa função pega uma posição e faz o homunculo patrulhar entre sua posição atual e a posição escolhida.
[3.36]

CODE
function OnPATROL_CMD (x,y)

TraceAI ("OnPATROL_CMD")

MyPatrolX , MyPatrolY = GetV (V_POSITION,MyID)
MyDestX = x
MyDestY = y
Move (MyID,x,y)
MyState = PATROL_CMD_ST

end


Esse é o ALT+T. Faz seu homunculo parar de fazer o que estiver fazendo e mudar para o estado de Hold.

[3.37]

CODE
function OnSKILL_OBJECT_CMD (level,skill,id)

TraceAI ("OnSKILL_OBJECT_CMD")

MySkillLevel = level
MySkill = skill
MyEnemy = id
MyState = CHASE_ST

end


Essa função pega um level de skill, uma ID da skill, um ID de inimigo e faz seu homunculo selecionar a skill no level escolhido e marcar o inimigo como seu alvo, mudando então para o estado de perseguição para se aproximar o bastante do inimigo e usar a skill escolhida.
[3.38]

CODE
function OnSKILL_AREA_CMD (level,skill,x,y)

TraceAI ("OnSKILL_AREA_CMD")

Move (MyID,x,y)
MyDestX = x
MyDestY = y
MySkillLevel = level
MySkill = skill
MyState = SKILL_AREA_CMD_ST

end


Essa função é basicamente igual à anterior, entretanto o homunculo escolhe uma posição ao invés de um inimigo. O Homunculo então se move para essa posição e seleciona o skill escolhido antes de mudar de estado para SKILL_AREA_CMD_ST.
[3.39]

CODE
function OnFOLLOW_CMD ()

if (MyState ~= FOLLOW_CMD_ST) then
MoveToOwner (MyID)
MyState = FOLLOW_CMD_ST
MyDestX, MyDestY = GetV (V_POSITION,GetV(V_OWNER,MyID))
MyEnemy = 0
MySkill = 0
TraceAI ("OnFOLLOW_CMD")
else
MyState = IDLE_ST
MyEnemy = 0
MySkill = 0
TraceAI ("FOLLOW_CMD_ST --> IDLE_ST")
end

end


Essa função faz o homunculo mover até seu dono e mudar para o estado de de seguir, se já não estiver nele. Caso já esteja no estado de seguir, faz o homunculo mudar para o estado Idle.
[3.3A]

CODE
function ProcessCommand (msg)

if (msg[1] == MOVE_CMD) then
OnMOVE_CMD (msg[2],msg[3])
TraceAI ("MOVE_CMD")
elseif (msg[1] == STOP_CMD) then
OnSTOP_CMD ()
TraceAI ("STOP_CMD")
elseif (msg[1] == ATTACK_OBJECT_CMD) then
OnATTACK_OBJECT_CMD (msg[2])
TraceAI ("ATTACK_OBJECT_CMD")
elseif (msg[1] == ATTACK_AREA_CMD) then
OnATTACK_AREA_CMD (msg[2],msg[3])
TraceAI ("ATTACK_AREA_CMD")
elseif (msg[1] == PATROL_CMD) then
OnPATROL_CMD (msg[2],msg[3])
TraceAI ("PATROL_CMD")
elseif (msg[1] == HOLD_CMD) then
OnHOLD_CMD ()
TraceAI ("HOLD_CMD")
elseif (msg[1] == SKILL_OBJECT_CMD) then
OnSKILL_OBJECT_CMD (msg[2],msg[3],msg[4],msg[5])
TraceAI ("SKILL_OBJECT_CMD")
elseif (msg[1] == SKILL_AREA_CMD) then
OnSKILL_AREA_CMD (msg[2],msg[3],msg[4],msg[5])
TraceAI ("SKILL_AREA_CMD")
elseif (msg[1] == FOLLOW_CMD) then
OnFOLLOW_CMD ()
TraceAI ("FOLLOW_CMD")
end
end


Essa é a função principal de todo o processo de comandos, faz seu homunculo realizar a função de acordo com o comando que é passado para ele. Note que msg[1], msg[2], msg[3], etc., todas apontam para diferentes partes da mesma mensagem. Portanto, em uma mensagem especificando um comando de movimento, você teria algo como msg = {MOVE_CMD, x,y}. Ou seja, onde a função chama por OnMOVE_CMD(msg[2],msg[3]), está na realidade chamando por OnMOVE_COMMAND(x,y), onde x e y são quaisquers numeros que foram usados nessa mensagem. A função usa o valor da primeira parte da mensagem para determinar quantas outras partes a mensagem contém. Estranhamente, o OnSKILL_OBJECT_COMMAND usa quatro partes de mensagem, ao invés de três que é o que a função realmente nescessita. Entretanto, como tudo parece funcionar mesmo assim, deixarei como está.
[3.40]
Agora veremos os processos de estados, que definem qual o comportamento do homunculo em determinado estado. Após o comando Process(msg) chamar uma função, o estado do homunculo normalmente muda, mostrando que o comando foi processado. A função AI então chama essas funções de estado para fazer o homunculo se comportar como ele deveria.
[3.41]

CODE
function OnIDLE_ST ()

TraceAI ("OnIDLE_ST")

local cmd = List.popleft(ResCmdList)
if (cmd ~= nil) then
ProcessCommand (cmd)
return
end

local object = GetOwnerEnemy (MyID)
if (object ~= 0) then
MyState = CHASE_ST
MyEnemy = object
TraceAI ("IDLE_ST -> CHASE_ST : MYOWNER_ATTACKED_IN")
return
end

object = GetMyEnemy (MyID)
if (object ~= 0) then
MyState = CHASE_ST
MyEnemy = object
TraceAI ("IDLE_ST -> CHASE_ST : ATTACKED_IN")
return
end

local distance = GetDistanceFromOwner(MyID)
if ( distance > 3 or distance == -1) then
MyState = FOLLOW_ST
TraceAI ("IDLE_ST -> FOLLOW_ST")
return;
end

end


Essa função define o comportamento do homunculo no estado Idle. A primeira coisa que ela faz é processar qualquer comando que estiver enfileirado, como movimentos finais quando o movimento inicial era longo demais, ou qualquer comando passado enquanto o homunculo mudava de estado. Então ele procura por inimigos do dono, se encontrar algum ele o atacará. Se não encontrar nenhum, ele procurará por inimigos do homunculo e os atacará. Se não encontrar nenhum, ele voltará para perto do seu dono caso esteja a mais de 3 celulas de distancia. Se nenhuma dessas condições for verdadeira, o homunculo não fará nada.

[3.42]

CODE
function OnFOLLOW_ST ()

TraceAI ("OnFOLLOW_ST")

if (GetDistanceFromOwner(MyID) <= 3) then
MyState = IDLE_ST
TraceAI ("FOLLOW_ST -> IDLW_ST")
return;
elseif (GetV(V_MOTION,MyID) == MOTION_STAND) then
MoveToOwner (MyID)
TraceAI ("FOLLOW_ST -> FOLLOW_ST")
return;
end

end


Essa função define o comportamento do homunculo no estado de seguir. Primeiro ele checa se está a menos de três celulas do dono, se sim, ele muda para o estado idle. Caso contrário, se estiver parado, ele se moverá para perto do dono. Note o erro de ditação em "Idle" no TraceAI. Foi a Gravity, não eu.
[3.43]

CODE
function OnCHASE_ST ()

TraceAI ("OnCHASE_ST")

if (true == IsOutOfSight(MyID,MyEnemy)) then
MyState = IDLE_ST
MyEnemy = 0
MyDestX, MyDestY = 0,0
TraceAI ("CHASE_ST -> IDLE_ST : ENEMY_OUTSIGHT_IN")
return
end
if (true == IsInAttackSight(MyID,MyEnemy)) then
MyState = ATTACK_ST
TraceAI ("CHASE_ST -> ATTACK_ST : ENEMY_INATTACKSIGHT_IN")
return
end

local x, y = GetV (V_POSITION,MyEnemy)
if (MyDestX ~= x or MyDestY ~= y) then
MyDestX, MyDestY = GetV (V_POSITION,MyEnemy);
Move (MyID,MyDestX,MyDestY)
TraceAI ("CHASE_ST -> CHASE_ST : DESTCHANGED_IN")
return
end

end


Essa função define o comportamento do homunculo no estado de perseguição. Se o inimigo estiver fora do campo visual, o homunculo irá parar desseleciona-lo e mudar para o estado Idle. Se o inimigo estiver dentro da distancia de ataque do homunculo, este irá mudar para o estado de ataque. Caso contrário, o homunculo continuará a se mover em direção ao inimigo.
[3.44]

CODE
function OnATTACK_ST ()

TraceAI ("OnATTACK_ST")

if (true == IsOutOfSight(MyID,MyEnemy)) then
MyState = IDLE_ST
TraceAI ("ATTACK_ST -> IDLE_ST")
return
end

if (MOTION_DEAD == GetV(V_MOTION,MyEnemy)) then
MyState = IDLE_ST
TraceAI ("ATTACK_ST -> IDLE_ST")
return
end

if (false == IsInAttackSight(MyID,MyEnemy)) then
MyState = CHASE_ST
MyDestX, MyDestY = GetV (V_POSITION,MyEnemy);
Move (MyID,MyDestX,MyDestY)
TraceAI ("ATTACK_ST -> CHASE_ST : ENEMY_OUTATTACKSIGHT_IN")
return
end

if (MySkill == 0) then
Attack (MyID,MyEnemy)
else
SkillObject (MyID,MySkillLevel,MySkill,MyEnemy)
MySkill = 0
end
TraceAI ("ATTACK_ST -> ATTACK_ST : ENERGY_RECHARGED_IN")
return

end


Essa função define o comportamento do homunculo enquanto ataca um inimigo. Se o inimigo estiver fora do campo visual ou morto, o homunculo irá voltar para o estado Idle.
[3.45]

CODE
function OnMOVE_CMD_ST ()

TraceAI ("OnMOVE_CMD_ST")

local x, y = GetV (V_POSITION,MyID)
if (x == MyDestX and y == MyDestY) then
MyState = IDLE_ST
end
end


Essa função define o comportamento do homunculo enquanto se move. Se a sua posição atual for igual ao destino que lhe havia sido dado, ele muda para o estado Idle.
[3.46]

CODE
function OnSTOP_CMD_ST ()


end

function OnATTACK_OBJECT_CMD_ST ()

end


Essas funções estão vazias, fazendo com que o homunculo não faça nda enquanto estiver nelas. Faz você se perguntar por que elas foram definidas, não faz?
[3.47]

CODE
function OnATTACK_AREA_CMD_ST ()

TraceAI ("OnATTACK_AREA_CMD_ST")

local object = GetOwnerEnemy (MyID)
if (object == 0) then
object = GetMyEnemy (MyID)
end

if (object ~= 0) then
MyState = CHASE_ST
MyEnemy = object
return
end

local x , y = GetV (V_POSITION,MyID)
if (x == MyDestX and y == MyDestY) then
MyState = IDLE_ST
end

end


Essa função define como o homunculo se comporta quando é ordenado a atacar uma localidade. Após se mover para essa localidade, ele irá procurar por inimigos assim como faz no estado Idle.
[3.48]

CODE
function OnPATROL_CMD_ST ()

TraceAI ("OnPATROL_CMD_ST")

local object = GetOwnerEnemy (MyID)
if (object == 0) then
object = GetMyEnemy (MyID)
end

if (object ~= 0) then
MyState = CHASE_ST
MyEnemy = object
TraceAI ("PATROL_CMD_ST -> CHASE_ST : ATTACKED_IN")
return
end

local x , y = GetV (V_POSITION,MyID)
if (x == MyDestX and y == MyDestY) then
MyDestX = MyPatrolX
MyDestY = MyPatrolY
MyPatrolX = x
MyPatrolY = y
Move (MyID,MyDestX,MyDestY)
end

end


Essa função define como o homunculo se comporta enquanto patrulha uma localidade. Ele primeiro procura por inimigos. Se encontrar algum, ele muda para o estado de Perseguição e o persegui-rá. Se nenhum inimigo for encontrado, ele ficará andando entre as posições que foram demarcadas até encontrar um.
[3.49]

CODE
function OnHOLD_CMD_ST ()

TraceAI ("OnHOLD_CMD_ST")

if (MyEnemy ~= 0) then
local d = GetDistance(MyEnemy,MyID)
if (d ~= -1 and d <= GetV(V_ATTACKRANGE,MyID)) then
Attack (MyID,MyEnemy)
else
MyEnemy = 0
end
return
end


local object = GetOwnerEnemy (MyID)
if (object == 0) then
object = GetMyEnemy (MyID)
if (object == 0) then
return
end
end

MyEnemy = object

end


Essa função define como o homunculo se comporta no estado de Hold. Se ele tiver um inimigo que estiver dentro de distancia de ataque, ele atacará o inimigo. Caso contrário, ele desselecionará o inimigo.
[3.4A]

CODE
function OnSKILL_OBJECT_CMD_ST ()

end


Outra função vazia.

CODE
function OnSKILL_AREA_CMD_ST ()

TraceAI ("OnSKILL_AREA_CMD_ST")

local x , y = GetV (V_POSITION,MyID)
if (GetDistance(x,y,MyDestX,MyDestY) <= GetV(V_SKILLATTACKRANGE,MyID,MySkill)) then
SkillGround (MyID,MySkillLevel,MySkill,MyDestX,MyDestY)
MyState = IDLE_ST
MySkill = 0
end

end


Essa função define como o homunculo se comporta ao tentar usar uma skill no chãol. Se ele estiver dentro da distancia minima para uso da skill, ele a usará no local indicado e mudará para o estado Idle.
[3.4C]

CODE
function OnFOLLOW_CMD_ST ()

TraceAI ("OnFOLLOW_CMD_ST")

local ownerX, ownerY, myX, myY
ownerX, ownerY = GetV (V_POSITION,GetV(V_OWNER,MyID))
myX, myY = GetV (V_POSITION,MyID)

local d = GetDistance (ownerX,ownerY,myX,myY)

if ( d <= 3) then
return
end

local motion = GetV (V_MOTION,MyID)
if (motion == MOTION_MOVE) then
d = GetDistance (ownerX, ownerY, MyDestX, MyDestY)
if ( d > 3) then
MoveToOwner (MyID)
MyDestX = ownerX
MyDestY = ownerY
return
end
else
MoveToOwner (MyID)
MyDestX = ownerX
MyDestY = ownerY
return
end

end


Essa função define como o homunculo se comporta no estado de Seguir. Ele se moverá para uma distancia maxima de 3 celulas do dono e tentará manter essa distancia.

[3.50]
A seguir estão as funções de seleção de inimigos, que são usadas em algumas das funções acima para fazer o homunculo escolher um inimigo como alvo. Há alguns critérios diferentes para se definir inimigos, estes estão separados nas funções abaixo:
[3.51]

CODE
function GetOwnerEnemy (myid)
local result = 0
local owner = GetV (V_OWNER,myid)
local actors = GetActors ()
local enemys = {}
local index = 1
local target
for i,v in ipairs(actors) do
if (v ~= owner and v ~= myid) then
target = GetV (V_TARGET,v)
if (target == owner) then
if (IsMonster(v) == 1) then
enemys[index] = v
index = index+1
else
local motion = GetV(V_MOTION,i)
if (motion == MOTION_ATTACK or motion == MOTION_ATTACK2) then
enemys[index] = v
index = index+1
end
end
end
end
end

local min_dis = 100
local dis
for i,v in ipairs(enemys) do
dis = GetDistance2 (myid,v)
if (dis < min_dis) then
result = v
min_dis = dis
end
end

return result
end


Essa função é bastante longa, mas apenas retorna o inimigo atacante do dono mais proximo para que o homunculo tenha ele como inimigo. Ela faz uma lista de todos objetos na tela e procura em todos eles aqueles que estão atacando o dono, seja um monstro ou não-monstro (jogadores em situações de PvP), então procura qual deles está mais perto do dono e marca este como o alvo de maior prioridade para o homunculo.
[3.52]

CODE
function GetMyEnemy (myid)
local result = 0

local type = GetV (V_HOMUNTYPE,myid)
if (type == LIF or type == LIF_H or type == AMISTR or type == AMISTR_H or type == LIF2 or type == LIF_H2 or type == AMISTR2 or

type == AMISTR_H2) then
result = GetMyEnemyA (myid)
elseif (type == FILIR or type == FILIR_H or type == VANILMIRTH or type == VANILMIRTH_H or type == FILIR2 or type == FILIR_H2 or

type == VANILMIRTH2 or type == VANILMIRTH_H2) then
result = GetMyEnemyB (myid)
end
return result
end


Essa função é usada em geral quando o dono do homunculo não tem inimigos e irá procurar por inimigos do homunculo. Para Amistr e Lif, essa função irá chamar GetMyEnemyA, a função passiva de procura por inimigos. Se for Filir ou Vanilmirth, irá chamar por GetMyEnemyB, a função agressiva de procura por inimigos.

[3.53]

CODE
function GetMyEnemyA (myid)
local result = 0
local owner = GetV (V_OWNER,myid)
local actors = GetActors ()
local enemys = {}
local index = 1
local target
for i,v in ipairs(actors) do
if (v ~= owner and v ~= myid) then
target = GetV (V_TARGET,v)
if (target == myid) then
enemys[index] = v
index = index+1
end
end
end

local min_dis = 100
local dis
for i,v in ipairs(enemys) do
dis = GetDistance2 (myid,v)
if (dis < min_dis) then
result = v
min_dis = dis
end
end

return result
end


Função de procura de inimigo padrão para Amistr e Lif, é muito parecida com GetOwnerEnemy: ela procura por inimigos do dono, mas também por inimigos que estejam atacando o homunculo. A prioridade é para aquele que estiver mais perto do homunculo.
[3.54]

CODE
function GetMyEnemyB (myid)
local result = 0
local owner = GetV (V_OWNER,myid)
local actors = GetActors ()
local enemys = {}
local index = 1
local type
for i,v in ipairs(actors) do
if (v ~= owner and v ~= myid) then
if (1 == IsMonster(v)) then
enemys[index] = v
index = index+1
end
end
end

local min_dis = 100
local dis
for i,v in ipairs(enemys) do
dis = GetDistance2 (myid,v)
if (dis < min_dis) then
result = v
min_dis = dis
end
end

return result
end


Essa função é parecida com a anterior, entretanto ela aceita todos inimigos na tela como alvos potenciais. É o sistema padrão de localização de inimigos para Filir e Valnirmith. Há um problema de lógica com esse script: ele não checa para ver se o monstro já está lutando com outro jogador, resultando em Kill-Steal (KS) por parte do homunculo. Isso pode ser facilmente corrigido e será discutido na sessão de custom AI.
[3.60]

CODE
function AI(myid)

MyID = myid
local msg = GetMsg (myid)
local rmsg = GetResMsg (myid)


if msg[1] == NONE_CMD then
if rmsg[1] ~= NONE_CMD then
if List.size(ResCmdList) < 10 then
List.pushright (ResCmdList,rmsg)
end
end
else
List.clear (ResCmdList)
ProcessCommand (msg)
end

if (MyState == IDLE_ST) then
OnIDLE_ST ()
elseif (MyState == CHASE_ST) then
OnCHASE_ST ()
elseif (MyState == ATTACK_ST) then
OnATTACK_ST ()
elseif (MyState == FOLLOW_ST) then
OnFOLLOW_ST ()
elseif (MyState == MOVE_CMD_ST) then
OnMOVE_CMD_ST ()
elseif (MyState == STOP_CMD_ST) then
OnSTOP_CMD_ST ()
elseif (MyState == ATTACK_OBJECT_CMD_ST) then
OnATTACK_OBJECT_CMD_ST ()
elseif (MyState == ATTACK_AREA_CMD_ST) then
OnATTACK_AREA_CMD_ST ()
elseif (MyState == PATROL_CMD_ST) then
OnPATROL_CMD_ST ()
elseif (MyState == HOLD_CMD_ST) then
OnHOLD_CMD_ST ()
elseif (MyState == SKILL_OBJECT_CMD_ST) then
OnSKILL_OBJECT_CMD_ST ()
elseif (MyState == SKILL_AREA_CMD_ST) then
OnSKILL_AREA_CMD_ST ()
elseif (MyState == FOLLOW_CMD_ST) then
OnFOLLOW_CMD_ST ()
end

end


Esse é o coração de todo o script de AI. Ele pega o ID do homunculo e imediatamente o armazena na variavel MyID, o que permite que muitas informações sejam adquiridas a partir da função GetV. Após isso, a função pega uma mensagem e uma mensagem reserve. Se não houver nenhuma mensagem, ele adicionará a rmsg para a sua lista e tentará efetuar os processos de estado (o padrão sendo Idle). Se houver uma mensagem, ela será processada pela função ProcessCommand(msg) que chamará o comando apropriadoÍndice:
[3.00] Desvendando AI.lua

[3.10] Constantes usadas para representar estados

[3.20] Variaveis Globais
[3.21] MyState
[3.22] MyEnemy
[3.23] MyDestX, MyDestY
[3.24] MyPatrolX, MyPatrolY
[3.25] ResCmdList
[3.26] MyID
[3.27] MySkill, MySkillLevel

[3.30] Processamento de Comandos
[3.31] OnMOVE_CMD
[3.32] OnSTOP_CMD
[3.33] OnATTACK_OBJECT_CMD
[3.34] OnATTACK_AREA_CMD
[3.35] OnPATROL_CMD
[3.36] OnHOLD_CMD
[3.37] OnSKILL_OBJECT_CMD
[3.38] OnSKILL_AREA_CMD
[3.39] OnFOLLOW_CMD
[3.3A] ProcessCommand

[3.40] Processamento de Estados
[3.41] OnIDLE_ST
[3.42] OnFOLLOW_ST
[3.43] OnCHASE_ST
[3.44] OnATTACK_ST
[3.45] OnMOVE_CMD_ST
[3.46] OnSTOP_CMD_ST, OnATTACK_OBJECT_CMD_ST
[3.47] OnATTACK_AREA_CMD_ST
[3.48] OnPATROL_CMD_ST
[3.49] OnHOLD_CMD_ST
[3.4A] OnSKILL_OBJECT_CMD_ST
[3.4B] OnSKILL_AREA_CMD_ST
[3.4C] OnFOLLOW_CMD_ST

[3.50] Funções de Seleção de Inimigos
[3.51] GetOwnerEnemy
[3.52] GetMyEnemy
[3.52] GetMyEnemyA
[3.53] GetMyEnemyB

[3.60] A Função AI
------------
[3.00]
Agora que já vimos todos nossos valores de constantes, nossas funções client-side e nossas funções de utilidades, só nos resta uma coisa a fazer: usar todo esse conhecimento adquirido para debulhar o arquivo AI.lua

CODE
require "./AI/Const.lua"
require "./AI/Util.lua"


Novamente, o arquivo de AI nescessita de outros arquivos na mesma pasta para rodar, pois usa funções de utilidades do Util.lua e valores definidos no Const.lua.
[3.10]

CODE
IDLE_ST = 0
FOLLOW_ST = 1
CHASE_ST = 2
ATTACK_ST = 3
MOVE_CMD_ST = 4
STOP_CMD_ST = 5
ATTACK_OBJECT_CMD_ST = 6
ATTACK_AREA_CMD_ST = 7
PATROL_CMD_ST = 8
HOLD_CMD_ST = 9
SKILL_OBJECT_CMD_ST = 10
SKILL_AREA_CMD_ST = 11
FOLLOW_CMD_ST = 12


Assim como os valores definidos em Const.lua, esses valores estão aqui para que lidar com os estados seja mais facil. Esses valores serão usados para alterar o valor da variavel MyState, que será discutido brevemente, assim como para comparar o estado atual do homunculo com outros estados.
[3.20]

CODE
MyState = IDLE_ST
MyEnemy = 0
MyDestX = 0
MyDestY = 0
MyPatrolX = 0
MyPatrolY = 0
ResCmdList = List.new()
MyID = 0
MySkill = 0
MySkillLevel = 0


[3.21]
MyState representa o estado atual do Homunculo. Ele guarda um valor númerico, mas esses valores serão lidados no arquivo de acordo com o que foi definido acima. O valor padrão de MyState é 0, portanto o homunculo inicializa em IDLE_ST.
[3.22]
MyEnemy guarda o ID do objeto que o homunculo tem atualmente como alvo. Esse valor é usado para saber o que o homunculo está visando, tanto para propositos de ataques como perseguições.
[3.23]
MyDestX e MyDestY são usadas para guardar a destinação atual do homunculo. Usadas para move ro homunculo ou para perseguir um inimigo.
[3.24]
MyPatrolX e MyPatrolY são usadas para armazenas as coordenadas da patrulha do homunculo. Na função de patrulha, o homunculo alterna entre (MyDestX,MyDestY) e (MyPatrolX,MyPatrolY).
[3.25]
ResCmdList é a lista em que os comandos do client e os comandos enfileirados são armazenados. Note que ele usa a função List.new() do Util.lua para criar uma nova lista de comandos.
MyID é usada para guardar a ID do homunculo para uso facil. O unico momento em que a ID do homunculo é passada para o programa é na função AI (id), que é a ultima função nesse arquivo, e esse número de ID é usado para obter todas outras informações nescessárias (como o ID do dono, que é nescessário para a posição do dono, inimigo do dono, etc.), portanto é uma variavel extremamente importante.
MySkill e MySkillLevel são usados para armazenar o ID do skill selecionado do homunculo e seu level, para uso na função SkillObject do Const.lua.
[3.30]
Agora passemos para o processamento de comandos, que define as respostas do homunculo aos comandos que seu dono pode lhe passar. Esses são todos chamados pela função Process (msg), que por sua vez é chamada pela função AI. Ou seja, essas são as funções que defininem cada comando que pode ser passado para o homunculo.
[3.31]

CODE
function OnMOVE_CMD (x,y)

TraceAI ("OnMOVE_CMD")

if ( x == MyDestX and y == MyDestY and MOTION_MOVE == GetV(V_MOTION,MyID)) then
return
end

local curX, curY = GetV (V_POSITION,MyID)
if (math.abs(x-curX)+math.abs(y-curY) > 15) then
List.pushleft (ResCmdList,{MOVE_CMD,x,y})
x = math.floor((x+curX)/2)
y = math.floor((y+curY)/2)
end

Move (MyID,x,y)

MyState = MOVE_CMD_ST
MyDestX = x
MyDestY = y
MyEnemy = 0
MySkill = 0

end


Essa função tenta mover o homunculo até o ponto (x,y). Se o ponto for muito longe, o homunculo irá se mover até metade do caminho e então marcar a destinação final como seu destino atual, fazendo na pratica dois movimentos para seguir a rota inteira. Comandar o homunculo para se mover faz com que ele desselecione quaisquer skills e alvos que havia selecionado e mude seu estado para MOVE_CMD_ST, o estado em que ele é comandado para se mover. Simples, não?
[3.32]

CODE
function OnSTOP_CMD ()

TraceAI ("OnSTOP_CMD")

if (GetV(V_MOTION,MyID) ~= MOTION_STAND) then
Move (MyID,GetV(V_POSITION,MyID))
end
MyState = IDLE_ST
MyDestX = 0
MyDestY = 0
MyEnemy = 0
MySkill = 0

end


Essa função faz o homunculo parar de se mover, entrar em estado IDLE_ST (estado Idle, "standby") e desselecionar quaisquer skills e alvos. Se o homunculo estiver fazendo algo além de estar parado, essa função o fará mover para sua posição atual (ou seja, parar) e então mudar seu estado para Idle.
[3.33]

CODE
function OnATTACK_OBJECT_CMD (id)

TraceAI ("OnATTACK_OBJECT_CMD")

MySkill = 0
MyEnemy = id
MyState = CHASE_ST

end


Essa função pega o ID de um inimigo e marca-o como alvo do homunculo. Então o homunculo muda para o estado de perseguição, no qual ele irá perseguir o inimigo. Também faz com que o homunculo desselecione qualquer skill, ou seja, ele irá atacar o alvo normalmente.
[3.34]

CODE
function OnATTACK_AREA_CMD (x,y)

TraceAI ("OnATTACK_AREA_CMD")

if (x ~= MyDestX or y ~= MyDestY or MOTION_MOVE ~= GetV(V_MOTION,MyID)) then
Move (MyID,x,y)
end
MyDestX = x
MyDestY = y
MyEnemy = 0
MyState = ATTACK_AREA_CMD_ST

end


Essa função pega uma posição (x,y) e manda o homunculo "atacar" aquela celula. Basicamente, o homunculo se moverá até o local e então procurará por inimigos proximos para começar a atacar (o que é parte do ATTACK_AREA_CMD_ST que será observado mais adiante).
[3.35]

CODE
function OnPATROL_CMD (x,y)

TraceAI ("OnPATROL_CMD")

MyPatrolX , MyPatrolY = GetV (V_POSITION,MyID)
MyDestX = x
MyDestY = y
Move (MyID,x,y)
MyState = PATROL_CMD_ST

end


Essa função pega uma posição e faz o homunculo patrulhar entre sua posição atual e a posição escolhida.
[3.36]

CODE
function OnPATROL_CMD (x,y)

TraceAI ("OnPATROL_CMD")

MyPatrolX , MyPatrolY = GetV (V_POSITION,MyID)
MyDestX = x
MyDestY = y
Move (MyID,x,y)
MyState = PATROL_CMD_ST

end


Esse é o ALT+T. Faz seu homunculo parar de fazer o que estiver fazendo e mudar para o estado de Hold.
[3.37]

CODE
function OnSKILL_OBJECT_CMD (level,skill,id)

TraceAI ("OnSKILL_OBJECT_CMD")

MySkillLevel = level
MySkill = skill
MyEnemy = id
MyState = CHASE_ST

end


Essa função pega um level de skill, uma ID da skill, um ID de inimigo e faz seu homunculo selecionar a skill no level escolhido e marcar o inimigo como seu alvo, mudando então para o estado de perseguição para se aproximar o bastante do inimigo e usar a skill escolhida.
[3.38]

CODE
function OnSKILL_AREA_CMD (level,skill,x,y)

TraceAI ("OnSKILL_AREA_CMD")

Move (MyID,x,y)
MyDestX = x
MyDestY = y
MySkillLevel = level
MySkill = skill
MyState = SKILL_AREA_CMD_ST

end


Essa função é basicamente igual à anterior, entretanto o homunculo escolhe uma posição ao invés de um inimigo. O Homunculo então se move para essa posição e seleciona o skill escolhido antes de mudar de estado para SKILL_AREA_CMD_ST.
[3.39]

CODE
function OnFOLLOW_CMD ()

if (MyState ~= FOLLOW_CMD_ST) then
MoveToOwner (MyID)
MyState = FOLLOW_CMD_ST
MyDestX, MyDestY = GetV (V_POSITION,GetV(V_OWNER,MyID))
MyEnemy = 0
MySkill = 0
TraceAI ("OnFOLLOW_CMD")
else
MyState = IDLE_ST
MyEnemy = 0
MySkill = 0
TraceAI ("FOLLOW_CMD_ST --> IDLE_ST")
end

end


Essa função faz o homunculo mover até seu dono e mudar para o estado de de seguir, se já não estiver nele. Caso já esteja no estado de seguir, faz o homunculo mudar para o estado Idle. 3.3A]

CODE
function ProcessCommand (msg)

if (msg[1] == MOVE_CMD) then
OnMOVE_CMD (msg[2],msg[3])
TraceAI ("MOVE_CMD")
elseif (msg[1] == STOP_CMD) then
OnSTOP_CMD ()
TraceAI ("STOP_CMD")
elseif (msg[1] == ATTACK_OBJECT_CMD) then
OnATTACK_OBJECT_CMD (msg[2])
TraceAI ("ATTACK_OBJECT_CMD")
elseif (msg[1] == ATTACK_AREA_CMD) then
OnATTACK_AREA_CMD (msg[2],msg[3])
TraceAI ("ATTACK_AREA_CMD")
elseif (msg[1] == PATROL_CMD) then
OnPATROL_CMD (msg[2],msg[3])
TraceAI ("PATROL_CMD")
elseif (msg[1] == HOLD_CMD) then
OnHOLD_CMD ()
TraceAI ("HOLD_CMD")
elseif (msg[1] == SKILL_OBJECT_CMD) then
OnSKILL_OBJECT_CMD (msg[2],msg[3],msg[4],msg[5])
TraceAI ("SKILL_OBJECT_CMD")
elseif (msg[1] == SKILL_AREA_CMD) then
OnSKILL_AREA_CMD (msg[2],msg[3],msg[4],msg[5])
TraceAI ("SKILL_AREA_CMD")
elseif (msg[1] == FOLLOW_CMD) then
OnFOLLOW_CMD ()
TraceAI ("FOLLOW_CMD")
end
end


Essa é a função principal de todo o processo de comandos, faz seu homunculo realizar a função de acordo com o comando que é passado para ele. Note que msg[1], msg[2], msg[3], etc., todas apontam para diferentes partes da mesma mensagem. Portanto, em uma mensagem especificando um comando de movimento, você teria algo como msg = {MOVE_CMD, x,y}. Ou seja, onde a função chama por OnMOVE_CMD(msg[2],msg[3]), está na realidade chamando por OnMOVE_COMMAND(x,y), onde x e y são quaisquers numeros que foram usados nessa mensagem. A função usa o valor da primeira parte da mensagem para determinar quantas outras partes a mensagem contém. Estranhamente, o OnSKILL_OBJECT_COMMAND usa quatro partes de mensagem, ao invés de três que é o que a função realmente nescessita. Entretanto, como tudo parece funcionar mesmo assim, deixarei como está.
[3.40]
Agora veremos os processos de estados, que definem qual o comportamento do homunculo em determinado estado. Após o comando Process(msg) chamar uma função, o estado do homunculo normalmente muda, mostrando que o comando foi processado. A função AI então chama essas funções de estado para fazer o homunculo se comportar como ele deveria.
[3.41]

CODE
function OnIDLE_ST ()

TraceAI ("OnIDLE_ST")

local cmd = List.popleft(ResCmdList)
if (cmd ~= nil) then
ProcessCommand (cmd)
return
end

local object = GetOwnerEnemy (MyID)
if (object ~= 0) then
MyState = CHASE_ST
MyEnemy = object
TraceAI ("IDLE_ST -> CHASE_ST : MYOWNER_ATTACKED_IN")
return
end

object = GetMyEnemy (MyID)
if (object ~= 0) then
MyState = CHASE_ST
MyEnemy = object
TraceAI ("IDLE_ST -> CHASE_ST : ATTACKED_IN")
return
end

local distance = GetDistanceFromOwner(MyID)
if ( distance > 3 or distance == -1) then
MyState = FOLLOW_ST
TraceAI ("IDLE_ST -> FOLLOW_ST")
return;
end

end


Essa função define o comportamento do homunculo no estado Idle. A primeira coisa que ela faz é processar qualquer comando que estiver enfileirado, como movimentos finais quando o movimento inicial era longo demais, ou qualquer comando passado enquanto o homunculo mudava de estado. Então ele procura por inimigos do dono, se encontrar algum ele o atacará. Se não encontrar nenhum, ele procurará por inimigos do homunculo e os atacará. Se não encontrar nenhum, ele voltará para perto do seu dono caso esteja a mais de 3 celulas de distancia. Se nenhuma dessas condições for verdadeira, o homunculo não fará nada.
[3.42]

CODE
function OnFOLLOW_ST ()

TraceAI ("OnFOLLOW_ST")

if (GetDistanceFromOwner(MyID) <= 3) then
MyState = IDLE_ST
TraceAI ("FOLLOW_ST -> IDLW_ST")
return;
elseif (GetV(V_MOTION,MyID) == MOTION_STAND) then
MoveToOwner (MyID)
TraceAI ("FOLLOW_ST -> FOLLOW_ST")
return;
end

end


Essa função define o comportamento do homunculo no estado de seguir. Primeiro ele checa se está a menos de três celulas do dono, se sim, ele muda para o estado idle. Caso contrário, se estiver parado, ele se moverá para perto do dono. Note o erro de ditação em "Idle" no TraceAI. Foi a Gravity, não eu.

[3.43]

CODE
function OnCHASE_ST ()

TraceAI ("OnCHASE_ST")

if (true == IsOutOfSight(MyID,MyEnemy)) then
MyState = IDLE_ST
MyEnemy = 0
MyDestX, MyDestY = 0,0
TraceAI ("CHASE_ST -> IDLE_ST : ENEMY_OUTSIGHT_IN")
return
end
if (true == IsInAttackSight(MyID,MyEnemy)) then
MyState = ATTACK_ST
TraceAI ("CHASE_ST -> ATTACK_ST : ENEMY_INATTACKSIGHT_IN")
return
end

local x, y = GetV (V_POSITION,MyEnemy)
if (MyDestX ~= x or MyDestY ~= y) then
MyDestX, MyDestY = GetV (V_POSITION,MyEnemy);
Move (MyID,MyDestX,MyDestY)
TraceAI ("CHASE_ST -> CHASE_ST : DESTCHANGED_IN")
return
end

end


Essa função define o comportamento do homunculo no estado de perseguição. Se o inimigo estiver fora do campo visual, o homunculo irá parar desseleciona-lo e mudar para o estado Idle. Se o inimigo estiver dentro da distancia de ataque do homunculo, este irá mudar para o estado de ataque. Caso contrário, o homunculo continuará a se mover em direção ao inimigo.
[3.44]

CODE
function OnATTACK_ST ()

TraceAI ("OnATTACK_ST")

if (true == IsOutOfSight(MyID,MyEnemy)) then
MyState = IDLE_ST
TraceAI ("ATTACK_ST -> IDLE_ST")
return
end

if (MOTION_DEAD == GetV(V_MOTION,MyEnemy)) then
MyState = IDLE_ST
TraceAI ("ATTACK_ST -> IDLE_ST")
return
end

if (false == IsInAttackSight(MyID,MyEnemy)) then
MyState = CHASE_ST
MyDestX, MyDestY = GetV (V_POSITION,MyEnemy);
Move (MyID,MyDestX,MyDestY)
TraceAI ("ATTACK_ST -> CHASE_ST : ENEMY_OUTATTACKSIGHT_IN")
return
end

if (MySkill == 0) then
Attack (MyID,MyEnemy)
else
SkillObject (MyID,MySkillLevel,MySkill,MyEnemy)
MySkill = 0
end
TraceAI ("ATTACK_ST -> ATTACK_ST : ENERGY_RECHARGED_IN")
return

end


Essa função define o comportamento do homunculo enquanto ataca um inimigo. Se o inimigo estiver fora do campo visual ou morto, o homunculo irá voltar para o estado Idle. Se o inimigo se afastar e não estiver mais dentro da distancia de ataque, o homunculo voltará para a instancia de perseguição. Caso contrário, o homunculo irá atacar. Ele usará o skill selecionado no level selecionado, se algum foi. Ou apenas atacará normalmente, se nenhum skill foi selecionado.
[3.45]

CODE
function OnMOVE_CMD_ST ()

TraceAI ("OnMOVE_CMD_ST")

local x, y = GetV (V_POSITION,MyID)
if (x == MyDestX and y == MyDestY) then
MyState = IDLE_ST
end
end


Essa função define o comportamento do homunculo enquanto se move. Se a sua posição atual for igual ao destino que lhe havia sido dado, ele muda para o estado Idle.
[3.46]

CODE
function OnSTOP_CMD_ST ()


end



function OnATTACK_OBJECT_CMD_ST ()


end


Essas funções estão vazias, fazendo com que o homunculo não faça nda enquanto estiver nelas. Faz você se perguntar por que elas foram definidas, não faz?
[3.47]

CODE
function OnATTACK_AREA_CMD_ST ()

TraceAI ("OnATTACK_AREA_CMD_ST")

local object = GetOwnerEnemy (MyID)
if (object == 0) then
object = GetMyEnemy (MyID)
end

if (object ~= 0) then
MyState = CHASE_ST
MyEnemy = object
return
end

local x , y = GetV (V_POSITION,MyID)
if (x == MyDestX and y == MyDestY) then
MyState = IDLE_ST
end

end


Essa função define como o homunculo se comporta quando é ordenado a atacar uma localidade. Após se mover para essa localidade, ele irá procurar por inimigos assim como faz no estado Idle.
[3.48]

CODE
function OnPATROL_CMD_ST ()

TraceAI ("OnPATROL_CMD_ST")

local object = GetOwnerEnemy (MyID)
if (object == 0) then
object = GetMyEnemy (MyID)
end

if (object ~= 0) then
MyState = CHASE_ST
MyEnemy = object
TraceAI ("PATROL_CMD_ST -> CHASE_ST : ATTACKED_IN")
return
end

local x , y = GetV (V_POSITION,MyID)
if (x == MyDestX and y == MyDestY) then
MyDestX = MyPatrolX
MyDestY = MyPatrolY
MyPatrolX = x
MyPatrolY = y
Move (MyID,MyDestX,MyDestY)
end

end


Essa função define como o homunculo se comporta enquanto patrulha uma localidade. Ele primeiro procura por inimigos. Se encontrar algum, ele muda para o estado de Perseguição e o persegui-rá. Se nenhum inimigo for encontrado, ele ficará andando entre as posições que foram demarcadas até encontrar um.
[3.49]

CODE
function OnHOLD_CMD_ST ()

TraceAI ("OnHOLD_CMD_ST")

if (MyEnemy ~= 0) then
local d = GetDistance(MyEnemy,MyID)
if (d ~= -1 and d <= GetV(V_ATTACKRANGE,MyID)) then
Attack (MyID,MyEnemy)
else
MyEnemy = 0
end
return
end


local object = GetOwnerEnemy (MyID)
if (object == 0) then
object = GetMyEnemy (MyID)
if (object == 0) then
return
end
end

MyEnemy = object

end


Essa função define como o homunculo se comporta no estado de Hold. Se ele tiver um inimigo que estiver dentro de distancia de ataque, ele atacará o inimigo. Caso contrário, ele desselecionará o inimigo. Caso o homunculo não tenha nenhum alvo atual, ele irá procurar por novos.
[3.4A]

CODE
function OnSKILL_OBJECT_CMD_ST ()

end


Outra função vazia.

CODE
function OnSKILL_AREA_CMD_ST ()

TraceAI ("OnSKILL_AREA_CMD_ST")

local x , y = GetV (V_POSITION,MyID)
if (GetDistance(x,y,MyDestX,MyDestY) <= GetV(V_SKILLATTACKRANGE,MyID,MySkill)) then
SkillGround (MyID,MySkillLevel,MySkill,MyDestX,MyDestY)
MyState = IDLE_ST
MySkill = 0
end

end


Essa função define como o homunculo se comporta ao tentar usar uma skill no chãol. Se ele estiver dentro da distancia minima para uso da skill, ele a usará no local indicado e mudará para o estado Idle.
[3.4C]

CODE
function OnFOLLOW_CMD_ST ()

TraceAI ("OnFOLLOW_CMD_ST")

local ownerX, ownerY, myX, myY
ownerX, ownerY = GetV (V_POSITION,GetV(V_OWNER,MyID))
myX, myY = GetV (V_POSITION,MyID)

local d = GetDistance (ownerX,ownerY,myX,myY)

if ( d <= 3) then
return
end

local motion = GetV (V_MOTION,MyID)
if (motion == MOTION_MOVE) then
d = GetDistance (ownerX, ownerY, MyDestX, MyDestY)
if ( d > 3) then
MoveToOwner (MyID)
MyDestX = ownerX
MyDestY = ownerY
return
end
else
MoveToOwner (MyID)
MyDestX = ownerX
MyDestY = ownerY
return
end

end


Essa função define como o homunculo se comporta no estado de Seguir. Ele se moverá para uma distancia maxima de 3 celulas do dono e tentará manter essa distancia.

[3.50]
A seguir estão as funções de seleção de inimigos, que são usadas em algumas das funções acima para fazer o homunculo escolher um inimigo como alvo. Há alguns critérios diferentes para se definir inimigos, estes estão separados nas funções abaixo:
[3.51]

CODE
function GetOwnerEnemy (myid)
local result = 0
local owner = GetV (V_OWNER,myid)
local actors = GetActors ()
local enemys = {}
local index = 1
local target
for i,v in ipairs(actors) do
if (v ~= owner and v ~= myid) then
target = GetV (V_TARGET,v)
if (target == owner) then
if (IsMonster(v) == 1) then
enemys[index] = v
index = index+1
else
local motion = GetV(V_MOTION,i)
if (motion == MOTION_ATTACK or motion == MOTION_ATTACK2) then
enemys[index] = v
index = index+1
end
end
end
end
end

local min_dis = 100
local dis
for i,v in ipairs(enemys) do
dis = GetDistance2 (myid,v)
if (dis < min_dis) then
result = v
min_dis = dis
end
end

return result
end


Essa função é bastante longa, mas apenas retorna o inimigo atacante do dono mais proximo para que o homunculo tenha ele como inimigo. Ela faz uma lista de todos objetos na tela e procura em todos eles aqueles que estão atacando o dono, seja um monstro ou não-monstro (jogadores em situações de PvP), então procura qual deles está mais perto do dono e marca este como o alvo de maior prioridade para o homunculo.

[3.52]

CODE
function GetMyEnemy (myid)
local result = 0

local type = GetV (V_HOMUNTYPE,myid)
if (type == LIF or type == LIF_H or type == AMISTR or type == AMISTR_H or type == LIF2 or type == LIF_H2 or type == AMISTR2 or

type == AMISTR_H2) then
result = GetMyEnemyA (myid)
elseif (type == FILIR or type == FILIR_H or type == VANILMIRTH or type == VANILMIRTH_H or type == FILIR2 or type == FILIR_H2 or

type == VANILMIRTH2 or type == VANILMIRTH_H2) then
result = GetMyEnemyB (myid)
end
return result
end


Essa função é usada em geral quando o dono do homunculo não tem inimigos e irá procurar por inimigos do homunculo. Para Amistr e Lif, essa função irá chamar GetMyEnemyA, a função passiva de procura por inimigos. Se for Filir ou Vanilmirth, irá chamar por GetMyEnemyB, a função agressiva de procura por inimigos.
[3.53]

CODE
function GetMyEnemyA (myid)
local result = 0
local owner = GetV (V_OWNER,myid)
local actors = GetActors ()
local enemys = {}
local index = 1
local target
for i,v in ipairs(actors) do
if (v ~= owner and v ~= myid) then
target = GetV (V_TARGET,v)
if (target == myid) then
enemys[index] = v
index = index+1
end
end
end

local min_dis = 100
local dis
for i,v in ipairs(enemys) do
dis = GetDistance2 (myid,v)
if (dis < min_dis) then
result = v
min_dis = dis
end
end

return result
end


Função de procura de inimigo padrão para Amistr e Lif, é muito parecida com GetOwnerEnemy: ela procura por inimigos do dono, mas também por inimigos que estejam atacando o homunculo. A prioridade é para aquele que estiver mais perto do homunculo. Ou seja, Amistir e Lif, pelo padrão, só atacam se forem atacados (ou se seu dono for atacado).
[3.54]

CODE
function GetMyEnemyB (myid)
local result = 0
local owner = GetV (V_OWNER,myid)
local actors = GetActors ()
local enemys = {}
local index = 1
local type
for i,v in ipairs(actors) do
if (v ~= owner and v ~= myid) then
if (1 == IsMonster(v)) then
enemys[index] = v
index = index+1
end
end
end

local min_dis = 100
local dis
for i,v in ipairs(enemys) do
dis = GetDistance2 (myid,v)
if (dis < min_dis) then
result = v
min_dis = dis
end
end

return result
end


Essa função é parecida com a anterior, entretanto ela aceita todos inimigos na tela como alvos potenciais. É o sistema padrão de localização de inimigos para Filir e Valnirmith. Há um problema de lógica com esse script: ele não checa para ver se o monstro já está lutando com outro jogador, resultando em Kill-Steal (KS) por parte do homunculo. Isso pode ser facilmente corrigido e será discutido na sessão de custom AI.
[3.60]

CODE
function AI(myid)

MyID = myid
local msg = GetMsg (myid)
local rmsg = GetResMsg (myid)


if msg[1] == NONE_CMD then
if rmsg[1] ~= NONE_CMD then
if List.size(ResCmdList) < 10 then
List.pushright (ResCmdList,rmsg)
end
end
else
List.clear (ResCmdList)
ProcessCommand (msg)
end

if (MyState == IDLE_ST) then
OnIDLE_ST ()
elseif (MyState == CHASE_ST) then
OnCHASE_ST ()
elseif (MyState == ATTACK_ST) then
OnATTACK_ST ()
elseif (MyState == FOLLOW_ST) then
OnFOLLOW_ST ()
elseif (MyState == MOVE_CMD_ST) then
OnMOVE_CMD_ST ()
elseif (MyState == STOP_CMD_ST) then
OnSTOP_CMD_ST ()
elseif (MyState == ATTACK_OBJECT_CMD_ST) then
OnATTACK_OBJECT_CMD_ST ()
elseif (MyState == ATTACK_AREA_CMD_ST) then
OnATTACK_AREA_CMD_ST ()
elseif (MyState == PATROL_CMD_ST) then
OnPATROL_CMD_ST ()
elseif (MyState == HOLD_CMD_ST) then
OnHOLD_CMD_ST ()
elseif (MyState == SKILL_OBJECT_CMD_ST) then
OnSKILL_OBJECT_CMD_ST ()
elseif (MyState == SKILL_AREA_CMD_ST) then
OnSKILL_AREA_CMD_ST ()
elseif (MyState == FOLLOW_CMD_ST) then
OnFOLLOW_CMD_ST ()
end

end


Esse é o coração de todo o script de AI. Ele pega o ID do homunculo e imediatamente o armazena na variavel MyID, o que permite que muitas informações sejam adquiridas a partir da função GetV. Após isso, a função pega uma mensagem e uma mensagem reserve. Se não houver nenhuma mensagem, ele adicionará a rmsg para a sua lista e tentará efetuar os processos de estado (o padrão sendo Idle). Se houver uma mensagem, ela será processada pela função ProcessCommand(msg) que chamará o comando apropriado. Após isso, o estado atual do homunculo é comparado com os varios estados definidos, e quando retornar verdadeiro ele chama a função para que o homunculo se comporte como deve naquele estado. É assim que o homunculo toma decisões

Índice:
[4.00] Personalizando sua AI
[4.10] Criando uma função GetMyEnemy melhor
[4.20] Sem mais homunculos perdidos
[4.30] Personalizando o estilo de batalha de seu homunculo
[4.31] Uso automaticos de skills de efeito direto
[4.32] Uso automatico de buffs
[4.33] Modos personalizados de batalha
[4.40] Custo em SP para habilidades de Homunculos
[4.41] Lif
[4.42] Amistir
[4.43] Filir
[4.44] Valnirmith
[4.50] Skill Delay para os buffs de Homunculos
[4.51] Lif
[4.52] Amistir
[4.53] Filir
[4.54] Valnirmith
[4.60] Truques legais para mascotes legais
[4.61] Script de conjuração automatica.
-------

[4.00]
Agora a parte que provavelmente todos estiveram esperando. Aqui eu entrarei em diversas técnicas que você pode usar para personalizar a AI de seu homunculo para que ele faça qualquer tipo de coisa, desde andar pelo mapa até usar skills. Você pode especificar qualquer tipo de coisa na AI personalizada, e o unico limite real é a sua imaginação e o que os códigos podem fazer. Mas antes de irmos para a parte criativa, vamos primeiro para as modifcações que acredito que todos devam fazer, coisas que a própria Gravity deveria ter feito.

[4.10]
O primeiro arquivo irá corrigir o Kill-Stealing da função agressiva de seleção de inimigos. Do modo padrão, o homunculo irá atacar qualquer inimigo que estiver na tela, mesmo que ele já esteja lutando com outro jogador. Nós não queremos isso, visto que é uma forma facil de conseguir um ban caso você jogue por uma semana sem conseguir pressionar Alt+T rapido o bastante. O que nós faremos para corrigir esse problema é adicionar uma nova função, GetMyEnemyC, com uma condição "if" modificada que faz com que o homunculo ataque apenas inimigos que não tenham alvos (exceto, claro, se o alvo for o próprio homunculo ou seu dono). Essa função também não seleciona plantas e guardiões de castelos.

CODE
function GetMyEnemyC (myid)
local result = 0
local owner = GetV (V_OWNER,myid)
local actors = GetActors ()
local enemys = {}
local index = 1
local type
local target
for i,v in ipairs(actors) do
if (v ~= owner and v ~= myid) then
target = GetV (V_TARGET, v)
if (1 == IsMonster(v)) then
type = GetV (V_HOMUNTYPE, v)
if (target ~= 0) then
if (target == myid or target == owner) then
enemys[index] = v
index = index+1
end
elseif (type~=1555 and type~=1575 and type~=1579 and type~=1589 and type~= 1590 and (type < 1285 or type > 1288) and (type < 1078 or type > 1085)) then
enemys[index] = v
index = index+1
end
end
end
end

local min_dis = 100
local dis
for i,v in ipairs(enemys) do
dis = GetDistance2 (myid,v)
if (dis < min_dis) then
result = v
min_dis = dis
end
end

return result
end


Essa função adiciona um critério novo no meio, checando para ver se o inimigo possui algum alvo, e se possuir checa para ver se o alvo não é nem o dono e nem o homunculo. Também checa para ver se o monstro é o uma planta (ou cogumelo) ou um Guardião, se for ele os ignora. Há um caso em que o homunculo ainda atacará os monstros de outro jogador: caso o jogador entre em sua tela com monstros os seguindo mas sem o atacar. Nesse caso o homunculo não irá reconhecer que os monstros estão visando o jogador, e irá ataca-los. Entretanto esse é um caso mais isolado que o Kill Steal simples e direto que o homunculo faria normalmente. Para implementar essa função em sua AI, você deve coloca-la logo após GetMyEnemyB e então modificar a função GetMyEnemy para que os homunculus agressivos usem GetMyEnemyC ao invés de GetMyEnemyB.

[4.20]
Essa é uma modificação à função IsOutOfSight do arquivo Util.lua. Há um problema com os homunculos agressivos em que eles costumam sair correndo pelo mapa, simplesmente porque o monstro está dentro do seu campo se visão. Então eles se perdem em algum lugar do mapa e seu dono tem que ir atras deles. O que devemos fazer é alterar um critério para determinar se o monstro está dentro ou fora do campo de visão do homunculo. Como a maioria dos usuarios de homunculos preferire manter seu homunculo nos limites de sua tela, usaremos a posição do dono do homunculo como centro para determinar o campo visual. Além disso, diminuiremos um pouco o valor maximo de distância. O valor padrão é de vinte celulas.

CODE
function IsOutOfSight (id1,id2)
local x1,y1 = GetV (V_POSITION,GetV(V_OWNER,id1))
local x2,y2 = GetV (V_POSITION,id2)
if (x1 == -1 or x2 == -1) then
return true
end
local d = GetDistance (x1,y1,x2,y2)
if d > 16 then
return true
else
return false
end
end


Ai está. Ele usa a distancia do dono do homunculo para o monstro, ao invés da distancia do homunculo para o monstro e diminui a distancia maxima de vinte para dezesseis celulas.

[4.30]
Agora vamos ao que interessa: como fazer os homunculos tomarem todas as suas decisões no calor da batalha? Programando-os para isso, óbvio. Há muitas coisas que um homunculo pode fazer por ele mesmo enquanto luta, como usar skills automaticamente, buffar-se, e ainda conseguir controlar o level que utiliza seus skills e buffs de forma util.

[4.40]
Aqui está uma referencia ao custo de SP dos skills que serão usados adiante, e você poderá achar util nas suas próprias aventuras nos scripts.
Obrigado novamente à Hahseckh por vários desses valores:

[4.41]
Lif:
Healing Touch:
lvl 1 = ?
lvl 2 = ?
lvl 3 = ?
lvl 4 = ?
lvl 5 = ?
Urgent Escape:
lvl 1 = ?
lvl 2 = ?
lvl 3 = ?
lvl 4 = ?
lvl 5 = 40 sp

[4.42]
Amistr:
Castling:
lvl 1 = ?
lvl 2 = ?
lvl 3 = ?
lvl 4 = ?
lvl 5 = 10 sp
Amistr Bulwark:
lvl 1 = 20 SP
lvl 2 = 25 SP
lvl 3 = 30 SP
lvl 4 = 35 SP
lvl 5 = 40 SP

[4.43]
Filir:
Moonlight:
lvl 1 = 4 SP
lvl 2 = 8 SP
lvl 3 = 12 SP
lvl 4 = 16 SP
lvl 5 = 20 SP
Flitting:
lvl 1 = 30 SP
lvl 2 = 40 SP
lvl 3 = 50 SP
lvl 4 = 60 SP
lvl 5 = 70 SP
Accelerated Flight:
lvl 1 = 30 SP
lvl 2 = 40 SP
lvl 3 = 50 SP
lvl 4 = 60 SP
lvl 5 = 70 SP

[4.44]
Vanilmirth:
Caprice:
lvl 1 = ?
lvl 2 = ?
lvl 3 = ?
lvl 4 = 28 SP
lvl 5 = 30 SP
Chaotic Blessings:
lvl 1 = ?
lvl 2 = ?
lvl 3 = ?
lvl 4 = ?
lvl 5 = 40 SP

[4.31]
Começarem com algumas técnicas básicas de uso automatico de skills de efeito direto. "Skills de Efeito Direto" é a forma com a qual me refiro a skills cujo o efeito é sentido instanameante, como skills de cura ou de causar dano. A primeira coisa que precisaremos são algumas variaveis globais, então vamos definir elas primeiro. Aqui está o pseudo-código para a definição dessas variaveis.

CODE
SkillDelay = 0

Homunc_Auto_DESkill = 1
Homunc_DESkillID = "XXXX"
Homunc_DESkillLevel = "Y"
Homunc_DESkillUseSP = Z
Homunc_DESkillDelay = 0
Homunc_DESkillDelayTimes = A


SkillDelay é um único valor que represanta o intervalo geral entre usos de skills, para se ter certeza que nenhum skill tentará ser usado dentro do tempo de Delay de outro skill. Qualquer coisa em 5 e 10 é um valor adequado para isso, entretanto começaremos com zero no arquivo para que o homunculo possa começar a usar skills imediatamente.
Homunc_Auto_DESkill é uma variavel que deve ser posta em 1 ou 0 para representar LIGADO ou DESLIGADO respectivamente. Essa variavel será usada mais adiante para determinar se o homunculo deve usar skills automaticamente ou não.
Homunc_DESkillID guarda o ID do skill que o homunculo deve usar. Os ID de skills foram mostrados na sessão [1.20].
Homunc_DESkillLevel guarda o level da skill que o homunculo deve usar.
Homunc_DESkillUseSP guarda a quantidade de SP nescessária para se usar o skill. Será usado para se comparar com o SP atual do homunculo, para que ele nao tente usar a skill sem ter SP suficiente.
Homunc_DESkillDelay guarda o tempo de Skill Delay da skill escolhida.
Homunc_DESkillDelayTimes será usado para definir o número de ataques que o homunculo deve usar antes de usar um skill novamente. Qualquer coisa entre 5 e 10 é um bom valor para essa váriavel.
Agora voltemos ao código da função OnATTACK_ST, onde implementaremos o uso do AutoSkill:

CODE
if (SkillDelay <= 0 and Homunc_Auto_DESkill == 1 and GetV(V_SP, MyID) >= Homunc_DESkillUseSP) then
if (Homunc_DESkillDelay > 0) then
Homunc_DESkillDelay = Homunc_DESkillDelay - 1
else
SkillObject (MyID, Homunc_DESkill_Level, Homunc_DESkillID, MyEnemy)
SkillDelay = 5
Homunc_DESkillDelay = Homunc_DESkillDelayTimes
end
end
if (SkillDelay > 0) then
SkillDelay = SkillDelay - 1
end


Esse código deve ser posto no OnATTACK_ST, logo após a chamada de TraceAI. Se o skill estiver configurado para ser usado automaticamente, não houver skill delay e o homunculo tiver SP suficiente, ele usará o skill e então gravará os valores de skill delay especificos, subtraindo-os a medida que ataca, até poder usar o skill novamente.

[4.32]
Agora entraremos no uso automatico de buffs. A principal diferença com o que fizemos acima é que buffs possuem skill delay maior e um determinado tempo de duração.
[4.50]
Falando sobre tempo de duração, aqui está o intervalo de skills de acordo com a descrição das mesmas:

[4.51]
Lif:
Urgent Escape:
lvl 1 = 40 seconds
lvl 2 = 35 seconds
lvl 3 = 30 seconds
lvl 4 = 25 seconds
lvl 5 = 20 seconds

[4.52]
Amistr:
Amistr Bulwark:
lvl 1 = 40 seconds
lvl 2 = 35 seconds
lvl 3 = 30 seconds
lvl 4 = 25 seconds
lvl 5 = 20 seconds

[4.53]
Filir:
Flitting:
lvl 1 = 60 second delay
lvl 2 = 70 second delay
lvl 3 = 80 second delay
lvl 4 = 90 second delay
lvl 5 = 120 second delay
Accelerated Flight:
lvl 1 = 60 second delay
lvl 2 = 70 second delay
lvl 3 = 80 second delay
lvl 4 = 90 second delay
lvl 5 = 120 second delay

[4.54]
Vanilmirth:
No buff skills

Para usarmos buffs automaticamente, precisamos também de uma lista de variaveis globais. Algumas são iguais as da função anteirior, outras não. Vejamos novamente em forma de pseudo-código:

CODE
SkillDelay = 0

Homunc_Auto_Buff = 1
Homunc_BuffID = "XXXX"
Homunc_BuffLevel = "Y"
Homunc_BuffTime = A
Homunc_BuffUseSP = Z
Homunc_NowTick_Buff = 0
Homunc_StartTick_Buff = 0


SkillDelay tem o mesmo uso que tinha antes: uma pequena margem de intervalo de tempo entre usos de skills. Não muito importante aqui, visto que usaremos GetTick() para manter a contagem do tempo, mas ainda pode ser útil.
Homunc_Auto_Buff deve ser deixado como 1 ou 0 para LIGADO ou DESLIGADO. Determina se o homunculo usará auto-buffs ou não.
Homunc_BuffID guarda o ID do skill do buff, para ser usado na função de SkillObject.
Homunc_BuffLevel guarda o level do buff especifico.
Homunc_BuffTime guarda o intervalo de tempo que deve se decorrer entre os usos do buff.
Homunc_BuffUseSP guarda o custo de SP do skill, para que o homunculo nao tente usa-lo sem ter SP suficiente.
Homunc_NowTick_Buff guardará o tick atual, para ser comparado com a proxima variavel.
Homunc_StartTick_Buff guardará o tick em que o buff foi usado, a partir da função GetTick() do Const.lua. Comparando com o valor da variavel acima pode ser possivel determinar quanto tempo se passou desde o ultimo uso do buff.

Agora, assim como para os efeitos diretos, nós devemos implementar isso no arquivo, dentro da função onATTACK_ST. O código ficará mais ou menos assim:

CODE
if (SkillDelay <= 0 and Homunc_Auto_Buff == 1 and GetV(V_SP, MyID) >= Homunc_BuffUseSP) then
Homunc_NowTick_Buff = GetTick()
if (Homunc_NowTick_Buff - Homunc_StartTick_Buff >= Homunc_BuffTime * 1000) then
Homunc_StartTick_Buff = GetTick()
SkillObject (MyID, Homunc_Buff_Level, Homun_BuffID, MyID)
SkillDelay = 5
end
end
if (SkillDelay > 0) then
SkillDelay = SkillDelay - 1
end


A primeira checagem verifica se o buff está marcado como auto-cast. Se sim, e não houver skill delay, e o homunculo tiver SP suficiente, ele passaráa contar quanto tempo se passou desde o ultimo buff. Se for tempo o suficiente, o buff será usado e o StartTick será marcado para o tick atual. Note que você pode combinar os dois scripts aqui para que seu homunculo use buffs e skills diretos automaticamente.
Há muitos outros critérios que poderiam ser usados. Se você não quiser que o homunculo use algum skill sempre, preferir que ele o use apenas quando tiver menos de 50% hp, pode usar algo assim:

CODE
Homunc_HPPercent = GetV(V_HP,MyID)*100/GetV(V_MaxHP,MyID)
if (Homunc_HPPercent < 50) then
...
end


O código para o autocast viria dentro do espaço onde estão as "...".

[4.33]
Outra idéia que pode ser de grande uso é a de criar um Modo de Batalha, onde alguns critérios mudam o comportamento do Homunculo. Essas mudanças podem ser algo como ligar ou desligar o uso de autoskills ou aumentar o nivel da skill que está sendo usada. Essa função precisa de duas partes importantes, além de algumas variaveis globais. As partes importantes são uma clausula de entrada, onde todas as mudanças podem ser efetuadas, e uma clausula de saida, onde tudo volta aos valores padrões. Aqui estão as variaveis globais nescessárias para esse tipo de função:

CODE
Homunc_Craziness = 1
Homunc_GoneCrazy = 0
Homunc_CrazyTime = 60
Start_Tick_Crazy = 0
Now_Tick_Crazy = 0


Homunc_Craziness pode ser 1 ou 0 para LIGADO ou DESLIGADO. Determina se o homunculo poderá usar o novo modo (o qual chamei de "crazy") ou não.
Homunc_GoneCrazy guarda o valor 1 para quando o homunculo está no Crazy Mode ou 0 para quando está normal.
Homunc_CrazyTime define o tempo minimo que o modo vai durar.
Start_Tick_Crazy guarda o tick em que o Crazy Mode iniciou.
Now_TickCrazy guarda o tick atual para ser comparado com as duas variaveis acima.
Agora que temos as variaveis definidas, precisamos de definir a função GoCrazy() que fará o homunculo entrar nesse modo. Estou considerando o uso das funções de AutoSkill e AutoBuff aqui, pois elas serão editadas pelo Crazy Mode. O critério que usaremos será que, quando o HP do homunculo estiver abaixo de 50%, ele entrará em Crazy Mode por pelo menos um minuto. Após um minuto, se o HP do homunculo estiver acima de 50%, ele voltará ao normal. Caso contrário, ele continuará em Crazy Mode até ter HP superior a 50%.

CODE
function GoCrazy()
Homunc_HP = GetV(V_HP, MyID)*100/GetV(V_MAXHP, MyID)
if (Homunc_Craziness == 1) then
if (Homunc_GoneCrazy == 0) then
if (Homunc_HP <= 50) then
Start_Tick_Crazy = GetTick()
Homunc_GoneCrazy = 1
Homunc_DESkillLevel = "5"
Homunc_DESkillDelayTimes = 5
Homunc_BuffLevel = "5"
Homunc_BuffTime = 120
end
elseif (Homunc_GoneCrazy == 1) then
if (Homunc_HP > 50) then
Homunc_NowTick_Crazy = GetTick()
if (Homunc_NowTick_Crazy - Homunc_StartTick_Crazy >= Homunc_CrazyTime*1000) then
Homunc_GoneCrazy = 0
Homunc_DESkillLevel = "3"
Homunc_DESkillDelayTimes = 10
Homunc_BuffLevel = "3"
Homunc_BuffTime = 50
end
end
end
end
end


Tenha em mente que, em uma função real, outros valores deveriam ser levados em conta, como o custo de SP. Um bom local para posicionar essa função no arquivo AI.lua seria logo no começo do processo de Command, antes de OnMOVE_CMD. Após adiciona-la a seu arquivo, você deve ir até o OnATTACK_ST e adicionar o comando GoCrazy() logo após a chamada de TraceAI para que o homunculo possa entrar nesse modo antes de proceder com seus ataques, se for o caso.

[4.60]
Bem, aqui chega ao fim os basicos da criação de scripts de AI. Essa ultima sessão possui alguns scripts individuais que achei inteiressantes.

[4.61]
O primeiro script a ser adicionado aqui é um auto-cast para Amistr usar Castling quando seu dono estiver cercado por três ou mais monstros e estiver com menos de 25% de hp. Isso faz com que Amistir tanque o dano e é extremamente util para alquimistas baseados em AGI.

CODE
--New Global Variables
Amistr_CastlingID = "8005"
Amistr_CastlingLevel = "5"
Amistr_CastlingUseSP = 10
...
function OnATTACK_ST ()

TraceAI ("OnATTACK_ST")
------------------------------------------------
local owner = GetV (V_OWNER,MyID)
local actors = GetActors ()
local index = 0
local target
Owner_HPPercent = GetV(V_HP,owner)*100/GetV(V_MAXHP,owner)
for i,v in ipairs(actors) do
if (v ~= owner and v ~= MyID) then
target = GetV (V_TARGET,v)
if (target == owner) then
index = index+1
end
end
end
if (index >= 3 and GetV(V_SP, MyID) >= Amistr_CastlingUseSP and OwnerHP_Percent > 25) then
SkillObject (MyID, Amistr_CastlingLevel, Amistr_CastlingID, owner)
return
end
------------------------------------------------
if (true == IsOutOfSight(MyID,MyEnemy)) then
MyState = IDLE_ST
TraceAI ("ATTACK_ST -> IDLE_ST")
return
end

if (MOTION_DEAD == GetV(V_MOTION,MyEnemy)) then
MyState = IDLE_ST
TraceAI ("ATTACK_ST -> IDLE_ST")
return
end

if (false == IsInAttackSight(MyID,MyEnemy)) then
MyState = CHASE_ST
MyDestX, MyDestY = GetV (V_POSITION,MyEnemy);
Move (MyID,MyDestX,MyDestY)
TraceAI ("ATTACK_ST -> CHASE_ST : ENEMY_OUTATTACKSIGHT_IN")
return
end

if (MySkill == 0) then
Attack (MyID,MyEnemy)
else
SkillObject (MyID,MySkillLevel,MySkill,MyEnemy)
MySkill = 0
end
TraceAI ("ATTACK_ST -> ATTACK_ST : ENERGY_RECHARGED_IN")
return

end
...


E aqui está. Ele usa uma função parecida com a do GetOwnerEnemy para determinar quantos inimigos estão atacando o dono, se for maior do que 3, ele verifica o HP do dono. Se o HP estiver abaixo de 25%, Amistr usará castling e passará a atacar um dos inimigos.
Qualquer dúvida, comentário, sugestão, poe ae em baixo ^^
bem isso é tudo uma noite todinha de trabalho para a felicidade de todos ^^
sayonara

BEM ACHEI ESSE TUTOR FEITO POR ROZANINHA DO FORUM REVOLUTION, MAS CASO ALGUEM SAIBA O VERDADEIRO AUTOR ME INFORMEM EM POST!!!