Ir para conteúdo
  • Cadastre-se

MMOCore Assíncrono


KhayrusS

Posts recomendados


Muito bom KhayrusS, você é um colírio para os olhos. 

Como contribuição vou upar um programa que gerou muita dor de cabeça um tempo atrás, para você analisar se há uma forma de fixar o problema juntamente nessa mudança, pois pelo que lembro a correção era feita no mmocore.

Gostaria de ajudar mais se possível, mas acredito que não é do meu nível de conhecimento tal façanha.

Link para o comentário
Compartilhar em outros sites

 

Como contribuição vou upar um programa que gerou muita dor de cabeça um tempo atrás, para você analisar se há uma forma de fixar o problema juntamente nessa mudança, pois pelo que lembro a correção era feita no mmocore.

Opa, com certeza analisarei. O próximo passo é utilizá-lo no Gameserver para ver como se comporta, corrigir as falhas que venham acontecer. Depois verificar questões de segurança.

 

Gostaria de ajudar mais se possível, mas acredito que não é do meu nível de conhecimento tal façanha.

Acredito que cada um pode contribuir independente de nível de conhecimento, afinal o conhecimento está por aí pra ser adquirido, quanto maior o desafio mais conhecimento é gerado. Toda ajuda é bem vinda ?

Link para o comentário
Compartilhar em outros sites

Bom dia campeão!

Também não tenho um conhecimento tão sólido, mas estarei acompanhando o tópico e caso aja algo em que eu possa ajudar, estou a disposição;

Link para o comentário
Compartilhar em outros sites

Jamais imaginei que alguém iria mexer nisso, e muito menos dessa forma, incrível.

Tomara que você consiga alcançar os devidos resultados, o foda e o mais triste, que jaja estará sendo implantado em futuros projetos e vai ter gente anunciando (Vendo projeto com MMOCore atualizado 10x mais desempenho) é triste.

Boa sorte com o projeto, estou acompanhando, apesar de não ter conhecimento para contribuir 

Um mundo de diversão no Lineage 2

https://www.primeworld.com.br

Discord: Em breve

Comunidade brasileira de Lineage. Interlude Remastered / High Five / Essence 

Classes remasterizadas, sistemas únicos, diversão garantida.

Link para o comentário
Compartilhar em outros sites

 

Jamais imaginei que alguém iria mexer nisso, e muito menos dessa forma, incrível.

Tomara que você consiga alcançar os devidos resultados, o foda e o mais triste, que jaja estará sendo implantado em futuros projetos e vai ter gente anunciando (Vendo projeto com MMOCore atualizado 10x mais desempenho) é triste.

Boa sorte com o projeto, estou acompanhando, apesar de não ter conhecimento para contribuir 

É realmente triste ver esse tipo de prática com open source. Eu poderia simplesmente implementar e vender, mas eu faço isso pelo prazer, pelo desafio. Então tento não pensar muito nisso.

 

 

Bom dia campeão!

Também não tenho um conhecimento tão sólido, mas estarei acompanhando o tópico e caso aja algo em que eu possa ajudar, estou a disposição;

O desenvolvimento ainda está no início, tem muitas coisas que planejo fazer, algumas a curto prazo e outras a longo prazo. Com certeza uma mãozinha a mais é sempre bem-vinda. 

O projeto está disponível no github async-mmocore. Assim como um projeto de referência para implementação. Apesar de ter realizado um teste de "sanidade" e não ter encontrado nenhum problema grave. Acredito que ainda existem bugs, mas não tenho tanto tempo para testar. Como eu sou usuário Linux, o teste foi realizado apenas em um Servidor Interlude baseado em L2jServer, pois o cliente interlude pode ser executado em Linux sem muitas dificuldades. Seria interessante utilizar em servidores mais atuais, então se alguém estiver disposto a tentar utilizá-lo,  pode contar com a minha ajuda.

Os próximos passos que pretendo fazer:

  • Escrever uma documentação, inicialmente simples, descrevendo como utilizá-lo;
  • Criar uma wiki com as principais dificuldades e suas prováveis resoluções;
  • Documentar e melhorar o código.

