Jump to content
  • 0

How can I make a custom quest? (HF)


Question

Posted (edited)

Hello, Im trying to make a custom quest on l2jmobius HF, what I need is a quest that will send players to hunt monster which drop custom quest item, I took Yoke Of The Past quest as an example and tried to duplicate it, changed the name, also replaced the destinations in the .java file, added custom npc ID and custom item ID inside, but whenever I click on quest ziggurat-1.htm shows up three times and nothing happens:

https://ibb.co/LJ31JRM

 

This is the original code  :

/*
 * This file is part of the L2J Mobius project.
 * 
 * This program 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.
 * 
 * This program 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.Q00385_YokeOfThePast;

import java.util.HashMap;
import java.util.Map;

import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.quest.Quest;
import org.l2jmobius.gameserver.model.quest.QuestState;
import org.l2jmobius.gameserver.model.quest.State;

/**
 * Yoke of the Past (385)
 * @author Pandragon
 */
public class Q00385_YokeOfThePast extends Quest
{
	// NPCs
	// @formatter:off
	private static final int[] ZIGGURATS =
	{
		31095, 31096, 31097, 31098, 31099, 31100, 31101,
		31102, 31103, 31104, 31105, 31106, 31107, 31108,
		31109, 31110, 31114, 31115, 31116, 31117, 31118,
		31119, 31120, 31121, 31122, 31123, 31124, 31125
	};
	// @formatter:on
	// Item
	private static final int SCROLL_OF_ANCIENT_MAGIC = 5902;
	// Reward
	private static final int BLANK_SCROLL = 5965;
	// Monsters
	private static final Map<Integer, Double> MONSTER_CHANCES = new HashMap<>();
	static
	{
		MONSTER_CHANCES.put(21144, 0.306); // Catacomb Shadow
		MONSTER_CHANCES.put(21156, 0.994); // Purgatory Shadow
		MONSTER_CHANCES.put(21208, 0.146); // Hallowed Watchman
		MONSTER_CHANCES.put(21209, 0.166); // Hallowed Seer
		MONSTER_CHANCES.put(21210, 0.202); // Vault Guardian
		MONSTER_CHANCES.put(21211, 0.212); // Vault Seer
		MONSTER_CHANCES.put(21213, 0.274); // Hallowed Monk
		MONSTER_CHANCES.put(21214, 0.342); // Vault Sentinel
		MONSTER_CHANCES.put(21215, 0.360); // Vault Monk
		MONSTER_CHANCES.put(21217, 0.460); // Hallowed Priest
		MONSTER_CHANCES.put(21218, 0.558); // Vault Overlord
		MONSTER_CHANCES.put(21219, 0.578); // Vault Priest
		MONSTER_CHANCES.put(21221, 0.710); // Sepulcher Inquisitor
		MONSTER_CHANCES.put(21222, 0.842); // Sepulcher Archon
		MONSTER_CHANCES.put(21223, 0.862); // Sepulcher Inquisitor
		MONSTER_CHANCES.put(21224, 0.940); // Sepulcher Guardian
		MONSTER_CHANCES.put(21225, 0.970); // Sepulcher Sage
		MONSTER_CHANCES.put(21226, 0.202); // Sepulcher Guardian
		MONSTER_CHANCES.put(21227, 0.290); // Sepulcher Sage
		MONSTER_CHANCES.put(21228, 0.316); // Sepulcher Guard
		MONSTER_CHANCES.put(21229, 0.426); // Sepulcher Preacher
		MONSTER_CHANCES.put(21230, 0.646); // Sepulcher Guard
		MONSTER_CHANCES.put(21231, 0.654); // Sepulcher Preacher
		MONSTER_CHANCES.put(21236, 0.238); // Barrow Sentinel
		MONSTER_CHANCES.put(21237, 0.274); // Barrow Monk
		MONSTER_CHANCES.put(21238, 0.342); // Grave Sentinel
		MONSTER_CHANCES.put(21239, 0.360); // Grave Monk
		MONSTER_CHANCES.put(21240, 0.410); // Barrow Overlord
		MONSTER_CHANCES.put(21241, 0.460); // Barrow Priest
		MONSTER_CHANCES.put(21242, 0.558); // Grave Overlord
		MONSTER_CHANCES.put(21243, 0.578); // Grave Priest
		MONSTER_CHANCES.put(21244, 0.642); // Crypt Archon
		MONSTER_CHANCES.put(21245, 0.700); // Crypt Inquisitor
		MONSTER_CHANCES.put(21246, 0.842); // Tomb Archon
		MONSTER_CHANCES.put(21247, 0.862); // Tomb Inquisitor
		MONSTER_CHANCES.put(21248, 0.940); // Crypt Guardian
		MONSTER_CHANCES.put(21249, 0.970); // Crypt Sage
		MONSTER_CHANCES.put(21250, 0.798); // Tomb Guardian
		MONSTER_CHANCES.put(21251, 0.710); // Tomb Sage
		MONSTER_CHANCES.put(21252, 0.684); // Crypt Guard
		MONSTER_CHANCES.put(21253, 0.574); // Crypt Preacher
		MONSTER_CHANCES.put(21254, 0.354); // Tomb Guard
		MONSTER_CHANCES.put(21255, 0.250); // Tomb Preacher
	}
	// Misc
	private static final int MIN_LEVEL = 20;
	
