/*
 * 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 instances.FinalEmperialTomb;

import static com.l2jserver.gameserver.ai.CtrlIntention.*;
import static com.l2jserver.gameserver.datatables.SkillData.*;

import java.util.Arrays;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import javolution.util.FastList;

import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.NpcData;
import com.l2jserver.gameserver.datatables.SkillData;
import com.l2jserver.gameserver.enums.AISkillScope;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.instancemanager.InstanceManager;
import com.l2jserver.gameserver.instancemanager.ZoneManager;
import com.l2jserver.gameserver.model.L2CommandChannel;
import com.l2jserver.gameserver.model.L2NpcPosition;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.L2Party;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.L2World;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.PcCondOverride;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2GrandBossInstance;
import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.actor.knownlist.NpcKnownList;
import com.l2jserver.gameserver.model.entity.Instance;
import com.l2jserver.gameserver.model.instancezone.InstanceWorld;
import com.l2jserver.gameserver.model.interfaces.ILocational;
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
import com.l2jserver.gameserver.model.quest.Quest;
import com.l2jserver.gameserver.model.quest.QuestState;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.model.zone.L2ZoneType;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
import com.l2jserver.gameserver.network.serverpackets.Earthquake;
import com.l2jserver.gameserver.network.serverpackets.ExShowScreenMessage;
import com.l2jserver.gameserver.network.serverpackets.FlyToLocation;
import com.l2jserver.gameserver.network.serverpackets.FlyToLocation.FlyType;
import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
import com.l2jserver.gameserver.network.serverpackets.MagicSkillCanceld;
import com.l2jserver.gameserver.network.serverpackets.MagicSkillUse;
import com.l2jserver.gameserver.network.serverpackets.NpcSay;
import com.l2jserver.gameserver.network.serverpackets.SocialAction;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.gameserver.network.serverpackets.ValidateLocation;
import com.l2jserver.gameserver.util.Util;

/**
 * Frintezza AI
 * 
 * @author Darki699
 * @author SANDMAN L2J_JP
 * @author JOJO
 * @author rocknow
 * @author L2jOff team
 */
/**
 * Final Emperial Tomb instance zone. TODO:<br>
 * Test when Frintezza song use 5008 effect skill.<br>
 * Maybe test more deeply halishas AI.<br>
 * Use proper zone spawn system.<br>
 * @author Gigiikun
 */
public final class FinalEmperialTomb extends Quest
{
	private static final boolean DEBUG = false;
	private static final boolean ASSERT = false;
	private static final boolean DETECT_ACTION_LOCK = true;
	private static final boolean DROP_DEWDROP_OF_DESTRUCTION = false;
	private static final boolean DROP_SOUL_BREAKING_ARROW = false;
	
	private class FETWorld extends InstanceWorld
	{
		public Lock lock = new ReentrantLock();
		public FastList<L2Npc> npcList = new FastList<>();
		public int npcMax = 0;
		public int darkChoirPlayerCount = 0;
		public ScheduledFuture<?> songTask = null;
		public boolean isVideo = false;
		public L2Npc frintezzaDummy = null;
		public L2Npc portraitDummy1 = null;
		public L2Npc portraitDummy3 = null;
		public L2Npc scarletDummy = null;
		public L2GrandBossInstance frintezza = null;
		public L2GrandBossInstance activeScarlet = null;
		public L2MonsterInstance[] ghosts = new L2MonsterInstance[4];
		public L2MonsterInstance[] portraits = new L2MonsterInstance[4];
		public int scarlet_x = 0;
		public int scarlet_y = 0;
		public int scarlet_z = 0;
		public int scarlet_h = 0;
		public int scarlet_a = 0;
		protected long lastAction;
		
		public FETWorld()
		{
if (DETECT_ACTION_LOCK) {{
			class ActionLockListener implements Runnable
			{
				@Override
				public void run()
				{
					if ((getStatus() == 1) || (getStatus() == 2))
					{
						Instance instance = InstanceManager.getInstance().getInstance(getInstanceId());
						if (instance == null)
						{
							return;
						}
						if ((System.currentTimeMillis() - lastAction) > 300000)
						{
							if (getStatus() == 1)
							{
								if (instance.getDoor(17130051).getOpen())
								{
									addAggroToMobs(FETWorld.this, ROOM1_CENTER_X, ROOM1_CENTER_Y, ROOM1_CENTER_Z);
								}
							}
							else if (getStatus() == 2)
							{
								if (instance.getDoor(17130061).getOpen())
								{
									addAggroToMobs(FETWorld.this, ROOM2_CENTER_X, ROOM2_CENTER_Y, ROOM2_CENTER_Z);
								}
							}
							lastAction = System.currentTimeMillis();
						}
						ThreadPoolManager.getInstance().scheduleGeneral(ActionLockListener.this, 30000);
					}
				}
			}
			lastAction = System.currentTimeMillis();
			ThreadPoolManager.getInstance().scheduleGeneral(new ActionLockListener(), 60000);
}}
		}
	}
	
	private static class FrintezzaSong
	{
		public int songId, songLevel;
		public int effectId, effectLevel;
		public NpcStringId songName;
		public int chance;
		
		public FrintezzaSong(int songId, int songLevel, int effectId, int effectLevel, NpcStringId songName, int chance)
		{
			this.songId = songId;
			this.songLevel = songLevel;
			this.effectId = effectId;
			this.effectLevel = effectLevel;
			this.songName = songName;
			this.chance = chance;
		}
	}
	
	private static final int INSTANCEID = 136; // this is the client number
	private static final int MIN_PLAYERS = 36;
	private static final int MAX_PLAYERS = 45;
	
	// Initialization at 6:30 am on Wednesday and Saturday
	private static final int RESET_HOUR_OF_DAY = 6;
	private static final int RESET_MINUTE = 30;
	private static final int[] RESET_DAY_OF_WEEK =
	{
		Calendar.WEDNESDAY,
		Calendar.SATURDAY,
	};
	
	// Items
	private static final int FRINTEZZA_SCROLL = 8073; // Frintezza's Magic Force Field Removal Scroll | フリンテッサの結界解除スクロール
	private static final int SOUL_BREAKING_ARROW = 8192; // Soul Breaking Arrow | 破魂の矢
	private static final int DEWDROP_OF_DESTRUCTION = 8556; // Dewdrop of Destruction | 破魂の露
	
	@SuppressWarnings("unused")
	private static final int FIRST_SCARLET_WEAPON = 8204; // --> npc.sql
	private static final int SECOND_SCARLET_WEAPON = 7903;
	@SuppressWarnings("unused")
	private static final int THIRD_SCARLET_WEAPON = 8222; // --> npc.sql
	
	// NPCs
	private static final int GUIDE = 32011; // Imperial Tomb Guide | フリンテッサ テレポーター
	private static final int CUBE = 29061; // Teleportation Cubic | テレポート キューブ
	
	// mobs: ROOM 3
	private static final int FRINTEZZA = 29045;
	private static final int SCARLET1 = 29046; // Daemon #1,#2 Scarlet van Halisha | スカーレット ヴァン ハリシャ
	private static final int SCARLET2 = 29047; // Daemon #3 Scarlet van Halisha | スカーレット ヴァン ハリシャ
	private static final int PORTRAIT_FIGHTER = 29048; // Evil Spirit | エヴィレイト(ファイター)
	private static final int PORTRAIT_MAGE = 29049; // Evil Spirit | エヴィレイト(メイジ)
	private static final int GHOST_FIGHTER = 29050; // Breath of Halisha | ハリシャ ブレス(ファイター)
	private static final int GHOST_MAGE = 29051; // Breath of Halisha | ハリシャ ブレス(メイジ)
	private static final int CAMERA_DUMMY = 29052;
	private static final int DIMENSIONAL_SHOCK = 29053;
	// mobs: ROOM 1
	private static final int HALL_ALARM = 18328; // ホール アラーム
	private static final int HALL_KEEPER_CAPTAIN = 18329; // Hall Keeper Captain | ホールキーパー キャプテン
	private static final int HALL_KEEPER_WIZARD = 18330; // Hall Keeper Wizard | ホールキーパー ウィザード
	private static final int HALL_KEEPER_GUARD = 18331; // Hall Keeper Guard | ホールキーパー ガード
	@SuppressWarnings("unused")
	private static final int HALL_KEEPER_PATROL = 18332; // Hall Keeper Patrol | ホールキーパー パトロール
	private static final int HALL_KEEPER_SUICIDAL_SOLDIER_1 = 18333; // Hall Keeper Suicidal Soldier | ホールキーパー カミカゼ(攻撃力16かなり高め／スキル4614-9 NPC Death Bomb)
	// mobs: ROOM 2
	private static final int DARK_CHOIR_CAPTAIN = 18334; // Dark Choir Captain | 黒聖歌団長
	private static final int DARK_CHOIR_PRIMA_DONNA = 18335; // Dark Choir Prima Donna | 黒聖歌団 プリマ
	private static final int DARK_CHOIR_LANCER = 18336; // Dark Choir Lancer | 黒聖歌団 ランサー
	private static final int DARK_CHOIR_ARCHER = 18337; // Dark Choir Archer | 黒聖歌団 アーチャー
	private static final int DARK_CHOIR_WITCH_DOCTOR = 18338; // Dark Choir Witch Doctor | 黒聖歌団 ウィザード
	private static final int DARK_CHOIR_PLAYER = 18339; // Dark Choir Player | 黒聖歌団 プレイヤー
	@SuppressWarnings("unused")
	private static final int HALL_KEEPER_SUICIDAL_SOLDIER_2a = 18340; // Hall Keeper Suicidal Soldier | ホールキーパー カミカゼ(攻撃力11普通／スキル5042-9 NPC Dispel Bomb)
	@SuppressWarnings("unused")
	private static final int HALL_KEEPER_SUICIDAL_SOLDIER_2b = 18341; // Hall Keeper Suicidal Soldier | ホールキーパー カミカゼ(攻撃力16かなり高め／スキル5042-9 NPC Dispel Bomb)
	
	private static final int[] AI_DISABLED_MOBS =
	{
		HALL_ALARM
	};
	private static final int[] NO_AGGRO_MOBS =
	{
		DARK_CHOIR_CAPTAIN
	};
	private static final int[] MUST_KILL_MOBS =
	{
	/* spawnHallKeepers() */
	/* １部屋め ホールキーパー */
		//HALL_ALARM,
		HALL_KEEPER_CAPTAIN,
		HALL_KEEPER_GUARD,
		HALL_KEEPER_SUICIDAL_SOLDIER_1,
		HALL_KEEPER_WIZARD,
	/* spawnDarkChoirs() */
	/* ２部屋め 黒聖歌団 */
		//DARK_CHOIR_PLAYER,
		DARK_CHOIR_ARCHER,
		DARK_CHOIR_CAPTAIN,
		DARK_CHOIR_LANCER,
		DARK_CHOIR_PRIMA_DONNA,
		DARK_CHOIR_WITCH_DOCTOR,
	};
	{ Arrays.sort(MUST_KILL_MOBS); }
	
	// Skills
	private static final int FRINTEZZA_SONG = 5007, FRINTEZZA_EFFECT = 5008;
	protected static final FrintezzaSong[] FRINTEZZA_SONG_LIST =
	{
		new FrintezzaSong(FRINTEZZA_SONG, 1, FRINTEZZA_EFFECT, 1, NpcStringId.REQUIEM_OF_HATRED, 5), // 5% ヒール演奏。
		new FrintezzaSong(FRINTEZZA_SONG, 2, FRINTEZZA_EFFECT, 2, NpcStringId.RONDO_OF_SOLITUDE, 50), // 45% 演出：ダッシュ+肖像画再生演奏。
		new FrintezzaSong(FRINTEZZA_SONG, 3, FRINTEZZA_EFFECT, 3, NpcStringId.FRENETIC_TOCCATA, 70), // 20% 攻撃/速度演奏。
		new FrintezzaSong(FRINTEZZA_SONG, 4, FRINTEZZA_EFFECT, 4, NpcStringId.MOURNFUL_CHORALE_PRELUDE, 90), // 20% 悲嘆のコラール
		new FrintezzaSong(FRINTEZZA_SONG, 5, FRINTEZZA_EFFECT, 5, NpcStringId.HYPNOTIC_MAZURKA, 100), // 10% 魅惑のマズルカ
	};
	
	private static final int[] FIRST_SCARLET_SKILLS =
	{
		getSkillHashCode(5014, 1), // Frintezza's Daemon Attack - デーモン1 一般攻撃。
		getSkillHashCode(5015, 1), // Frintezza's Daemon Charge - デーモン1 突撃。
		getSkillHashCode(5015, 4), // Frintezza's Daemon Charge - デーモン1 遅い突撃。
	};
	private static final int[] SECOND_SCARLET_SKILLS =
	{
		getSkillHashCode(5014, 2), // Frintezza's Daemon Attack - デーモン2 一般攻撃。
		getSkillHashCode(5015, 2), // Frintezza's Daemon Charge - デーモン2 突撃。
		getSkillHashCode(5015, 5), // Frintezza's Daemon Charge - デーモン2 遅い突撃。
		getSkillHashCode(5018, 1), // Frintezza's Daemon Field - デーモン2 魔法陣。
	};
	private static final int[] THIRD_SCARLET_SKILLS =
	{
		getSkillHashCode(5014, 3), // Frintezza's Daemon Attack - デーモン3 一般攻撃。
		getSkillHashCode(5015, 3), // Frintezza's Daemon Charge - デーモン3 突撃。
		getSkillHashCode(5015, 6), // Frintezza's Daemon Charge - デーモン3 遅い突撃。
		getSkillHashCode(5016, 1), // スカーレットの束縛 - 瞬時に動けなくなった状態。(プカプカ)
		getSkillHashCode(5018, 2), // Frintezza's Daemon Field - デーモン3 魔法陣。
		getSkillHashCode(5019, 1), // Frintezza's Daemon Drain - デーモン3 範囲HP吸収。
	};
	
