ZURSULUS L2

Saga of the Storm Screamer

ID
90
Название
Saga of the Storm Screamer
start_npcs_json
[]
npc_ids_json
[]
constants_json
{}
Статус разбора
metadata_only; dynamic Java conditions/rewards retained in source; unresolved starts: []
Источник
game/data/scripts/quests/Q00090_SagaOfTheStormScreamer/Q00090_SagaOfTheStormScreamer.java

NPC квеста

Записей нет.

Условия уровней: выражения из Java

if (player.getLevel() < 76)
if (player.getLevel() < 76)
if (player.getLevel() >= 76)

Выдача предметов, адены и опыта: выражения из Java

giveItems(player, _items[10], 1);
addExpAndSp(player, 2299404, 0);
giveAdena(player, 5000000, true);
giveItems(player, 6622, 1);
giveItems(player, _items[1], 1);
giveItems(player, _items[4], 1);
giveItems(player, _items[7], 1);
giveItems(player, _items[9], 1);
giveItems(player, _items[9], 1);
giveItems(player, _items[8], 1);
giveItems(player, _items[5], 1);
giveItems(player, _items[6], 1);
giveItems(player, _items[8], 1);
addExpAndSp(player, 2299404, 0);
giveAdena(player, 5000000, true);
giveItems(player, 6622, 1); // XXX rewardItems?
giveItems(player, _items[3], getRandom(1, 4));

Квесты содержат динамические условия Java. Выражения выдачи включают промежуточные предметы, варианты и случайные награды; это не гарантированная награда. Константы приведены выше. Полные условия — в исходнике.

Тексты квеста