Quando tiver um tempo irei atualizar o post principal e o wiki do projeto no github.

 

[ ]'s

Link para o comentário
Compartilhar em outros sites

 

 

Não pensa nisso mesmo, tem gente que faz? Tem! Mas o lineage 2 também não é tão nosso para apontarmos o dedo para isso.

Com esse pensamento de não compartilhar por que vão vender, se todos pensassem assim ninguém nunca teria feito nada. Uma coisa é você fazer para si, para utilizar, etc, entendível a questão de não compartilhar. Mas fazer pensando em não postar por que vão vender é meio sei lá, eu não pensaria assim, nem penso. Tenho algumas tralhas feitas, e provavelmente que quando não for utilizar postarei tudo.

Link para o comentário
Compartilhar em outros sites

 

Não pensa nisso mesmo, tem gente que faz? Tem! Mas o lineage 2 também não é tão nosso para apontarmos o dedo para isso.

Com esse pensamento de não compartilhar por que vão vender, se todos pensassem assim ninguém nunca teria feito nada. Uma coisa é você fazer para si, para utilizar, etc, entendível a questão de não compartilhar. Mas fazer pensando em não postar por que vão vender é meio sei lá, eu não pensaria assim, nem penso. Tenho algumas tralhas feitas, e provavelmente que quando não for utilizar postarei tudo.

Infelizmente tu sabe que é assim que funciona, caras como @KhayrusS criam, mas quem ganha com isso não são os desenvolvedores.

Porque sempre tem uns "zé ruela" que vem aqui o fórum pegam as coisas e vão pro facebook vender, quando não mandam mp querendo vender aqui no fórum mesmo.

# FATO

QdeQ9Kp.png

Link para o comentário
Compartilhar em outros sites

 

Falta só colocar online para saber as possíveis falhas? Ou existe outra maneira de se obter isso?

Eu já fiz alguns testes básicos, mas ainda é necessário ver como é comportamento com vários players logados. Ainda existe a probabilidade de haver falhas que seriam evidenciadas ao colocar online, embora eu não planeje colocar um servidor para teste por agora, nem aconselho que usem em servidores reais por enquanto. Como não tenho tanto tempo pra fazer um teste real em um servidor online nesse momento, ficarei esperando algum aventureiro tentar usá-lo e reportar os bugs que surgirem.

Alguém que tenha conhecimento sólido em Java já é capaz de utilizá-lo, em teoria em poucos passos:

  1. Compilar o mmocore disponível no repósitorio do github;
  2. Colocá-lo no classpath do projeto que pretende utilizar;
  3. Realizar as mudanças necessárias para utilizar as novas classes. 

 

Há algumas mudanças necessárias nas chamadas de método dos Packets, que provavelmente tendem a ser mais demoradas devido a quantidade de Classes existentes. Com relação a mudança do mmocore em si, basicamente o que precisa ser feito é substituir essa parte do código*:

// TODO: Unhardcode this configuration options
final SelectorConfig sc = new SelectorConfig();
sc.MAX_READ_PER_PASS = 12; // Config.MMO_MAX_READ_PER_PASS;
sc.MAX_SEND_PER_PASS = 12; // Config.MMO_MAX_SEND_PER_PASS;
sc.SLEEP_TIME = 20; // Config.MMO_SELECTOR_SLEEP_TIME;
sc.HELPER_BUFFER_COUNT = 20; // Config.MMO_HELPER_BUFFER_COUNT;
sc.TCP_NODELAY = false; // Config.MMO_TCP_NODELAY;

L2GamePacketHandler gph = new L2GamePacketHandler();
_selectorThread = new SelectorThread<>(sc, gph, gph, gph, new IPv4Filter());
InetAddress bindAddress = null;
if (!Config.GAMESERVER_HOSTNAME.equals("*")) {
    try {
        bindAddress = InetAddress.getByName(Config.GAMESERVER_HOSTNAME);
    } catch (UnknownHostException e1) {
        _log.error( getMessage("error.invalid.bind.address",  e1.getMessage()), e1); 
    }
}