	protected void levelUpScarletSkills(L2Npc npc, int level)
	{
		if (level != 1) disableScarletSkills(npc, FIRST_SCARLET_SKILLS);
		if (level != 2) disableScarletSkills(npc, SECOND_SCARLET_SKILLS);
		if (level != 3) disableScarletSkills(npc, THIRD_SCARLET_SKILLS);
		if (level == 1) enableScarletSkills(npc, FIRST_SCARLET_SKILLS);
		if (level == 2) enableScarletSkills(npc, SECOND_SCARLET_SKILLS);
		if (level == 3) enableScarletSkills(npc, THIRD_SCARLET_SKILLS);
	}
	private void disableScarletSkills(L2Npc npc, int... skillHashCode)
	{
		for (int s : skillHashCode)
		{
			Skill skill = getSkill(s);
			npc.disableSkill(skill, -1);
		}
	}
	private void enableScarletSkills(L2Npc npc, int... skillHashCode)
	{
		for (int s : skillHashCode)
		{
			Skill skill = getSkill(s);
			npc.enableSkill(skill);
		}
	}
	
	// Doors/Walls/Zones
	protected static final int[] FIRST_ROOM_DOORS =
	{
		17130051,
		17130052,
		17130053,
		17130054,
		17130055,
		17130056,
		17130057,
		17130058
	};
	protected static final int[] SECOND_ROOM_DOORS =
	{
		17130061,
		17130062,
		17130063,
		17130064,
		17130065,
		17130066,
		17130067,
		17130068,
		17130069,
		17130070
	};
	
	protected static final int[] FIRST_ROUTE_DOORS =
	{
		17130042,
		17130043
	};
	protected static final int[] SECOND_ROUTE_DOORS =
	{
		17130045,
		17130046
	};
	
	private static final int ROOM1_CENTER_X = -87904, ROOM1_CENTER_Y = -141296, ROOM1_CENTER_Z = -9168;
	private static final int ROOM2_CENTER_X = -87904, ROOM2_CENTER_Y = -147065, ROOM2_CENTER_Z = -9168;
	private static final int ROOM3_CENTER_X = -87789, ROOM3_CENTER_Y = -153295, ROOM3_CENTER_Z = -9176;
	private static final int ROOM3_ZONE = 12911;
	
	// Teleports
	private static final Location ENTER_TELEPORT = new Location(-88015, -141153, -9168);
	
	// spawns
	private static final int GHOST_RESPAWN_DELAY = 10; // sec.
	protected static final L2NpcPosition[] PORTRAIT_SPAWNS =
	{
		new L2NpcPosition(PORTRAIT_FIGHTER, -89381, -153981, -9168, 3368),
		new L2NpcPosition(PORTRAIT_FIGHTER, -86234, -152467, -9168, 37656),
		new L2NpcPosition(PORTRAIT_MAGE, -89342, -152479, -9168, -5152),
		new L2NpcPosition(PORTRAIT_MAGE, -86189, -153968, -9168, 29456),
	};
	protected static final L2NpcPosition[] GHOST_SPAWNS =
	{
		new L2NpcPosition(GHOST_FIGHTER, -89378, -153968, -9168, 3368),
		new L2NpcPosition(GHOST_FIGHTER, -86261, -152492, -9168, 37656),
		new L2NpcPosition(GHOST_MAGE, -89311, -152491, -9168, -5152),
		new L2NpcPosition(GHOST_MAGE, -86217, -153956, -9168, 29456),
	};
	
	private FinalEmperialTomb()
	{
		super(-1, FinalEmperialTomb.class.getSimpleName(), "instances");
		addStartNpc(GUIDE);
		addTalkId(GUIDE);
		addStartNpc(CUBE);
		addTalkId(CUBE);
		addKillId(HALL_ALARM);
		addKillId(DARK_CHOIR_PLAYER);
		for (int npcId : MUST_KILL_MOBS)
		{
			addKillId(npcId);
			if (!NpcData.getInstance().getTemplate(npcId).getAISkills(AISkillScope.SUICIDE).isEmpty())
				addSpellFinishedId(npcId);
		}
		addSkillSeeId(FRINTEZZA);
		addAttackId(FRINTEZZA);
		addAttackId(SCARLET1);
		addKillId(SCARLET1);
		addKillId(SCARLET2);
		addKillId(PORTRAIT_FIGHTER);
		addKillId(PORTRAIT_MAGE);
		addEnterZoneId(ROOM3_ZONE);
		addSpellFinishedId(SCARLET1);
		addSpellFinishedId(SCARLET2);
		if (ASSERT) if (!(ZoneManager.getInstance().getZoneById(ROOM3_ZONE) != null)) throw new RuntimeException();	//<zone id="12911" type="ScriptZone" shape="Cuboid" ... />
	}
	
	protected void openDoors(int[] doorIds, int instanceId)
	{
		for (int doorId : doorIds)
		{
			openDoor(doorId, instanceId);
		}
	}
	
	protected void closeDoors(int[] doorIds, int instanceId)
	{
		for (int doorId : doorIds)
		{
			closeDoor(doorId, instanceId);
		}
	}
	