[0-01.htm] Grand Magister Fairen: So you want to become a Storm Screamer, eh? Well, I suppose you're ready. I'd hoped that you would at least preserve your appearance! When you become a Storm Screamer, you'll actually break free of this mortal coil and enter the realm of the gods! You must absorb their very power into your body! Long ago, the foolish gods sealed the power in an attempt to keep Humans from reaching their full potential. "How do I absorb the power?" [0-010.htm] Grand Magister Fairen: You're not ready to transfer classes yet. Improve your abilities and come back. I'll transfer you when you're qualified! (Only characters of level 76 or above may transfer to the Storm Screamer class. Don't abandon the quest until your class transfer is complete.) [0-02.htm] Grand Magister Fairen: So, you want to be a Storm Screamer? You're not ready to take that path yet. Train and try again later. (Only characters of level 76 or above and of the Spellhowler class may undertake this quest.) [0-03.htm] Grand Magister Fairen: Well, I suppose you have your mind made up, eh? Well, I won't try to stop you. But I'll give you one last piece of advice: the Tablet of Vision cannot be read with your eyes alone. You must use a Stone of Commune to truly comprehend its message. This is known as communing with the tablet. At one time, the Stone of Commune was very rare, but lately, it's been turning up everywhere! I think that dark forces are behind this! Now, go and speak with Magister Kamilen in Goddard Castle Town. He'll tell you what to do next. Good luck! Pick up a copy of the guild bulletin on your way out! [0-04.htm] Grand Magister Fairen: To become a Storm Screamer, you must absorb information from the six Tablets of Vision scattered throughout the world. You must undergo a process of obtaining the power stored in the six stone tablets. First, speak with Magister Kamilen in Goddard Castle Town. He'll tell you what to do next. [0-05.htm] Grand Magister Fairen: The gods divided the power between the stones, and then buried and sealed them throughout the world. The stones are known as the Tablets of Vision. Absorb the knowledge from all six Tablets of Vision, and you'll become much stronger than you currently are. After you've done this, return to me and I'll make you a Storm Screamer! I must warn you... You've not chosen an easy path! Are you sure you want to become a Storm Screamer? "I want to become a Storm Screamer!" [0-06.htm] Grand Magister Fairen: The news of your success has preceded you! Congratulations! . What? You want the truth? Very well. What did Medina tell you? I suppose there's no harm... I've seen too many of my treasured disciples, whom I raised with great care and devotion, fall in battle. I couldn't bear to have you, my most treasured disciple, step into the maelstrom! The more powerful you become, the more dangerous battles you'll be drawn into! That's why I tried to block your class transfer! I sent Allector to stop you... but he failed! Finally, just as you'd reached the last stone tablet, I tried to stop you myself! But that busybody Medina got in the way, and it became impossible to carry out my plan. I should've taken you both out then! "So why did you give up?" [0-07.htm] Grand Magister Fairen: I realized, after suffering your awesome attack, that you'd actually become more powerful than any disciple I'd ever taught! I knew at that moment I didn't have to worry about you anymore, so I backed off! I realize I can't keep you in the nest forever. At some point I must let you go. Please forgive me! I was wrong. Your diligence is inspiring. Congratulations! You're now a Storm Screamer! [0-08.htm] Grand Magister Fairen: I realized, after suffering your awesome attack, that you'd actually become more powerful than any disciple I'd ever taught! I knew at that moment I didn't have to worry about you anymore, so I backed off! I realize I can't keep you in the nest forever. At some point I must let you go. Please forgive me! I was wrong. Your diligence is inspiring, but you're not ready to transfer to the Storm Screamer class yet. Come back when you've improved your skills! (Only characters of level 76 or above may transfer to the Storm Screamer class. Don't abandon the quest until your class transfer is complete.) [0-09.htm] Grand Magister Fairen: Thank you for your hard work. Congratulations! You're a Storm Screamer! [1-01.htm] Information Broker Mist: I know that M.B. is pretending to be Magister Kamilen of Goddard Castle Town. I have the report she requested. This investigation was difficult, so I can't give it for free! "What do you want?" [1-02.htm] Information Broker Mist: Bring me some Ice Crystals and I'll give you the report I prepared for the Truth Scholar. If you help Chef Jeremy prepare for the cooking contest, he'll probably give you some. [1-03.htm] Information Broker Mist: You've brought the ice crystal! "Here it is." [1-04.htm] Information Broker Mist: Take the report to M.B., who is pretending to be Magister Kamilen in Goddard Castle Town! [1-05.htm] Information Broker Mist: I've heard that you can find Ice Crystals in this hot springs area. I've been suffering from chronic back pain lately, and I'd like to try to make an ice pack with them. Help Chef Jeremy prepare for the upcoming cooking competition and he'll give you some. [1-06.htm] Information Broker Mist: Ah! So nice and cool. Now my back ache is gone! Give this report to M.B.. [10-01.htm] Tablet of Vision: You sense the presence of the Stone of Commune. Examine the area. [10-02.htm] Tablet of Vision: You see a vision of two men. The one being chased has the Stone of Commune. [10-03.htm] Tablet of Vision: Listen to Medina. [10-04.htm] Tablet of Vision: There is too much noise to find the Stone of Commune. Come back when it's quieter. [10-05.htm] Tablet of Vision: The tablet is covered with indecipherable hieroglyphs. Commune with the Tablet of Vision. [10-06.htm] Tablet of Vision: Thoughts beyond understanding race through your mind. You hear the sound of distant laughter. A man announces the birth of another Hero. The woman in blue disagrees... This is the last time she'll see the child! Communion with the six Tablets of Vision is complete. Return to Magister Fairen. [10-07.htm] Tablet of Vision: Further communion with this tablet would be futile. Communion with the six Tablets of Vision is complete. Now return to Grand Magister Fairen. [11-01.htm] Magister Kamilen: Now I must continue my investigation about who is trying to stop you from becoming a Storm Screamer. I'll need this stone myself, but I can tell you how to get your own. "How can I get one?" [11-02.htm] Magister Kamilen: You can get the next stone by killing the Archon of Halisha in the Four Sepulchers. You'll need help to gain entry. If that proves too difficult, go to the Shrine of the Loyal and slay Halisha's minions. If you collect 700 Halisha's Marks, the Archon will appear. The minions include Grave Scarabs, Scavenger Scarabs, Grave Ants, Scavenger Ants, Shrine Knights, and Shrine Guards. [11-03.htm] Magister Kamilen: You can get the next stone by killing the Archon of Halisha in the Four Sepulchers. You'll need help to gain entry. If that proves too difficult, go to the Shrine of the Loyal and slay Halisha's minions. If you collect 700 Halisha's Marks, the Archon will appear. The minions include Grave Scarabs, Scavenger Scarabs, Grave Ants, Scavenger Ants, Shrine Knights, and Shrine Guards. [2-01.htm] Magister Kamilen: Fairen didn't know that I'm conducting an investigation under the guise of Kamilen. In a letter I intercepted Fairen wanted Kamilen to discourage you from becoming a Storm Screamer! Don't worry, since I'm not bound to him I can still tell you what you need to do to become one. "What are you investigating?" [2-02.htm] Magister Kamilen: Visit Information Broker Mist at the hot springs resort and pick up the Investigative Report I requested. Tell him M.B. sent you. Bring the report and I'll tell you how to get the power of the six stone tablets. [2-03.htm] Magister Kamilen: Thanks for the report. This merits further investigation. To become a Storm Screamer, you'll need a Stone of Commune for each of the six stone tablets. Use the stones to commune with the tablets and your path will become clear. Here's the first Stone of Commune, take it to the Tablet of Vision. "How will my path become clear?" [2-04.htm] Magister Kamilen: Commune with the Tablet of Vision south of the Tower of Insolence using the Stone of Commune I gave you. The path will then become clear. [2-05.htm] Magister Kamilen: I'll tell you in due time. Meet with Information Broker Mist at the hot springs resort. Get the Investigative Report I asked for. Tell him M.B. sent you. Bring back the report and I'll tell you of the six stone tablets. [2-06.htm] Magister Kamilen: Stones of commune and Tablets of Vision have a magical mutual attraction. You can use this force to locate the Tablets of Vision. Put simply, when you have a Stone of Commune, the location of the corresponding Tablet of Vision will appear in your mind. After you commune with it, the location of the next Stone of Commune will be revealed to you. This process will become clear to you as you move along. Now, take the first Stone of Commune I gave you and find the Tablet of Vision south of the Tower of Insolence! [3-01.htm] Magister Kamilen: You say you fought with Allector, the fallen angel? How could he have escaped the prison in the Ivory Tower? He must have had help. But who? It could only be .... I shouldn't say, I need more proof. I have the Stone of Commune, but it's unstable. You'll need the other fragment. "How can I get it?" [3-02.htm] Magister Kamilen: Then visit the Ketra Orcs to get the missing fragment, the Divine Stone of Wisdom. If you earn the trust of Asefa, guide of dead souls, through Ketra's Messenger Wahkan and prove to her your wisdom, you'll find it. If you change your mind halfway, you can get it from the best Shaman of Varka Silenos, Soul Guide Udan Mardui through Varka's Messenger Naran Ashanuk., just bring it to me. [3-03.htm] Magister Kamilen: Then visit the Varka Silenos to get the missing fragment, the Divine Stone of Wisdom. If you earn the Soul Guide Udan Mardui through Varka's Messenger Naran Ashanuk and prove to her your wisdom, you'll find it. If you change your mind halfway, you can get it from the best Shaman of Ketra Orcs, Soul Guide Asefa through through Ketra's Messenger Wahkan, just bring it to me. [3-04.htm] Magister Kamilen: Go to the Ketra Orcs or the Varka Silenos to get the missing fragment, the Divine Stone of Wisdom . They both know the mysterious knowledge of the stone, but not its exact use. They'll give it to the wisest of the tribe. So, it is presented as some kind of mark for ‘the wisest man of the tribe.' If you earn the trust of Asefa, guide of dead souls, through Ketra's Messenger Wahkan and prove to her your wisdom, you'll find it. Or, you can get the Divine Stone of Wisdom from Soul Guide Udan Mardui through Varka's Messenger Naran Ashanuk by gaining his trust and proving your wisdom. Either way is fine. [3-05.htm] Magister Kamilen: The Divine Stone of Wisdom! Good work. My hunch was right. The only person who could have freed Allector is indeed the Grand Magister of the Ivory Tower! Never let your guard down, there are powerful forces trying to stop you! Shall I combine the stones now? "By all means!" [3-06.htm] Magister Kamilen: Take the Stone of Commune I gave you and go to the next Tablet of Vision on the north side of the Varka Silenos barracks. [3-07.htm] Magister Kamilen: Go to the Ketra Orcs or the Varka Silenos to get the Divine Stone of Wisdom, a fragment of the Stone of Commune. They know of its powerful magic, but not its exact use. They'll reward the wisest of their tribe with it. You'll need to earn the trust of Asefa, chief shaman of the Ketra Orcs, or Udan Mardui, chief shaman of the Varka Silenos. Which side will you choose? The Ketra Orcs The Varka Silenos [3-08.htm] Magister Kamilen: Now it's a complete Stone of Commune. Find the Tablet of Vision on the north side of the Varka Silenos barracks. [4-01.htm] Medina Blackheart: He's getting away! Help me, he's the one trying to stop you! [4-010.htm] Medina Blackheart: Fairen got away, but I got the Stone of Commune! I'm not sure if she was trying to stop you or to guard the tablet. Either way, she changed her mind and didn't put up a fight when she could have easily dealt with both of us. I'll have to find out from her. At least you've succeeded! Farewell! I must find her. "Wait!" [4-011.htm] Medina Blackheart: Fairen got away, but I got the Stone of Commune! I'm not sure if she was trying to stop you or to guard the tablet. Either way, she changed her mind and didn't put up a fight when she could have easily dealt with both of us. I'll have to find out from her. At least you've succeeded! Farewell! I must find her. [4-02.htm] Medina Blackheart: He's getting away! [4-03.htm] Medina Blackheart: I missed him again! I'm going to track him down! [4-04.htm] Medina Blackheart: He's getting away! Help me, he's the one trying to stop you! [4-05.htm] Medina Blackheart: Don't let him get away! [4-06.htm] Medina Blackheart: Sorry for the confusion, but I'm really Medina Blackheart. I disguised myself as Magister Kamilen of Goddard Castle Town to investigate who was trying to stop the Storm Screamers. It was Grand Magister Fairen! You saw her in disguise at the stone tablet. Listen [4-07.htm] Medina Blackheart: Sorry for the confusion, but I'm really Medina Blackheart. I disguised myself as Magister Kamilen of Goddard Castle Town to investigate who was trying to stop the Storm Screamers. It was Grand Magister Fairen! You saw her in disguise at the stone tablet. "Yes?" [4-08.htm] Medina Blackheart: Go to the tablet with the stone I gave you! [4-09.htm] Medina Blackheart: I have to find Fairen to get to the bottom of this. Take the stone I gave you and commune with the Tablet of Vision! [5-01.htm] Tablet of Vision: The Tablet of Vision is engraved with many incomprehensible hieroglyphs. Commune with the Tablet of Vision. [5-02.htm] Tablet of Vision: Countless thoughts beyond comprehension sear painfully into your brain. A female voice seems to float on by as if she were quietly laughing at you... You sense the location of the next Stone of Commune... It is being held by the Guardians of Forbidden Knowledge beside the Tablet of Vision in the western Valley of the Saints [5-03.htm] Tablet of Vision: Further communion with this tablet is futile. You must go and find the next Stone of Commune! You sense that the next stone is being held by the Guardians of Forbidden Knowledge beside the Tablet of Vision in the western Valley of the Saints [6-01.htm] Tablet of Vision: You must have a certain Stone of Commune to access this Tablet of Vision. You get a feeling that one of Guardians of Forbidden Knowledge protecting this tablet has the Stone of Commune. [6-02.htm] Tablet of Vision: The Tablet of Vision is engraved with many incomprehensible hieroglyphs. Commune with the Tablet of Vision. [6-03.htm] Tablet of Vision: Countless thoughts beyond comprehension sear painfully into your brain. A female voice seems to float on by as if she were quietly laughing at you... You sense the location of the next Stone of Commune... It is being held by a suspicious person beside the Tablet of Vision in the northeastern outpost of the Ketra Orc. [6-04.htm] Tablet of Vision: Further communion with this tablet is futile. You must go and find the next Stone of Commune. It is being held by a suspicious person beside the Tablet of Vision in the northeastern outpost of the Ketra Orc. [7-01.htm] Tablet of Vision: I feel the Stone of Commune nearby. Examine the area. [7-02.htm] Tablet of Vision: Fallen Angel Allector? I should have known! What was I thinking? I sense that he has the Stone of Commune. [7-03.htm] Tablet of Vision: The time has come to get the first Stone of Commune. Destroy Allector and take his stone. [7-04.htm] Tablet of Vision: Someone nearby must have the Stone of Commune! It's too noisy now. Try again later when things quiet down a bit. [7-05.htm] Tablet of Vision: The Tablet of Vision is engraved with many incomprehensible hieroglyphs. Commune with the Tablet of Vision. [7-06.htm] Tablet of Vision: Countless thoughts beyond comprehension sear painfully into your brain. A vision appears of a woman in blue. The location of the next Stone of Commune suddenly becomes clear... Magister Kamilen of Goddard Castle Town has it. [7-07.htm] Tablet of Vision: Further communion with this tablet would be futile. You must find the next Stone of Commune! Magister Kamilen of Goddard Castle Town has it. [8-01.htm] Tablet of Vision: The tablet is covered with indecipherable hieroglyphs. Commune with the Tablet of Vision. [8-02.htm] Tablet of Vision: Countless thoughts beyond comprehension sear painfully into your brain. You hear a man's voice lingering in the air... Suddenly, the location of the next Stone of Commune is clear! Magister Kamilen of Goddard Castle Town has it. [8-03.htm] Table of Vision: Further communion with this tablet would be futile. Get the next Stone of Commune from Magister Kamilen of Goddard Castle Town. [9-01.htm] Tablet of Vision: The Tablet of Vision is useless without a Stone of Commune. Kill the Archon of Halisha and take it from him. [9-02.htm] Tablet of Vision: The tablet is covered with indecipherable hieroglyphs. Commune with the Tablet of Vision. [9-03.htm] The Tablet of Vision: Incomprehensible knowledge is seared painfully into your mind. A series of visions appear... Of a black knight! The location of the next Stone of Commune is flashed into my head! The next Stone of Commune... There is a suspicious figure near the next Tablet of Vision in the southeast of the Hunters' Town. It seems the figure has the Stone of Commune. [9-04.htm] Tablet of Vision: Communing with this tablet is completed. It's time to find the next Stone of Commune. Near the Tablet of Vision in the south-east of the Hunters' Town, there is a suspicious figure apparently having the Stone of Commune.
Исходник условий и наград (Java)
/*
 * 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.Q00090_SagaOfTheStormScreamer;

import quests.AbstractSagaQuest;

/**
 * @author Emperorc
 */
