Noticias:

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

Menú Principal

Recompensa por matar por tiempo

Iniciado por Swarlog, Ago 19, 2022, 12:40 AM

Tema anterior - Siguiente tema

Swarlog

Este ha sido un pedido que me ha parecido interesante para cualquier clase de server.
Es un salto mayor del que hubiera deseado para el publico que sigue estas Quests (uno o dos  ;)) pero insisto en abriros las ganas de aprender a programar  :hu2_2:

Esta quest incita al jugador a entrar cada dia a matar cierta clase de mobs. Por cada 100 mobs que mate, recibe una recompensa, y la recompesa aumenta por cada dia acumulado. Es un chollo, cualquier viciosillo acabará enganchado a esta quest  :ork1_1:

Este es el código:

Código (javascript) [Seleccionar]
/*
 * 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.Q1003_MataMata;

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;

/**
 * @author Kimeraweb <br>
 * @nota: Heredamos "Quest" con extends.<br>
 *        Esto significa que todo lo que hay en Quest.java es como si ya estuviera aqui escrito
 */
public class Q1003_MataMata extends Quest
{
// Es de buena costumbre anteceder de un guion los nombres de las variables de la clase.
// Se llaman de la clase porque se declaran fueran de los metodos y desde los metodos se pueden acceder a ellas.
// Si son constantes, se usa el nombre completo en mayusculas, ejemplo: float PI = 3.141689;
private final int _mobId = 18342, _npcId = 1000009; // El mob es el gremlin de Lv1
private int _conteo; // Lleva la cuenta de los mobs muertos

/**
* @param questId
* @param name
* @param descr
*/
public Q1003_MataMata(int questId, String name, String descr)
{
// "super" sirve para enviar a la superclase de la que se hereda (Quest) el valor de las variables
super(questId, name, descr);

// NPC que comienza la Quest.
// Este metodo está sobrecargado. Significa que hay otro metodo con el mismo nombre pero con parametros distintos.
// En este caso, se acepta un numero indefinido de parametros de tipo int, ejemplo addStartNpc(1000009,10100,10101,10200);
// Otro parametro que acepta es el objeto Collection que contenga objetos Integer: Collection<Integer> pjs = MiInstancia.getCollection();
// Mas info en http://kimeraweb.com.es/SCJP/tema42.php
addStartNpc(_npcId);

// Muestra el primer dialogo del NPC cuando son clicados. Es decir, sustituyen el dialogo por defecto si el PJ esta haciendo una Quest donde interviene este NPC
// addFirstTalkId() ;

// Añade el NPC a esta Quest para poder leer sus links con los eventos
// Esta sobrecargado. Tambien acepta un numero indefinido de parametros de tipo int y un objeto Collection que contenga objetos Integer.
addTalkId(_npcId);

// Añade este NPC un escuchador, para saber cuando este NPC ha muerto
// Esta sobrecargado. Acepta numero indeterminado de parametros de tipo int.
// Acepta un objeto Collection que contengan objetos Integer.
addKillId(_mobId);

// Añade este NPC un escuchador, para saber cuando esta siendo atacado
// Acepta numero de parametros indeterminados int, y un Collection de objetos Integer
// addAttackId(int npcId);

// Añade al NPC la ventana de aprender skilles
// Soporta un numero indeterminado de parametros de tipo int y una Coleccion que contenga objetos Integer.
// addAcquireSkillId(int npcId);

// Cuando este mob es spawneado, este NPC lo sabe
// Soporta un numero indeterminado de parametros de tipo int y una coleccion que contega objetos Integer
// addSpawnId(int npcId);

// El NPC ve a un objetivo cualquiera ejecutando una skill
// Soporta un numero indeterminado de parametros de tipo int y una Coleccion que contenga objetos Integer.
// addSkillSeeId(int npcId)

// Acciones que emprendera el NPC cuando se termine un casteo
// Soporta un numero indeterminado de parametros de tipo int y una Coleccion que contenga objetos Integer.
// addSpellFinishedId(int... npcIds)

// Al salir de una zona...
// Soporta un numero indeterminado de parametros de tipo int y una Coleccion que contenga objetos Integer.
// addTrapActionId(int npcId)

// Se ha visto castear una skill (sin importar quien lo haya hecho)
// Soporta un numero indeterminado de parametros de tipo int y una Coleccion que contenga objetos Integer.
// addFactionCallId(int npcId)

// Alguien entro en el rango agro del npc
// Soporta un numero indeterminado de parametros de tipo int y una Coleccion que contenga objetos Integer.
// addAggroRangeEnterId(int npcId)

// Este NPC, al ver un mob...
// Soporta un numero indeterminado de parametros de tipo int y una Coleccion que contenga objetos Integer.
// addSeeCreatureId(int npcId)

// Al entrar en la zona...
// Soporta un numero indeterminado de parametros de tipo int y una Coleccion que contenga objetos Integer.
// addEnterZoneId(int zoneId)

// Al salir de una zona
// Soporta un numero indeterminado de parametros de tipo int y una Coleccion que contenga objetos Integer.
// addExitZoneId(int zoneId)

// Este NPC recibe un evento de otro NPC
// Soporta un numero indeterminado de parametros de tipo int y una Coleccion que contenga objetos Integer.
// addEventReceivedId(int... npcIds)

// Cuando el NPC deja de moverse
// Soporta un numero indeterminado de parametros de tipo int y una Coleccion que contenga objetos Integer.
// addMoveFinishedId(int... npcIds)

// Cuando un NPC Walker llega al siguiente nodo
// Soporta un numero indeterminado de parametros de tipo int y una Coleccion que contenga objetos Integer.
// addNodeArrivedId(int... npcIds)

// Cuando un NPC Walker termina su ruta
// Soporta un numero indeterminado de parametros de tipo int y una Coleccion que contenga objetos Integer.
// addRouteFinishedId(int... npcIds)
}

/**
* A continuacion los metodos invocados al usar los add. Puedes encontrar la lista de ellos en la clase Quest a partir de la linea 1144
*/

/**
* This function is called whenever a player clicks to the "Quest" link of an NPC that is registered for the quest.
* @param npc this parameter contains a reference to the exact instance of the NPC that the player is talking with.
* @param talker this parameter contains a reference to the exact instance of the player who is talking to the NPC.
* @return the text returned by the event (may be {@code null}, a filename or just text)
*/
@SuppressWarnings("null")
@Override
public String onTalk(L2Npc npc, L2PcInstance player)
{
String htmltext = "<html><head><title>Personal Trainer</title></head><body>";
QuestState st = player.getQuestState(Q1003_MataMata.class.getSimpleName());
st.setState(State.CREATED);

if (st.getState() != State.STARTED)
{
// Inicializo las variables globales de la quest
st.saveGlobalQuestVar("Q1003_Pvez", String.valueOf(System.currentTimeMillis())); // Primera vez que participo
st.saveGlobalQuestVar("Q1003_Uvez", "0"); // Ultima vez que participo
st.saveGlobalQuestVar("Q1003_MobsMuertos", "0"); // Mobs muertos en total
}

// Si el PJ ya estaba jugando antes (State.STARTED), cargamos los avances hechos
if (st.getState() == State.STARTED)
{
_conteo = Integer.valueOf(st.getGlobalQuestVar("Q1003_MobsMuertos"));

}

htmltext = htmltext + "No dejes de hacerlo cada dia y la recompensa sera mayor!";
return htmltext + "</body></html>";
}

/**
* This function is called whenever a player kills a NPC that is registered for the quest.
* @param npc this parameter contains a reference to the exact instance of the NPC that got killed.
* @param killer this parameter contains a reference to the exact instance of the player who killed the NPC.
* @param isSummon this parameter if it's {@code false} it denotes that the attacker was indeed the player, else it specifies that the killer was the player's pet.
* @return the text returned by the event (may be {@code null}, a filename or just text)
*/
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
QuestState st = killer.getQuestState(Q1003_MataMata.class.getSimpleName());
playSound(killer, QuestSound.ITEMSOUND_QUEST_ITEMGET);
_conteo++;
// Grabo la hora en que mato el ultimo mob
st.saveGlobalQuestVar("Q1003_Uvez", String.valueOf(System.currentTimeMillis()));
// Grabo la cantidad de mobs que lleva muertos
st.saveGlobalQuestVar("Q1003_MobsMuertos", String.valueOf(_conteo));

if (st.getState() == State.CREATED)
{
st.setState(State.STARTED); // State.STARTED indicara que el PJ ya ha estado matando mobs
}

// Le damos una adena por cada 100 mobs que mate, como premio a su persistencia :p
// Dividimos los dias que lleva matando mobs y multiplicamos el premio por los dias consecutivos
if ((_conteo % 100) == 0)
{
// Antes de dar el premio bonificado, verificamos la ultima vez que entro
if ((System.currentTimeMillis() - Long.valueOf(st.getGlobalQuestVar("Q1003_Pvez"))) > 86400000)
{
htmltext = htmltext + "Ya ha pasado mas de un dia desde tu ultimo entrenamiento!<br>Has perdido tu bonificacion!<br><br>";
st.saveGlobalQuestVar("Q1003_Pvez", String.valueOf(System.currentTimeMillis()));
}

int bonus = (int) ((System.currentTimeMillis() - (Long.valueOf(st.getGlobalQuestVar("Q1003_Pvez")))) / 86400000);
if (bonus < 1)
{
bonus = 1;
}
killer.sendMessage("Juega cada dia para acumular bonos a los premios! Bonos acumulados: " + String.valueOf(bonus));
killer.addItem("Q1003_MataMata", 57, 1 * bonus, killer, true);

}
return null;
}