try {
	_selectorThread.openServerSocket(bindAddress, Config.PORT_GAME);
} catch (IOException e) {
	_log.error( getMessage("error.open.socket", e.getMessage()), e);
    System.exit(1);
}

_selectorThread.start();

por essa:

L2GamePacketHandler gph = new L2GamePacketHandler();

InetSocketAddress bindAddress;
if (!Config.GAMESERVER_HOSTNAME.equals("*")) {
	bindAddress =  new InetSocketAddress(Config.GAMESERVER_HOSTNAME, Config.PORT_GAME);
} else {
	bindAddress = new InetSocketAddress(Config.PORT_GAME);
}

connectionHandler = ConnectionBuilder.create(bindAddress, gph,gph,gph).filter(new IPv4Filter()).build();
connectionHandler.start();

 

Contudo, há mudanças de hierarquia em L2GamePacketHandler e no Ipv4Filter. Essas alterações entre outros detalhes postarei depois quando estiver com um pouco mais de tempo.

Essas e as outras mudanças necessárias podem ser encontradas nesse repositório.

* Essa mudança está utilizando como base L2jserver.

 

 

[ ]'s

Link para o comentário
Compartilhar em outros sites

São essas coisas que fazem você um dos melhores membros do fórum. Desde 2008 até hoje!

Parabéns, brother. Que maravilha de tópico. Com toda certeza irei estudar um pouco sobre o assunto.

Você sabia que a L2JBrasil tem uma empresa de Hosting Oficial?
Conheça a L2JCenter.com

L2JBRASIL - 15 anos vendendo SS e flechas em Giran! (Trade / Adena)

Link para o comentário
Compartilhar em outros sites

 

São essas coisas que fazem você um dos melhores membros do fórum. Desde 2008 até hoje!

Parabéns, brother. Que maravilha de tópico. Com toda certeza irei estudar um pouco sobre o assunto.

Obrigado, brother ?

 

Adicionei uma descrição básica de como usar no githubE a primeira alpha release.

Link para o comentário
Compartilhar em outros sites

  • 1 month later...
  • 1 month later...
 

Foi testada com quantos jogadores online?

Não foi realizado testes relacionados a quantidade de jogadores online. Esse tipo de teste sairia do escopo do projeto, além de ser um teste difícil de realizar, difícil de mensurar e altamente custoso. Os testes são realizados utilizando Jmeter. O último teste que realizei, há um tempo, foram considerados 5000 usuários concorrentes enviando 10000 pacotes,  os pacotes foram entregues em menos de 1s. Infelizmente tive um problema com a infraestrutura que utilizei pro teste, e acabei perdendo os dados. No momento, estou um pouco sem tempo pra provisionar tudo outra vez e realizar um novo teste com a última versão, mas assim que der realizarei.

Link para o comentário
Compartilhar em outros sites

  • Marlon pinned this Tópico
  • L2JBr ADM
Em 25/09/2018 at 15:57, KhayrusS disse:

 


MMOCore utilizando Selector:
_________________________________________________________________
|Players  | Média | Min  | Max    | D. Padrão | Throughput |Erro |
|----------------------------------------------------------------|
|998	  | 60ms  | 43ms | 101ms  | 8.68      |   487.3/s  |0.0	 |  
|1999	  | 62ms  | 44ms | 115ms  | 9.01      |   769.73/s |0.0	 |  
|3993	  | 100ms | 42ms | 1261ms | 190.44    |   733.60/s |0.0	 |  
|7988	  | 411ms | 43ms | 7285ms | 889.66    |   807.27/s |0.0	 |  
|31976	  | 804ms | 6ms	 | 8792ms | 1628.33   |   769.96/s |11,3%|
 ͞ ͞ ͞ ͞ ͞ ͞ ͞͞ ͞ ͞ ͞ ͞ ͞ ͞ ͞ ͞͞ ͞ ͞ ͞ ͞ ͞ ͞͞ ͞ ͞ ͞ ͞ ͞ ͞ ͞ ͞͞ ͞ ͞ ͞ ͞ ͞ ͞͞ ͞ ͞ ͞ ͞ ͞ ͞ ͞ ͞͞ ͞ ͞ ͞ ͞ ͞ ͞͞ ͞ ͞ ͞ ͞ ͞ ͞ ͞ ͞͞ ͞ ͞ ͞ ͞ ͞ ͞͞ ͞

 MMOCore Assíncrono (2.0)
 _________________________________________________________________