public class Q00090_SagaOfTheStormScreamer extends AbstractSagaQuest
{
	public Q00090_SagaOfTheStormScreamer()
	{
		super(90, "Saga of the Storm Screamer");
		_npc = new int[]
		{
			30175,
			31627,
			31287,
			31287,
			31598,
			31646,
			31649,
			31652,
			31654,
			31655,
			31659,
			31287
		};
		_items = new int[]
		{
			7080,
			7531,
			7081,
			7505,
			7288,
			7319,
			7350,
			7381,
			7412,
			7443,
			7084,
			0
		};
		_mob = new int[]
		{
			27252,
			27239,
			27256
		};
		_classId = new int[]
		{
			110
		};
		_prevClass = new int[]
		{
			0x28
		};
		_x = new int[]
		{
			161719,
			124376,
			124355
		};
		_y = new int[]
		{
			-92823,
			82127,
			82155
		};
		_z = new int[]
		{
			-1893,
			-2796,
			-2803
		};
		_text = new String[]
		{
			"PLAYERNAME! Pursued to here! However, I jumped out of the Banshouren boundaries! You look at the giant as the sign of power!",
			"... Oh ... good! So it was ... let's begin!",
			"I do not have the patience ..! I have been a giant force ...! Cough chatter ah ah ah!",
			"Paying homage to those who disrupt the orderly will be PLAYERNAME's death!",
			"Now, my soul freed from the shackles of the millennium, Halixia, to the back side I come ...",
			"Why do you interfere others' battles?",
			"This is a waste of time.. Say goodbye...!",
			"...That is the enemy",
			"...Goodness! PLAYERNAME you are still looking?",
			"PLAYERNAME ... Not just to whom the victory. Only personnel involved in the fighting are eligible to share in the victory.",
			"Your sword is not an ornament. Don't you think, PLAYERNAME?",
			"Goodness! I no longer sense a battle there now.",
			"let...",
			"Only engaged in the battle to bar their choice. Perhaps you should regret.",
			"The human nation was foolish to try and fight a giant's strength.",
			"Must...Retreat... Too...Strong.",
			"PLAYERNAME. Defeat...by...retaining...and...Mo...Hacker",
			"....! Fight...Defeat...It...Fight...Defeat...It..."
		};
		registerNPCs();
	}
}