	public Q00385_YokeOfThePast()
	{
		super(385);
		addStartNpc(ZIGGURATS);
		addTalkId(ZIGGURATS);
		addKillId(MONSTER_CHANCES.keySet());
		registerQuestItems(SCROLL_OF_ANCIENT_MAGIC);
	}
	
	@Override
	public String onAdvEvent(String event, Npc npc, Player player)
	{
		final QuestState qs = getQuestState(player, false);
		String htmltext = null;
		if (qs != null)
		{
			switch (event)
			{
				case "ziggurat-03.htm":
				case "ziggurat-04.htm":
				case "ziggurat-06.htm":
				case "ziggurat-07.htm":
				{
					htmltext = event;
					break;
				}
				case "ziggurat-05.htm":
				{
					if (qs.isCreated())
					{
						qs.startQuest();
						htmltext = event;
					}
					break;
				}
				case "ziggurat-10.html":
				{
					qs.exitQuest(true, true);
					htmltext = event;
					break;
				}
			}
		}
		return htmltext;
	}
	
	@Override
	public String onTalk(Npc npc, Player talker)
	{
		final QuestState qs = getQuestState(talker, true);
		String htmltext = getNoQuestMsg(talker);
		switch (qs.getState())
		{
			case State.CREATED:
			{
				htmltext = (talker.getLevel() >= MIN_LEVEL) ? "ziggurat-01.htm" : "ziggurat-02.htm";
				break;
			}
			case State.STARTED:
			{
				if (hasQuestItems(talker, SCROLL_OF_ANCIENT_MAGIC))
				{
					rewardItems(talker, BLANK_SCROLL, getQuestItemsCount(talker, SCROLL_OF_ANCIENT_MAGIC));
					takeItems(talker, SCROLL_OF_ANCIENT_MAGIC, -1);
					htmltext = "ziggurat-09.html";
				}
				else
				{
					htmltext = "ziggurat-08.html";
				}
				break;
			}
		}
		return htmltext;
	}
	
	@Override
	public String onKill(Npc npc, Player killer, boolean isSummon)
	{
		final QuestState qs = getRandomPartyMemberState(killer, -1, 3, npc);
		if (qs != null)
		{
			giveItemRandomly(qs.getPlayer(), npc, SCROLL_OF_ANCIENT_MAGIC, 1, 0, MONSTER_CHANCES.get(npc.getId()), true);
		}
		return super.onKill(npc, killer, isSummon);
	}
}

 

 

