Noticias:

Debes de estar registrado para poder ver el contenido indicado. Registrate o Conectate

Menú Principal

[Guía] Crear una Custom Quest

Iniciado por Swarlog, Ago 05, 2022, 12:45 AM

Tema anterior - Siguiente tema

Swarlog

Esta Quest es una demostración que sirve como iniciación a la programación en el server.

Si aun no tenéis habilidad manejando el core, el datapack es un buen sustituto, ya que L2J desde hace tiempo, unió el datapack al core de manera que obtenemos la ayuda de las clases de la misma manera que si estuviéramos en el core, es decir, al escribir el nombre de la clase (o de su instancia) y poner un punto, "Ejemplo L2Player." Eclipse nos proporciona los métodos, como getLevel(), getClan(), getInventory()... etc

En esta ocasión, se trata de devolver a un PJ que alcanzó el Lv85 al Lv1, pero añadiendole una nueva skill.

El proceso comienza creando el archivo java con un nombre descriptivo de la clase, en mi caso se adivina de que trata el archivo sin mirar el código.

Este archivo debe heredar la clase Quest, que posee los métodos para que nuestra quest funcione. Es decir, nos da todo el trabajo hecho, solo nos limitamos a escribir que queremos que pase segun las circunstancias.

 Y cuales son esas circunstancias?

Estan descritas en el archivo "documentation.txt" o en la misma clase Quest. Cada método es descrito en detalle e incluso algunos de ellos aportan ejemplos, como OnAdvEvent().

Código (javascript) [Seleccionar]
### Eclipse Workspace Patch 1.0
#P L2J_DataPack
Index: dist/game/data/scripts/quests/Q1000_NuevaSkillPor85Levels/Q1000_NuevaSkillPor85Levels.java
===================================================================
--- dist/game/data/scripts/quests/Q1000_NuevaSkillPor85Levels/Q1000_NuevaSkillPor85Levels.java (revision 0)
+++ dist/game/data/scripts/quests/Q1000_NuevaSkillPor85Levels/Q1000_NuevaSkillPor85Levels.java (working copy)
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2004-2014 L2J DataPack
+ *
+ * This file is part of L2J DataPack.
+ *
+ * L2J DataPack is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J DataPack is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package quests.Q1000_NuevaSkillPor85Levels;
+
+import com.l2jserver.gameserver.datatables.SkillTable;
+import com.l2jserver.gameserver.model.actor.L2Npc;
+import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.model.quest.Quest;
+import com.l2jserver.gameserver.model.quest.QuestState;
+import com.l2jserver.gameserver.model.quest.State;
+import com.l2jserver.gameserver.model.skills.L2Skill;
+
+/**
+ * @author Kimeraweb
+ */
+public class Q1000_NuevaSkillPor85Levels extends Quest
+{
+
+ private final int _NPC_RENACENTISTA = 1000005, _MIN_LEVEL = 85;
+ L2Skill _skillAprendida;
+
+ /**
+ * @param questId
+ * @param name
+ * @param descr
+ */
+ public Q1000_NuevaSkillPor85Levels(int questId, String name, String descr)
+ {
+ super(questId, name, descr);
+
+ addStartNpc(_NPC_RENACENTISTA);
+ addTalkId(_NPC_RENACENTISTA);
+ // registerQuestItems();
+ }
+
+ /**
+ * This function is called whenever a player clicks on a link in a quest dialog
+ */
+ @Override
+ public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
+ {
+ final QuestState st = player.getQuestState(getName());
+ if (st == null)
+ {
+ return null;
+ }
+
+ String htmltext = null;
+ switch (event)
+ {
+ // Renacer a su riesgo
+ case "1000-02.htm":
+ {
+ if (player.getLevel() >= _MIN_LEVEL)
+ {
+ st.startQuest();
+ htmltext = "1000-03.html";
+ _skillAprendida = SkillTable.getInstance().getInfo(1, 1); // Triple Slash
+ player.setExp(1);
+ player.addSkill(_skillAprendida);
+ playSound(player, QuestSound.AMBSOUND_WINGFLAP);
+ st.exitQuest(false, true);
+ player.sendMessage("Has obtenido la skill " + _skillAprendida.getName());
+ }
+ break;
+ }
+
+ default:
+ {
+ System.out.println("El evento " + event + " no esta registrado en Q1000");
+ }
+ }
+ return htmltext;
+ }
+
+ /**
+ * This function is called whenever a player clicks to the "Quest" link of an NPC that is registered for the quest.
+ */
+ @Override
+ public String onTalk(L2Npc npc, L2PcInstance player)
+ {
+ QuestState st = player.getQuestState(Q1000_NuevaSkillPor85Levels.class.getSimpleName());
+ st.setState(State.CREATED);
+
+ /*
+ * if (st == null) { return getNoQuestMsg(player); }
+ */
+
+ String htmltext = "Ni idea de que hablas!!"; // getNoQuestMsg(player);
+ switch (st.getState())
+ {
+ case State.CREATED:
+ {
+ htmltext = (player.getLevel() < _MIN_LEVEL) ? "1000-01.html" : "1000-02.html";
+ break;
+ }
+
+ case State.STARTED:
+ {
+ htmltext = "8)";
+ break;
+ }
+
+ case State.COMPLETED:
+ {
+ htmltext = getAlreadyCompletedMsg(player);
+ break;
+ }
+ }
+ return htmltext;
+ }
+
+ public static void main(String[] args)
+ {
+ new Q1000_NuevaSkillPor85Levels(1000, Q1000_NuevaSkillPor85Levels.class.getSimpleName(), "NuevaSkillPor85Levels");
+ }
+
+}
Si os habeis fijado, htmltext contiene el nombre del archivo html que queremos cargar de la quest. No es magia. La clase Quest comprueba que el mensaje a devolver por htmltext (mejor dicho, por el método donde se encuentra) incluye la coletilla ".htm" o ".html" y de ser así, en lugar de mostrar un texto, busca ese archivo para mostrarlo como texto.