|Players  | Média  | Min | Max    | D. Padrão | Throughput |Erro  |
|-----------------------------------------------------------------|
|1000	  |1ms	   |0ms	 |45ms	  |4.94	      |539.08      |0.0   |  
|2000	  |1ms	   |0ms	 |55ms	  |4.34	      |764.81      |0.0   |	  
|4000	  |2ms	   |0ms	 |64ms	  |4.62	      |804.50      |0.0   |	  
|8000	  |1ms	   |0ms	 |152ms	  |6.13	      |1106.19     |0.0   |	  
|32000	  |726ms   |0ms	 |45,159s |2060.37    |696.06      |11,7% |
 ͞ ͞ ͞ ͞ ͞ ͞ ͞͞ ͞ ͞ ͞ ͞ ͞ ͞ ͞ ͞͞ ͞ ͞ ͞ ͞ ͞ ͞͞ ͞ ͞ ͞ ͞ ͞ ͞ ͞ ͞͞ ͞ ͞ ͞ ͞ ͞ ͞͞ ͞ ͞ ͞ ͞ ͞ ͞ ͞ ͞͞ ͞ ͞ ͞ ͞ ͞ ͞͞ ͞ ͞ ͞ ͞ ͞ ͞ ͞ ͞͞ ͞ ͞ ͞ ͞ ͞ ͞͞ ͞ ͞

 

 

 

Eu não sei se você sabe interpretar essas informações do jmeter, mas vou tentar sintetizar aqui pra você:

 

No primeiro caso usando o Selector, você tem uma variação  quase na mesma proporção no Throughput de 1000 (998 falha de 2 que não foi computado) para 2000(falha de 1 que não foi computado) players (50%)  porém a variação de 2000 para 4000 é quase a mesma, ali está o ponto que dá lag, o Throughput deveria crescer de forma proporcional ao Throughput, então pode-se concluir que o limite nessa sua configuração é por volta de 2000 players (se o pacote fosse estável e constante, mas sabemos que é variado então pode variar pra mais ou menos). É natural que assim que você aumentar a quantidade de usuários você tenha aumento de Throughput, pois significa que vc tem mais usuários e precisa enviar mais requisições.

No caso com o MMOCore Assíncrono é um pouco diferente temos um Throughput crescendo junto com o número de usuários atingindo o limite de proporção 8:1 com 8 mil usuários, provavelmente por alguma limitação de hardware ou rede (que só se sanaria com uma escala horizontal dos recursos de hardware). O que representa um ganho muito bom!  Olhando por alto,  além de um tempo de resposta menor  por ser assíncrono é normal já que a conexão é terminada antes do processamento, o  Desvio Padrão bem estável também até 8000 mil usuários, quebrando somente em algum lugar entre 8000 e 32000 .

Arrisco que o ganho do  MMOCore Assíncrono é cerca de 5x ou 6x maior em comparação ao Selector e tenho certeza que da pra polir mais isso ai. Players que jogarem em servidores com essa tecnologia certamente terão uma experiência muito mais fluída de jogo.

 

 

@KhayrusS Seria interessante linkar esse tópico no readme do projeto , ajudaria o fórum certamente ?

EJoOSOj.gif

Sua pergunta foi respondida? Certifique-se de marcar a resposta como a solução aceita.
Se existe mais de uma resposta, utilize o "vote up" para destacá-la.
Se você achar uma resposta útil, diga obrigado clicando no botão "Gostei".

Link para o comentário
Compartilhar em outros sites