This is code changed by me, I swapped Q00385_YokeOfThePast to  Q10600_SkillScroll as this is what I named the duplicate quest folder, and also added this lines QuestMasterHandler.java:

import quests.Q10504_JewelOfAntharas.Q10504_JewelOfAntharas;
import quests.Q10505_JewelOfValakas.Q10505_JewelOfValakas;
import quests.Q10600_SkillScroll.Q10600_SkillScroll;
Q10504_JewelOfAntharas.class,
Q10505_JewelOfValakas.class,
Q10600_SkillScroll.class

 

/*
 * This file is part of the L2J Mobius project.
 * 
 * This program 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.
 * 
 * This program 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.Q10600_SkillScroll;

import java.util.HashMap;
import java.util.Map;

import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.quest.Quest;
import org.l2jmobius.gameserver.model.quest.QuestState;
import org.l2jmobius.gameserver.model.quest.State;

/**
 * Yoke of the Past (385)
 * @author Pandragon
 */
public class Q10600_SkillScroll extends Quest
{
	// NPCs
	// @formatter:off
	private static final int[] ZIGGURATS =
	{
		31729, 31730, 31731, 31732, 31733, 1002000
	};
	// @formatter:on
	// Item
	private static final int SCROLL_OF_ANCIENT_MAGIC = 5902;
	// Reward
    private static final int FIRST_CLASSSKILLSCROLL = 9142;
	// Monsters
	private static final Map<Integer, Double> MONSTER_CHANCES = new HashMap<>();
	static
	{
		MONSTER_CHANCES.put(21144, 0.306); // Catacomb Shadow
		MONSTER_CHANCES.put(21156, 0.994); // Purgatory Shadow
		MONSTER_CHANCES.put(21208, 0.146); // Hallowed Watchman
		MONSTER_CHANCES.put(21209, 0.166); // Hallowed Seer
		MONSTER_CHANCES.put(21210, 0.202); // Vault Guardian
		MONSTER_CHANCES.put(21211, 0.212); // Vault Seer
		MONSTER_CHANCES.put(21213, 0.274); // Hallowed Monk
		MONSTER_CHANCES.put(21214, 0.342); // Vault Sentinel
		MONSTER_CHANCES.put(21215, 0.360); // Vault Monk
		MONSTER_CHANCES.put(21217, 0.460); // Hallowed Priest
		MONSTER_CHANCES.put(21218, 0.558); // Vault Overlord
		MONSTER_CHANCES.put(21219, 0.578); // Vault Priest
		MONSTER_CHANCES.put(21221, 0.710); // Sepulcher Inquisitor
		MONSTER_CHANCES.put(21222, 0.842); // Sepulcher Archon
		MONSTER_CHANCES.put(21223, 0.862); // Sepulcher Inquisitor
		MONSTER_CHANCES.put(21224, 0.940); // Sepulcher Guardian
		MONSTER_CHANCES.put(21225, 0.970); // Sepulcher Sage
		MONSTER_CHANCES.put(21226, 0.202); // Sepulcher Guardian
		MONSTER_CHANCES.put(21227, 0.290); // Sepulcher Sage
		MONSTER_CHANCES.put(21228, 0.316); // Sepulcher Guard
		MONSTER_CHANCES.put(21229, 0.426); // Sepulcher Preacher
		MONSTER_CHANCES.put(21230, 0.646); // Sepulcher Guard
		MONSTER_CHANCES.put(21231, 0.654); // Sepulcher Preacher
		MONSTER_CHANCES.put(21236, 0.238); // Barrow Sentinel
		MONSTER_CHANCES.put(21237, 0.274); // Barrow Monk
		MONSTER_CHANCES.put(21238, 0.342); // Grave Sentinel
		MONSTER_CHANCES.put(21239, 0.360); // Grave Monk
		MONSTER_CHANCES.put(21240, 0.410); // Barrow Overlord
		MONSTER_CHANCES.put(21241, 0.460); // Barrow Priest
		MONSTER_CHANCES.put(21242, 0.558); // Grave Overlord
		MONSTER_CHANCES.put(21243, 0.578); // Grave Priest
		MONSTER_CHANCES.put(21244, 0.642); // Crypt Archon
		MONSTER_CHANCES.put(21245, 0.700); // Crypt Inquisitor
		MONSTER_CHANCES.put(21246, 0.842); // Tomb Archon
		MONSTER_CHANCES.put(21247, 0.862); // Tomb Inquisitor
		MONSTER_CHANCES.put(21248, 0.940); // Crypt Guardian
		MONSTER_CHANCES.put(21249, 0.970); // Crypt Sage
		MONSTER_CHANCES.put(21250, 0.798); // Tomb Guardian
		MONSTER_CHANCES.put(21251, 0.710); // Tomb Sage
		MONSTER_CHANCES.put(21252, 0.684); // Crypt Guard
		MONSTER_CHANCES.put(21253, 0.574); // Crypt Preacher
		MONSTER_CHANCES.put(21254, 0.354); // Tomb Guard
		MONSTER_CHANCES.put(21255, 0.250); // Tomb Preacher
	}
	// Misc
	private static final int MIN_LEVEL = 20;
	