El problema es que si queremos sustituir parte del texto del HTML que hemos cargado, por ejemplo si queremos incluir el level mínimo de la quest usando el comodín %level% en el html
Código (html5) [Seleccionar]
<p>No tienes el level %level% para hacer esta quest!</p> y desde nuestro archivo java pretendemos hacer una sustitución
Código (javascript) [Seleccionar]
htmltext = htmltext.replace("%level%", _levelMinimo); no funcionará. Tendremos que hacer este apaño editando la clase Quest, en su método showResult(). En el cual podemos ver que ya existe una sustitucion disponible, se trata de %playername%.

A continuación vienen los htmls, puros y simples.

Código (html5) [Seleccionar]
Index: dist/game/data/scripts/quests/Q1000_NuevaSkillPor85Levels/1000-02.html
===================================================================
--- dist/game/data/scripts/quests/Q1000_NuevaSkillPor85Levels/1000-02.html (revision 0)
+++ dist/game/data/scripts/quests/Q1000_NuevaSkillPor85Levels/1000-02.html (working copy)
@@ -0,0 +1,13 @@
+<html><head><title>Renacer</title></head>
+ <body>
+ Ah ya veo... A si que quieres volver a renacer conservando tus poderes?<br>
+ Imagino que sabras que esto no es reversible, asi que voy a explicarte lo que sucedera si aceptas.<br><br>
+ Volveras a nacer! Pero conservaras todas tus facultades, tu memoria, tus recuerdos, y a cambio de tu experiencia vivida, obtendras un nuevo poder, una nueva habilidad.<br><br>
+ <font color="LEVEL">Te preguntas, en que consiste esa habilidad?</font><br>
+ Pues... debes descubrirla... en cada individuo es distinta. Podrias ser mas veloz, o ser capaz de producir armas, tener mas vida... la magia de los dioses es aun oscura para los mas sabios.<br>
+ Realmente, estas hablando con la persona equivocada. Solo soy un aprendiz, no puedo decirte lo que un erudito podria aclararte. Pero me temo que eso es imposible. No se dejan ver hace muchas decadas.<br>
+ <br>
+ <br>
+ <a action="bypass -h Quest Q1000_NuevaSkillPor85Levels 1000-02.htm">Renacer a mi propio riesgo</a>
+ </body>
+</html>
\ No newline at end of file