	private boolean checkConditions(L2PcInstance player)
	{
		if (DEBUG || player.canOverrideCond(PcCondOverride.INSTANCE_CONDITIONS))
		{
			return true;
		}
		L2Party party = player.getParty();
		if (party == null)
		{
			player.sendPacket(SystemMessageId.NOT_IN_PARTY_CANT_ENTER);
			return false;
		}
		L2CommandChannel channel = player.getParty().getCommandChannel();
		if (channel == null)
		{
			player.sendPacket(SystemMessageId.NOT_IN_COMMAND_CHANNEL_CANT_ENTER);
			return false;
		}
		else if (channel.getLeader() != player)
		{
			player.sendPacket(SystemMessageId.ONLY_PARTY_LEADER_CAN_ENTER);
			return false;
		}
		else if (player.getInventory().getItemByItemId(FRINTEZZA_SCROLL) == null)
		{
			SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_ITEM_REQUIREMENT_NOT_SUFFICIENT);
			sm.addPcName(player);
			player.sendPacket(sm);
			return false;
		}
		else if ((channel.getMemberCount() < MIN_PLAYERS) || (channel.getMemberCount() > MAX_PLAYERS))
		{
			player.sendPacket(SystemMessageId.PARTY_EXCEEDED_THE_LIMIT_CANT_ENTER);
			return false;
		}
		boolean condition = true;
		for (L2PcInstance channelMember : channel.getMembers())
		{
			if (channelMember.getLevel() < 80)
			{
				SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_LEVEL_REQUIREMENT_NOT_SUFFICIENT);
				sm.addPcName(channelMember);
				party.broadcastPacket(sm);
				condition = false;
			}
			if (!Util.checkIfInRange(1000, player, channelMember, true))
			{
				SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_LOCATION_THAT_CANNOT_BE_ENTERED);
				sm.addPcName(channelMember);
				party.broadcastPacket(sm);
				condition = false;
			}
			long reentertime = InstanceManager.getInstance().getInstanceTime(channelMember.getObjectId(), INSTANCEID);
			if (System.currentTimeMillis() < reentertime)
			{
				SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_MAY_NOT_REENTER_YET);
				sm.addPcName(channelMember);
				party.broadcastPacket(sm);
				condition = false;
			}
		}
		return condition;
	}
	
	@Override
	public void teleportPlayer(L2PcInstance player, Location loc, int instanceId)/*20130131テスト済*/
	{
		this.teleportPlayer(player, loc, instanceId, true);
	}
	
	@Override
	public void teleportPlayer(L2PcInstance player, Location loc, int instanceId, boolean allowRandomOffset)
	{
		super.teleportPlayer(player, loc, instanceId, allowRandomOffset);
		if (ASSERT) if (player.getInstanceId() != instanceId) throw new RuntimeException("player.getInstanceId(){"+player.getInstanceId()+"} != instanceId{"+instanceId+"}");
		destroyAllItem(player, SOUL_BREAKING_ARROW);
		destroyAllItem(player, DEWDROP_OF_DESTRUCTION);
	}
	
	private void destroyAllItem(L2PcInstance player, int itemId)/*テスト済*/
	{
		L2ItemInstance item = player.getInventory().getItemByItemId(itemId);
		if (item != null)
		{
			player.destroyItemByItemId(getName(), itemId, item.getCount(), player, true);
		}
	}
	
	protected int enterInstance(L2PcInstance player, String template, Location loc)
	{
		int instanceId = 0;
		// check for existing instances for this player
		InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
		// existing instance
		if (world != null)
		{
			if (!(world instanceof FETWorld))
			{
				player.sendPacket(SystemMessageId.ALREADY_ENTERED_ANOTHER_INSTANCE_CANT_ENTER);
				return 0;
			}
			teleportPlayer(player, loc, world.getInstanceId());
			return world.getInstanceId();
		}
		
		// New instance
		if (!checkConditions(player))
		{
			return 0;
		}
		if (!player.canOverrideCond(PcCondOverride.INSTANCE_CONDITIONS) && !player.destroyItemByItemId("Quest", FRINTEZZA_SCROLL, 1, player, true))
		{
			return 0;
		}
		instanceId = InstanceManager.getInstance().createDynamicInstance(template);
		// Instance ins = InstanceManager.getInstance().getInstance(instanceId);
		// ins.setSpawnLoc(new int[]{player.getX(),player.getY(),player.getZ()});
		world = new FETWorld();
		world.setInstanceId(instanceId);
		world.setStatus(0);
		InstanceManager.getInstance().addWorld(world);
		controlStatus((FETWorld) world);
		_log.info("Final Emperial Tomb started " + template + " Instance: " + instanceId + " created by player: " + player.getName());
		// teleport players
		if ((player.getParty() == null) || (player.getParty().getCommandChannel() == null))
		{
			world.addAllowed(player);
			teleportPlayer(player, loc, instanceId);
		}
		else
		{
			for (L2PcInstance channelMember : player.getParty().getCommandChannel().getMembers())
			{
				world.addAllowed(channelMember);
				teleportPlayer(channelMember, loc, instanceId);
			}
		}
		return instanceId;
	}
	
	/**
	 * モンスター配置：１部屋め ホールアラーム
	 * @param world
	 */
	private void spawnHallAlarm(FETWorld world)/*テスト済*/
	{
		spawn(world, HALL_ALARM, -87904, -141296, -9168, 0);
	}
	
	/**
	 * モンスター配置：１部屋め ホールキーパー
	 * @param world
	 */
	protected void spawnHallKeepers(FETWorld world)/*テスト済*/
	{
		spawn(world, HALL_KEEPER_WIZARD, -89179, -141151, -9084, 29201);
		spawn(world, HALL_KEEPER_WIZARD, -89072, -141422, -9084, 55195);
		spawn(world, HALL_KEEPER_WIZARD, -89241, -140900, -9084, 29568);
		spawn(world, HALL_KEEPER_GUARD, -88982, -141058, -9084, 18641);
		spawn(world, HALL_KEEPER_GUARD, -89168, -141063, -9084, 24129);
		spawn(world, HALL_KEEPER_GUARD, -89013, -141080, -9084, 15361);
		spawn(world, HALL_KEEPER_GUARD, -89060, -141558, -9084, 12654);
		spawn(world, HALL_KEEPER_GUARD, -89277, -141133, -9084, 27853);
		spawn(world, HALL_KEEPER_GUARD, -88982, -141441, -9084, 41976);
		spawn(world, HALL_KEEPER_GUARD, -89154, -141486, -9084, 55794);
		spawn(world, HALL_KEEPER_GUARD, -89002, -141243, -9084, 46318);
		spawn(world, HALL_KEEPER_GUARD, -89175, -141221, -9084, 32141);
		spawn(world, HALL_KEEPER_GUARD, -89286, -141786, -9084, 59388);
		spawn(world, HALL_KEEPER_CAPTAIN, -89265, -141731, -9084, 4186);
		spawn(world, HALL_KEEPER_CAPTAIN, -89154, -141696, -9084, 40154);
		spawn(world, HALL_KEEPER_CAPTAIN, -89004, -141261, -9084, 26412);
		spawn(world, HALL_KEEPER_CAPTAIN, -89098, -141667, -9084, 6500);
		spawn(world, HALL_KEEPER_CAPTAIN, -89238, -140994, -9084, 34003);
		spawn(world, HALL_KEEPER_CAPTAIN, -89221, -140948, -9084, 413);
		spawn(world, HALL_KEEPER_CAPTAIN, -89177, -141249, -9084, 32846);
		spawn(world, HALL_KEEPER_CAPTAIN, -89277, -141646, -9084, 50123);
		spawn(world, HALL_KEEPER_CAPTAIN, -89289, -141179, -9084, 38433);
		spawn(world, HALL_KEEPER_CAPTAIN, -89048, -141471, -9084, 23960);
		spawn(world, HALL_KEEPER_WIZARD, -89293, -141554, -9084, 44386);
		spawn(world, HALL_KEEPER_WIZARD, -89279, -141608, -9084, 17601);
		spawn(world, HALL_KEEPER_WIZARD, -89293, -141733, -9084, 22291);
		spawn(world, HALL_KEEPER_WIZARD, -89261, -140966, -9084, 33093);
		spawn(world, HALL_KEEPER_WIZARD, -89110, -141304, -9084, 49199);
		spawn(world, HALL_KEEPER_WIZARD, -89201, -141057, -9084, 61192);
		spawn(world, HALL_KEEPER_WIZARD, -88970, -141444, -9084, 33115);
		spawn(world, HALL_KEEPER_WIZARD, -89287, -141117, -9084, 31752);
		spawn(world, HALL_KEEPER_WIZARD, -89144, -141588, -9084, 9834);
		spawn(world, HALL_KEEPER_WIZARD, -89141, -141262, -9084, 48686);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -89206, -141647, -9084, 2679);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88991, -141322, -9084, 9016);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -89094, -141219, -9084, 54854);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -89041, -141506, -9084, 46264);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -89206, -141299, -9084, 7060);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -89137, -141194, -9084, 46678);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -89255, -141383, -9084, 1658);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -89239, -141546, -9084, 4935);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -89253, -141120, -9084, 15924);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -89236, -140921, -9084, 37100);
		spawn(world, HALL_KEEPER_WIZARD, -88994, -141895, -9084, 40023);
		spawn(world, HALL_KEEPER_WIZARD, -88671, -142486, -9084, 63707);
		spawn(world, HALL_KEEPER_WIZARD, -89070, -141952, -9084, 55610);
		spawn(world, HALL_KEEPER_GUARD, -88677, -142231, -9084, 5076);
		spawn(world, HALL_KEEPER_GUARD, -88911, -142162, -9084, 46095);
		spawn(world, HALL_KEEPER_GUARD, -89206, -141915, -9084, 29714);
		spawn(world, HALL_KEEPER_GUARD, -88913, -142183, -9084, 9773);
		spawn(world, HALL_KEEPER_GUARD, -88940, -141918, -9084, 59795);
		spawn(world, HALL_KEEPER_GUARD, -88750, -142240, -9084, 40924);
		spawn(world, HALL_KEEPER_GUARD, -88995, -141945, -9084, 4964);
		spawn(world, HALL_KEEPER_GUARD, -88456, -142398, -9084, 28245);
		spawn(world, HALL_KEEPER_GUARD, -89184, -141910, -9084, 31201);
		spawn(world, HALL_KEEPER_GUARD, -88621, -142366, -9084, 14877);
		spawn(world, HALL_KEEPER_CAPTAIN, -88581, -142228, -9084, 59733);
		spawn(world, HALL_KEEPER_CAPTAIN, -88605, -142268, -9084, 16013);
		spawn(world, HALL_KEEPER_CAPTAIN, -88804, -142360, -9084, 2054);
		spawn(world, HALL_KEEPER_CAPTAIN, -89085, -141940, -9084, 24413);
		spawn(world, HALL_KEEPER_CAPTAIN, -88521, -142542, -9084, 42030);
		spawn(world, HALL_KEEPER_CAPTAIN, -88856, -142048, -9084, 56049);
		spawn(world, HALL_KEEPER_CAPTAIN, -89033, -142038, -9084, 7498);
		spawn(world, HALL_KEEPER_CAPTAIN, -88685, -142335, -9084, 12201);
		spawn(world, HALL_KEEPER_CAPTAIN, -88827, -142060, -9084, 23417);
		spawn(world, HALL_KEEPER_CAPTAIN, -88895, -142065, -9084, 56831);
		spawn(world, HALL_KEEPER_WIZARD, -88890, -142145, -9084, 13966);
		spawn(world, HALL_KEEPER_WIZARD, -88814, -142315, -9084, 23378);
		spawn(world, HALL_KEEPER_WIZARD, -88985, -141993, -9084, 20346);
		spawn(world, HALL_KEEPER_WIZARD, -88882, -141894, -9084, 39953);
		spawn(world, HALL_KEEPER_WIZARD, -88772, -142064, -9084, 8081);
		spawn(world, HALL_KEEPER_WIZARD, -89193, -141924, -9084, 1410);
		spawn(world, HALL_KEEPER_WIZARD, -88515, -142586, -9084, 50268);
		spawn(world, HALL_KEEPER_WIZARD, -88951, -141997, -9084, 36420);
		spawn(world, HALL_KEEPER_WIZARD, -89080, -141960, -9084, 64618);
		spawn(world, HALL_KEEPER_WIZARD, -88911, -142051, -9084, 47432);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88630, -142205, -9084, 34636);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88511, -142481, -9084, 61532);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88854, -141942, -9084, 19805);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88888, -142146, -9084, 41516);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88811, -142349, -9084, 34329);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88515, -142514, -9084, 46043);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -89187, -141975, -9084, 18674);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88540, -142353, -9084, 51463);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -89009, -142081, -9084, 52367);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -89073, -141879, -9084, 36950);
		spawn(world, HALL_KEEPER_WIZARD, -87487, -142622, -9084, 11560);
		spawn(world, HALL_KEEPER_WIZARD, -87699, -142648, -9084, 8491);
		spawn(world, HALL_KEEPER_WIZARD, -87977, -142597, -9084, 20714);
		spawn(world, HALL_KEEPER_GUARD, -87625, -142520, -9084, 23555);
		spawn(world, HALL_KEEPER_GUARD, -88273, -142655, -9084, 55342);
		spawn(world, HALL_KEEPER_GUARD, -87945, -142633, -9084, 35172);
		spawn(world, HALL_KEEPER_GUARD, -87736, -142630, -9084, 24731);
		spawn(world, HALL_KEEPER_GUARD, -87968, -142406, -9084, 60800);
		spawn(world, HALL_KEEPER_GUARD, -87796, -142378, -9084, 58660);
		spawn(world, HALL_KEEPER_GUARD, -87632, -142640, -9084, 56686);
		spawn(world, HALL_KEEPER_GUARD, -87678, -142539, -9084, 7582);
		spawn(world, HALL_KEEPER_GUARD, -87793, -142541, -9084, 29086);
		spawn(world, HALL_KEEPER_GUARD, -87447, -142630, -9084, 60299);
		spawn(world, HALL_KEEPER_CAPTAIN, -87799, -142466, -9084, 5759);
		spawn(world, HALL_KEEPER_CAPTAIN, -87514, -142628, -9084, 58262);
		spawn(world, HALL_KEEPER_CAPTAIN, -87724, -142647, -9084, 24200);
		spawn(world, HALL_KEEPER_CAPTAIN, -88087, -142588, -9084, 10858);
		spawn(world, HALL_KEEPER_CAPTAIN, -87967, -142663, -9084, 57780);
		spawn(world, HALL_KEEPER_CAPTAIN, -87720, -142648, -9084, 37602);
		spawn(world, HALL_KEEPER_CAPTAIN, -87929, -142660, -9084, 46137);
		spawn(world, HALL_KEEPER_CAPTAIN, -88174, -142673, -9084, 24488);
		spawn(world, HALL_KEEPER_CAPTAIN, -88240, -142449, -9084, 13398);
		spawn(world, HALL_KEEPER_CAPTAIN, -87607, -142680, -9084, 17097);
		spawn(world, HALL_KEEPER_WIZARD, -88200, -142534, -9084, 15141);
		spawn(world, HALL_KEEPER_WIZARD, -88108, -142534, -9084, 32296);
		spawn(world, HALL_KEEPER_WIZARD, -87730, -142419, -9084, 42508);
		spawn(world, HALL_KEEPER_WIZARD, -87719, -142525, -9084, 49712);
		spawn(world, HALL_KEEPER_WIZARD, -88154, -142633, -9084, 46219);
		spawn(world, HALL_KEEPER_WIZARD, -87627, -142460, -9084, 41723);
		spawn(world, HALL_KEEPER_WIZARD, -87838, -142485, -9084, 1086);
		spawn(world, HALL_KEEPER_WIZARD, -87938, -142561, -9084, 8226);
		spawn(world, HALL_KEEPER_WIZARD, -87762, -142527, -9084, 17686);
		spawn(world, HALL_KEEPER_WIZARD, -88098, -142438, -9084, 13467);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87900, -142655, -9084, 53098);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87862, -142433, -9084, 23101);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87887, -142604, -9084, 16537);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88230, -142612, -9084, 38105);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88049, -142431, -9084, 26056);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87878, -142463, -9084, 31627);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88044, -142632, -9084, 41814);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87675, -142577, -9084, 35302);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87983, -142414, -9084, 24927);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87884, -142401, -9084, 46450);
		spawn(world, HALL_KEEPER_WIZARD, -86759, -141907, -9084, 17429);
		spawn(world, HALL_KEEPER_WIZARD, -86651, -141971, -9084, 5614);
		spawn(world, HALL_KEEPER_WIZARD, -86955, -142198, -9084, 31911);
		spawn(world, HALL_KEEPER_GUARD, -87092, -142250, -9084, 22242);
		spawn(world, HALL_KEEPER_GUARD, -86888, -142003, -9084, 3622);
		spawn(world, HALL_KEEPER_GUARD, -87177, -142347, -9084, 30199);
		spawn(world, HALL_KEEPER_GUARD, -86769, -141937, -9084, 9524);
		spawn(world, HALL_KEEPER_GUARD, -87163, -142476, -9084, 62322);
		spawn(world, HALL_KEEPER_GUARD, -86909, -142200, -9084, 13244);
		spawn(world, HALL_KEEPER_GUARD, -86788, -141977, -9084, 19113);
		spawn(world, HALL_KEEPER_GUARD, -87025, -142281, -9084, 40342);
		spawn(world, HALL_KEEPER_GUARD, -87125, -142427, -9084, 23676);
		spawn(world, HALL_KEEPER_GUARD, -87043, -142051, -9084, 61011);
		spawn(world, HALL_KEEPER_CAPTAIN, -86660, -141918, -9084, 60818);
		spawn(world, HALL_KEEPER_CAPTAIN, -87041, -142298, -9084, 4384);
		spawn(world, HALL_KEEPER_CAPTAIN, -87024, -142242, -9084, 52296);
		spawn(world, HALL_KEEPER_CAPTAIN, -86942, -142164, -9084, 18800);
		spawn(world, HALL_KEEPER_CAPTAIN, -87334, -142391, -9084, 26082);
		spawn(world, HALL_KEEPER_CAPTAIN, -86811, -141878, -9084, 24000);
		spawn(world, HALL_KEEPER_CAPTAIN, -86886, -141984, -9084, 52192);
		spawn(world, HALL_KEEPER_CAPTAIN, -87362, -142430, -9084, 362);
		spawn(world, HALL_KEEPER_CAPTAIN, -87313, -142321, -9084, 35934);
		spawn(world, HALL_KEEPER_CAPTAIN, -87164, -142092, -9084, 2405);
		spawn(world, HALL_KEEPER_WIZARD, -87174, -142324, -9084, 40368);
		spawn(world, HALL_KEEPER_WIZARD, -87022, -142014, -9084, 49873);
		spawn(world, HALL_KEEPER_WIZARD, -86978, -142210, -9084, 27160);
		spawn(world, HALL_KEEPER_WIZARD, -87316, -142380, -9084, 24693);
		spawn(world, HALL_KEEPER_WIZARD, -87166, -142212, -9084, 55605);
		spawn(world, HALL_KEEPER_WIZARD, -87147, -142416, -9084, 28904);
		spawn(world, HALL_KEEPER_WIZARD, -87393, -142346, -9084, 8960);
		spawn(world, HALL_KEEPER_WIZARD, -86909, -141964, -9084, 28331);
		spawn(world, HALL_KEEPER_WIZARD, -86680, -141996, -9084, 25744);
		spawn(world, HALL_KEEPER_WIZARD, -87047, -142082, -9084, 29196);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -86952, -141993, -9084, 40622);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -86960, -142294, -9084, 35741);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87257, -142281, -9084, 39057);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -86915, -141969, -9084, 52851);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87180, -142479, -9084, 59051);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -86946, -142118, -9084, 7156);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87216, -142452, -9084, 30191);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87169, -142482, -9084, 31494);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87087, -142319, -9084, 59175);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87244, -142336, -9084, 2847);
		spawn(world, HALL_KEEPER_WIZARD, -86553, -140940, -9084, 42599);
		spawn(world, HALL_KEEPER_WIZARD, -86573, -140862, -9084, 27920);
		spawn(world, HALL_KEEPER_WIZARD, -86687, -141658, -9084, 50112);
		spawn(world, HALL_KEEPER_GUARD, -86578, -141628, -9084, 16570);
		spawn(world, HALL_KEEPER_GUARD, -86845, -141272, -9084, 49416);
		spawn(world, HALL_KEEPER_GUARD, -86543, -141609, -9084, 9735);
		spawn(world, HALL_KEEPER_GUARD, -86702, -141546, -9084, 18913);
		spawn(world, HALL_KEEPER_GUARD, -86634, -141286, -9084, 25878);
		spawn(world, HALL_KEEPER_GUARD, -86833, -141524, -9084, 36512);
		spawn(world, HALL_KEEPER_GUARD, -86642, -140920, -9084, 12438);
		spawn(world, HALL_KEEPER_GUARD, -86627, -141565, -9084, 10380);
		spawn(world, HALL_KEEPER_GUARD, -86746, -140969, -9084, 4535);
		spawn(world, HALL_KEEPER_GUARD, -86806, -141341, -9084, 25441);
		spawn(world, HALL_KEEPER_CAPTAIN, -86568, -141314, -9084, 54899);
		spawn(world, HALL_KEEPER_CAPTAIN, -86798, -141130, -9084, 11892);
		spawn(world, HALL_KEEPER_CAPTAIN, -86836, -141468, -9084, 29780);
		spawn(world, HALL_KEEPER_CAPTAIN, -86717, -141395, -9084, 37205);
		spawn(world, HALL_KEEPER_CAPTAIN, -86711, -141351, -9084, 16553);
		spawn(world, HALL_KEEPER_CAPTAIN, -86625, -141329, -9084, 12887);
		spawn(world, HALL_KEEPER_CAPTAIN, -86629, -141758, -9084, 13472);
		spawn(world, HALL_KEEPER_CAPTAIN, -86700, -141048, -9084, 58459);
		spawn(world, HALL_KEEPER_CAPTAIN, -86649, -140899, -9084, 37420);
		spawn(world, HALL_KEEPER_CAPTAIN, -86656, -141659, -9084, 53390);
		spawn(world, HALL_KEEPER_WIZARD, -86639, -141628, -9084, 27370);
		spawn(world, HALL_KEEPER_WIZARD, -86678, -140895, -9084, 51579);
		spawn(world, HALL_KEEPER_WIZARD, -86666, -141401, -9084, 2166);
		spawn(world, HALL_KEEPER_WIZARD, -86707, -141364, -9084, 38717);
		spawn(world, HALL_KEEPER_WIZARD, -86626, -141263, -9084, 34845);
		spawn(world, HALL_KEEPER_WIZARD, -86843, -141133, -9084, 43750);
		spawn(world, HALL_KEEPER_WIZARD, -86683, -141644, -9084, 46859);
		spawn(world, HALL_KEEPER_WIZARD, -86540, -140925, -9084, 52340);
		spawn(world, HALL_KEEPER_WIZARD, -86764, -141468, -9084, 29290);
		spawn(world, HALL_KEEPER_WIZARD, -86789, -141479, -9084, 39464);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -86821, -141526, -9084, 586);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -86836, -141079, -9084, 2316);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -86583, -140867, -9084, 55682);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -86723, -141179, -9084, 57311);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -86551, -140986, -9084, 36818);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -86825, -141415, -9084, 57390);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -86549, -141026, -9084, 34174);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -86671, -141631, -9084, 4159);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -86631, -140963, -9084, 49098);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -86552, -140935, -9084, 54831);
		spawn(world, HALL_KEEPER_WIZARD, -86913, -140358, -9084, 29722);
		spawn(world, HALL_KEEPER_WIZARD, -87255, -140089, -9084, 21995);
		spawn(world, HALL_KEEPER_WIZARD, -87118, -140500, -9084, 64831);
		spawn(world, HALL_KEEPER_GUARD, -87362, -140225, -9084, 18420);
		spawn(world, HALL_KEEPER_GUARD, -87353, -140230, -9084, 57857);
		spawn(world, HALL_KEEPER_GUARD, -87044, -140238, -9084, 14115);
		spawn(world, HALL_KEEPER_GUARD, -87321, -140279, -9084, 56692);
		spawn(world, HALL_KEEPER_GUARD, -87178, -140473, -9084, 29072);
		spawn(world, HALL_KEEPER_GUARD, -86888, -140620, -9084, 28810);
		spawn(world, HALL_KEEPER_GUARD, -87132, -140419, -9084, 53381);
		spawn(world, HALL_KEEPER_GUARD, -87162, -140553, -9084, 65457);
		spawn(world, HALL_KEEPER_GUARD, -87102, -140306, -9084, 34336);
		spawn(world, HALL_KEEPER_GUARD, -87145, -140561, -9084, 31080);
		spawn(world, HALL_KEEPER_CAPTAIN, -86925, -140704, -9084, 36929);
		spawn(world, HALL_KEEPER_CAPTAIN, -87049, -140669, -9084, 52241);
		spawn(world, HALL_KEEPER_CAPTAIN, -87164, -140348, -9084, 886);
		spawn(world, HALL_KEEPER_CAPTAIN, -87088, -140315, -9084, 45956);
		spawn(world, HALL_KEEPER_CAPTAIN, -87091, -140383, -9084, 59410);
		spawn(world, HALL_KEEPER_CAPTAIN, -86991, -140683, -9084, 16050);
		spawn(world, HALL_KEEPER_CAPTAIN, -86954, -140636, -9084, 62620);
		spawn(world, HALL_KEEPER_CAPTAIN, -86778, -140547, -9084, 38397);
		spawn(world, HALL_KEEPER_CAPTAIN, -86569, -140711, -9084, 19800);
		spawn(world, HALL_KEEPER_CAPTAIN, -87137, -140466, -9084, 47134);
		spawn(world, HALL_KEEPER_WIZARD, -87090, -140437, -9084, 54990);
		spawn(world, HALL_KEEPER_WIZARD, -86914, -140597, -9084, 10165);
		spawn(world, HALL_KEEPER_WIZARD, -87228, -140344, -9084, 38409);
		spawn(world, HALL_KEEPER_WIZARD, -86788, -140669, -9084, 56995);
		spawn(world, HALL_KEEPER_WIZARD, -86970, -140551, -9084, 2111);
		spawn(world, HALL_KEEPER_WIZARD, -87113, -140269, -9084, 45123);
		spawn(world, HALL_KEEPER_WIZARD, -86771, -140659, -9084, 62476);
		spawn(world, HALL_KEEPER_WIZARD, -86998, -140535, -9084, 17946);
		spawn(world, HALL_KEEPER_WIZARD, -87164, -140367, -9084, 31052);
		spawn(world, HALL_KEEPER_WIZARD, -87177, -140427, -9084, 21561);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87074, -140212, -9084, 54927);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87216, -140397, -9084, 50949);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -86945, -140425, -9084, 3892);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87195, -140156, -9084, 5887);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87204, -140445, -9084, 25114);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87006, -140498, -9084, 39595);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87155, -140363, -9084, 10302);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87189, -140528, -9084, 64655);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87052, -140527, -9084, 28893);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87317, -139959, -9084, 54399);
		spawn(world, HALL_KEEPER_WIZARD, -87628, -140026, -9084, 57208);
		spawn(world, HALL_KEEPER_WIZARD, -87744, -139968, -9084, 9834);
		spawn(world, HALL_KEEPER_WIZARD, -88052, -140041, -9084, 49080);
		spawn(world, HALL_KEEPER_GUARD, -88286, -140125, -9084, 34428);
		spawn(world, HALL_KEEPER_GUARD, -87949, -139989, -9084, 44173);
		spawn(world, HALL_KEEPER_GUARD, -87503, -139971, -9084, 63468);
		spawn(world, HALL_KEEPER_GUARD, -88041, -140029, -9084, 63562);
		spawn(world, HALL_KEEPER_GUARD, -88072, -140021, -9084, 60924);
		spawn(world, HALL_KEEPER_GUARD, -88138, -140250, -9084, 54354);
		spawn(world, HALL_KEEPER_GUARD, -87913, -140068, -9084, 5959);
		spawn(world, HALL_KEEPER_GUARD, -87615, -140033, -9084, 54464);
		spawn(world, HALL_KEEPER_GUARD, -88242, -140194, -9084, 57541);
		spawn(world, HALL_KEEPER_GUARD, -88269, -139985, -9084, 65308);
		spawn(world, HALL_KEEPER_CAPTAIN, -88139, -140250, -9084, 62428);
		spawn(world, HALL_KEEPER_CAPTAIN, -87949, -140037, -9084, 21905);
		spawn(world, HALL_KEEPER_CAPTAIN, -87569, -140051, -9084, 58704);
		spawn(world, HALL_KEEPER_CAPTAIN, -88137, -140234, -9084, 58580);
		spawn(world, HALL_KEEPER_CAPTAIN, -87661, -140093, -9084, 38266);
		spawn(world, HALL_KEEPER_CAPTAIN, -87577, -140146, -9084, 27046);
		spawn(world, HALL_KEEPER_CAPTAIN, -87773, -140149, -9084, 37681);
		spawn(world, HALL_KEEPER_CAPTAIN, -88014, -140241, -9084, 7654);
		spawn(world, HALL_KEEPER_CAPTAIN, -88087, -140070, -9084, 7795);
		spawn(world, HALL_KEEPER_CAPTAIN, -87570, -140181, -9084, 36646);
		spawn(world, HALL_KEEPER_WIZARD, -87994, -139974, -9084, 57714);
		spawn(world, HALL_KEEPER_WIZARD, -88248, -139972, -9084, 62214);
		spawn(world, HALL_KEEPER_WIZARD, -87858, -140172, -9084, 46664);
		spawn(world, HALL_KEEPER_WIZARD, -88101, -140173, -9084, 61120);
		spawn(world, HALL_KEEPER_WIZARD, -88131, -140048, -9084, 60111);
		spawn(world, HALL_KEEPER_WIZARD, -88184, -140116, -9084, 58359);
		spawn(world, HALL_KEEPER_WIZARD, -87658, -139936, -9084, 11270);
		spawn(world, HALL_KEEPER_WIZARD, -87877, -140104, -9084, 5007);
		spawn(world, HALL_KEEPER_WIZARD, -87618, -140158, -9084, 57288);
		spawn(world, HALL_KEEPER_WIZARD, -88337, -140037, -9084, 50516);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87572, -140110, -9084, 14254);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88267, -140147, -9084, 12254);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -87423, -139957, -9084, 54758);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88355, -140024, -9084, 35328);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88422, -139969, -9084, 39172);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88084, -140054, -9084, 30771);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88076, -140072, -9084, 12242);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88271, -140150, -9084, 37892);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88025, -140147, -9084, 23699);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88163, -140079, -9084, 40986);
		spawn(world, HALL_KEEPER_WIZARD, -88733, -140567, -9084, 9785);
		spawn(world, HALL_KEEPER_WIZARD, -88547, -140103, -9084, 20344);
		spawn(world, HALL_KEEPER_WIZARD, -88617, -140237, -9084, 48681);
		spawn(world, HALL_KEEPER_GUARD, -88425, -140302, -9084, 33198);
		spawn(world, HALL_KEEPER_GUARD, -88985, -140693, -9084, 61882);
		spawn(world, HALL_KEEPER_GUARD, -88587, -140341, -9084, 6286);
		spawn(world, HALL_KEEPER_GUARD, -88555, -140020, -9084, 25728);
		spawn(world, HALL_KEEPER_GUARD, -88632, -140197, -9084, 49223);
		spawn(world, HALL_KEEPER_GUARD, -88693, -140230, -9084, 49954);
		spawn(world, HALL_KEEPER_GUARD, -89118, -140666, -9084, 61663);
		spawn(world, HALL_KEEPER_GUARD, -88966, -140668, -9084, 39800);
		spawn(world, HALL_KEEPER_GUARD, -88902, -140795, -9084, 10329);
		spawn(world, HALL_KEEPER_GUARD, -89137, -140658, -9084, 26689);
		spawn(world, HALL_KEEPER_CAPTAIN, -89014, -140617, -9084, 18805);
		spawn(world, HALL_KEEPER_CAPTAIN, -88674, -140157, -9084, 19431);
		spawn(world, HALL_KEEPER_CAPTAIN, -88816, -140546, -9084, 11754);
		spawn(world, HALL_KEEPER_CAPTAIN, -89023, -140482, -9084, 50721);
		spawn(world, HALL_KEEPER_CAPTAIN, -88634, -140389, -9084, 53263);
		spawn(world, HALL_KEEPER_CAPTAIN, -89019, -140784, -9084, 31464);
		spawn(world, HALL_KEEPER_CAPTAIN, -88593, -140403, -9084, 55532);
		spawn(world, HALL_KEEPER_CAPTAIN, -88511, -140243, -9084, 57893);
		spawn(world, HALL_KEEPER_CAPTAIN, -88919, -140751, -9084, 31574);
		spawn(world, HALL_KEEPER_CAPTAIN, -88901, -140622, -9084, 2091);
		spawn(world, HALL_KEEPER_WIZARD, -88496, -139996, -9084, 60873);
		spawn(world, HALL_KEEPER_WIZARD, -88854, -140695, -9084, 51659);
		spawn(world, HALL_KEEPER_WIZARD, -88998, -140537, -9084, 46494);
		spawn(world, HALL_KEEPER_WIZARD, -88746, -140309, -9084, 58583);
		spawn(world, HALL_KEEPER_WIZARD, -88617, -140235, -9084, 23701);
		spawn(world, HALL_KEEPER_WIZARD, -88848, -140390, -9084, 38252);
		spawn(world, HALL_KEEPER_WIZARD, -88776, -140566, -9084, 33157);
		spawn(world, HALL_KEEPER_WIZARD, -88859, -140367, -9084, 53480);
		spawn(world, HALL_KEEPER_WIZARD, -89087, -140682, -9084, 13235);
		spawn(world, HALL_KEEPER_WIZARD, -88506, -140087, -9084, 17858);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88770, -140340, -9084, 22287);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88770, -140441, -9084, 2029);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88421, -140322, -9084, 28902);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88942, -140701, -9084, 10314);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88546, -140214, -9084, 65055);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88503, -139978, -9084, 17454);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88629, -140177, -9084, 48872);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88934, -140417, -9084, 32545);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88874, -140323, -9084, 64196);
		spawn(world, HALL_KEEPER_SUICIDAL_SOLDIER_1, -88833, -140384, -9084, 33);
	}
	
	/**
	 * モンスター配置：２部屋め 聖歌団プレイヤー
	 * @param world
	 */
	private void spawnDarkPlayers(FETWorld world)/*テスト済*/
	{
		spawn(world, DARK_CHOIR_PLAYER, -87875, -147001, -9128, 39939);
		spawn(world, DARK_CHOIR_PLAYER, -88014, -147087, -9128, 35800);
		spawn(world, DARK_CHOIR_PLAYER, -87785, -147219, -9128, 53478);
		spawn(world, DARK_CHOIR_PLAYER, -87825, -147176, -9128, 59347);
	}
	
	/**
	 * モンスター配置：２部屋め 黒聖歌団
	 * @param world
	 */
	protected void spawnDarkChoirs(FETWorld world)/*テスト済*/
	{
		spawn(world, DARK_CHOIR_CAPTAIN, -88755, -147395, -9138, 0);
		spawn(world, DARK_CHOIR_CAPTAIN, -88755, -147187, -9138, 0);
		spawn(world, DARK_CHOIR_CAPTAIN, -88755, -146963, -9138, 0);
		spawn(world, DARK_CHOIR_CAPTAIN, -88755, -146723, -9138, 0);
		spawn(world, DARK_CHOIR_CAPTAIN, -87155, -147411, -9138, 33000);
		spawn(world, DARK_CHOIR_CAPTAIN, -87155, -147219, -9138, 33000);
		spawn(world, DARK_CHOIR_CAPTAIN, -87155, -146963, -9138, 33000);
		spawn(world, DARK_CHOIR_CAPTAIN, -87171, -146739, -9138, 33000);
		
		spawn(world, DARK_CHOIR_LANCER, -88467, -148467, -9170, 0);
		spawn(world, DARK_CHOIR_LANCER, -88467, -148403, -9170, 0);
		spawn(world, DARK_CHOIR_LANCER, -88467, -148339, -9170, 0);
		spawn(world, DARK_CHOIR_LANCER, -88467, -148271, -9170, 0);
		spawn(world, DARK_CHOIR_LANCER, -88471, -148199, -9170, 0);
		spawn(world, DARK_CHOIR_LANCER, -88499, -148435, -9170, 0);
		spawn(world, DARK_CHOIR_LANCER, -88503, -148375, -9170, 0);
		spawn(world, DARK_CHOIR_LANCER, -88499, -148307, -9170, 0);
		spawn(world, DARK_CHOIR_LANCER, -88503, -148239, -9170, 0);
		spawn(world, DARK_CHOIR_LANCER, -87427, -148191, -9170, 33000);
		spawn(world, DARK_CHOIR_LANCER, -87427, -148263, -9170, 33000);
		spawn(world, DARK_CHOIR_LANCER, -87427, -148331, -9170, 33000);
		spawn(world, DARK_CHOIR_LANCER, -87427, -148395, -9170, 33000);
		spawn(world, DARK_CHOIR_LANCER, -87427, -148467, -9170, 33000);
		spawn(world, DARK_CHOIR_LANCER, -87395, -148435, -9170, 33000);
		spawn(world, DARK_CHOIR_LANCER, -87395, -148371, -9170, 33000);
		spawn(world, DARK_CHOIR_LANCER, -87395, -148303, -9170, 33000);
		spawn(world, DARK_CHOIR_LANCER, -87395, -148227, -9170, 33000);
		spawn(world, DARK_CHOIR_LANCER, -87427, -145683, -9170, 33000);
		spawn(world, DARK_CHOIR_LANCER, -87427, -145747, -9170, 33000);
		spawn(world, DARK_CHOIR_LANCER, -87427, -145883, -9170, 33000);
		spawn(world, DARK_CHOIR_LANCER, -87427, -145819, -9170, 33000);
		spawn(world, DARK_CHOIR_LANCER, -87427, -145955, -9170, 33000);
		spawn(world, DARK_CHOIR_LANCER, -87395, -145715, -9170, 33000);
		spawn(world, DARK_CHOIR_LANCER, -87395, -145779, -9170, 33000);
		spawn(world, DARK_CHOIR_LANCER, -87395, -145859, -9170, 33000);
		spawn(world, DARK_CHOIR_LANCER, -87395, -145923, -9170, 33000);
		spawn(world, DARK_CHOIR_LANCER, -88463, -145971, -9170, 0);
		spawn(world, DARK_CHOIR_LANCER, -88467, -145899, -9170, 0);
		spawn(world, DARK_CHOIR_LANCER, -88467, -145827, -9170, 0);
		spawn(world, DARK_CHOIR_LANCER, -88467, -145763, -9170, 0);
		spawn(world, DARK_CHOIR_LANCER, -88471, -145699, -9170, 0);
		spawn(world, DARK_CHOIR_LANCER, -88495, -145939, -9170, 0);
		spawn(world, DARK_CHOIR_LANCER, -88499, -145863, -9170, 0);
		spawn(world, DARK_CHOIR_LANCER, -88499, -145795, -9170, 0);
		spawn(world, DARK_CHOIR_LANCER, -88499, -145731, -9170, 0);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -88708, -146105, -9152, 46242);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -88931, -146103, -9152, 15665);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -88846, -146548, -9152, 57906);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -88745, -146356, -9152, 47356);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -88867, -146608, -9152, 2847);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -88734, -146033, -9152, 249);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -88813, -146453, -9152, 34935);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -88773, -145967, -9152, 63174);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -88928, -146028, -9152, 43447);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -88918, -146165, -9152, 26885);
		spawn(world, DARK_CHOIR_ARCHER, -89207, -147428, -9156, 45072);
		spawn(world, DARK_CHOIR_ARCHER, -89018, -147611, -9156, 59002);
		spawn(world, DARK_CHOIR_ARCHER, -89053, -147079, -9156, 61936);
		spawn(world, DARK_CHOIR_ARCHER, -89158, -147440, -9156, 10110);
		spawn(world, DARK_CHOIR_ARCHER, -89047, -147321, -9156, 42674);
		spawn(world, DARK_CHOIR_ARCHER, -89102, -146927, -9156, 55423);
		spawn(world, DARK_CHOIR_ARCHER, -89238, -146461, -9156, 46669);
		spawn(world, DARK_CHOIR_ARCHER, -89074, -146800, -9156, 42740);
		spawn(world, DARK_CHOIR_ARCHER, -89080, -146722, -9156, 51097);
		spawn(world, DARK_CHOIR_ARCHER, -89094, -146927, -9156, 57530);
		spawn(world, DARK_CHOIR_WITCH_DOCTOR, -89292, -146968, -9156, 23921);
		spawn(world, DARK_CHOIR_WITCH_DOCTOR, -89098, -146973, -9156, 53398);
		spawn(world, DARK_CHOIR_WITCH_DOCTOR, -89364, -146683, -9156, 55886);
		spawn(world, DARK_CHOIR_WITCH_DOCTOR, -89137, -147813, -9156, 58589);
		spawn(world, DARK_CHOIR_WITCH_DOCTOR, -89031, -146677, -9156, 16478);
		spawn(world, DARK_CHOIR_WITCH_DOCTOR, -89248, -147458, -9156, 28103);
		spawn(world, DARK_CHOIR_WITCH_DOCTOR, -89192, -146584, -9156, 60165);
		spawn(world, DARK_CHOIR_WITCH_DOCTOR, -89267, -147106, -9156, 2957);
		spawn(world, DARK_CHOIR_WITCH_DOCTOR, -89100, -147886, -9156, 29995);
		spawn(world, DARK_CHOIR_WITCH_DOCTOR, -89233, -147463, -9156, 4825);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -88958, -147968, -9152, 27850);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -88924, -147685, -9152, 26191);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -88877, -147770, -9152, 12542);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -88663, -148105, -9152, 62369);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -88898, -147524, -9152, 49103);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -88826, -147954, -9152, 5382);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -88691, -148079, -9152, 10623);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -88900, -148144, -9152, 60510);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -88674, -148034, -9152, 48606);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -88780, -148206, -9152, 30841);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -87198, -148242, -9132, 2239);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -87006, -147837, -9132, 23704);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -87106, -147738, -9132, 20373);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -87024, -147805, -9132, 10273);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -87133, -147746, -9132, 63628);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -87200, -148138, -9132, 36796);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -87178, -147893, -9132, 53531);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -87018, -147727, -9132, 39064);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -87162, -148270, -9132, 44769);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -87232, -148216, -9132, 23745);
		spawn(world, DARK_CHOIR_ARCHER, -86848, -146626, -9140, 21800);
		spawn(world, DARK_CHOIR_ARCHER, -86898, -147680, -9140, 12664);
		spawn(world, DARK_CHOIR_ARCHER, -86803, -146525, -9140, 4869);
		spawn(world, DARK_CHOIR_ARCHER, -86809, -147543, -9140, 32242);
		spawn(world, DARK_CHOIR_ARCHER, -86682, -146528, -9140, 26051);
		spawn(world, DARK_CHOIR_ARCHER, -86843, -147847, -9140, 37485);
		spawn(world, DARK_CHOIR_ARCHER, -86793, -146556, -9140, 17726);
		spawn(world, DARK_CHOIR_ARCHER, -86594, -147369, -9140, 25664);
		spawn(world, DARK_CHOIR_ARCHER, -86729, -147721, -9140, 39674);
		spawn(world, DARK_CHOIR_ARCHER, -86706, -147356, -9140, 64275);
		spawn(world, DARK_CHOIR_WITCH_DOCTOR, -86892, -146732, -9140, 44902);
		spawn(world, DARK_CHOIR_WITCH_DOCTOR, -86972, -148050, -9140, 64642);
		spawn(world, DARK_CHOIR_WITCH_DOCTOR, -86822, -147296, -9140, 39669);
		spawn(world, DARK_CHOIR_WITCH_DOCTOR, -86748, -146511, -9140, 59277);
		spawn(world, DARK_CHOIR_WITCH_DOCTOR, -86811, -147359, -9140, 54652);
		spawn(world, DARK_CHOIR_WITCH_DOCTOR, -86930, -146945, -9140, 16040);
		spawn(world, DARK_CHOIR_WITCH_DOCTOR, -86741, -147577, -9140, 53106);
		spawn(world, DARK_CHOIR_WITCH_DOCTOR, -86614, -146629, -9140, 36495);
		spawn(world, DARK_CHOIR_WITCH_DOCTOR, -86899, -146940, -9140, 62921);
		spawn(world, DARK_CHOIR_WITCH_DOCTOR, -86650, -146646, -9140, 56177);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -87162, -146112, -9132, 59727);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -87187, -146185, -9132, 21514);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -87308, -146022, -9132, 22939);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -87152, -146145, -9132, 20344);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -87235, -146167, -9132, 12091);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -86976, -146437, -9132, 17215);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -86990, -146411, -9132, 12879);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -86957, -146378, -9132, 28758);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -87042, -146025, -9132, 26909);
		spawn(world, DARK_CHOIR_PRIMA_DONNA, -87142, -146307, -9132, 17233);
	}
	
	protected boolean controlStatus(FETWorld world)
	{
		if (world.lock.tryLock())
		{
			try
			{
				if (DEBUG)
				{
					_log.info("[Final Emperial Tomb] Starting " + world.getStatus() + ". status.");
				}
				switch (world.getStatus())
				{
					case 0:
						spawnHallAlarm(world);
						break;
					case 1:
						if (ASSERT) if (!(world.npcList.size() == 0)) throw new RuntimeException("npcList.size()=" + world.npcList.size());
						spawnDarkPlayers(world);
						break;
					case 2:
						ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(world, 0), 600000);
						break;
					case 3:
						ThreadPoolManager.getInstance().executeTask(new IntroTask(world, 200));
						break;
					case 4:
						ThreadPoolManager.getInstance().executeTask(new IntroTask(world, 300));
						break;
					case 5:
						ThreadPoolManager.getInstance().executeTask(new IntroTask(world, 400));
						break;
					case 6:
						InstanceManager.getInstance().getInstance(world.getInstanceId()).setDuration(300000);
						openDoors(FIRST_ROOM_DOORS, world.getInstanceId());
						openDoors(FIRST_ROUTE_DOORS, world.getInstanceId());
						openDoors(SECOND_ROUTE_DOORS, world.getInstanceId());
						openDoors(SECOND_ROOM_DOORS, world.getInstanceId());
						break;
					default:
						if (ASSERT) throw new RuntimeException("status=" + world.getStatus());
				}
				world.incStatus();
				return true;
			}
			finally
			{
				world.lock.unlock();
			}
		}
		return false;
	}
	
	private void spawn(FETWorld world, int npcId, int x, int y, int z, int h)
	{
		L2Npc npc = addSpawn(npcId, x, y, z, h, false, 0, false, world.getInstanceId());
		if (Arrays.binarySearch(MUST_KILL_MOBS, npcId) >= 0)
		{
			world.npcList.add(npc);
			world.npcMax = world.npcList.size();
			npc.setIsNoRndWalk(true);
		}
		if (npc.isInstanceTypes(InstanceType.L2Attackable))
		{
			((L2Attackable) npc).setSeeThroughSilentMove(true);
		}
		if (Util.contains(AI_DISABLED_MOBS, npcId))
		{
			npc.disableCoreAI(true);
		}
		if (npcId == DARK_CHOIR_PLAYER)
		{
			++world.darkChoirPlayerCount;
		}
	}
	
	protected boolean isZZZ(L2Character character)
	{
		return character.isStunned() || character.isSleeping() || character.isParalyzed();
	}
	
	private boolean isZZZ(Skill skill)
	{
		switch (skill.getAbnormalType())
		{
			case STUN:
			case SLEEP:
			case PARALYZE:
				return true;
		}
		return false;
	}
	
	private class SongTask implements Runnable/*テスト済*/
	{
		private final FETWorld _world;
		
		SongTask(FETWorld world)
		{
			_world = world;
		}
		
		@Override
		public void run()
		{
			if (InstanceManager.getInstance().getWorld(_world.getInstanceId()) != _world)
			{
				return;
			}
			if ((_world.frintezza == null) || _world.frintezza.isDead() || !_world.frintezza.isVisible())
			{
				return;
			}
			if (isZZZ(_world.frintezza))
			{
				_world.songTask = ThreadPoolManager.getInstance().scheduleGeneral(SongTask.this, 1000);
				return;
			}
			if (_world.isVideo)
			{
				_world.songTask = ThreadPoolManager.getInstance().scheduleGeneral(SongTask.this, 1000);
				return;
			}
			
			// new song play
			int rnd = getRandom(100);
			for (FrintezzaSong song : FRINTEZZA_SONG_LIST)
			{
				if (rnd < song.chance)
				{
					Skill skill = SkillData.getInstance().getSkill(song.songId, song.songLevel);
					broadcastSongTitle(_world, song.songName);
					broadcastPacket(_world, new MagicSkillUse(_world.frintezza, _world.frintezza, skill.getId(), skill.getLevel(), skill.getHitTime(), 0));
					doSongEffect(song.effectId, song.effectLevel);
					_world.songTask = ThreadPoolManager.getInstance().scheduleGeneral(SongTask.this, skill.getHitTime() + getRandom(5000));
					break;
				}
			}
		}
		
		public void doSongEffect(int effectId, int effectLevel)
		{
			// Frintezza song effect
			if ((_world.activeScarlet == null) || _world.activeScarlet.isDead() || !_world.activeScarlet.isVisible())
			{
				return;
			}
			if (_world.isVideo)
			{
				return;
			}
			
			_world.activeScarlet.doCast(SkillData.getInstance().getSkill(effectId, effectLevel));
		}
	}
	
	//[JOJO]-------------------------------------------------
	private static class SpecialCamera extends com.l2jserver.gameserver.network.serverpackets.SpecialCamera
	{
		public SpecialCamera(L2Character creature, int dist, int yaw, int pitch, int time, int duration, int turn, int rise, int widescreen, int heading, int unkonown)
		{
			super(creature.getObjectId(), dist, yaw, pitch, time, duration, turn, rise, widescreen, heading, unkonown);
		}
	}
	//-------------------------------------------------------
	
	private class IntroTask implements Runnable
	{
		private final FETWorld _world;
		private final int _taskId;
		
		IntroTask(FETWorld world, int taskId)
		{
			_world = world;
			_taskId = taskId;
		}
//TODO:	void scheduleNextTask(int taskId, long delay)
//		{
//			_taskId = taskId;
//			ThreadPoolManager.getInstance().scheduleGeneral(this, delay);
//		}
		
		@Override
		public void run()
		{
			switch (_taskId)
			{
				/********************/
				/* SPAWN DAEMON 1ST */
				/********************/
				case 0:
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 1), 28000);
					broadcastPacket(_world, new Earthquake(-87780, -155086, -9080, 45, 27));
					
					_world.frintezza = (L2GrandBossInstance) addSpawn(FRINTEZZA, -88595, -153695, -7446, 16384, false, 0, false, _world.getInstanceId());
					_world.frintezza.setIsImmobilized(true);
					_world.frintezza.setIsInvul(true);
					_world.frintezza.disableAllSkills();
					_world.frintezza.disableCoreAI(true);
					_world.frintezza.getSpawn().setXYZ(-87780, -155086, -9080);
					updateKnownList(_world, _world.frintezza);
					
					_world.activeScarlet = (L2GrandBossInstance) addSpawn(SCARLET1, -88595, -153695, -7446, 16384, false, 0, false, _world.getInstanceId());
					_world.activeScarlet.setIsImmobilized(true);
					_world.activeScarlet.setIsInvul(true);
					_world.activeScarlet.disableAllSkills();
					_world.activeScarlet.disableCoreAI(true);
					_world.activeScarlet.getSpawn().setXYZ(ROOM3_CENTER_X, ROOM3_CENTER_Y, ROOM3_CENTER_Z);
					_world.activeScarlet.setOnKillDelay(100);
					updateKnownList(_world, _world.activeScarlet);
					
					_world.frintezzaDummy = addSpawn(CAMERA_DUMMY, -87780, -155086, -9080, 16384, false, 0, false, _world.getInstanceId());
					_world.frintezzaDummy.setIsInvul(true);
					updateKnownList(_world, _world.frintezzaDummy);
					
					_world.portraitDummy1 = addSpawn(CAMERA_DUMMY, -89566, -153168, -9165, 16048, false, 0, false, _world.getInstanceId());
					_world.portraitDummy1.setIsInvul(true);
					updateKnownList(_world, _world.portraitDummy1);
					
					_world.portraitDummy3 = addSpawn(CAMERA_DUMMY, -86004, -153168, -9165, 16048, false, 0, false, _world.getInstanceId());
					_world.portraitDummy3.setIsInvul(true);
					updateKnownList(_world, _world.portraitDummy3);
					
					_world.scarletDummy = addSpawn(DIMENSIONAL_SHOCK, -87789, -153295, -9176, 16384, false, 0, false, _world.getInstanceId());
					_world.scarletDummy.setIsInvul(true);
					updateKnownList(_world, _world.scarletDummy);
					break;
				case 1:
					closeDoors(FIRST_ROOM_DOORS, _world.getInstanceId());
					closeDoors(FIRST_ROUTE_DOORS, _world.getInstanceId());
					closeDoors(SECOND_ROOM_DOORS, _world.getInstanceId());
					closeDoors(SECOND_ROUTE_DOORS, _world.getInstanceId());
					for (L2Npc n : _world.npcList)
					{
						n.deleteMe();
					}
					_world.npcList.clear();
					addSpawn(CUBE, -87904, -141296, -9168, 0, false, 0, false, _world.getInstanceId());
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 2), 1000);
					break;
				case 2:
					_world.isVideo = true;
					stopNpc();
					stopPc();
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 3), 1000);
					break;
				case 3:
					broadcastPacket(_world, new SpecialCamera(_world.scarletDummy, 0, 120, -89, 0, 100, 0, 0, 1, 0, 0));
					broadcastPacket(_world, new SpecialCamera(_world.scarletDummy, 0, 120, -89, 0, 100, 0, 0, 1, 0, 0));
					broadcastPacket(_world, new SpecialCamera(_world.scarletDummy, 300, 90, 50, 6500, 7000, 0, 50, 1, 0, 0));
					
					_world.frintezza.setXYZ(_world.frintezza.getSpawn());
					broadcastPacket(_world, new ValidateLocation(_world.frintezza));
					
					for (int i = 0; i < 4; ++i)
					{
						L2NpcPosition gs = GHOST_SPAWNS[i];
						L2MonsterInstance ghost = _world.ghosts[i] = (L2MonsterInstance) addSpawn(gs.npcId, gs, false, 0, false, _world.getInstanceId());
						ghost.setIsImmobilized(true);
						ghost.setIsNoRndWalk(true);
						ghost.disableAllSkills();
						updateKnownList(_world, ghost);
						
						L2Spawn spawn = ghost.getSpawn();
						spawn.setAmount(1);
						spawn.setRespawnDelay(GHOST_RESPAWN_DELAY);//TODO: spawn.setRespawnDelay(0);
						spawn.startRespawn();
					}
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 4), 6500);
					break;
				case 4:
					broadcastPacket(_world, new SpecialCamera(_world.frintezzaDummy, 1800, 90, 8, 6500, 7000, 0, 0, 1, 0, 0));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 5), 900);
					break;
				case 5:
					broadcastPacket(_world, new SpecialCamera(_world.frintezzaDummy, 140, 90, 10, 2500, 4500, 0, 0, 1, 0, 0));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 6), 4000);
					break;
				case 6:
					broadcastPacket(_world, new SpecialCamera(_world.frintezza, 40, 75, -10, 0, 1000, 0, 0, 1, 0, 0));
					broadcastPacket(_world, new SpecialCamera(_world.frintezza, 40, 75, -10, 0, 12000, 0, 0, 1, 0, 0));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 7), 1000);
					break;
				case 7:
					broadcastPacket(_world, new SocialAction(_world.frintezza.getObjectId(), 2));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 9), 5000);
					break;
				case 9:
					broadcastPacket(_world, new SocialAction(_world.ghosts[1].getObjectId(), 1));
					broadcastPacket(_world, new SocialAction(_world.ghosts[2].getObjectId(), 1));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 10), 400);
					break;
				case 10:
					broadcastPacket(_world, new SocialAction(_world.ghosts[0].getObjectId(), 1));
					broadcastPacket(_world, new SocialAction(_world.ghosts[3].getObjectId(), 1));
					sendPacketX(new SpecialCamera(_world.portraitDummy1, 1000, 118, 0, 0, 1000, 0, 0, 1, 0, 0), new SpecialCamera(_world.portraitDummy3, 1000, 62, 0, 0, 1000, 0, 0, 1, 0, 0), -87784);
					sendPacketX(new SpecialCamera(_world.portraitDummy1, 1000, 118, 0, 0, 10000, 0, 0, 1, 0, 0), new SpecialCamera(_world.portraitDummy3, 1000, 62, 0, 0, 10000, 0, 0, 1, 0, 0), -87784);
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 11), 2000);
					break;
				case 11:
					broadcastPacket(_world, new SpecialCamera(_world.frintezza, 240, 90, 0, 0, 1000, 0, 0, 1, 0, 0));
					broadcastPacket(_world, new SpecialCamera(_world.frintezza, 240, 90, 25, 5500, 10000, 0, 0, 1, 0, 0));
					broadcastPacket(_world, new SocialAction(_world.frintezza.getObjectId(), 3));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 12), 3000);
					break;
				case 12:
					broadcastPacket(_world, new SpecialCamera(_world.frintezza, 100, 195, 35, 0, 10000, 0, 0, 1, 0, 0));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 13), 300);
					break;
				case 13:
					broadcastPacket(_world, new SpecialCamera(_world.frintezza, 100, 195, 35, 0, 10000, 0, 0, 1, 0, 0));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 14), 300);
					break;
				case 14:
					broadcastPacket(_world, new SpecialCamera(_world.frintezza, 120, 180, 45, 1500, 10000, 0, 0, 1, 0, 0));
					broadcastSongTitle(_world, NpcStringId.RONDO_OF_SOLITUDE); // RONDO_OF_SOLITUDE ? MOURNFUL_CHORALE_PRELUDE ?
					broadcastPacket(_world, new MagicSkillUse(_world.frintezza, _world.frintezza, 5006, 1, 34000, 0));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 15), 1500);
					break;
				case 15:
					broadcastPacket(_world, new SpecialCamera(_world.frintezza, 520, 135, 45, 8000, 10000, 0, 0, 1, 0, 0));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 16), 7500);
					break;
				case 16:
					broadcastPacket(_world, new SpecialCamera(_world.frintezza, 1500, 110, 25, 10000, 13000, 0, 0, 1, 0, 0));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 17), 9500);
					break;
				case 17:
					broadcastPacket(_world, new SpecialCamera(_world.scarletDummy, 930, 160, 0, 0, 1000, 0, 20, 1, 0, 0));
					broadcastPacket(_world, new SpecialCamera(_world.scarletDummy, 600, 180, 0, 0, 10000, 0, 30, 1, 0, 0));
					broadcastPacket(_world, new MagicSkillUse(_world.scarletDummy, _world.scarletDummy, 5004, 1, 5800, 0));
					
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 18), 2500);
					break;
				case 18:
					_world.activeScarlet.setXYZ(_world.activeScarlet.getSpawn());
					broadcastPacket(_world, new ValidateLocation(_world.activeScarlet));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 19), 2000);
					break;
				case 19:
					broadcastPacket(_world, new SocialAction(_world.activeScarlet.getObjectId(), 3));
					broadcastPacket(_world, new SpecialCamera(_world.scarletDummy, 800, 180, 10, 1000, 10000, 0, 0, 1, 0, 0));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 20), 1500);
					break;
				case 20:
					updateKnownList(_world, _world.scarletDummy);
					throwUp(_world.scarletDummy, 500, SystemMessage.getSystemMessage(SystemMessageId.YOU_FEEL_S1_EFFECT).addSkillName(5004, 1));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 21), 2600);
					break;
				case 21:
					broadcastPacket(_world, new SpecialCamera(_world.scarletDummy, 300, 60, 8, 0, 10000, 0, 0, 1, 0, 0));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 22), 2000);
					break;
				case 22:
					broadcastPacket(_world, new SpecialCamera(_world.activeScarlet, 500, 90, 10, 3000, 5000, 0, 0, 1, 0, 0));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 23), 3000);
					break;
				case 23:
					for (int i = 0; i < 4; ++i)
					{
						L2NpcPosition ps = PORTRAIT_SPAWNS[i];
						L2MonsterInstance portrait = _world.portraits[i] = (L2MonsterInstance) addSpawn(ps.npcId, ps, false, 0, false, _world.getInstanceId());
						updateKnownList(_world, portrait);
					}
					
					startPc();
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 24), 10000);
					break;
				case 24:
					_world.scarletDummy.deleteMe(); _world.scarletDummy = null;
					_world.portraitDummy3.deleteMe(); _world.portraitDummy3 = null;
					_world.portraitDummy1.deleteMe(); _world.portraitDummy1 = null;
					_world.frintezzaDummy.deleteMe(); _world.frintezzaDummy = null;
					
					_world.activeScarlet.disableCoreAI(false);
					_world.activeScarlet.enableAllSkills();
					_world.activeScarlet.setIsInvul(false);
					_world.activeScarlet.setIsImmobilized(false);
					_world.activeScarlet.setRunning();
					
					_world.frintezza.setIsInvul(false);
					_world.frintezza.setIsMortal(false);
					_world.songTask = ThreadPoolManager.getInstance().scheduleGeneral(new SongTask(_world), 5000);	//+
					
					startNpc();
					levelUpScarletSkills(_world.activeScarlet, 1);
					_world.isVideo = false;
					break;
				/********************/
				/* MORPH DAEMON 2ND */
				/********************/
				case 200:
					_world.activeScarlet.setIsInvul(true);
					if (_world.activeScarlet.isCastingNow())
					{
						_world.activeScarlet.abortCast();
					}
					setInstanceTimeRestrictions(_world);
					_world.activeScarlet.doCast(SkillData.getInstance().getSkill(5017, 1));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 201), 1500);
					break;
				case 201:
					_world.activeScarlet.setRHandId(SECOND_SCARLET_WEAPON);
					_world.activeScarlet.setIsInvul(false);
					levelUpScarletSkills(_world.activeScarlet, 2);
					break;
				/********************/
				/* MORPH DAEMON 3RD */
				/********************/
				case 300:
					_world.isVideo = true;
					_world.activeScarlet.setIsInvul(true);
					stopNpc();
					stopPc();
					_world.activeScarlet.abortAttack();
					_world.activeScarlet.abortCast();
					_world.activeScarlet.setIsImmobilized(true);
					_world.activeScarlet.disableAllSkills();
					broadcastPacket(_world, new SpecialCamera(_world.frintezza, 250, 120, 15, 0, 1000, 0, 0, 1, 0, 0));
					broadcastPacket(_world, new SpecialCamera(_world.frintezza, 250, 120, 15, 0, 10000, 0, 0, 1, 0, 0));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 301), 1000);
					//
					if (Util.calculateDistance(_world.activeScarlet, _world.activeScarlet.getSpawn(), false, false) > 1200) {
						_world.activeScarlet.setHeading(Util.calculateHeadingFrom(_world.activeScarlet, _world.activeScarlet.getSpawn()));
						broadcastPacket(_world, new ValidateLocation(_world.activeScarlet));
					}
					break;
				case 301:
					_world.frintezza.stopAllEffects();
					broadcastPacket(_world, new MagicSkillCanceld(_world.frintezza.getObjectId()));
					broadcastPacket(_world, new SocialAction(_world.frintezza.getObjectId(), 4));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 302), 4000);
					break;
				case 302:
					broadcastPacket(_world, new MagicSkillUse(_world.frintezza, _world.frintezza, 5006, 1, 34000, 0));
					broadcastPacket(_world, new SpecialCamera(_world.frintezza, 500, 70, 15, 3000, 10000, 0, 0, 1, 0, 0));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 303), 3000);
					break;
				case 303:
					broadcastPacket(_world, new SpecialCamera(_world.frintezza, 2500, 90, 12, 6000, 10000, 0, 0, 1, 0, 0));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 304), 3000);
					break;
				case 304:
					_world.scarlet_x = _world.activeScarlet.getX();
					_world.scarlet_y = _world.activeScarlet.getY();
					_world.scarlet_z = _world.activeScarlet.getZ();
					_world.scarlet_h = _world.activeScarlet.getHeading();
					_world.scarlet_a = Util.calcCameraAngle(_world.activeScarlet);
					broadcastPacket(_world, new SpecialCamera(_world.activeScarlet, 250, _world.scarlet_a, 12, 0, 1000,  0, 0, 1, 0, 0));
					broadcastPacket(_world, new SpecialCamera(_world.activeScarlet, 250, _world.scarlet_a, 12, 0, 10000, 0, 0, 1, 0, 0));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 305), 500);
					break;
				case 305:
					_world.activeScarlet.doDie(_world.activeScarlet);
					broadcastPacket(_world, new SpecialCamera(_world.activeScarlet, 450, _world.scarlet_a, 14, 8000, 8000, 0, 0, 1, 0, 0));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 306), 6250);
					break;
				case 306:
					_world.activeScarlet.deleteMe();
					_world.activeScarlet = null;
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 307), 950);
					break;
				case 307:
					_world.activeScarlet = (L2GrandBossInstance) addSpawn(SCARLET2, _world.scarlet_x, _world.scarlet_y, _world.scarlet_z, _world.scarlet_h, false, 0, false, _world.getInstanceId());
					_world.activeScarlet.setIsImmobilized(true);
					_world.activeScarlet.setIsInvul(true);
					_world.activeScarlet.disableAllSkills();
					_world.activeScarlet.disableCoreAI(true);
					_world.activeScarlet.getSpawn().setXYZ(ROOM3_CENTER_X, ROOM3_CENTER_Y, ROOM3_CENTER_Z);
					_world.activeScarlet.setOnKillDelay(100);
					updateKnownList(_world, _world.activeScarlet);
					
					broadcastPacket(_world, new SpecialCamera(_world.activeScarlet, 450, _world.scarlet_a, 12, 500, 14000, 0, 0, 1, 0, 0));
					
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 308), 5000);
					break;
				case 308:
					broadcastPacket(_world, new SocialAction(_world.activeScarlet.getObjectId(), 2));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 309), 5000);
					break;
				case 309:
					startPc();
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 310), 10000);
					break;
				case 310:
					_world.activeScarlet.disableCoreAI(false);
					_world.activeScarlet.enableAllSkills();
					_world.activeScarlet.setIsInvul(false);
					_world.activeScarlet.setIsImmobilized(false);
					startNpc();
					levelUpScarletSkills(_world.activeScarlet, 3);
					_world.isVideo = false;
					break;
				/********************/
				/*    DIE DAEMON    */
				/********************/
				case 400:
					_world.isVideo = true;
					stopNpc();
					stopPc();
					if (_world.songTask != null)
					{
						_world.songTask.cancel(true);
						_world.songTask = null;
					}
					_world.scarlet_a = Util.calcCameraAngle(_world.activeScarlet);
					broadcastPacket(_world, new MagicSkillCanceld(_world.frintezza.getObjectId()));
					broadcastPacket(_world, new SpecialCamera(_world.activeScarlet, 300, _world.scarlet_a - 180, 5, 0, 7000, 0, 0, 1, 0, 0));
					broadcastPacket(_world, new SpecialCamera(_world.activeScarlet, 200, _world.scarlet_a, 85, 4000, 10000, 0, 0, 1, 0, 0));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 401), 7400);
					break;
				case 401:
					_world.frintezza.doDie(_world.frintezza);
					for (int i = 0; i < 4; ++i)
					{
						L2MonsterInstance portrait = _world.portraits[i];
						if (portrait != null)
						{
							portrait.deleteMe();
							_world.portraits[i] = null;
						}
						L2MonsterInstance ghost = _world.ghosts[i];
						if (ghost != null)
						{
							ghost.getSpawn().stopRespawn();
						}
					}
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 402), 100);
					break;
				case 402:
					broadcastPacket(_world, new SpecialCamera(_world.frintezza, 100, 120, 5, 0, 7000, 0, 0, 1, 0, 0));
					broadcastPacket(_world, new SpecialCamera(_world.frintezza, 100, 90, 5, 5000, 15000, 0, 0, 1, 0, 0));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 403), 7000);
					break;
				case 403:
					broadcastPacket(_world, new SpecialCamera(_world.frintezza, 900, 90, 25, 7000, 10000, 0, 0, 1, 0, 0));
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 404), 9000);
					break;
				case 404:
					if (ASSERT) if (!(_world.getStatus() == 6)) throw new RuntimeException("status=" + _world.getStatus());
					controlStatus(_world);
					startPc();
					ThreadPoolManager.getInstance().scheduleGeneral(new IntroTask(_world, 405), 10000);
					break;
				case 405:
					startNpc();
					_world.isVideo = false;
					break;
				default:
					if (ASSERT) throw new RuntimeException("_taskId=" + _taskId);
			}
		}
		
		private void stopNpc(L2MonsterInstance npc)/*テスト済*/
		{
			npc.abortAttack();
			npc.abortCast();
			npc.disableAllSkills();
			npc.setTarget(null);
			npc.stopMove(null);
			npc.setIsImmobilized(true);
			if (npc.hasAI())
			{
				npc.getAI().setIntention(AI_INTENTION_IDLE);
			}
		}
		
		private void startNpc(L2MonsterInstance npc)/*テスト済*/
		{
			npc.setIsImmobilized(false);
			npc.enableAllSkills();
		}
		
		private void stopNpc()/*テスト済*/
		{
			final int instanceId = _world.getInstanceId();
			L2ZoneType zone = ZoneManager.getInstance().getZoneById(ROOM3_ZONE);
			
			for (L2Character c : zone.getCharactersInside())
			{
				if ((c == null) || (c.getInstanceId() != instanceId) || c.isDead() || !c.isVisible())
				{
					continue;
				}
				if (c.isImmobilized())
				{
					continue;
				}
				if (c.isAllSkillsDisabled())
				{
					continue;
				}
				if (c instanceof L2MonsterInstance)
				{
					L2MonsterInstance monster = (L2MonsterInstance) c;
					stopNpc(monster);
					monster.setBusyMessage("STOP");
				}
			}
		}
		
		private boolean isActiveMinion(L2MonsterInstance npc)/*テスト済*/
		{
			switch (npc.getId())
			{
				case GHOST_FIGHTER:
				case GHOST_MAGE:
				case PORTRAIT_FIGHTER:
				case PORTRAIT_MAGE:
					return true;
				default:
					return false;
			}
		}
		
		private void startNpc()/*テスト済*/
		{
			final int instanceId = _world.getInstanceId();
			L2ZoneType zone = ZoneManager.getInstance().getZoneById(ROOM3_ZONE);
			
			for (L2Character c : zone.getCharactersInside())
			{
				if ((c == null) || (c.getInstanceId() != instanceId) || c.isDead() || !c.isVisible())
				{
					continue;
				}
				if (c instanceof L2MonsterInstance)
				{
					L2MonsterInstance monster = (L2MonsterInstance) c;
					if ((monster.getBusyMessage() == "STOP") || isActiveMinion(monster))
					{
						monster.setBusyMessage(null);
						startNpc(monster);
					}
				}
			}
		}
		
		private void stopPc()/*テスト済*/
		{
			for (int objId : _world.getAllowed())
			{
				L2PcInstance player = L2World.getInstance().getPlayer(objId);
				if ((player != null) && player.isOnline() && (player.getInstanceId() == _world.getInstanceId()))
				{
					player.abortAttack();
					player.abortCast();
					player.disableAllSkills();
					player.setTarget(null);
					player.stopMove(null);
					player.setIsImmobilized(true);
					player.getAI().setIntention(AI_INTENTION_IDLE);
				}
			}
		}
		
		private void startPc()/*テスト済*/
		{
			for (int objId : _world.getAllowed())
			{
				L2PcInstance player = L2World.getInstance().getPlayer(objId);
				if ((player != null) && player.isOnline() && (player.getInstanceId() == _world.getInstanceId()))
				{
					player.enableAllSkills();
					player.setIsImmobilized(false);
				}
			}
		}
		
		private void sendPacketX(L2GameServerPacket packet1, L2GameServerPacket packet2, int x)/*テスト済*/
		{
			for (int objId : _world.getAllowed())
			{
				L2PcInstance player = L2World.getInstance().getPlayer(objId);
				if ((player != null) && player.isOnline() && (player.getInstanceId() == _world.getInstanceId()))
				{
					if (player.getX() < x)
					{
						player.sendPacket(packet1);
					}
					else
					{
						player.sendPacket(packet2);
					}
				}
			}
		}
	}
	
	private class OnKillHallAlarmTask implements Runnable/*テスト済*/
	{
		private final FETWorld _world;
		private int _taskId;
		
		OnKillHallAlarmTask(FETWorld world)
		{
			_world = world;
			_taskId = 0;
		}
		
		void scheduleNextTask(int taskId, long delay)
		{
			_taskId = taskId;
			ThreadPoolManager.getInstance().scheduleGeneral(this, delay);
		}
		
		@Override
		public void run()
		{
			if (InstanceManager.getInstance().getWorld(_world.getInstanceId()) != _world)
			{
				return;
			}
			switch (_taskId)
			{
				case 0:
					spawnHallKeepers(_world);
					scheduleNextTask(1, 1000);
					break;
				case 1:
					openDoors(FIRST_ROOM_DOORS, _world.getInstanceId());
					scheduleNextTask(2, 1000);
					break;
				case 2:
					addAggroToMobs(_world, ROOM1_CENTER_X, ROOM1_CENTER_Y, ROOM1_CENTER_Z);
					break;
			}
		}
	}
	
	private class OnKillDarkChoirPlayerTask implements Runnable/*テスト済*/
	{
		private final FETWorld _world;
		private int _taskId;
		
		OnKillDarkChoirPlayerTask(FETWorld world)
		{
			_world = world;
			_taskId = 0;
		}
		
		void scheduleNextTask(int taskId, long delay)
		{
			_taskId = taskId;
			ThreadPoolManager.getInstance().scheduleGeneral(this, delay);
		}
		
		@Override
		public void run()
		{
			if (InstanceManager.getInstance().getWorld(_world.getInstanceId()) != _world)
			{
				return;
			}
			switch (_taskId)
			{
				case 0:
					closeDoors(SECOND_ROUTE_DOORS, _world.getInstanceId());
					spawnDarkChoirs(_world);
					scheduleNextTask(1, 1000);
					break;
				case 1:
					openDoors(SECOND_ROOM_DOORS, _world.getInstanceId());
					scheduleNextTask(2, 1000);
					break;
				case 2:
					for (L2Npc actor : _world.npcList)
					{
						if (actor.getId() == DARK_CHOIR_CAPTAIN)
						{
							// 1010645 黒聖歌団の演奏を妨げる邪魔者を消せ！
							// 1010646 死の演奏が聞こえないのか！黒聖歌団の恐ろしさを見せてやれ！
							// 1010644 黒聖歌団のステージをぶち壊すとは．．．許せぬ！
							int npcstring = getRandom(1010644, 1010646);
							actor.broadcastPacket(new NpcSay(actor.getObjectId(), Say2.SHOUT, actor.getId(), npcstring));
							break;
						}
					}
					addAggroToMobs(_world, ROOM2_CENTER_X, ROOM2_CENTER_Y, ROOM2_CENTER_Z);
					break;
			}
		}
	}
	
	protected void addAggroToMobs(FETWorld _world, int x, int y, int z)/*テスト済*/
	{
		L2PcInstance target = L2World.getInstance().getPlayer(_world.getAllowed().get(getRandom(_world.getAllowed().size())));
		if ((target == null) || (target.getInstanceId() != _world.getInstanceId()) || target.isDead() || target.isFakeDeath())
		{
			for (int objId : _world.getAllowed())
			{
				target = L2World.getInstance().getPlayer(objId);
				if ((target != null) && (target.getInstanceId() == _world.getInstanceId()) && !target.isDead() && !target.isFakeDeath())
				{
					break;
				}
				target = null;
			}
		}
		for (L2Npc mob : _world.npcList)
		{
			if (Util.contains(NO_AGGRO_MOBS, mob.getId()))
			{
				continue;
			}
			if ((mob.getAI().getIntention() != AI_INTENTION_ACTIVE) && (mob.getAI().getIntention() != AI_INTENTION_IDLE) && mob.isInCombat())
			{
				continue;
			}
			mob.setRunning();
			if (target != null)
			{
				((L2MonsterInstance) mob).addDamageHate(target, 0, 500);
				mob.getAI().setIntention(AI_INTENTION_ATTACK, target);
			}
			else
			{
				mob.getAI().setIntention(AI_INTENTION_MOVE_TO, new Location(x, y, z, 0));/* TODO:一点に集中しておだんごになってしまう */
			}
		}
	}
	
	protected void setInstanceTimeRestrictions(FETWorld world)/*テスト済*/
	{
		long now = System.currentTimeMillis();
		GregorianCalendar reenter = new GregorianCalendar();
		reenter.setTimeInMillis(now);
		reenter.set(Calendar.MILLISECOND, 0);
		reenter.set(Calendar.SECOND, 0);
		reenter.set(Calendar.MINUTE, RESET_MINUTE);
		reenter.set(Calendar.HOUR_OF_DAY, RESET_HOUR_OF_DAY);
		// if time is >= RESET_HOUR - roll to the next day
		if (reenter.getTimeInMillis() <= now)
		{
			reenter.add(Calendar.DAY_OF_MONTH, 1);
		}
		while (!Util.contains(RESET_DAY_OF_WEEK, reenter.get(Calendar.DAY_OF_WEEK)))
		{
			reenter.add(Calendar.DAY_OF_MONTH, 1);
		}
		
		SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.INSTANT_ZONE_S1_RESTRICTED);
		sm.addInstanceName(INSTANCEID);
		
		// set instance reenter time for all allowed players
		for (int objectId : world.getAllowed())
		{
			L2PcInstance player = L2World.getInstance().getPlayer(objectId);
			InstanceManager.getInstance().setInstanceTime(objectId, INSTANCEID, reenter.getTimeInMillis());
			if ((player != null) && player.isOnline())
			{
				player.sendPacket(sm);
			}
		}
	}
	
	protected void broadcastPacket(FETWorld world, L2GameServerPacket packet)
	{
		for (int objId : world.getAllowed())
		{
			L2PcInstance player = L2World.getInstance().getPlayer(objId);
			if ((player != null) && player.isOnline() && (player.getInstanceId() == world.getInstanceId()))
			{
				player.sendPacket(packet);
			}
		}
	}
	
	protected void broadcastSongTitle(FETWorld world, NpcStringId song)/*テスト済*/
	{
		broadcastPacket(world, new ExShowScreenMessage(/* type= */2, /* messageId= */-1, /* position= */2, /* unk1= */0, /* size= */0, /* unk2= */0, /* unk3= */0, /* showEffect= */true, /* time= */4000, /* fade= */false, /* text= */null, song));
	}
	
	protected void updateKnownList(FETWorld world, L2Npc npc)
	{
		NpcKnownList npcKnownList = npc.getKnownList();
		npcKnownList.distanceToWatchObject = 3800;
		npcKnownList.distanceToForgetObject = 4500;
		for (int objId : world.getAllowed())
		{
			L2PcInstance player = L2World.getInstance().getPlayer(objId);
			if ((player != null) && player.isOnline() && (player.getInstanceId() == world.getInstanceId()))
			{
				npcKnownList.addKnownObject(player);
				player.getKnownList().addKnownObject(npc);
			}
		}
	}
	
	protected void throwUp(L2Character attacker, final double range, SystemMessage msg)/*テスト済*/
	{
		final int mx = attacker.getX(), my = attacker.getY();
		for (L2Object obj : attacker.getKnownList().getKnownObjects().values())
		{
			if (!(obj instanceof L2Character))
			{
				continue;
			}
			L2Character target = (L2Character) obj;
			if ((obj == attacker) || isFrintezzaFriend(target))
			{
				continue;
			}
			double dx = target.getX() - mx;
			double dy = target.getY() - my;
			if ((dx == 0) && (dy == 0))
			{
				dx = dy = range / 2;
			}
			double aa = range / Math.sqrt((dx * dx) + (dy * dy));
			if (aa > 1.0)
			{
				int x = mx + (int) (dx * aa);
				int y = my + (int) (dy * aa);
				int z = target.getZ();
				
				target.getAI().setIntention(AI_INTENTION_IDLE);
				target.abortAttack();
				target.abortCast();
				
				target.broadcastPacket(new FlyToLocation(target, x, y, z, FlyType.THROW_UP));
				target.setXYZ(x, y, z);
				target.setHeading(Util.calculateHeadingFrom(x, y, mx, my));
				target.broadcastPacket(new ValidateLocation(target));
				if (msg != null)
				{
					target.sendPacket(msg);
				}
				if (target instanceof L2PcInstance)
				{
					((L2PcInstance) target).standUp();
				}
			}
		}
	}
	
	private boolean isFrintezzaFriend(L2Object target)/*テスト済*/
	{
		if (target instanceof L2Npc)
		{
			int npcId = ((L2Npc) target).getId();
			return (npcId >= 29045) && (npcId <= 29053);
		}
		return false;
	}
	
	@Override
	public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon, Skill skill)
	{
		final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
		if (tmpworld instanceof FETWorld)
		{
			final FETWorld world = (FETWorld) tmpworld;
			if (DETECT_ACTION_LOCK)
			{
				world.lastAction = System.currentTimeMillis();
			}
			switch (npc.getId())
			{
				case FRINTEZZA:
					if (!npc.isDead() && npc.isVisible())
					{
						npc.getStatus().setCurrentHp(npc.getMaxHp(), false); // TODO: npc.sql側で調整できないか
					}
					break;
				case SCARLET1:
					if ((world.getStatus() == 3) && (npc.getCurrentHp() < (npc.getMaxHp() * 0.80)))/*テスト済*/
					{
						controlStatus(world);
					}
					else if ((world.getStatus() == 4) && (npc.getCurrentHp() < (npc.getMaxHp() * 0.20)))/*テスト済*/
					{
						controlStatus(world);
					}
					break;
			}
		}
		return null;
	}
	
	@Override
	public String onSkillSee(L2Npc npc, L2PcInstance player, Skill skill, L2Object[] targets, boolean isPet)
	{
		InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
		if (tmpworld instanceof FETWorld)
		{
			FETWorld world = (FETWorld) tmpworld;
			if (DETECT_ACTION_LOCK)
			{
				world.lastAction = System.currentTimeMillis();
			}
			if ((npc == world.frintezza) && !npc.isDead() && npc.isVisible())
			{
				npc.getStatus().setCurrentHp(npc.getMaxHp(), false); //TODO: npc.sql側で調整できないか
			}
			if ((targets.length > 0) && (targets[0] == npc) && (npc == world.frintezza))
			{
				// skill 2234 Soul Breaking Arrow ...
				if (isZZZ(npc) && isZZZ(skill))
				{
					broadcastPacket(world, new MagicSkillCanceld(npc.getObjectId()));
				}
			}
		}
		return super.onSkillSee(npc, player, skill, targets, isPet);
	}
	
	@Override
	public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)/*テスト済*/
	{
		if (skill.isSuicideAttack())
		{
			return onKill(npc, null, false);
		}
		// SCARLET1, SCARLET2
		if (npc.getId() == SCARLET1 || npc.getId() == SCARLET2)
		{
			final L2MonsterInstance mob = (L2MonsterInstance) npc;
			final ILocational spawn = mob.getSpawnPoint();
			final int AGGRO_RANGE = 1700;
			if (Util.calculateDistance(spawn, mob, true, false) > AGGRO_RANGE)
			{
				final L2Object originalTarget = mob.getTarget();
				L2PcInstance newTarget = null;
				double distance = Double.MAX_VALUE;
				for (L2PcInstance pc : mob.getKnownList().getKnownPlayers().values())
				{
					if (pc != originalTarget && !pc.isDead() && !pc.isInvul())
					{
						double q = Util.calculateDistance(spawn, pc, true, false);
						if (q < AGGRO_RANGE && q < distance)
						{
							distance = q;
							newTarget = pc;
						}
					}
				}
				mob.abortAttack();
				mob.abortCast();
				mob.clearAggroList();
				if (newTarget == null)
				{
					mob.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, spawn);
					return null;
				}
				else
				{
					mob.addDamageHate(newTarget, 0, 500);
					mob.getAI().setIntention(AI_INTENTION_ATTACK, newTarget);
					return null;
				}
			}
		}
		return super.onSpellFinished(npc, player, skill);
	}
	
	@Override
	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon)
	{
		InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
		if (tmpworld instanceof FETWorld)
		{
			FETWorld world = (FETWorld) tmpworld;
			if (DETECT_ACTION_LOCK)
			{
				world.lastAction = System.currentTimeMillis();
			}
			switch (npc.getId())
			{
				case HALL_ALARM:/*テスト済*/
					if (ASSERT) if (!(world.getStatus() == 1)) throw new RuntimeException("status=" + world.getStatus());
					new OnKillHallAlarmTask(world).run();
					if (DEBUG)
					{
						_log.info("[Final Emperial Tomb] Hall alarm is disabled, doors will open!");
					}
					break;
				
				case DARK_CHOIR_PLAYER:/*テスト済*/
					if (ASSERT) if (!(world.getStatus() >= 2)) throw new RuntimeException("status=" + world.getStatus());
					// note: world.status は変化しない.ドアの開閉のみ制御する.
					/*if (world.getStatus() == 2)*/
					{
						final int count;
						synchronized (world)
						{
							count = --world.darkChoirPlayerCount;
						}
						if (count == 0)
						{
							new OnKillDarkChoirPlayerTask(world).run();
							if (DEBUG)
							{
								_log.info("[Final Emperial Tomb] All Dark Choir Players are killed, doors will open!");
							}
						}
					}
					break;
				
				default:
					if (world.getStatus() == 1)
					{
						// 1st room - Hall Keepers /*テスト済*/
						final boolean done;
						synchronized (world)
						{
							done = world.npcList.remove(npc) && (world.npcList.size() == 0);
						}
						if (done)
						{
							controlStatus(world);
							openDoors(FIRST_ROUTE_DOORS, world.getInstanceId());
							openDoors(SECOND_ROUTE_DOORS, world.getInstanceId());
						}
						
						if ((player != null) && (getRandom(world.npcMax) < 3))
						{
							if (DROP_DEWDROP_OF_DESTRUCTION) npc.dropItem(player, DEWDROP_OF_DESTRUCTION, 1);
							else player.addItem(getName(), DEWDROP_OF_DESTRUCTION, 1, npc, true); // Dewdrop of Destruction
						}
					}
					else /*if (world.getStatus() == 2)*/
					{
						// 2nd room - Dark Choirs/*テスト済*/
						final boolean done;
						synchronized (world)
						{
							done = world.npcList.remove(npc) && (world.npcList.size() == 0);
						}
						if (done)
						{
							openDoors(SECOND_ROUTE_DOORS, world.getInstanceId());
						}
						
						if ((player != null) && (getRandom(world.npcMax) < 5))
						{
							if (DROP_SOUL_BREAKING_ARROW) npc.dropItem(player, SOUL_BREAKING_ARROW, 1);
							else player.addItem(getName(), SOUL_BREAKING_ARROW, 1, npc, true); // Soul Breaking Arrow
						}
						
						if (npc.getId() == DARK_CHOIR_CAPTAIN)
						{
							// 1010644 黒聖歌団のステージをぶち壊すとは．．．許せぬ！
							// 1010645 黒聖歌団の演奏を妨げる邪魔者を消せ！
							// 1010646 死の演奏が聞こえないのか！黒聖歌団の恐ろしさを見せてやれ！
							int npcstring = getRandom(1010644, 1010646);
							npc.broadcastPacket(new NpcSay(npc.getObjectId(), Say2.SHOUT, npc.getId(), npcstring));
						}
					}
					break;
				
				case SCARLET1:/*テスト済*/
					if (ASSERT) if (!(world.getStatus() == 3 || world.getStatus() == 4)) throw new RuntimeException("status=" + world.getStatus());
					world.setStatus(5);
					controlStatus(world);
					break;
				
				case SCARLET2:/*テスト済*/
					if (ASSERT) if (!(world.getStatus() == 5)) throw new RuntimeException("status=" + world.getStatus());
					controlStatus(world);
					break;
				
				case PORTRAIT_FIGHTER:/*テスト済*/
				case PORTRAIT_MAGE:/*テスト済*/
					for (int i = 0; i < 4; ++i)
					{
						if (npc == world.portraits[i])
						{
							L2MonsterInstance ghost = world.ghosts[i];
							ghost.getSpawn().stopRespawn();
							world.portraits[i] = null;
							return null;
						}
					}
					if (ASSERT) throw new RuntimeException();
					else break;
			}
		}
		return "";
	}
	