public static void main(String[] args)
{
new Q1003_MataMata(1003, Q1003_MataMata.class.getSimpleName(), "MataMata");
}
}

Para empezar el nombre de la quest... penoso, pero no se me ocurria nada  :D

En esta ocasión, he añadido como comentario todas las posibilidades que tiene el crear una Quest, se puede ver que practicamente se puede hacer de todo. Esto, como dije anteriormente, está bien descrito en Debes de estar registrado para poder ver el contenido indicado. Registrate o Conectate. Lo unico que hacemos es copiar el metodo y rescribir el código, para que se ejecuten las acciones que deseamos en lugar de las creadas en la superclase (asi es como se llama la clase de la que se hereda).

Esta vez, para que la quest siga activa y tenga memorizada los avances del jugador despues del restart del server, he usado GlobalQuestVar. Asi cuando entre el jugador, podrá seguir repartiendo leña sin tener que comenzar la quest desde cero.

Creo que el código está bastante bien comentado, pero si teneis mas preguntas, adelante  :delf2_2:

MataMata seguro que será del agrado de muchos  :elf2_7:

%hr1%

He editado el codigo un poco.
Antes, en el método onTalk, tenia puesta la verificación de que el PJ jugase cada dia para recibir su premio bonificado. Pero si el PJ no habla con el NPC, pues la bonificacion se mantiene, aunque no haya entrado en varios dias.

Por eso, he puesto este script:
Código (javascript) [Seleccionar]
// Antes de dar el premio bonificado, verificamos la ultima vez que entro
if ((System.currentTimeMillis() - Long.valueOf(st.getGlobalQuestVar("Q1003_Pvez"))) > 86400000)
{
htmltext = htmltext + "Ya ha pasado mas de un dia desde tu ultimo entrenamiento!<br>Has perdido tu bonificacion!<br><br>";
st.saveGlobalQuestVar("Q1003_Pvez", String.valueOf(System.currentTimeMillis()));
}
dentro del método onKill, asi se verifica el ultimo dia que entró a matar mobs antes de dar el premio bonificado cuando el PJ este matando mobs, en lugar de hacerlo al hablar con el NPC. Está obligado a matar mobs cada dia, pero no a hablar con el NPC cada dia.

By Kimeraweb