// Shared quest dependency: AbstractSagaQuest.java
/*
 * Copyright (c) 2013 L2jMobius
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
 * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package quests;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.l2jmobius.gameserver.config.PlayerConfig;
import org.l2jmobius.gameserver.entity.World;
import org.l2jmobius.gameserver.entity.WorldObject;
import org.l2jmobius.gameserver.entity.actor.Creature;
import org.l2jmobius.gameserver.entity.actor.Npc;
import org.l2jmobius.gameserver.entity.actor.Player;
import org.l2jmobius.gameserver.entity.groups.Party;
import org.l2jmobius.gameserver.mechanics.script.Quest;
import org.l2jmobius.gameserver.mechanics.script.QuestState;
import org.l2jmobius.gameserver.mechanics.skill.Skill;
import org.l2jmobius.gameserver.network.enums.ChatType;
import org.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
import org.l2jmobius.gameserver.network.serverpackets.NpcSay;

public abstract class AbstractSagaQuest extends Quest
{
	protected int[] _npc = {};
	protected int[] _items = {};
	protected int[] _mob = {};
	protected int[] _classId = {};
	protected int[] _prevClass = {};
	protected int[] _x = {};
	protected int[] _y = {};
	protected int[] _z = {};
	protected String[] _text = {};
	private static final Map<Npc, Integer> SPAWN_LIST = new HashMap<>();
	// @formatter:off
	private static final int[][] QUEST_CLASSES =
	{
		{ 0x7f }, { 0x80, 0x81 }, { 0x82 }, { 0x05 }, { 0x14 }, { 0x15 },
		{ 0x02 }, { 0x03 }, { 0x2e }, { 0x30 }, { 0x33 }, { 0x34 }, { 0x08 },
		{ 0x17 }, { 0x24 }, { 0x09 }, { 0x18 }, { 0x25 }, { 0x10 }, { 0x11 },
		{ 0x1e }, { 0x0c }, { 0x1b }, { 0x28 }, { 0x0e }, { 0x1c }, { 0x29 },
		{ 0x0d }, { 0x06 }, { 0x22 }, { 0x21 }, { 0x2b }, { 0x37 }, { 0x39 }
	};
	// @formatter:on
	private static final int[] ARCHON_HALISHA_NORM =
	{
		18212,
		18214,
		18215,
		18216,
		18218
	};
	
	public AbstractSagaQuest(int questId, String description)
	{
		super(questId, description);
	}
	
	public void registerNPCs()
	{
		addStartNpc(_npc[0]);
		addAttackId(_mob[2]);
		addAttackId(_mob[1]);
		addSkillSeeId(_mob[1]);
		addFirstTalkId(_npc[4]);
		addTalkId(_npc);
		addKillId(_mob);
		final int[] questItemIds = _items.clone();
		questItemIds[0] = 0;
		questItemIds[2] = 0; // remove Ice Crystal and Divine Stone of Wisdom
		registerQuestItems(questItemIds);
		for (int archonMinion = 21646; archonMinion < 21652; archonMinion++)
		{
			addKillId(archonMinion);
		}
		
		addKillId(ARCHON_HALISHA_NORM);
		for (int guardianAngel = 27214; guardianAngel < 27217; guardianAngel++)
		{
			addKillId(guardianAngel);
		}
	}
	
	@Override
	public String onEvent(String event, Npc npc, Player player)
	{
		final QuestState st = getQuestState(player, false);
		if (st == null)
		{
			return null;
		}
		
		String htmltext = null;
		switch (event)
		{
			case "0-011.htm":
			case "0-012.htm":
			case "0-013.htm":
			case "0-014.htm":
			case "0-015.htm":
			{
				htmltext = event;
				break;
			}
			case "accept":
			{
				st.startQuest();
				giveItems(player, _items[10], 1);
				htmltext = "0-03.htm";
				break;
			}
			case "0-1":
			{
				if (player.getLevel() < 76)
				{
					htmltext = "0-02.htm";
					if (st.isCreated())
					{
						st.exitQuest(true);
					}
				}
				else
				{
					htmltext = "0-05.htm";
				}
				break;
			}
			case "0-2":
			{
				if (player.getLevel() < 76)
				{
					takeItems(player, _items[10], -1);
					st.setCond(20, true);
					htmltext = "0-08.htm";
				}
				else
				{
					takeItems(player, _items[10], -1);
					addExpAndSp(player, 2299404, 0);
					giveAdena(player, 5000000, true);
					giveItems(player, 6622, 1);
					final int playerClass = getPlayerClass(player);
					final int prevClass = getPrevClass(player);
					player.setPlayerClass(playerClass);
					if (!player.isSubClassActive() && (player.getBaseClass() == prevClass))
					{
						player.setBaseClass(playerClass);
					}
					
					player.broadcastUserInfo();
					cast(npc, player, 4339, 1);
					st.exitQuest(false);
					htmltext = "0-07.htm";
				}
				break;
			}
			case "1-3":
			{
				st.setCond(3);
				htmltext = "1-05.htm";
				break;
			}
			case "1-4":
			{
				st.setCond(4);
				takeItems(player, _items[0], 1);
				if (_items[11] != 0)
				{
					takeItems(player, _items[11], 1);
				}
				
				giveItems(player, _items[1], 1);
				htmltext = "1-06.htm";
				break;
			}
			case "2-1":
			{
				st.setCond(2);
				htmltext = "2-05.htm";
				break;
			}
			case "2-2":
			{
				st.setCond(5);
				takeItems(player, _items[1], 1);
				giveItems(player, _items[4], 1);
				htmltext = "2-06.htm";
				break;
			}
			case "3-5":
			{
				htmltext = "3-07.htm";
				break;
			}
			case "3-6":
			{
				st.setCond(11);
				htmltext = "3-02.htm";
				break;
			}
			case "3-7":
			{
				st.setCond(12);
				htmltext = "3-03.htm";
				break;
			}
			case "3-8":
			{
				st.setCond(13);
				takeItems(player, _items[2], 1);
				giveItems(player, _items[7], 1);
				htmltext = "3-08.htm";
				break;
			}
			case "4-1":
			{
				htmltext = "4-010.htm";
				break;
			}
			case "4-2":
			{
				giveItems(player, _items[9], 1);
				st.setCond(18, true);
				htmltext = "4-011.htm";
				break;
			}
			case "4-3":
			{
				giveItems(player, _items[9], 1);
				st.setCond(18, true);
				autoChat(npc, _text[13].replace("PLAYERNAME", player.getName()));
				st.set("Quest0", "0");
				cancelQuestTimer("Mob_2 has despawned", npc, player);
				deleteSpawn(npc);
				return null;
			}
			case "5-1":
			{
				st.setCond(6, true);
				takeItems(player, _items[4], 1);
				cast(npc, player, 4546, 1);
				htmltext = "5-02.htm";
				break;
			}
			case "6-1":
			{
				st.setCond(8, true);
				st.set("spawned", "0");
				takeItems(player, _items[5], 1);
				cast(npc, player, 4546, 1);
				htmltext = "6-03.htm";
				break;
			}
			case "7-1":
			{
				if (st.getInt("spawned") == 1)
				{
					htmltext = "7-03.htm";
				}
				else if (st.getInt("spawned") == 0)
				{
					final Npc mob1 = addSpawn(_mob[0], _x[0], _y[0], _z[0], -1);
					st.set("spawned", "1");
					startQuestTimer("Mob_1 Timer 1", 500, mob1, player);
					startQuestTimer("Mob_1 has despawned", 300000, mob1, player);
					addSpawn(st, mob1);
					htmltext = "7-02.htm";
				}
				else
				{
					htmltext = "7-04.htm";
				}
				break;
			}
			case "7-2":
			{
				st.setCond(10, true);
				takeItems(player, _items[6], 1);
				cast(npc, player, 4546, 1);
				htmltext = "7-06.htm";
				break;
			}
			case "8-1":
			{
				st.setCond(14, true);
				takeItems(player, _items[7], 1);
				cast(npc, player, 4546, 1);
				htmltext = "8-02.htm";
				break;
			}
			case "9-1":
			{
				st.setCond(17, true);
				st.set("Quest0", "0");
				st.set("Tab", "0");
				takeItems(player, _items[8], 1);
				cast(npc, player, 4546, 1);
				htmltext = "9-03.htm";
				break;
			}
			case "10-1":
			{
				if (st.getInt("Quest0") == 0)
				{
					final Npc mob3 = addSpawn(_mob[2], _x[1], _y[1], _z[1], -1);
					final Npc mob2 = addSpawn(_npc[4], _x[2], _y[2], _z[2], -1);
					addSpawn(st, mob3);
					addSpawn(st, mob2);
					st.set("Mob_2", String.valueOf(mob2.getObjectId()));
					st.set("Quest0", "1");
					st.set("Quest1", "45");
					startQuestTimer("Mob_3 Timer 1", 500, mob3, player, true);
					startQuestTimer("Mob_3 has despawned", 59000, mob3, player);
					startQuestTimer("Mob_2 Timer 1", 500, mob2, player);
					startQuestTimer("Mob_2 has despawned", 60000, mob2, player);
					htmltext = "10-02.htm";
				}
				else if (st.getInt("Quest1") == 45)
				{
					htmltext = "10-03.htm";
				}
				else
				{
					htmltext = "10-04.htm";
				}
				break;
			}
			case "10-2":
			{
				st.setCond(19, true);
				takeItems(player, _items[9], 1);
				cast(npc, player, 4546, 1);
				htmltext = "10-06.htm";
				break;
			}
			case "11-9":
			{
				st.setCond(15);
				htmltext = "11-03.htm";
				break;
			}
			case "Mob_1 Timer 1":
			{
				autoChat(npc, _text[0].replace("PLAYERNAME", player.getName()));
				return null;
			}
			case "Mob_1 has despawned":
			{
				autoChat(npc, _text[1].replace("PLAYERNAME", player.getName()));
				st.set("spawned", "0");
				deleteSpawn(npc);
				return null;
			}
			case "Archon Hellisha has despawned":
			{
				autoChat(npc, _text[6].replace("PLAYERNAME", player.getName()));
				st.set("spawned", "0");
				deleteSpawn(npc);
				return null;
			}
			case "Mob_3 Timer 1":
			{
				final Npc mob2 = findSpawn(player, World.findObject(st.getInt("Mob_2")).asNpc());
				if ((World.getFirstVisibleObject(npc, Npc.class, it -> it == mob2) != null))
				{
					npc.asAttackable().addDamageHate(mob2, 0, 99999);
					npc.getAI().setIntentionAttack(mob2);
					mob2.getAI().setIntentionAttack(npc);
					autoChat(npc, _text[14].replace("PLAYERNAME", player.getName()));
					cancelQuestTimer("Mob_3 Timer 1", npc, player);
				}
				
				return null;
			}
			case "Mob_3 has despawned":
			{
				autoChat(npc, _text[15].replace("PLAYERNAME", player.getName()));
				st.set("Quest0", "2");
				deleteSpawn(npc);
				return null;
			}
			case "Mob_2 Timer 1":
			{
				autoChat(npc, _text[7].replace("PLAYERNAME", player.getName()));
				startQuestTimer("Mob_2 Timer 2", 1500, npc, player);
				if (st.getInt("Quest1") == 45)
				{
					st.set("Quest1", "0");
				}
				
				return null;
			}
			case "Mob_2 Timer 2":
			{
				autoChat(npc, _text[8].replace("PLAYERNAME", player.getName()));
				startQuestTimer("Mob_2 Timer 3", 10000, npc, player);
				return null;
			}
			case "Mob_2 Timer 3":
			{
				if (st.getInt("Quest0") == 0)
				{
					startQuestTimer("Mob_2 Timer 3", 13000, npc, player);
					if (getRandomBoolean())
					{
						autoChat(npc, _text[9].replace("PLAYERNAME", player.getName()));
					}
					else
					{
						autoChat(npc, _text[10].replace("PLAYERNAME", player.getName()));
					}
				}
				
				return null;
			}
			case "Mob_2 has despawned":
			{
				st.set("Quest1", String.valueOf(st.getInt("Quest1") + 1));
				if ((st.getInt("Quest0") == 1) || (st.getInt("Quest0") == 2) || (st.getInt("Quest1") > 3))
				{
					st.set("Quest0", "0");
					
					// TODO: This "if" will never be true.
					if (st.getInt("Quest0") == 1)
					{
						autoChat(npc, _text[11].replace("PLAYERNAME", player.getName()));
					}
					else
					{
						autoChat(npc, _text[12].replace("PLAYERNAME", player.getName()));
					}
					
					deleteSpawn(npc);
				}
				else
				{
					startQuestTimer("Mob_2 has despawned", 1000, npc, player);
				}
				
				return null;
			}
		}
		
		return htmltext;
	}
	
	@Override
	public void onAttack(Npc npc, Player player, int damage, boolean isSummon)
	{
		final QuestState st2 = findRightState(npc);
		if (st2 != null)
		{
			final int cond = st2.getCond();
			final QuestState st = getQuestState(player, false);
			final int npcId = npc.getId();
			if ((npcId == _mob[2]) && (st == st2) && (cond == 17))
			{
				int quest0 = st.getInt("Quest0") + 1;
				if (quest0 == 1)
				{
					autoChat(npc, _text[16].replace("PLAYERNAME", player.getName()));
				}
				
				if (quest0 > 15)
				{
					quest0 = 1;
					autoChat(npc, _text[17].replace("PLAYERNAME", player.getName()));
					cancelQuestTimer("Mob_3 has despawned", npc, st2.getPlayer());
					st.set("Tab", "1");
					deleteSpawn(npc);
				}
				
				st.set("Quest0", Integer.toString(quest0));
			}
			else if ((npcId == _mob[1]) && (cond == 15) && ((st != st2) || player.isInParty()))
			{
				autoChat(npc, _text[5].replace("PLAYERNAME", player.getName()));
				cancelQuestTimer("Archon Hellisha has despawned", npc, st2.getPlayer());
				st2.set("spawned", "0");
				deleteSpawn(npc);
			}
		}
	}
	
	@Override
	public String onFirstTalk(Npc npc, Player player)
	{
		String htmltext = "";
		final QuestState st = getQuestState(player, false);
		final int npcId = npc.getId();
		if ((st != null) && (npcId == _npc[4]))
		{
			final int cond = st.getCond();
			if (cond == 17)
			{
				final QuestState st2 = findRightState(npc);
				if (st2 != null)
				{
					player.setLastQuestNpcObject(npc.getObjectId());
					final int tab = st.getInt("Tab");
					final int quest0 = st.getInt("Quest0");
					if (st == st2)
					{
						if (tab == 1)
						{
							if (quest0 == 0)
							{
								htmltext = "4-04.htm";
							}
							else if (quest0 == 1)
							{
								htmltext = "4-06.htm";
							}
						}
						else if (quest0 == 0)
						{
							htmltext = "4-01.htm";
						}
						else if (quest0 == 1)
						{
							htmltext = "4-03.htm";
						}
					}
					else if (tab == 1)
					{
						if (quest0 == 0)
						{
							htmltext = "4-05.htm";
						}
						else if (quest0 == 1)
						{
							htmltext = "4-07.htm";
						}
					}
					else if (quest0 == 0)
					{
						htmltext = "4-02.htm";
					}
				}
			}
			else if (cond == 18)
			{
				htmltext = "4-08.htm";
			}
		}
		
		if (htmltext.isEmpty())
		{
			npc.showChatWindow(player);
		}
		
		return htmltext;
	}
	
	@Override
	public void onKill(Npc npc, Player player, boolean isSummon)
	{
		final int npcId = npc.getId();
		QuestState st = getQuestState(player, false);
		for (int archonMinion = 21646; archonMinion < 21652; archonMinion++)
		{
			if (npcId == archonMinion)
			{
				final Party party = player.getParty();
				if (party != null)
				{
					final List<QuestState> partyQuestMembers = new ArrayList<>();
					for (Player player1 : party.getMembers())
					{
						final QuestState st1 = findQuest(player1);
						if ((st1 != null) && st1.isCond(15) && player1.isInsideRadius2D(player, PlayerConfig.ALT_PARTY_RANGE))
						{
							partyQuestMembers.add(st1);
						}
					}
					
					if (!partyQuestMembers.isEmpty())
					{
						final QuestState st2 = partyQuestMembers.get(getRandom(partyQuestMembers.size()));
						giveHalishaMark(st2);
					}
				}
				else
				{
					final QuestState st1 = findQuest(player);
					if ((st1 != null) && st1.isCond(15))
					{
						giveHalishaMark(st1);
					}
				}
				return;
			}
		}
		
		for (int element : ARCHON_HALISHA_NORM)
		{
			if (npcId == element)
			{
				final QuestState st1 = findQuest(player);
				if ((st1 != null) && st1.isCond(15))
				{
					// This is just a guess....not really sure what it actually says, if anything
					autoChat(npc, _text[4].replace("PLAYERNAME", st1.getPlayer().getName()));
					giveItems(player, _items[8], 1);
					takeItems(player, _items[3], -1);
					st1.setCond(16, true);
				}
				return;
			}
		}
		
		for (int guardianAngel = 27214; guardianAngel < 27217; guardianAngel++)
		{
			if (npcId == guardianAngel)
			{
				final QuestState st1 = findQuest(player);
				if ((st1 != null) && st1.isCond(6))
				{
					final int kills = st1.getInt("kills");
					if (kills < 9)
					{
						st1.set("kills", Integer.toString(kills + 1));
					}
					else
					{
						giveItems(player, _items[5], 1);
						st.setCond(7, true);
					}
				}
				return;
			}
		}
		
		if ((st != null) && (npcId != _mob[2]))
		{
			final QuestState st2 = findRightState(npc);
			if (st2 != null)
			{
				final int cond = st.getCond();
				if ((npcId == _mob[0]) && (cond == 8))
				{
					if (!player.isInParty() && (st == st2))
					{
						autoChat(npc, _text[12].replace("PLAYERNAME", player.getName()));
						giveItems(player, _items[6], 1);
						st.setCond(9, true);
					}
					
					cancelQuestTimer("Mob_1 has despawned", npc, st2.getPlayer());
					st2.set("spawned", "0");
					deleteSpawn(npc);
				}
				else if ((npcId == _mob[1]) && (cond == 15))
				{
					if (!player.isInParty())
					{
						if (st == st2)
						{
							autoChat(npc, _text[4].replace("PLAYERNAME", player.getName()));
							giveItems(player, _items[8], 1);
							takeItems(player, _items[3], -1);
							st.setCond(16, true);
						}
						else
						{
							autoChat(npc, _text[5].replace("PLAYERNAME", player.getName()));
						}
					}
					
					cancelQuestTimer("Archon Hellisha has despawned", npc, st2.getPlayer());
					st2.set("spawned", "0");
					deleteSpawn(npc);
				}
			}
		}
		else if (npcId == _mob[0])
		{
			st = findRightState(npc);
			if (st != null)
			{
				cancelQuestTimer("Mob_1 has despawned", npc, st.getPlayer());
				st.set("spawned", "0");
				deleteSpawn(npc);
			}
		}
		else if (npcId == _mob[1])
		{
			st = findRightState(npc);
			if (st != null)
			{
				cancelQuestTimer("Archon Hellisha has despawned", npc, st.getPlayer());
				st.set("spawned", "0");
				deleteSpawn(npc);
			}
		}
		else if (npcId == _mob[2])
		{
			st = findRightState(npc);
			if (st != null)
			{
				st.setCond(18, true);
				autoChat(npc, _text[13].replace("PLAYERNAME", player.getName()));
				st.set("Quest0", "0");
				cancelQuestTimer("Mob_2 has despawned", npc, player);
				deleteSpawn(npc);
			}
		}
	}
	
	@Override
	public void onSkillSee(Npc npc, Player player, Skill skill, List<WorldObject> targets, boolean isSummon)
	{
		if (SPAWN_LIST.containsKey(npc) && (SPAWN_LIST.get(npc) != player.getObjectId()))
		{
			final Player questPlayer = World.findObject(SPAWN_LIST.get(npc)).asPlayer();
			if (questPlayer == null)
			{
				return;
			}
			
			for (WorldObject obj : targets)
			{
				if ((obj == questPlayer) || (obj == npc))
				{
					final QuestState st2 = findRightState(npc);
					if (st2 == null)
					{
						return;
					}
					
					autoChat(npc, _text[5].replace("PLAYERNAME", player.getName()));
					cancelQuestTimer("Archon Hellisha has despawned", npc, st2.getPlayer());
					st2.set("spawned", "0");
					deleteSpawn(npc);
				}
			}
		}
	}
	
	@Override
	public String onTalk(Npc npc, Player player)
	{
		final QuestState st = getQuestState(player, true);
		String htmltext = getNoQuestMsg(player);
		final int npcId = npc.getId();
		if ((npcId == _npc[0]) && st.isCompleted())
		{
			htmltext = getAlreadyCompletedMsg(player);
		}
		else if (player.getPlayerClass().getId() == getPrevClass(player))
		{
			switch (st.getCond())
			{
				case 0:
				{
					if (npcId == _npc[0])
					{
						htmltext = "0-01.htm";
					}
					break;
				}
				case 1:
				{
					if (npcId == _npc[0])
					{
						htmltext = "0-04.htm";
					}
					else if (npcId == _npc[2])
					{
						htmltext = "2-01.htm";
					}
					break;
				}
				case 2:
				{
					if (npcId == _npc[2])
					{
						htmltext = "2-02.htm";
					}
					else if (npcId == _npc[1])
					{
						htmltext = "1-01.htm";
					}
					break;
				}
				case 3:
				{
					if ((npcId == _npc[1]) && hasQuestItems(player, _items[0]))
					{
						if ((_items[11] == 0) || hasQuestItems(player, _items[11]))
						{
							htmltext = "1-03.htm";
						}
						else
						{
							htmltext = "1-02.htm";
						}
					}
					break;
				}
				case 4:
				{
					if (npcId == _npc[1])
					{
						htmltext = "1-04.htm";
					}
					else if (npcId == _npc[2])
					{
						htmltext = "2-03.htm";
					}
					break;
				}
				case 5:
				{
					if (npcId == _npc[2])
					{
						htmltext = "2-04.htm";
					}
					else if (npcId == _npc[5])
					{
						htmltext = "5-01.htm";
					}
					break;
				}
				case 6:
				{
					if (npcId == _npc[5])
					{
						htmltext = "5-03.htm";
					}
					else if (npcId == _npc[6])
					{
						htmltext = "6-01.htm";
					}
					break;
				}
				case 7:
				{
					if (npcId == _npc[6])
					{
						htmltext = "6-02.htm";
					}
					break;
				}
				case 8:
				{
					if (npcId == _npc[6])
					{
						htmltext = "6-04.htm";
					}
					else if (npcId == _npc[7])
					{
						htmltext = "7-01.htm";
					}
					break;
				}
				case 9:
				{
					if (npcId == _npc[7])
					{
						htmltext = "7-05.htm";
					}
					break;
				}
				case 10:
				{
					if (npcId == _npc[7])
					{
						htmltext = "7-07.htm";
					}
					else if (npcId == _npc[3])
					{
						htmltext = "3-01.htm";
					}
					break;
				}
				case 11:
				case 12:
				{
					if (npcId == _npc[3])
					{
						if (hasQuestItems(player, _items[2]))
						{
							htmltext = "3-05.htm";
						}
						else
						{
							htmltext = "3-04.htm";
						}
					}
					break;
				}
				case 13:
				{
					if (npcId == _npc[3])
					{
						htmltext = "3-06.htm";
					}
					else if (npcId == _npc[8])
					{
						htmltext = "8-01.htm";
					}
					break;
				}
				case 14:
				{
					if (npcId == _npc[8])
					{
						htmltext = "8-03.htm";
					}
					else if (npcId == _npc[11])
					{
						htmltext = "11-01.htm";
					}
					break;
				}
				case 15:
				{
					if (npcId == _npc[11])
					{
						htmltext = "11-02.htm";
					}
					else if (npcId == _npc[9])
					{
						htmltext = "9-01.htm";
					}
					break;
				}
				case 16:
				{
					if (npcId == _npc[9])
					{
						htmltext = "9-02.htm";
					}
					break;
				}
				case 17:
				{
					if (npcId == _npc[9])
					{
						htmltext = "9-04.htm";
					}
					else if (npcId == _npc[10])
					{
						htmltext = "10-01.htm";
					}
					break;
				}
				case 18:
				{
					if (npcId == _npc[10])
					{
						htmltext = "10-05.htm";
					}
					break;
				}
				case 19:
				{
					if (npcId == _npc[10])
					{
						htmltext = "10-07.htm";
					}
					else if (npcId == _npc[0])
					{
						htmltext = "0-06.htm";
					}
					break;
				}
				case 20:
				{
					if (npcId == _npc[0])
					{
						if (player.getLevel() >= 76)
						{
							htmltext = "0-09.htm";
							
							st.exitQuest(false);
							addExpAndSp(player, 2299404, 0);
							giveAdena(player, 5000000, true);
							giveItems(player, 6622, 1); // XXX rewardItems?
							final int playerClass = getPlayerClass(player);
							final int prevClass = getPrevClass(player);
							player.setPlayerClass(playerClass);
							if (!player.isSubClassActive() && (player.getBaseClass() == prevClass))
							{
								player.setBaseClass(playerClass);
							}
							
							player.broadcastUserInfo();
							cast(npc, player, 4339, 1);
						}
						else
						{
							htmltext = "0-010.htm";
						}
					}
					break;
				}
			}
		}
		
		return htmltext;
	}
	
	private QuestState findQuest(Player player)
	{
		final QuestState st = getQuestState(player, false);
		if (st != null)
		{
			if (getId() == 68)
			{
				for (int q = 0; q < 2; q++)
				{
					if (player.getPlayerClass().getId() == QUEST_CLASSES[1][q])
					{
						return st;
					}
				}
			}
			else if (player.getPlayerClass().getId() == QUEST_CLASSES[getId() - 67][0])
			{
				return st;
			}
		}
		
		return null;
	}
	
	private void autoChat(Npc npc, String text)
	{
		npc.broadcastPacket(new NpcSay(npc.getObjectId(), ChatType.GENERAL, npc.getId(), text));
	}
	
	private void cast(Npc npc, Creature target, int skillId, int level)
	{
		target.broadcastSkillPacket(new MagicSkillUse(target, target, skillId, level, 6000, 1), target);
		target.broadcastSkillPacket(new MagicSkillUse(npc, npc, skillId, level, 6000, 1), npc);
	}
	
	private void addSpawn(QuestState st, Npc mob)
	{
		SPAWN_LIST.put(mob, st.getPlayer().getObjectId());
	}
	
	private static Npc findSpawn(Player player, Npc npc)
	{
		if (SPAWN_LIST.containsKey(npc) && (SPAWN_LIST.get(npc) == player.getObjectId()))
		{
			return npc;
		}
		
		return null;
	}
	
	private void deleteSpawn(Npc npc)
	{
		if (SPAWN_LIST.remove(npc) != null)
		{
			npc.deleteMe();
		}
	}
	
	private QuestState findRightState(Npc npc)
	{
		Player player = null;
		QuestState st = null;
		final Integer spawned = SPAWN_LIST.get(npc);
		if (spawned != null)
		{
			player = World.getPlayer(spawned);
			if (player != null)
			{
				st = player.getQuestState(getName());
			}
		}
		
		return st;
	}
	
	private int getPlayerClass(Player player)
	{
		if (player.getPlayerClass().getId() == 0x81)
		{
			return _classId[1];
		}
		
		return _classId[0];
	}
	
	private int getPrevClass(Player player)
	{
		if (player.getPlayerClass().getId() == 0x81)
		{
			if (_prevClass.length == 1)
			{
				return -1;
			}
			
			return _prevClass[1];
		}
		
		return _prevClass[0];
	}
	
	private void giveHalishaMark(QuestState st)
	{
		if (st.getInt("spawned") == 0)
		{
			final Player player = st.getPlayer();
			if (getQuestItemsCount(player, _items[3]) >= 700)
			{
				takeItems(player, _items[3], 20);
				final int xx = st.getPlayer().getX();
				final int yy = st.getPlayer().getY();
				final int zz = st.getPlayer().getZ();
				final Npc archon = addSpawn(_mob[1], xx, yy, zz, -1);
				addSpawn(st, archon);
				st.set("spawned", "1");
				startQuestTimer("Archon Hellisha has despawned", 600000, archon, player);
				autoChat(archon, _text[13].replace("PLAYERNAME", st.getPlayer().getName()));
				archon.asAttackable().addDamageHate(st.getPlayer(), 0, 99999);
				archon.getAI().setIntentionAttack(st.getPlayer());
			}
			else
			{
				giveItems(player, _items[3], getRandom(1, 4));
			}
		}
	}
}