//	@Override
//	public String onDeath(L2Character killer, L2Character victim, QuestState qs)
//	{
//		TRACE("onDeath("+STR(killer)+","+STR(victim)+","+(qs == null ? "NULL" : qs.getQuest() == null ? "NUL" : qs.getQuest().getName())+")");
//		TODO: キャラクターが死亡して○○分以内に復活しないと場外にとばされてしまう
//		return super.onDeath(killer, victim, qs);
//	}
	
	@Override
	public String onEnterZone(L2Character character, L2ZoneType zone)/*テスト済*/
	{
		if (character instanceof L2PcInstance)
		{
			if (ASSERT) if (!(zone.getId() == ROOM3_ZONE)) throw new RuntimeException();
			InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(character.getInstanceId());
			if (tmpworld instanceof FETWorld)
			{
				FETWorld world = (FETWorld) tmpworld;
				if (world.getStatus() == 2)
				{
					controlStatus(world);
				}
			}
		}
		return super.onEnterZone(character, zone);
	}
	
	@Override
	public String onTalk(L2Npc npc, L2PcInstance player)
	{
		QuestState st = player.getQuestState(getName());
		if (st == null)
		{
			st = newQuestState(player);
		}
		switch (npc.getId())
		{
			case GUIDE:
				enterInstance(player, "FinalEmperialTomb.xml", ENTER_TELEPORT);
				break;
			case CUBE:
				player.teleToLocation(-87784 + getRandom(-250, 250), -153298 + getRandom(-250, 250), -9175);
				return null;
		}
		return "";
	}
	
	public static void main(String[] args)
	{
		// now call the constructor (starts up the)
		new FinalEmperialTomb();
	}
}