	public Q10600_SkillScroll()
	{
		super(385);
		addStartNpc(ZIGGURATS);
		addTalkId(ZIGGURATS);
		addKillId(MONSTER_CHANCES.keySet());
		registerQuestItems(SCROLL_OF_ANCIENT_MAGIC);
	}
	
	@Override
	public String onAdvEvent(String event, Npc npc, Player player)
	{
		final QuestState qs = getQuestState(player, false);
		String htmltext = null;
		if (qs != null)
		{
			switch (event)
			{
				case "ziggurat-03.htm":
				case "ziggurat-04.htm":
				case "ziggurat-06.htm":
				case "ziggurat-07.htm":
				{
					htmltext = event;
					break;
				}
				case "ziggurat-05.htm":
				{
					if (qs.isCreated())
					{
						qs.startQuest();
						htmltext = event;
					}
					break;
				}
				case "ziggurat-10.html":
				{
					qs.exitQuest(true, true);
					htmltext = event;
					break;
				}
			}
		}
		return htmltext;
	}
	
	@Override
	public String onTalk(Npc npc, Player talker)
	{
		final QuestState qs = getQuestState(talker, true);
		String htmltext = getNoQuestMsg(talker);
		switch (qs.getState())
		{
			case State.CREATED:
			{
				htmltext = (talker.getLevel() >= MIN_LEVEL) ? "ziggurat-01.htm" : "ziggurat-02.htm";
				break;
			}
			case State.STARTED:
			{
				if (hasQuestItems(talker, SCROLL_OF_ANCIENT_MAGIC))
				{
					rewardItems(talker, FIRST_CLASSSKILLSCROLL, getQuestItemsCount(talker, SCROLL_OF_ANCIENT_MAGIC));
					takeItems(talker, SCROLL_OF_ANCIENT_MAGIC, -1);
					htmltext = "ziggurat-09.html";
				}
				else
				{
					htmltext = "ziggurat-08.html";
				}
				break;
			}
		}
		return htmltext;
	}
	
	@Override
	public String onKill(Npc npc, Player killer, boolean isSummon)
	{
		final QuestState qs = getRandomPartyMemberState(killer, -1, 3, npc);
		if (qs != null)
		{
			giveItemRandomly(qs.getPlayer(), npc, SCROLL_OF_ANCIENT_MAGIC, 1, 0, MONSTER_CHANCES.get(npc.getId()), true);
		}
		return super.onKill(npc, killer, isSummon);
	}
}

 

 

 

what is wrong?

Edited by 77upup

9 answers to this question

Recommended Posts

  • 0
Posted
10 minutes ago, BAN_L2JDev said:

cade o ID do NPC onde pega a quest pra falar no chat ele tem que estar com Bypass -h quest name

