Ir para conteúdo
  • Cadastre-se

Ubuntu & Debian ( Configuração Avançada de Segurança MySQL )


deproxmonrox

Posts recomendados

Esse tutorial foi escrito para o Linux Ubuntu, se o seu sistema é outro então adapte este tutorial conforme sua necessidade, sempre verificando o path dos arquivos mencionados e criando uma cópia de segurança além de anotar as permissões dos mesmos antes de começar as alterações.

Sempre gosto de posta coisa que vai ajudar a garantir a segurança do seu servidor de lineage 2 isso vai garantir mais tempo em servidores de lineage 2 hoje em dia.

 

Open-source-database-also-needs-powerful

Por padrão é possível logar-se localmente em um servidor MySQL como usuário anônimo sem a necessidade de autenticação, apesar do acesso ficar restrito as bases test e information_schema, uma mente criativa pode através de script coletar dados da máquina e armazenar estes dados dentro da base test para futura consulta sem chamar a atenção.

Os parâmetros mais utilizados para conexão com o servidor são
-u nome do usuário
-p requisição de senha
-h host / ip
-P porta de conexão (padrão 3306)
-D base de dados

Observação: Apesar de apontarem para o mesmo local, no servidor, localhost e 127.0.0.1 são vistos como coisas diferentes, então um usuário que tem acesso a localhost não necessariamente conseguirá logar em 127.0.0.1, ou seja, dentro da base mysql na tabela user localhost é uma coisa e 127.0.0.1 é outra, ja no arquivo my.conf usa-se apenas 127.0.0.1 quando se fala de acesso local.

Tornando o MySQL um pouco mais seguro

Para solucionar a questão do login temos três possíveis soluções.

  • Criar uma senha para o usuário anônimo
  • Remover o usuário anônimo (identificado como '' na tabela user)
  • Deletar a base test

Optei por criar uma senha forte para o usuário anônimo ao invés de deletá-lo ou de deletar a base test pois ambos podem ser úteis no futuro, assim você não precisa se dar o trabalho de criar uma nova conta ou tabela caso precise de algo corriqueiro e dificilmente alguém tentará crackear a senha de usuário com privilégios restritos apenas para salvar dados na base, mas se a senha for nula essa técnica pode ser válida.

Conecte-se como root no servidor através do ip 127.0.0.1 ou localhost
$ mysql -u root -p -h 127.0.0.1 -D mysql Altere a senha do usuário anônimo que é identificado como ''@'localhost' substituindo o respectivo texto pela nova senha.
mysql>SET PASSWORD FOR ''@'localhost' = password('nova senha');
Query OK, 0 rows affected (0.00 sec) Para testar basta sair do servidor e se conectar como anônimo informando a nova senha, lembre-se de utilizar o parâmetro -p
mysql>exit
Bye