Ojalá te hayas fijado en el bypass, 1000-02.htm y verás que esa página HTML no se encuentra en la carpeta. Sin embargo, si te fijas en el código Java, el método onAdvEvent() recoge esta información para procesarla. Ya habrás adivinado que 1000-02.htm es solo la infomación mandada por el enlace desde la página HTML, es decir, si hubiera puesto PEPE, hubiera llegado PEPE al método. Esto es muy interesante porque podrias sustituir esa cadena por la ID del PJ y realizar cambios importantes sin tener que programar en el core :)


Código (html5) [Seleccionar]
Index: dist/game/data/scripts/quests/Q1000_NuevaSkillPor85Levels/1000-03.html
===================================================================
--- dist/game/data/scripts/quests/Q1000_NuevaSkillPor85Levels/1000-03.html (revision 0)
+++ dist/game/data/scripts/quests/Q1000_NuevaSkillPor85Levels/1000-03.html (working copy)
@@ -0,0 +1 @@
+<html><head><title>Renacer</title></head><body>Bienvenido...</body></html>
\ No newline at end of file
Index: dist/game/data/scripts/quests/Q1000_NuevaSkillPor85Levels/1000-01.html
===================================================================
--- dist/game/data/scripts/quests/Q1000_NuevaSkillPor85Levels/1000-01.html (revision 0)
+++ dist/game/data/scripts/quests/Q1000_NuevaSkillPor85Levels/1000-01.html (working copy)
@@ -0,0 +1,10 @@
+<html>
+ <head><title>Renacer</title></head>
+ <body>
+ A si que quieres renacer con una nueva habilidad, eh?<br>
+ Veamos... sabes? Veo que tienes potencial, carisma, valor... pero careces de la experiencia necesaria.<br>
+ <br>
+ No me malinterpretes, pero este conjuro requiere de un individuo experimentado. Podrias regresar sin nada, entiendes?<br>
+ Vuelve a verme cuando hayas alcanzado el nivel <font color="LEVEL">85</font>.
+ </body>
+</html>
\ No newline at end of file

Una vez hecho esto, y sin olvidar de que vuestro NPC debe iniciar la Quest con el siguiente bypass:

Código (html5) [Seleccionar]
<button value="Quest" action="bypass -h npc_%objectId%_Quest" width=50 height=15 back="L2UI_ct1.button_df" fore="L2UI_ct1.button_df">
teneis que añadir el nombre de la quest y su ruta en script.cfg
Código (html5) [Seleccionar]
quests/Q1000_NuevaSkillPor85Levels/Q1000_NuevaSkillPor85Levels.java
Una advertencia. Si se os ocurriera hacer una carpeta para separar vuestras quests custom de las quests del server, teneis que saber las htmls creadas para vuestras quests serán buscadas en la ruta con el nombre de la quest, es decir, si pretendeis hacer:
quests/Mis Quests Customs/Q1000_NuevaSkillPor85Levels/1000-01.html
en realidad, los npcs buscaran las htmls en esta ruta:
quests/Q1000_NuevaSkillPor85Levels/1000-01.html

es decir, la carpeta con el nombre de la quest.

Espero que os haya servido para iluminaros de ideas y hacer vuestros servers mas interesantes, en lugar de copias retail editando los rates y pegando NPCs que ya existen en otros servers. Cread vuestra propia aventura!

By Kimeraweb