Both original npc and custom has this same bypass

<a action="bypass -h npc_%objectId%_Quest">Quest</a>

 

  • 0
Posted
14 minutes ago, 77upup said:

Tanto o npc original quanto o custom tem esse mesmo bypass

 

 

now look in the quest for the ID of the Npc that registers the mission, you have to link it together with the script, registering it with the monsters

  • 0
Posted (edited)
36 minutes ago, BAN_L2JDev said:

now look in the quest for the ID of the Npc that registers the mission, you have to link it together with the script, registering it with the monsters

Added objectID in java file, also changed in html, doesn't work. Every html file uses default %objectId%, I think it searches the objectid automatically so it has to be a different problem. And also java files use npc id's not their object id's I checked. It's different in different server packs.

<a action="bypass -h npc_%objectId%_Quest">Quest</a>

<a action="bypass -h npc_%268479192%_Quest">Quest</a>

<a action="bypass -h npc_268479192_Quest">Quest</a>

 

Edited by 77upup
  • 0
Posted (edited)

onTalk

 

the id of the Npc that will take the quest must be there in the list
it has to be registered together
addTalkId(ZIGGURATS);

in the scrpits.xml file you also have to register the quest

Edited by BAN_L2JDev
  • 0
Posted
10 minutes ago, BAN_L2JDev said:

onTalk

 

the id of the Npc that will take the quest must be there in the list
it has to be registered together
addTalkId(ZIGGURATS);

in the scrpits.xml file you also have to register the quest

I did include the id, the custom npc id is 1002000 also included some Adventure Guildsman Id's for testing, none works

	private static final int[] ZIGGURATS =
	{
		31729, 31730, 31731, 31732, 31733, 1002000
	};

 

scripts.xml

<?xml version="1.0" encoding="UTF-8"?> 
<list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../data/xsd/Scripts.xsd">
	<!-- Skip these filenames from script loading, because they are already loaded using a different way. -->
	<exclude file="package-info.java" />
	<exclude file="handlers" />
	
	<!--
	With this file you can exclude/include specific folders/files from within the scripts directory.
	
	In order to exclude a folder/file simply add the following line:
	<exclude file="{FOLDER/FILE NAME HERE}" />
	For example to exclude the quests directory, use:
	<exclude file="quests" />
	
	If you want to exclude all files within a directory except certain file(s), you can do it like so:
	<exclude file="{FOLDER NAME HERE}">
		<include file="{FOLDER/FILE NAME HERE}" />
		<include file="{FOLDER/FILE NAME HERE}" />
		...
	</exclude>
	For example to exclude ForgeOfTheGods folder except Valakas script, use:
	<exclude file="ForgeOfTheGods">
		<include file="Valakas.java" />
	</exclude>
	-->
</list>

 

  • 0
Posted
22 minutes ago, 77upup said:

I did include the id, the custom npc id is 1002000 also included some Adventure Guildsman Id's for testing, none works

	private static final int[] ZIGGURATS =
	{
		31729, 31730, 31731, 31732, 31733, 1002000
	};

 

scripts.xml

<?xml version="1.0" encoding="UTF-8"?> 
<list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../data/xsd/Scripts.xsd">
	<!-- Skip these filenames from script loading, because they are already loaded using a different way. -->
	<exclude file="package-info.java" />
	<exclude file="handlers" />
	
	<!--
	With this file you can exclude/include specific folders/files from within the scripts directory.
	
	In order to exclude a folder/file simply add the following line:
	<exclude file="{FOLDER/FILE NAME HERE}" />
	For example to exclude the quests directory, use:
	<exclude file="quests" />
	
	If you want to exclude all files within a directory except certain file(s), you can do it like so:
	<exclude file="{FOLDER NAME HERE}">
		<include file="{FOLDER/FILE NAME HERE}" />
		<include file="{FOLDER/FILE NAME HERE}" />
		...
	</exclude>
	For example to exclude ForgeOfTheGods folder except Valakas script, use:
	<exclude file="ForgeOfTheGods">
		<include file="Valakas.java" />
	</exclude>
	-->