$ mysql -p -h 127.0.0.1
Password: Para evitar logins remotos (ip's externos), procure a seguinte linha no arquivo /etc/mysql/my.conf (este é o path relativo para distro ubuntu, caso não encontre o arquivo procure-o através do comando locate ou find)
skip-networking Ao encontrá-la, descomente-a retirando o # da frente do comando, caso essa linha não exista, crie-a.

Certifique-se de que no mesmo arquivo a linha abaixo contém o IP local 127.0.0.1 ao invés de 0.0.0.0 assim apenas conexões locais serão aceitas
bind-address = 127.0.0.1 Pronto! Menos uma questão de segurança para se preocupar.
Se você pretende habilitar acesso remoto, siga as instruções abaixo, caso contrário "por hoje é só pessoal!"

Habilitando acesso remoto

Atenção: Aqui será feito exatamente o contrário de parte do que fizemos acima! Pois vamos liberar o acesso remoto ao invés de bloqueá-lo, porém de uma forma segura.

O primeiro passo é garantir a algum usuário permissão para conectar ao servidor e especificar quais serão seus privilégios, abaixo a lista dos possíveis privilégios:

ALL/ALL PRIVILEGES – Simboliza todos os privilégios abaixo;
ALTER – Permite alterar a estrutura de tabelas;
ALTER ROUTINE – Permite alterar e excluir stored procedures/functions;
CREATE – Permite criar base de dados e tabelas;
CREATE ROUTINE – Permite criar stored procedures/functions;
CREATE TEMPORARY TABLES – Permite a criação de tabelas temporárias em expressões SQL que utilizam esse recurso;
CREATE USER – Permite criar e gerenciar usuários;
CREATE VIEW – Permite criar visões;
DELETE – Permite excluir informações;
DROP – Permite excluir estruturas (bases e tabelas);
EVENT – Permite criar event schedulers;
EXECUTE – Permite executar stored procedures;
FILE – Permite ler e escrever arquivos no sistema;
GRANT – Permite cadastrar seus privilégios para outros usuários;
INDEX – Permite o gerenciamento de índices;
INSERT – Permite inserir informações em tabelas;
LOCK TABLES – Permite bloquear tabelas;
PROCESS – Permite visualizar e finalizar processos do MySQL;
RELOAD – Permite recarregar bases de dados;
REPLICATION CLIENT – Permite solicitar replicação;
REPLICATION SLAVE – Permite replicar suas informações;
SELECT – Permite consultas;
SHOW DATABASES – Permite visualizar todas as estruturas das bases existentes;
SHOW VIEW – Permite visualizar os códigos de criação de visões;
SHUTDOWN – Permite desligar o servidor MySQL;
SUPER – Permite configurar os dados do servidor MASTER (em caso de replicação);
TRIGGER – Permite criar e gerenciar triggers;
UPDATE – Permite alterar informações em tabelas;
USAGE – Permite utilizar comandos básicos.

Vamos criar uma usuária chamada amanda (sugiro a criação de um usuário específico para acesso remoto, uma das vantagens é a identificação nos arquivos de log) e ja definir seus privilégios, isso será feito através do comando GRANT, a sintaxe do mesmo é:

GRANT <privilégios> ON <base>.<tabela> TO '<usuario>'@'<dominio>' IDENTIFIED BY '<senha>'

Sendo que

*.* – Aplica-se a todas as bases!
<base>.* – Aplica-se a todas as tabelas da base determinada
<base>.<tabela> – Aplica-se a uma determinada tabela

Criando a usuária amanda e atribuindo seus privilégios:
$ mysql -u root -p -D mysql
mysql> GRANT SELECT,INSERT,DELETE,UPDATE ON test.* TO 'amanda'@'%'
IDENTIFIED BY 'senha da amanda'; Nota: O uso de ' %' define que a usuária poderá se logar tanto localmente quanto remotamente.

Observação: O Comando GRANT cria um novo usuário e atribui privilégios a cada vez que é utilizado, se você estiver realizando alguns testes nesta parte, recomendo que ao terminar de um select na tabela user para verificar se não foi criada mais de uma entrada para o mesmo usuário com hosts diferentes, para revogar privilégios utilize o comando REVOKE

Para habilitar conexões remotas ao seu servidor MySQL vamos considerar o cenário do diagrama abaixo, o IP 200.220.4.113 é apenas para fim ilustrativo, substitua-o por seu IP externo! para descobrir seu IP externo visite o site ifconfig.me ou o Ip Chicken.

networksetup.gif

Vamos começar com o mínimo de alterações e caso isso não seja o suficiente partiremos para outra etapa, assim restringimos as mudanças ao que for realmente necessário.

Primeiro o arquivo my.conf (o oposto do que fizemos no início deste tutorial) vamos comentar a linha skip-networking (caso essa linha não exista não é necessário cria-la) e alterar o bind-adress para 0.0.0.0, ao comentar a linha skip-networking estamos habilitando as conexões via tcp/ip, ja o bind-adress como 0.0.0.0 permite conexões de qualquer faixa de ip.
#skip-networking
bind-address = 0.0.0.0 Se ao tentar um login remoto ocorrer o erro:
$ mysql -u amanda -p -h 200.220.4.113 -P 3306
ERROR 1042 (HY000): Can't get hostname for your address Procure a linha abaixo no arquivo my.conf, caso exista certifique-se de que ela não está comentada com #, caso não exista, crie-a.
skip-name-resolve Se depois disso você receber time-out
$ mysql -u amanda -p -h 200.220.4.113 -P 3306
Enter password:
ERROR 2003 (HY000): Can't connect to MySQL server on '200.220.4.113' (110) Talvez seu firewall esteja bloqueando a conexão, se for este o caso adicione a seguinte regra ao firewall:
$ sudo ufw allow 3306/tcp Para verificar se a regra foi adicionada corretamente
$ sudo ufw status

Status: active

To Action From
-- ------ ----
3306/tcp ALLOW Anywhere
3306/tcp ALLOW Anywhere (v6)
Se tudo estiver correto você conseguirá logar remotamente:
$ mysql -u yourusername -p -h 200.220.4.113 -P 3306 # Use seu IP externo!
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.

Copyright © 2000, 2013, Oracle and/or its affiliates.
All rights reserved.

Oracle is a registered trademark of Oracle Corporation
and/or its affiliates.
Other names may be trademarks of their respective owners.

Type 'help;' or '\h' for help. Type '\c' to clear
the current input statement.

mysql>


É isto!

Observação: Se ainda assim não conseguir conectar remotamente e você utilizar um roteador, será preciso redirecionar a porta do roteador para sua máquina, porém devido a imensa diversidade de modelos de roteadores não irei incluir isto neste tutorial, mas você encontrará informações sobre como fazer o "foward" de portas de diversos modelos no site Port Foward


Para remover a usuária amanda que foi criada apenas como teste:
$ mysql -u root -p -D mysql
mysql> DELETE FROM user WHERE user='amanda';
Para bloquear novamente o acesso no firewall mude a regra de allow para deny:
$ sudo ufw deny 3306/tcp

Interrompendo o inicio automático do servidor MySQL

Geralmente após instalado o servidor passa a ser iniciado como um serviço no boot do sistema, se você o utiliza apenas eventualmente quando está em produção e não como servidor permanente local, como medida de segurança adicional recomendo iniciar o servidor apenas quando você for trabalhar com o mesmo. O cancelamento do início automático pode ser feito de duas maneiras.

A Primeira é criando um arquivo override com a instrução "manual", a vantagem deste metódo é que você não precisa alterar o arquivo de inicialização do MySQL, (caso queira voltar a inicializar o servidor automaticamente no boot basta remover o arquivo mysql.override.)

Criando o arquivo mysql.override
$ sudo touch /etc/init/mysql.override
$ echo "manual" | sudo tee /etc/init/mysql.override
A outra opção é como root comentar a seguinte linha no arquivo /etc/init/myql.init
#start on runlevel [2345] A partir dai para iniciar manualmente o servidor:
$ sudo initctl start mysql Para interromper o servidor
$ sudo initctl stop mysql Como alternativa também é possível iniciar ou parar o servidor através do comando service mysql <start / stop>

0016.gifNa minha opinião, a Microsoft é muito melhor em fazer dinheiro do que Sistemas Operacionais.0016.gif


Você tem que encontrar o que você gosta. E isso é verdade tanto para o seu trabalho quanto para seus companheiros. Seu trabalho vai ocupar uma grande parte da sua vida, e a única maneira de estar verdadeiramente satisfeito é fazendo aquilo que você acredita ser um ótimo trabalho. E a única maneira de fazer um ótimo trabalho é fazendo o que você ama fazer. Se você ainda não encontrou, continue procurando. Não se contente. Assim como com as coisas do coração, você saberá quando encontrar. E, como qualquer ótimo relacionamento, fica melhor e melhor com o passar dos anos. Então continue procurando e você vai encontrar. Não se contente.

Link para o comentário
Compartilhar em outros sites


  • 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.