@Grundor Obrigado pelas observações ?. Ainda tenho algumas modificações pra fazer no tópico, mas meu tempo anda curto pra fazer algo elaborado que acrescente um pouco de valor.

 

18 horas atrás, Grundor disse:

@KhayrusS Seria interessante linkar esse tópico no readme do projeto , ajudaria o fórum certamente ?

Assim que fizer o próximo commit adicionarei ?

Link para o comentário
Compartilhar em outros sites

  • 6 months later...
  • 3 weeks later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Visitante
Responder

×   Você colou conteúdo com formatação.   Remover formatação

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Processando...
  • Registre-se

    Faça parte da maior e  mais antigas comunidades sobre Lineage2 da América Latina.





  • Patrocinadores

  • Quem Está Navegando

    • Nenhum usuário registrado visualizando esta página.
  • Posts

    • Teria como fazer do dusk shield e do zombie shield dessa maneira?     Teria como fazer do dusk shield e do zombie shield dessa maneira?     Teria como fazer do dusk shield e do zombie shield dessa maneira?     Teria como fazer do dusk shield e do zombie shield dessa maneira?     Teria como fazer do dusk shield e do zombie shield dessa maneira?     Teria como fazer do dusk shield e do zombie shield dessa maneira?    
    • muchas gracias muy lindos NPC 🙂
    • relaxa jovem gafanhoto, testa as quests. e posTa os erros indesejaveis.  
    • Se alguém pudesse me ensinar como codificar as missões, eu ficaria feliz em fazer isso sozinho ou pelo menos ajudar. Eu realmente quero jogar em um servidor onde todas as quests funcionem bem e melhor ainda se você puder fazer quests customizadas!
    • mas no interlude, nem todas as quests de class,  vai mostrar onde tem que ir, ate o reborn nao mostrava quando era interlude, só mostrou depois que eles colocaram client classic pra rodar, e ficou melhor ainda quando virou hellbound em diante, mas ha sim alguma chance de modificar isso direto no script para fazer igualmente, só basta te um pouco de paciencia e persistencia exato
    • 408_PathToElvenwizard dá Orion eu tive que mexer tbm, até modifiquei e consegui deixar ela igual do Classic, com a seta e a marcação no mapa. (não retail IL) Dá pra importar py de várias revs, o foda é que não da regular as quest py através do debug em tempo real, pelo menos eu não consegui rsrs
    • Hasta el momento todas las QUESTS son completables si te guias con un tutorial de youtube. El problema es que tienen bugs de locacion y de subquests que no avanzan o no te marcan correctamente a donde ir en el mapa, cosa que en Retail si se ve como corresponde.
    • estranho, mas pelo menos a galera nunca reclamo das quests quando tinha aberto 5x, geral fez class primeira e segunda job, poucos que compraram a class
    • en RUSaCis-3.5 data pack, las Quests estan en formato .java y son diferentes a como estan redactadas en jOrion y jFrozen 1.5 (ProyectX) package net.sf.l2j.gameserver.scripting.quest; import net.sf.l2j.commons.random.Rnd; import net.sf.l2j.gameserver.enums.Paperdoll; import net.sf.l2j.gameserver.enums.QuestStatus; import net.sf.l2j.gameserver.enums.actors.ClassId; import net.sf.l2j.gameserver.model.actor.Creature; import net.sf.l2j.gameserver.model.actor.Npc; import net.sf.l2j.gameserver.model.actor.Player; import net.sf.l2j.gameserver.network.serverpackets.SocialAction; import net.sf.l2j.gameserver.scripting.QuestState; public class Q224_TestOfSagittarius extends SecondClassQuest { private static final String QUEST_NAME = "Q224_TestOfSagittarius"; // Items private static final int BERNARD_INTRODUCTION = 3294; private static final int HAMIL_LETTER_1 = 3295; private static final int HAMIL_LETTER_2 = 3296; private static final int HAMIL_LETTER_3 = 3297; private static final int HUNTER_RUNE_1 = 3298; private static final int HUNTER_RUNE_2 = 3299; private static final int TALISMAN_OF_KADESH = 3300; private static final int TALISMAN_OF_SNAKE = 3301; private static final int MITHRIL_CLIP = 3302; private static final int STAKATO_CHITIN = 3303; private static final int REINFORCED_BOWSTRING = 3304; private static final int MANASHEN_HORN = 3305; private static final int BLOOD_OF_LIZARDMAN = 3306; private static final int CRESCENT_MOON_BOW = 3028; private static final int WOODEN_ARROW = 17; // Rewards private static final int MARK_OF_SAGITTARIUS = 3293; // NPCs private static final int BERNARD = 30702; private static final int HAMIL = 30626; private static final int SIR_ARON_TANFORD = 30653; private static final int VOKIAN = 30514; private static final int GAUEN = 30717; // Monsters private static final int ANT = 20079; private static final int ANT_CAPTAIN = 20080; private static final int ANT_OVERSEER = 20081; private static final int ANT_RECRUIT = 20082; private static final int ANT_PATROL = 20084; private static final int ANT_GUARD = 20086; private static final int NOBLE_ANT = 20089; private static final int NOBLE_ANT_LEADER = 20090; private static final int BREKA_ORC_SHAMAN = 20269; private static final int BREKA_ORC_OVERLORD = 20270; private static final int MARSH_STAKATO_WORKER = 20230; private static final int MARSH_STAKATO_SOLDIER = 20232; private static final int MARSH_STAKATO_DRONE = 20234; private static final int MARSH_SPIDER = 20233; private static final int ROAD_SCAVENGER = 20551; private static final int MANASHEN_GARGOYLE = 20563; private static final int LETO_LIZARDMAN = 20577; private static final int LETO_LIZARDMAN_ARCHER = 20578; private static final int LETO_LIZARDMAN_SOLDIER = 20579; private static final int LETO_LIZARDMAN_WARRIOR = 20580; private static final int LETO_LIZARDMAN_SHAMAN = 20581; private static final int LETO_LIZARDMAN_OVERLORD = 20582; private static final int SERPENT_DEMON_KADESH = 27090; public Q224_TestOfSagittarius() { super(224, "Test Of Sagittarius"); setItemsIds(BERNARD_INTRODUCTION, HAMIL_LETTER_1, HAMIL_LETTER_2, HAMIL_LETTER_3, HUNTER_RUNE_1, HUNTER_RUNE_2, TALISMAN_OF_KADESH, TALISMAN_OF_SNAKE, MITHRIL_CLIP, STAKATO_CHITIN, REINFORCED_BOWSTRING, MANASHEN_HORN, BLOOD_OF_LIZARDMAN, CRESCENT_MOON_BOW); addQuestStart(BERNARD); addTalkId(BERNARD, HAMIL, SIR_ARON_TANFORD, VOKIAN, GAUEN); addMyDying(ANT, ANT_CAPTAIN, ANT_OVERSEER, ANT_RECRUIT, ANT_PATROL, ANT_GUARD, NOBLE_ANT, NOBLE_ANT_LEADER, BREKA_ORC_SHAMAN, BREKA_ORC_OVERLORD, MARSH_STAKATO_WORKER, MARSH_STAKATO_SOLDIER, MARSH_STAKATO_DRONE, MARSH_SPIDER, ROAD_SCAVENGER, MANASHEN_GARGOYLE, LETO_LIZARDMAN, LETO_LIZARDMAN_ARCHER, LETO_LIZARDMAN_SOLDIER, LETO_LIZARDMAN_WARRIOR, LETO_LIZARDMAN_SHAMAN, LETO_LIZARDMAN_OVERLORD, SERPENT_DEMON_KADESH); } @Override public String onAdvEvent(String event, Npc npc, Player player) { String htmltext = event; QuestState st = player.getQuestList().getQuestState(QUEST_NAME); if (st == null) return htmltext; // BERNARD if (event.equalsIgnoreCase("30702-04.htm")) { st.setState(QuestStatus.STARTED); st.setCond(1); playSound(player, SOUND_ACCEPT); giveItems(player, BERNARD_INTRODUCTION, 1); if (giveDimensionalDiamonds39(player)) htmltext = "30702-04a.htm"; } // HAMIL else if (event.equalsIgnoreCase("30626-03.htm")) { st.setCond(2); playSound(player, SOUND_MIDDLE); takeItems(player, BERNARD_INTRODUCTION, 1); giveItems(player, HAMIL_LETTER_1, 1); } else if (event.equalsIgnoreCase("30626-07.htm")) { st.setCond(5); playSound(player, SOUND_MIDDLE); takeItems(player, HUNTER_RUNE_1, 10); giveItems(player, HAMIL_LETTER_2, 1); } // SIR_ARON_TANFORD else if (event.equalsIgnoreCase("30653-02.htm")) { st.setCond(3); playSound(player, SOUND_MIDDLE); takeItems(player, HAMIL_LETTER_1, 1); } // VOKIAN else if (event.equalsIgnoreCase("30514-02.htm")) { st.setCond(6); playSound(player, SOUND_MIDDLE); takeItems(player, HAMIL_LETTER_2, 1); } return htmltext; } @Override public String onTalk(Npc npc, Player player) { String htmltext = getNoQuestMsg(); QuestState st = player.getQuestList().getQuestState(QUEST_NAME); if (st == null) return htmltext; switch (st.getState()) { case CREATED: if (player.getClassId() != ClassId.ROGUE && player.getClassId() != ClassId.ELVEN_SCOUT && player.getClassId() != ClassId.ASSASSIN) htmltext = "30702-02.htm"; else if (player.getStatus().getLevel() < 39) htmltext = "30702-01.htm"; else htmltext = "30702-03.htm"; break; case STARTED: int cond = st.getCond(); switch (npc.getNpcId()) { case BERNARD: htmltext = "30702-05.htm"; break; case HAMIL: if (cond == 1) htmltext = "30626-01.htm"; else if (cond == 2 || cond == 3) htmltext = "30626-04.htm"; else if (cond == 4) htmltext = "30626-05.htm"; else if (cond > 4 && cond < 8) htmltext = "30626-08.htm"; else if (cond == 8) { htmltext = "30626-09.htm"; st.setCond(9); playSound(player, SOUND_MIDDLE); takeItems(player, HUNTER_RUNE_2, 10); giveItems(player, HAMIL_LETTER_3, 1); } else if (cond > 8 && cond < 12) htmltext = "30626-10.htm"; else if (cond == 12) { htmltext = "30626-11.htm"; st.setCond(13); playSound(player, SOUND_MIDDLE); } else if (cond == 13) htmltext = "30626-12.htm"; else if (cond == 14) { htmltext = "30626-13.htm"; takeItems(player, BLOOD_OF_LIZARDMAN, -1); takeItems(player, CRESCENT_MOON_BOW, 1); takeItems(player, TALISMAN_OF_KADESH, 1); giveItems(player, MARK_OF_SAGITTARIUS, 1); rewardExpAndSp(player, 54726, 20250); player.broadcastPacket(new SocialAction(player, 3)); playSound(player, SOUND_FINISH); st.exitQuest(false); } break; case SIR_ARON_TANFORD: if (cond == 2) htmltext = "30653-01.htm"; else if (cond > 2) htmltext = "30653-03.htm"; break; case VOKIAN: if (cond == 5) htmltext = "30514-01.htm"; else if (cond == 6) htmltext = "30514-03.htm"; else if (cond == 7) { htmltext = "30514-04.htm"; st.setCond(8); playSound(player, SOUND_MIDDLE); takeItems(player, TALISMAN_OF_SNAKE, 1); } else if (cond > 7) htmltext = "30514-05.htm"; break; case GAUEN: if (cond == 9) { htmltext = "30717-01.htm"; st.setCond(10); playSound(player, SOUND_MIDDLE); takeItems(player, HAMIL_LETTER_3, 1); } else if (cond == 10) htmltext = "30717-03.htm"; else if (cond == 11) { htmltext = "30717-02.htm"; st.setCond(12); playSound(player, SOUND_MIDDLE); takeItems(player, MANASHEN_HORN, 1); takeItems(player, MITHRIL_CLIP, 1); takeItems(player, REINFORCED_BOWSTRING, 1); takeItems(player, STAKATO_CHITIN, 1); giveItems(player, CRESCENT_MOON_BOW, 1); giveItems(player, WOODEN_ARROW, 10); } else if (cond > 11) htmltext = "30717-04.htm"; break; } break; case COMPLETED: htmltext = getAlreadyCompletedMsg(); break; } return htmltext; } @Override public void onMyDying(Npc npc, Creature killer) { final Player player = killer.getActingPlayer(); final QuestState st = checkPlayerState(player, npc, QuestStatus.STARTED); if (st == null) return; switch (npc.getNpcId()) { case ANT: case ANT_CAPTAIN: case ANT_OVERSEER: case ANT_RECRUIT: case ANT_PATROL: case ANT_GUARD: case NOBLE_ANT: case NOBLE_ANT_LEADER: if (st.getCond() == 3 && dropItems(player, HUNTER_RUNE_1, 1, 10, 500000)) st.setCond(4); break; case BREKA_ORC_SHAMAN: case BREKA_ORC_OVERLORD: if (st.getCond() == 6 && dropItems(player, HUNTER_RUNE_2, 1, 10, 500000)) { st.setCond(7); giveItems(player, TALISMAN_OF_SNAKE, 1); } break; case MARSH_STAKATO_WORKER: case MARSH_STAKATO_SOLDIER: case MARSH_STAKATO_DRONE: if (st.getCond() == 10 && dropItems(player, STAKATO_CHITIN, 1, 1, 100000) && player.getInventory().hasItems(MANASHEN_HORN, MITHRIL_CLIP, REINFORCED_BOWSTRING)) st.setCond(11); break; case MARSH_SPIDER: if (st.getCond() == 10 && dropItems(player, REINFORCED_BOWSTRING, 1, 1, 100000) && player.getInventory().hasItems(MANASHEN_HORN, MITHRIL_CLIP, STAKATO_CHITIN)) st.setCond(11); break; case ROAD_SCAVENGER: if (st.getCond() == 10 && dropItems(player, MITHRIL_CLIP, 1, 1, 100000) && player.getInventory().hasItems(MANASHEN_HORN, REINFORCED_BOWSTRING, STAKATO_CHITIN)) st.setCond(11); break; case MANASHEN_GARGOYLE: if (st.getCond() == 10 && dropItems(player, MANASHEN_HORN, 1, 1, 100000) && player.getInventory().hasItems(REINFORCED_BOWSTRING, MITHRIL_CLIP, STAKATO_CHITIN)) st.setCond(11); break; case LETO_LIZARDMAN: case LETO_LIZARDMAN_ARCHER: case LETO_LIZARDMAN_SOLDIER: case LETO_LIZARDMAN_WARRIOR: case LETO_LIZARDMAN_SHAMAN: case LETO_LIZARDMAN_OVERLORD: if (st.getCond() == 13) { if (((player.getInventory().getItemCount(BLOOD_OF_LIZARDMAN) - 120) * 5) > Rnd.get(100)) { playSound(player, SOUND_BEFORE_BATTLE); takeItems(player, BLOOD_OF_LIZARDMAN, -1); addSpawn(SERPENT_DEMON_KADESH, player, false, 300000, true); } else dropItemsAlways(player, BLOOD_OF_LIZARDMAN, 1, 0); } break; case SERPENT_DEMON_KADESH: if (st.getCond() == 13) { if (player.getInventory().getItemIdFrom(Paperdoll.RHAND) == CRESCENT_MOON_BOW) { st.setCond(14); playSound(player, SOUND_MIDDLE); giveItems(player, TALISMAN_OF_KADESH, 1); } else addSpawn(SERPENT_DEMON_KADESH, player, false, 300000, true); } break; } } }  
×
×
  • Criar Novo...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.