</list>

 

tente com um ID menor se possivel 5 casa E.p 65535 

  • 0
Posted (edited)
6 hours ago, BAN_L2JDev said:

tente com um ID menor se possivel 5 casa E.p 65535 

Now it does work, turns out nothing needed editing, strange thing happened, even though I renamed the Q00385_YokeOfThePast  folder in quests, it remained as Q00385_YokeOfThePast  - Copy, some windows explorer bug, I just had to make a new folder then rename and put the files inside manually.

There is one more important thing, how can I customize the quest item, in this case Scroll of Ancient Magic should show 1stClassSkillScroll. 

I tried editing questname-e.dat from original :

1	385	1	a,Yoke of the Past\0	a,Scroll of Ancient Magic\0	a,The Gatekeeper Ziggurat wants to become a human again and asks you to slay the guardians of ancient magic and collect the scrolls of ancient magic. You'll receive a blank scroll as a reward. The blank scroll will be helpful when dealing with the Trader of Mammon. Journey into the necropolises and catacombs and find monsters whose name contain lookout, watcher, guard, monk, overlord, shaman, consul, inquisitor, guardian, Elder, court guard, and preacher. Exclude Nephilim, Lilim, Gigant and Lith.\\n\0	1	5902														1	0														0.00000000	0.00000000	0.00000000	20	75	0	a,	1	1	1	0	0.00000000	0.00000000	0.00000000	a,No Requirements\0	a,The Gatekeeper Ziggurat, who longs to become Human again, asks you to slay the guardians and collect the scrolls of ancient magic.\0	0																																																																						0						0	0	0	179	1	1	5902											1	1											1	0			
1	385	-1	a,Yoke of the Past \0	a,	a,	0															0															0.00000000	0.00000000	0.00000000	20	75	0	a,	1	1	1	0	0.00000000	0.00000000	0.00000000	a,No Requirements\0	a,The Gatekeeper Ziggurat, who longs to become Human again, asks you to slay the guardians and collect the scrolls of ancient magic.\0	0																																																																						0						0	0	0	179	1	1	5902											1	1											1	1			

 

To modified, the name, the quest item name, and Id 5902 to 9142, yet the window stays the same

1	10600	1	a,Skill Scroll\0	a,1stClassSkillScroll\0	a,The Gatekeeper Ziggurat wants to become a human again and asks you to slay the guardians of ancient magic and collect the scrolls of ancient magic. You'll receive a blank scroll as a reward. The blank scroll will be helpful when dealing with the Trader of Mammon. Journey into the necropolises and catacombs and find monsters whose name contain lookout, watcher, guard, monk, overlord, shaman, consul, inquisitor, guardian, Elder, court guard, and preacher. Exclude Nephilim, Lilim, Gigant and Lith.\\n\0	1	9142														1	0														0.00000000	0.00000000	0.00000000	20	75	0	a,	1	1	1	0	0.00000000	0.00000000	0.00000000	a,No Requirements\0	a,The Gatekeeper Ziggurat, who longs to become Human again, asks you to slay the guardians and collect the scrolls of ancient magic.\0	0																																																																						0						0	0	0	179	1	1	5902											1	1											1	0			
1	10600	-1	a,Skill Scroll\0	a,	a,	0															0															0.00000000	0.00000000	0.00000000	20	75	0	a,	1	1	1	0	0.00000000	0.00000000	0.00000000	a,No Requirements\0	a,The Gatekeeper Ziggurat, who longs to become Human again, asks you to slay the guardians and collect the scrolls of ancient magic.\0	0																																																																						0						0	0	0	179	1	1	9142											1	1											1	1			

 

itemquet.jpg

Update: Changed id inside the script,

now it works, admin can close the thread.

Edited by 77upup
Guest
This topic is now closed to further replies.
×
×
  • Create New...