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

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

import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;

import javolution.util.FastList;
import quests.Q10286_ReunionWithSirra.Q10286_ReunionWithSirra;
import ai.npc.AbstractNpcAI;

import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.enums.MountType;
import com.l2jserver.gameserver.instancemanager.InstanceManager;
import com.l2jserver.gameserver.model.L2CommandChannel;
import com.l2jserver.gameserver.model.L2Party;
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.L2Summon;
import com.l2jserver.gameserver.model.actor.instance.L2GrandBossInstance;
import com.l2jserver.gameserver.model.actor.instance.L2NpcInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.actor.instance.L2QuestGuardInstance;
import com.l2jserver.gameserver.model.actor.instance.L2RaidBossInstance;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.instancezone.InstanceWorld;
import com.l2jserver.gameserver.model.quest.QuestState;
import com.l2jserver.gameserver.model.quest.State;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.model.variables.NpcVariables;
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.ActionFailed;
import com.l2jserver.gameserver.network.serverpackets.ExChangeClientEffectInfo;
import com.l2jserver.gameserver.network.serverpackets.ExSendUIEvent;
import com.l2jserver.gameserver.network.serverpackets.ExShowScreenMessage;
import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.gameserver.taskmanager.DecayTaskManager;
import com.l2jserver.gameserver.util.Util;
import com.l2jserver.util.Rnd;

/**
 * Ice Queen's Castle (Normal Battle) instance zone.
 * @author St3eT
 */
public final class IceQueensCastleNormalBattle extends AbstractNpcAI
{
	protected class IQCNBWorld extends InstanceWorld
	{
		ArrayList<L2PcInstance> playersInside = new ArrayList<>();
		ArrayList<L2Npc> knightStatues = new ArrayList<>();
		FastList<L2Attackable> spawnedMobs = new FastList<L2Attackable>().shared();	//[JOJO] -CopyOnWriteArrayList
		L2NpcInstance controller = null;
		L2GrandBossInstance freya = null;
		L2QuestGuardInstance supp_Jinia = null;
		L2QuestGuardInstance supp_Kegor = null;
		boolean isSupportActive = false;
		boolean canSpawnMobs = true;
	}
	
	// Npcs
	private static final int FREYA_THRONE = 29177; // First freya29177
	private static final int FREYA_SPELLING = 29178; // Second freya
	private static final int FREYA_STAND = 29179; // Last freya
	private static final int INVISIBLE_NPC = 18919;
	private static final int KNIGHT = 18855; // Archery Knight
	private static final int GLACIER = 18853; // Glacier
	private static final int BREATH = 18854; // Archer's Breath
	private static final int GLAKIAS = 25699; // Glakias (Archery Knight Captain)
	private static final int SIRRA = 32762; // Sirra
	private static final int JINIA = 32781; // Jinia
	private static final int SUPP_JINIA = 18850; // Jinia
	private static final int SUPP_KEGOR = 18851; // Kegor
	// Skills
	private static final int BLIZZARD = getSkillHashCode(6274, 1); // Eternal Blizzard
	private static final int BLIZZARD_BREATH = getSkillHashCode(6299, 1); // Breath of Ice Palace - Ice Storm
	private static final int SUICIDE_BREATH = getSkillHashCode(6300, 1); // Self-Destruction
	private static final int JINIA_SUPPORT = getSkillHashCode(6288, 1); // Jinia's Prayer
	private static final int KEGOR_SUPPORT = getSkillHashCode(6289, 1); // Kegor's Courage
	private static final int ICE_STONE = getSkillHashCode(6301, 1); // Cold Mana's Fragment
	private static final int CANCEL = getSkillHashCode(4618, 1); // NPC Cancel PC Target
	private static final int POWER_STRIKE = getSkillHashCode(6293, 1); // Power Strike
	private static final int POINT_TARGET = getSkillHashCode(6295, 1); // Point Target
	private static final int CYLINDER_THROW = getSkillHashCode(6297, 1); // Cylinder Throw
	private static final int SELF_RANGE_BUFF = getSkillHashCode(6294, 1); // Leader's Roar
	private static final int LEADER_RUSH = getSkillHashCode(6296, 1); // Rush
	private static final int ANTI_STRIDER = getSkillHashCode(4258, 1); // Hinder Strider
	private static final int ICE_BALL = getSkillHashCode(6278, 1); // Ice Ball
	private static final int SUMMON_ELEMENTAL = getSkillHashCode(6277, 1); // Summon Spirits
	private static final int SELF_NOVA = getSkillHashCode(6279, 1); // Attack Nearby Range
	private static final int REFLECT_MAGIC = getSkillHashCode(6282, 1); // Reflect Magic
	// Locations
	private static final Location FREYA_SPAWN = new Location(114720, -117085, -11088, 15956);
	private static final Location FREYA_SPELLING_SPAWN = new Location(114723, -117502, -10672, 15956);
	private static final Location FREYA_CORPSE = new Location(114767, -114795, -11200, 0);
	private static final Location MIDDLE_POINT = new Location(114730, -114805, -11200);
	private static final Location KEGOR_FINISH = new Location(114659, -114796, -11205);
	private static final Location GLAKIAS_SPAWN = new Location(114707, -114799, -11199, 15956);
	private static final Location SUPP_JINIA_SPAWN = new Location(114751, -114781, -11205);
	private static final Location SUPP_KEGOR_SPAWN = new Location(114659, -114796, -11205);
	private static final Location BATTLE_PORT = new Location(114694, -113700, -11200);
	private static final Location CONTROLLER_LOC = new Location(114394, -112383, -11200);
	private static final Location[] ENTER_LOC =
	{
		new Location(114185, -112435, -11210),
		new Location(114183, -112280, -11210),
		new Location(114024, -112435, -11210),
		new Location(114024, -112278, -11210),
		new Location(113865, -112435, -11210),
		new Location(113865, -112276, -11210),
	
	};
	private static final Location[] STATUES_STAGE_1_LOC =
	{
		new Location(113845, -116091, -11168, 8264),
		new Location(113381, -115622, -11168, 8264),
		new Location(113380, -113978, -11168, -8224),
		new Location(113845, -113518, -11168, -8224),
		new Location(115591, -113516, -11168, -24504),
		new Location(116053, -113981, -11168, -24504),
		new Location(116061, -115611, -11168, 24804),
		new Location(115597, -116080, -11168, 24804),
	};
	private static final Location[] STATUES_STAGE_2_LOC =
	{
		new Location(112942, -115480, -10960, 52),
		new Location(112940, -115146, -10960, 52),
		new Location(112945, -114453, -10960, 52),
		new Location(112945, -114123, -10960, 52),
		new Location(116497, -114117, -10960, 32724),
		new Location(116499, -114454, -10960, 32724),
		new Location(116501, -115145, -10960, 32724),
		new Location(116502, -115473, -10960, 32724),
	};
	private static Location[] KNIGHTS_LOC =
	{
		new Location(114502, -115315, -11205, 15451),
		new Location(114937, -115323, -11205, 18106),
		new Location(114722, -115185, -11205, 16437),
	};
	// Misc
	private static final int MAX_PLAYERS = 27;
	private static final int MIN_PLAYERS = 10;
	private static final int MIN_LEVEL = 82;
	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 };
	private long calculateNextInstanceTime()
	{
		long now = System.currentTimeMillis();
		GregorianCalendar reset = new GregorianCalendar();
		reset.setTimeInMillis(now);
		reset.set(Calendar.MILLISECOND, 0);
		reset.set(Calendar.SECOND, 0);
		reset.set(Calendar.MINUTE, RESET_MINUTE);
		reset.set(Calendar.HOUR_OF_DAY, RESET_HOUR_OF_DAY);
		while (reset.getTimeInMillis() < now)
			reset.add(Calendar.DATE, 1);
		while (! Util.contains(RESET_DAY_OF_WEEK, reset.get(Calendar.DAY_OF_WEEK)))
			reset.add(Calendar.DATE, 1);
		return reset.getTimeInMillis();
	}
	private static final int TEMPLATE_ID = 139; // Ice Queen's Castle
	private static final int DOOR_ID = 23140101;
	
	private IceQueensCastleNormalBattle()
	{
		super(IceQueensCastleNormalBattle.class.getSimpleName(), "instances");
		addStartNpc(SIRRA, SUPP_KEGOR, SUPP_JINIA);
		addFirstTalkId(SUPP_KEGOR, SUPP_JINIA);
		addTalkId(SIRRA, JINIA, SUPP_KEGOR);
		addAttackId(FREYA_THRONE, FREYA_STAND, GLAKIAS, GLACIER, BREATH, KNIGHT);
		addKillId(GLAKIAS, FREYA_STAND, KNIGHT, GLACIER, BREATH);
		addSpawnId(GLAKIAS, FREYA_STAND, KNIGHT, GLACIER, BREATH);
		addSpellFinishedId(GLACIER, BREATH);
	}
	
	@Override
	public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
	{
		if (event.equals("enter"))
		{
			enterInstance(player, "IceQueensCastleNormalBattle.xml");
		}
		else
		{
			final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
			
			if (tmpworld instanceof IQCNBWorld)
			{
				final IQCNBWorld world = (IQCNBWorld) tmpworld;
				switch (event)
				{
					case "openDoor":
					{
						if (npc.isScriptValue(0))
						{
							npc.setScriptValue(1);
							openDoor(DOOR_ID, world.getInstanceId());
							world.controller = (L2NpcInstance) addSpawn(INVISIBLE_NPC, CONTROLLER_LOC, false, 0, true, world.getInstanceId());
							for (Location loc : STATUES_STAGE_1_LOC)
							{
								final L2Npc statue = addSpawn(INVISIBLE_NPC, loc, false, 0, false, world.getInstanceId());
								world.knightStatues.add(statue);
							}
							for (L2PcInstance players : world.playersInside)
							{
								if (players != null && !players.isDead() && players.getInstanceId() == world.getInstanceId())
								{
									final QuestState qs = player.getQuestState(Q10286_ReunionWithSirra.class.getSimpleName());
									if (qs != null && qs.getState() == State.STARTED && qs.isCond(5))
									{
										qs.setCond(6, true);
									}
								}
							}
							startQuestTimer("STAGE_1_MOVIE", 60000, world.controller, null);
						}
						break;
					}
					case "portInside":
					{
						teleportPlayer(player, BATTLE_PORT, world.getInstanceId());
						break;
					}
					case "killFreya":/*18851.html Kegor: "Rest in peace!"*/
					{
						final QuestState qs = player.getQuestState(Q10286_ReunionWithSirra.class.getSimpleName());
						if (qs != null && qs.getState() == State.STARTED && qs.isCond(6))
						{
							qs.setMemoState(10);
							qs.setCond(7, true);
						}
						world.supp_Kegor.deleteMe();
						world.freya.deleteMe();	//[JOJO] -decayMe()
						manageMovie(world, 20);
						cancelQuestTimer("FINISH_WORLD", world.controller, null);
						startQuestTimer("FINISH_WORLD", 58500, world.controller, null);
						break;
					}
					case "18851-01.html":
					{
						return event;
					}
					case "STAGE_1_MOVIE":
					{
						closeDoor(DOOR_ID, world.getInstanceId());
						world.setStatus(1);
						manageMovie(world, 15);
						startQuestTimer("STAGE_1_START", 53500, world.controller, null);
						break;
					}
					case "STAGE_1_START":
					{
						world.freya = (L2GrandBossInstance) addSpawn(FREYA_THRONE, FREYA_SPAWN, false, 0, true, world.getInstanceId());
						world.freya.setIsMortal(false);
						manageScreenMsg(world, NpcStringId.BEGIN_STAGE_1);
						startQuestTimer("CAST_BLIZZARD", 50000, world.controller, null);
						startQuestTimer("STAGE_1_SPAWN", 2000, world.freya, null);
						break;
					}
					case "STAGE_1_SPAWN":	// 29177アイス クイーン フレヤ(玉座)
					{
						world.canSpawnMobs = true;
						notifyEvent("START_SPAWN", world.controller, null);
						break;
					}
					case "STAGE_1_FINISH":/*onAttack FREYA_THRONE HP < 2%*/
					{
						world.canSpawnMobs = false;
						world.freya.deleteMe();
						world.freya = null;
						manageDespawnMinions(world);
						manageMovie(world, 16);
						startQuestTimer("STAGE_1_PAUSE", 24100 - 1000, world.controller, null);
						break;
					}
					case "STAGE_1_PAUSE":
					{
						world.freya = (L2GrandBossInstance) addSpawn(FREYA_SPELLING, FREYA_SPELLING_SPAWN, false, 0, true, world.getInstanceId());
						world.freya.setIsInvul(true);
						world.freya.disableCoreAI(true);
						manageTimer(world, 60);
						world.setStatus(2);
						startQuestTimer("STAGE_2_START", 60000, world.controller, null);
						break;
					}
					case "STAGE_2_START":
					{
						world.canSpawnMobs = true;
						notifyEvent("START_SPAWN", world.controller, null);
						manageScreenMsg(world, NpcStringId.BEGIN_STAGE_2);
						break;
					}
					case "STAGE_2_MOVIE":
					{
						manageMovie(world, 23);
						startQuestTimer("STAGE_2_GLAKIAS", 7000, world.controller, null);
						break;
					}
					case "STAGE_2_GLAKIAS":
					{
						for (Location loc : STATUES_STAGE_2_LOC)
						{
							final L2Npc statue = addSpawn(INVISIBLE_NPC, loc, false, 0, false, world.getInstanceId());
							world.knightStatues.add(statue);
							startQuestTimer("SPAWN_KNIGHT", 5000, statue, null);
						}
						final L2RaidBossInstance glakias = (L2RaidBossInstance) addSpawn(GLAKIAS, GLAKIAS_SPAWN, false, 0, true, world.getInstanceId());
						startQuestTimer("LEADER_DELAY", 5000, glakias, null);
						break;
					}
					case "STAGE_3_MOVIE":
					{
						manageMovie(world, 17);
						startQuestTimer("STAGE_3_START", 21500, world.controller, null);
						break;
					}
					case "STAGE_3_START":
					{
						for (L2PcInstance players : world.playersInside)
						{
							if (players != null)
							{
								players.broadcastPacket(ExChangeClientEffectInfo.STATIC_FREYA_DESTROYED);
							}
						}
						world.setStatus(4);
						world.freya.deleteMe();
						world.freya = (L2GrandBossInstance) addSpawn(FREYA_STAND, FREYA_SPAWN, false, 0, true, world.getInstanceId());
						world.controller.getVariables().set("FREYA_MOVE", 0);
						world.canSpawnMobs = true;
						notifyEvent("START_SPAWN", world.controller, null);
						startQuestTimer("START_MOVE", 10000, world.controller, null);
						startQuestTimer("CAST_BLIZZARD", 50000, world.controller, null);
						manageScreenMsg(world, NpcStringId.BEGIN_STAGE_3);
						break;
					}
					case "START_MOVE":
					{
						if (npc.getVariables().getInt("FREYA_MOVE") == 0)
						{
							world.controller.getVariables().set("FREYA_MOVE", 1);
							world.freya.setIsRunning(true);
							world.freya.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, MIDDLE_POINT);
						}
						break;
					}
					case "CAST_BLIZZARD":
					{
						if (!world.freya.isInvul())
						{
							world.freya.doCast(getSkill(BLIZZARD));
							manageScreenMsg(world, NpcStringId.STRONG_MAGIC_POWER_CAN_BE_FELT_FROM_SOMEWHERE);
						}
						
						for (L2Attackable minion : world.spawnedMobs)
						{
							if (minion != null && !minion.isDead() && !minion.isInCombat())
							{
								manageRandomAttack(world, minion);
							}
						}
						startQuestTimer("CAST_BLIZZARD", getRandom(55, 60) * 1000, world.controller, null);
						break;
					}
					case "SPAWN_SUPPORT":
					{
						for (L2PcInstance players : world.playersInside)
						{
							if (players != null && players.getInstanceId() == world.getInstanceId())
							{
								players.setIsInvul(false);
							}
						}
						world.freya.setIsInvul(false);
						world.freya.disableCoreAI(false);
						manageScreenMsg(world, NpcStringId.BEGIN_STAGE_4);
						world.supp_Jinia = (L2QuestGuardInstance) addSpawn(SUPP_JINIA, SUPP_JINIA_SPAWN, false, 0, true, world.getInstanceId());
						world.supp_Jinia.setIsRunning(true);
						world.supp_Jinia.setIsInvul(true);
						world.supp_Jinia.setCanReturnToSpawnPoint(false);
						world.supp_Kegor = (L2QuestGuardInstance) addSpawn(SUPP_KEGOR, SUPP_KEGOR_SPAWN, false, 0, true, world.getInstanceId());
						world.supp_Kegor.setIsRunning(true);
						world.supp_Kegor.setIsInvul(true);
						world.supp_Kegor.setCanReturnToSpawnPoint(false);
						startQuestTimer("ATTACK_FREYA", 5000, world.supp_Jinia, null);
						startQuestTimer("ATTACK_FREYA", 5000, world.supp_Kegor, null);
						startQuestTimer("GIVE_SUPPORT", 1000, world.controller, null);
						break;
					}
					case "GIVE_SUPPORT":
					{
						if (world.isSupportActive)
						{
							world.supp_Jinia.doCast(getSkill(JINIA_SUPPORT));
							world.supp_Kegor.doCast(getSkill(KEGOR_SUPPORT));
							startQuestTimer("GIVE_SUPPORT", 25000, world.controller, null);
						}
						break;
					}
					case "FINISH_STAGE":
					{
						if (world.supp_Jinia != null) // [JOJO] NPE
						{
							world.supp_Jinia.deleteMe();
							world.supp_Jinia = null;
						}
						world.freya.teleToLocation(FREYA_CORPSE);
						if (world.supp_Kegor != null) // [JOJO] NPE
						{
							world.supp_Kegor.teleToLocation(KEGOR_FINISH);
						}
						break;
					}
					case "START_SPAWN":
					{
						for (L2Npc statues : world.knightStatues)
						{
							notifyEvent("SPAWN_KNIGHT", statues, null);
						}
						
						for (Location loc : KNIGHTS_LOC)
						{
							final L2Attackable knight = (L2Attackable) addSpawn(KNIGHT, loc, false, 0, false, world.getInstanceId());
							knight.disableCoreAI(true);
							knight.setDisplayEffect(1);
							knight.getSpawn().setLocation(loc);
							world.spawnedMobs.add(knight);
							startQuestTimer("ICE_RUPTURE", getRandom(2, 5) * 1000, knight, null);
						}
						
						for (int i = 0; i < world.getStatus(); i++)
						{
							notifyEvent("SPAWN_GLACIER", world.controller, null);
						}
						break;
					}
					case "SPAWN_KNIGHT":
					{
						if (world.canSpawnMobs)
						{
							final Location loc = new Location(MIDDLE_POINT.getX() + getRandom(-1000, 1000), MIDDLE_POINT.getY() + getRandom(-1000, 1000), MIDDLE_POINT.getZ());
							final L2Attackable knight = (L2Attackable) addSpawn(KNIGHT, npc.getLocation(), false, 0, false, world.getInstanceId());
							knight.getVariables().set("SPAWNED_NPC", npc);
							knight.disableCoreAI(true);
							knight.setIsImmobilized(true);
							knight.setDisplayEffect(1);
							knight.getSpawn().setLocation(loc);
							world.spawnedMobs.add(knight);
							startQuestTimer("ICE_RUPTURE", getRandom(5, 10) * 1000, knight, null);
						}
						break;
					}
					case "SPAWN_GLACIER":
					{
						if (world.canSpawnMobs)
						{
							final Location loc = new Location(MIDDLE_POINT.getX() + getRandom(-1000, 1000), MIDDLE_POINT.getY() + getRandom(-1000, 1000), MIDDLE_POINT.getZ());
							final L2Attackable glacier = (L2Attackable) addSpawn(GLACIER, loc, false, 0, false, world.getInstanceId());
							glacier.setDisplayEffect(1);
							glacier.disableCoreAI(true);
							glacier.setIsImmobilized(true);
							world.spawnedMobs.add(glacier);
							startQuestTimer("CHANGE_STATE", 1400, glacier, null);
						}
						break;
					}
					case "ICE_RUPTURE":	// 18855氷宮の騎士
					{
						if (npc.isDead() || !npc.isVisible()) break;	//+[JOJO]
						
						if (npc.isCoreAIDisabled())
						{
							npc.disableCoreAI(false);
							npc.setIsImmobilized(false);
							npc.setDisplayEffect(2);
							manageRandomAttack(world, (L2Attackable) npc);
						}
						break;
					}
					case "FIND_TARGET":
					{
						if (npc.isDead() || !npc.isVisible()) break;	//+[JOJO]
						
						manageRandomAttack(world, (L2Attackable) npc);
						break;
					}
					case "CHANGE_STATE":	// 18853決氷石
					{
						if (npc.isDead() || !npc.isVisible()) break;	//+[JOJO]
						
						npc.setDisplayEffect(2);
						startQuestTimer("CAST_SKILL", 20000, npc, null);
						break;
					}
					case "CAST_SKILL":	// 18853決氷石
					{
						if (npc.isDead() || !npc.isVisible()) break;	//+[JOJO]
						
						if (npc.isScriptValue(0))
						{
							npc.setScriptValue(1);
							npc.setTarget(npc);
							npc.doCast(getSkill(ICE_STONE));
						}
						break;
					}
					case "SUICIDE":	// 18853決氷石
					{
						cancelQuestTimers(npc);	//+[JOJO] "CAST_SKILL"
						npc.setDisplayEffect(3);
						npc.setIsMortal(true);
						npc.doDie(null);
						break;
					}
					case "BLIZZARD":	// 18854氷宮の息吹
					{
						if (npc.isDead() || !npc.isVisible()) break;	//+[JOJO]
						
						npc.getVariables().set("SUICIDE_COUNT", npc.getVariables().getInt("SUICIDE_COUNT") + 1);
						
						if (npc.getVariables().getInt("SUICIDE_ON") == 0)
						{
							if (npc.getVariables().getInt("SUICIDE_COUNT") == 2)
							{
								startQuestTimer("ELEMENTAL_SUICIDE", 20000, npc, null);
							}
							else
							{
								final Skill s;
								if (npc.checkDoCastConditions(s = getSkill(BLIZZARD_BREATH)) && !npc.isCastingNow())
								{
									npc.setTarget(npc);
									npc.doCast(s);
								}
								startQuestTimer("BLIZZARD", 20000, npc, null);
							}
						}
						break;
					}
					case "ELEMENTAL_SUICIDE":	// 18854氷宮の息吹
					{
						if (npc.isDead() || !npc.isVisible()) break;	//+[JOJO]
						
						npc.setTarget(npc);
						npc.doCast(getSkill(SUICIDE_BREATH));
						break;
					}
					case "ELEMENTAL_KILLED":
					{
						if (npc.getVariables().getInt("SUICIDE_ON") == 1)
						{
							npc.setTarget(npc);
							npc.doCast(getSkill(SUICIDE_BREATH));
						}
						break;
					}
					case "ATTACK_FREYA":	//18850ジニア|18851ケゴル
					{
						if (npc.isInsideRadius(world.freya, 100, true, false))
						{
							final Skill skill = npc.getTemplate().getParameters().getObject("Skill01_ID", SkillHolder.class).getSkill();
							if (npc.checkDoCastConditions(skill) && !npc.isCastingNow())
							{
								npc.setTarget(world.freya);
								npc.doCast(skill);
								startQuestTimer("ATTACK_FREYA", 20000, npc, null);
							}
							else
							{
								startQuestTimer("ATTACK_FREYA", 5000, npc, null);
							}
						}
						else
						{
							npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, world.freya);
							startQuestTimer("ATTACK_FREYA", 5000, npc, null);
						}
						break;
					}
					case "FINISH_WORLD":
					{
						if (world.freya != null)
						{
							world.freya.deleteMe();	//[JOJO] -decayMe()
						}
						
						for (L2PcInstance players : world.playersInside)
						{
							if (players != null)
							{
								players.broadcastPacket(ExChangeClientEffectInfo.STATIC_FREYA_DEFAULT);
							}
						}
						InstanceManager.getInstance().destroyInstance(world.getInstanceId());
						break;
					}
					case "LEADER_RANGEBUFF":	// 25699氷宮の騎士団長グラキエス
					{
						if (npc.isDead() || !npc.isVisible()) break;	//+[JOJO]
						
						final Skill s;
						if (npc.checkDoCastConditions(s = getSkill(SELF_RANGE_BUFF)) && !npc.isCastingNow())
						{
							npc.setTarget(npc);
							npc.doCast(s);
						}
						else
						{
							startQuestTimer("LEADER_RANGEBUFF", 30000, npc, null);
						}
						break;
					}
					case "LEADER_RANDOMIZE":	// 25699氷宮の騎士団長グラキエス
					{
						if (npc.isDead() || !npc.isVisible()) break;	//+[JOJO]
						
						final L2Attackable mob = (L2Attackable) npc;
						mob.clearAggroList();
						
						for (L2Character characters : npc.getKnownList().getKnownPlayersInRadius(1000))
						{
							if (characters != null)
							{
								mob.addDamageHate(characters, 0, getRandom(10000, 20000));
							}
						}
						startQuestTimer("LEADER_RANDOMIZE", 25000, npc, null);
						break;
					}
					case "LEADER_DASH":	// 25699氷宮の騎士団長グラキエス
					{
						if (npc.isDead() || !npc.isVisible()) break;	//+[JOJO]
						
						if (getRandomBoolean())
						{
							final L2Character mostHated = ((L2Attackable) npc).getMostHated();
							final boolean canReachMostHated = mostHated != null && !mostHated.isDead() && npc.calculateDistance(mostHated, true, false) <= 1000;
							if (canReachMostHated && !npc.isCastingNow())
							{
								npc.setTarget(mostHated);
								npc.doCast(getSkill(LEADER_RUSH));
							}
						}
						startQuestTimer("LEADER_DASH", 10000, npc, null);
						break;
					}
					case "LEADER_DESTROY":	// 25699氷宮の騎士団長グラキエス
					{
						if (npc.isDead() || !npc.isVisible()) break;	//+[JOJO]
						
						if (npc.getVariables().getInt("OFF_SHOUT") == 0)
						{
							manageScreenMsg(world, NpcStringId.THE_SPACE_FEELS_LIKE_ITS_GRADUALLY_STARTING_TO_SHAKE);
							
							switch (getRandom(4))
							{
								case 0:
								{
									broadcastNpcSay(npc, Say2.SHOUT, NpcStringId.ARCHER_GIVE_YOUR_BREATH_FOR_THE_INTRUDER);
									break;
								}
								case 1:
								{
									broadcastNpcSay(npc, Say2.SHOUT, NpcStringId.MY_KNIGHTS_SHOW_YOUR_LOYALTY);
									break;
								}
								case 2:
								{
									broadcastNpcSay(npc, Say2.SHOUT, NpcStringId.I_CAN_TAKE_IT_NO_LONGER);
									break;
								}
								case 3:
								{
									broadcastNpcSay(npc, Say2.SHOUT, NpcStringId.ARCHER_HEED_MY_CALL);
									for (int i = 0; i < 3; i++)
									{
										final L2Attackable breath = (L2Attackable) addSpawn(BREATH, npc.getLocation(), true, 0, false, world.getInstanceId());
										breath.setIsRunning(true);
										final L2Attackable mob = (L2Attackable) npc;
										breath.addDamageHate(mob.getMostHated(), 0, 999);
										breath.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, mob.getMostHated());
										startQuestTimer("BLIZZARD", 20000, breath, null);
										world.spawnedMobs.add(breath);
									}
									break;
								}
							}
						}
						break;
					}
					case "LEADER_DELAY":	// 25699氷宮の騎士団長グラキエス
					{
						if (npc.getVariables().getInt("DELAY_VAL") == 0)
						{
							npc.getVariables().set("DELAY_VAL", 1);
						}
						break;
					}
				}
			}
		}
		return super.onAdvEvent(event, npc, player);
	}
	
	@Override
	public String onSpawn(L2Npc npc)
	{
		((L2Attackable) npc).setOnKillDelay(0);
		return super.onSpawn(npc);
	}
	
	@Override
	public String onFirstTalk(L2Npc npc, L2PcInstance player)
	{
		final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
		
		if (tmpworld instanceof IQCNBWorld)
		{
			final IQCNBWorld world = (IQCNBWorld) tmpworld;
			
			if (npc.getId() == SUPP_JINIA)
			{
				player.sendPacket(ActionFailed.STATIC_PACKET);
				return null;
			}
			else if (npc.getId() == SUPP_KEGOR)
			{
				if (world.isSupportActive)
				{
					player.sendPacket(ActionFailed.STATIC_PACKET);
					return null;
				}
				return "18851.html";
			}
		}
		player.sendPacket(ActionFailed.STATIC_PACKET);
		return null;
	}
	
	@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 IQCNBWorld)
		{
			final IQCNBWorld world = (IQCNBWorld) tmpworld;
			switch (npc.getId())
			{
				case FREYA_THRONE:
				{
					if (world.controller.getVariables().getInt("FREYA_MOVE") == 0 && world.isStatus(1))
					{
						world.controller.getVariables().set("FREYA_MOVE", 1);
						manageScreenMsg(world, NpcStringId.FREYA_HAS_STARTED_TO_MOVE);
						world.freya.setIsRunning(true);
						world.freya.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, MIDDLE_POINT);
					}
					
					if (npc.getCurrentHp() < npc.getMaxHp() * 0.02)
					{
						cancelQuestTimer("CAST_BLIZZARD", world.controller, null);
						notifyEvent("STAGE_1_FINISH", world.controller, null);
					}
					else
					{
						if (attacker.getMountType() == MountType.STRIDER) 
						{
							final Skill s;
							if (!npc.isSkillDisabled(s = getSkill(ANTI_STRIDER)) && !attacker.isAffectedBySkill(s.getId()) && !npc.isCastingNow())
							{
								npc.setTarget(attacker);
								npc.doCast(s);
							}
						}
						
						final L2Character mostHated = ((L2Attackable) npc).getMostHated();
						final boolean canReachMostHated = mostHated != null && !mostHated.isDead() && npc.calculateDistance(mostHated, true, false) <= 800;
						
						if (getRandom(10000) < 3333)
						{
							if (getRandomBoolean())
							{
								final Skill s;
								if (npc.calculateDistance(attacker, true, false) <= 800 && npc.checkDoCastConditions(s = getSkill(ICE_BALL)) && !npc.isCastingNow())
								{
									npc.setTarget(attacker);
									npc.doCast(s);
								}
							}
							else
							{
								final Skill s;
								if (canReachMostHated && npc.checkDoCastConditions(s = getSkill(ICE_BALL)) && !npc.isCastingNow())
								{
									npc.setTarget(mostHated);
									npc.doCast(s);
								}
							}
						}
						else if (getRandom(10000) < 800)
						{
							if (getRandomBoolean())
							{
								final Skill s;
								if (npc.calculateDistance(attacker, true, false) <= 800 && npc.checkDoCastConditions(s = getSkill(SUMMON_ELEMENTAL)) && !npc.isCastingNow())
								{
									npc.setTarget(attacker);
									npc.doCast(s);
								}
							}
							else
							{
								final Skill s;
								if (canReachMostHated && npc.checkDoCastConditions(s = getSkill(SUMMON_ELEMENTAL)) && !npc.isCastingNow())
								{
									npc.setTarget(mostHated);
									npc.doCast(s);
								}
							}
						}
						else if (getRandom(10000) < 1500)
						{
							final Skill s;
							if (!npc.isAffectedBySkill((s = getSkill(SELF_NOVA)).getId()) && npc.checkDoCastConditions(s) && !npc.isCastingNow())
							{
								npc.setTarget(npc);
								npc.doCast(s);
							}
						}
					}
					break;
				}
				case FREYA_STAND:
				{
					if (world.controller.getVariables().getInt("FREYA_MOVE") == 0)
					{
						world.controller.getVariables().set("FREYA_MOVE", 1);
						world.freya.setIsRunning(true);
						world.freya.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, MIDDLE_POINT);
					}
					
					if (npc.getCurrentHp() < npc.getMaxHp() * 0.2 && !world.isSupportActive)
					{
						world.isSupportActive = true;
						world.freya.setIsInvul(true);
						world.freya.disableCoreAI(true);
						for (L2PcInstance players : world.playersInside)
						{
							players.setIsInvul(true);
							players.abortAttack();
						}
						manageMovie(world, 18);
						startQuestTimer("SPAWN_SUPPORT", 27000, world.controller, null);
					}
					
					if (attacker.getMountType() == MountType.STRIDER)
					{
						final Skill s;
						if (!npc.isSkillDisabled(s = getSkill(ANTI_STRIDER)) && !attacker.isAffectedBySkill(s.getId()) && !npc.isCastingNow())
						{
							npc.setTarget(attacker);
							npc.doCast(s);
						}
					}
					
					final L2Character mostHated = ((L2Attackable) npc).getMostHated();
					final boolean canReachMostHated = mostHated != null && !mostHated.isDead() && npc.calculateDistance(mostHated, true, false) <= 800;
					
					if (getRandom(10000) < 3333)
					{
						if (getRandomBoolean())
						{
							final Skill s;
							if (npc.calculateDistance(attacker, true, false) <= 800 && npc.checkDoCastConditions(s = getSkill(ICE_BALL)) && !npc.isCastingNow())
							{
								npc.setTarget(attacker);
								npc.doCast(s);
							}
						}
						else
						{
							final Skill s;
							if (canReachMostHated && npc.checkDoCastConditions(s = getSkill(ICE_BALL)) && !npc.isCastingNow())
							{
								npc.setTarget(mostHated);
								npc.doCast(s);
							}
						}
					}
					else if (getRandom(10000) < 1333)
					{
						if (getRandomBoolean())
						{
							final Skill s;
							if (npc.calculateDistance(attacker, true, false) <= 800 && npc.checkDoCastConditions(s = getSkill(SUMMON_ELEMENTAL)) && !npc.isCastingNow())
							{
								npc.setTarget(attacker);
								npc.doCast(s);
							}
						}
						else
						{
							final Skill s;
							if (canReachMostHated && npc.checkDoCastConditions(s = getSkill(SUMMON_ELEMENTAL)) && !npc.isCastingNow())
							{
								npc.setTarget(mostHated);
								npc.doCast(s);
							}
						}
					}
					else if (getRandom(10000) < 1500)
					{
						final Skill s;
						if (!npc.isAffectedBySkill((s = getSkill(SELF_NOVA)).getId()) && npc.checkDoCastConditions(s) && !npc.isCastingNow())
						{
							npc.setTarget(npc);
							npc.doCast(s);
						}
					}
					else if (getRandom(10000) < 1333)
					{
						Skill s;
						if (!npc.isAffectedBySkill((s = getSkill(REFLECT_MAGIC)).getId()) && npc.checkDoCastConditions(s) && !npc.isCastingNow())
						{
							npc.setTarget(npc);
							npc.doCast(s);
						}
					}
					break;
				}
				case GLACIER:
				{
					if (npc.isScriptValue(0) && npc.getCurrentHp() < npc.getMaxHp() * 0.5)
					{
						npc.setScriptValue(1);
						npc.setTarget(attacker);
						npc.doCast(getSkill(ICE_STONE));
					}
					break;
				}
				case BREATH:
				{
					if (npc.getCurrentHp() < npc.getMaxHp() / 20 && npc.getVariables().getInt("SUICIDE_ON", 0) == 0)
					{
						npc.getVariables().set("SUICIDE_ON", 1);
						startQuestTimer("ELEMENTAL_KILLED", 1000, npc, null);
					}
					break;
				}
				case KNIGHT:
				{
					if (npc.isCoreAIDisabled())
					{
						npc.disableCoreAI(false);
						cancelQuestTimer("ICE_RUPTURE", npc, null);
						manageRandomAttack(world, (L2Attackable) npc);
						npc.setIsImmobilized(false);
						npc.setDisplayEffect(2);
					}
					break;
				}
				case GLAKIAS:
				{
					if (npc.getCurrentHp() < npc.getMaxHp() * 0.02)
					{
						if (npc.getVariables().getInt("OFF_SHOUT") == 0)
						{
							npc.getVariables().set("OFF_SHOUT", 1);
							npc.getVariables().set("DELAY_VAL", 2);
							npc.setTarget(attacker);
							npc.doCast(getSkill(CANCEL));
						}
						else if (npc.getVariables().getInt("OFF_SHOUT") == 1)
						{
							npc.setTarget(attacker);
							npc.doCast(getSkill(CANCEL));
						}
					}
					else if (npc.getVariables().getInt("OFF_SHOUT") == 0 && npc.getVariables().getInt("DELAY_VAL") == 1)
					{
						final L2Character mostHated = ((L2Attackable) npc).getMostHated();
						final boolean canReachMostHated = mostHated != null && !mostHated.isDead() && npc.calculateDistance(mostHated, true, false) < 1000;
						
						if (npc.getVariables().getInt("TIMER_ON") == 0)
						{
							npc.getVariables().set("TIMER_ON", 1);
							startQuestTimer("LEADER_RANGEBUFF", getRandom(5, 30) * 1000, npc, null);
							startQuestTimer("LEADER_RANDOMIZE", 25000, npc, null);
							startQuestTimer("LEADER_DASH", 5000, npc, null);
							startQuestTimer("LEADER_DESTROY", 60000, npc, null);
						}
						
						if (getRandom(10000) < 2500)
						{
							if (getRandom(10000) < 2500)
							{
								final Skill s;
								if (npc.checkDoCastConditions(s = getSkill(POWER_STRIKE)) && !npc.isCastingNow())
								{
									npc.setTarget(attacker);
									npc.doCast(s);
								}
							}
							else if (canReachMostHated)
							{
								final Skill s;
								if (npc.checkDoCastConditions(s = getSkill(POWER_STRIKE)) && !npc.isCastingNow())
								{
									npc.setTarget(mostHated);
									npc.doCast(s);
								}
							}
						}
						else if (getRandom(10000) < 1500)
						{
							if (getRandomBoolean())
							{
								final Skill s;
								if (npc.checkDoCastConditions(s = getSkill(POINT_TARGET)) && !npc.isCastingNow())
								{
									npc.setTarget(attacker);
									npc.doCast(s);
								}
							}
							else if (canReachMostHated)
							{
								final Skill s;
								if (npc.checkDoCastConditions(s = getSkill(POINT_TARGET)) && !npc.isCastingNow())
								{
									npc.setTarget(mostHated);
									npc.doCast(s);
								}
							}
						}
						else if (getRandom(10000) < 1500)
						{
							if (getRandomBoolean())
							{
								final Skill s;
								if (npc.checkDoCastConditions(s = getSkill(CYLINDER_THROW)) && !npc.isCastingNow())
								{
									npc.setTarget(attacker);
									npc.doCast(s);
								}
							}
							else if (canReachMostHated)
							{
								final Skill s;
								if (npc.checkDoCastConditions(s = getSkill(CYLINDER_THROW)) && !npc.isCastingNow())
								{
									npc.setTarget(mostHated);
									npc.doCast(s);
								}
							}
						}
					}
					break;
				}
			}
		}
		return super.onAttack(npc, attacker, damage, isSummon, skill);
	}
	
	@Override
	public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
	{
		final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
		
		if (tmpworld instanceof IQCNBWorld)
		{
			final IQCNBWorld world = (IQCNBWorld) tmpworld;
			
			switch (npc.getId())
			{
				case GLACIER:
				{
					if (skill.getReuseHashCode() == ICE_STONE)
					{
						if (getRandom(100) < 75)
						{
							final L2Attackable breath = (L2Attackable) addSpawn(BREATH, npc.getLocation(), false, 0, false, world.getInstanceId());
							if (player != null)
							{
								breath.setIsRunning(true);
								breath.addDamageHate(player, 0, 999);
								breath.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, player);
							}
							else
							{
								manageRandomAttack(world, breath);
							}
							world.spawnedMobs.add(breath);
							startQuestTimer("BLIZZARD", 20000, breath, null);
						}
						notifyEvent("SUICIDE", npc, null);
					}
					break;
				}
				case BREATH:
				{
					if (skill.getReuseHashCode() == SUICIDE_BREATH)
					{
						npc.doDie(null);
					}
					break;
				}
			}
		}
		return super.onSpellFinished(npc, player, skill);
	}
	
	@Override
	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
	{
		final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
		
		if (tmpworld instanceof IQCNBWorld)
		{
			final IQCNBWorld world = (IQCNBWorld) tmpworld;
			switch (npc.getId())
			{
				case GLAKIAS:
				{
					world.canSpawnMobs = false;
					manageDespawnMinions(world);
					cancelQuestTimers(npc);	//+[JOJO] "LEADER_DESTROY","LEADER_DASH","LEADER_RANDOMIZE","LEADER_RANGEBUFF"
					cancelQuestTimers("SPAWN_KNIGHT", world.getInstanceId());	//+[JOJO]
					
					manageTimer(world, 60);
					startQuestTimer("STAGE_3_MOVIE", 60000, world.controller, null);
					break;
				}
				case FREYA_STAND:
				{
					world.canSpawnMobs = false;
					world.isSupportActive = false;
					DecayTaskManager.getInstance().cancel(world.freya);
					manageDespawnMinions(world);
					cancelQuestTimers("SPAWN_KNIGHT", world.getInstanceId());	//+[JOJO]
					cancelQuestTimer("ATTACK_FREYA", world.supp_Jinia, null);
					cancelQuestTimer("ATTACK_FREYA", world.supp_Kegor, null);
					cancelQuestTimer("GIVE_SUPPORT", world.controller, null);
					cancelQuestTimer("CAST_BLIZZARD", world.controller, null);
					
					final long reenter = calculateNextInstanceTime();
					for (L2PcInstance player : world.playersInside)
					{
						if (player != null && player.getInstanceId() == world.getInstanceId())
						{
							InstanceManager.getInstance().setInstanceTime(player.getObjectId(), TEMPLATE_ID, reenter);
							final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.INSTANT_ZONE_S1_RESTRICTED);
							sm.addInstanceName(TEMPLATE_ID);
							player.sendPacket(sm);
						}
					}
					
					manageMovie(world, 19);
					startQuestTimer("FINISH_STAGE", 16000, world.controller, null);
					startQuestTimer("FINISH_WORLD", 300000, world.controller, null);
					break;
				}
				case KNIGHT:
				{
					cancelQuestTimers(npc);	//+[JOJO] "ICE_RUPTURE"
					final L2Npc spawnedBy = npc.getVariables().getObject("SPAWNED_NPC", L2Npc.class);
					final NpcVariables var = world.controller.getVariables();
					int knightCount = var.getInt("KNIGHT_COUNT");
					
					if (var.getInt("FREYA_MOVE") == 0 && world.isStatus(1))
					{
						var.set("FREYA_MOVE", 1);
						manageScreenMsg(world, NpcStringId.FREYA_HAS_STARTED_TO_MOVE);
						world.freya.setIsRunning(true);
						world.freya.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, MIDDLE_POINT);
					}
					
					if (knightCount < 10 && world.isStatus(2))
					{
						knightCount++;
						var.set("KNIGHT_COUNT", knightCount);
						
						if (knightCount == 10)
						{
							notifyEvent("STAGE_2_MOVIE", world.controller, null);
							world.setStatus(3);
						}
					}
					
					if (spawnedBy != null)
					{
						startQuestTimer("SPAWN_KNIGHT", getRandom(30, 60) * 1000, spawnedBy, null);
					}
					world.spawnedMobs.remove(npc);
					break;
				}
				case GLACIER:
				{
					cancelQuestTimers(npc);	//+[JOJO] "CHANGE_STATE","CAST_SKILL"
					startQuestTimer("SPAWN_GLACIER", getRandom(30, 60) * 1000, world.controller, null);
					world.spawnedMobs.remove(npc);
					break;
				}
				case BREATH:
				{
					cancelQuestTimers(npc);	//+[JOJO] "BLIZZARD","ELEMENTAL_SUICIDE"
					world.spawnedMobs.remove(npc);
					break;
				}
			}
		}
		return super.onKill(npc, killer, isSummon);
	}
	
	private void enterInstance(L2PcInstance player, String template)
	{
		InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
		
		if (world != null)
		{
			if (world instanceof IQCNBWorld)
			{
				player.stopAllEffectsExceptThoseThatLastThroughDeath();
				if (player.hasSummon())
				{
					player.getSummon().stopAllEffectsExceptThoseThatLastThroughDeath();
				}
				
				if (world.isStatus(4))
				{
					teleportPlayer(player, BATTLE_PORT, world.getInstanceId());
				}
				else
				{
					teleportPlayer(player, ENTER_LOC[getRandom(ENTER_LOC.length)], world.getInstanceId(), false);
				}
				return;
			}
			player.sendPacket(SystemMessageId.ALREADY_ENTERED_ANOTHER_INSTANCE_CANT_ENTER);
			return;
		}
		
		if (checkConditions(player))
		{
			world = new IQCNBWorld();
			world.setInstanceId(InstanceManager.getInstance().createDynamicInstance(template));
			world.setTemplateId(TEMPLATE_ID);
			world.setStatus(0);
			InstanceManager.getInstance().addWorld(world);
			_log.info("Ice Queen Castle started (Normal Battle)" + template + " Instance: " + world.getInstanceId() + " created by player: " + player.getName());
			
			if (!player.isInParty())
			{
				managePlayerEnter(player, (IQCNBWorld) world);
			}
			else if (player.getParty().isInCommandChannel())
			{
				for (L2PcInstance players : player.getParty().getCommandChannel().getMembers())
				{
					managePlayerEnter(players, (IQCNBWorld) world);
				}
			}
			else
			{
				for (L2PcInstance players : player.getParty().getMembers())
				{
					managePlayerEnter(players, (IQCNBWorld) world);
				}
			}
		}
	}
	
	private void managePlayerEnter(L2PcInstance player, IQCNBWorld world)
	{
		player.stopAllEffectsExceptThoseThatLastThroughDeath();
		L2Summon s;
		if ((s = player.getSummon()) != null)
		{
			s.stopAllEffectsExceptThoseThatLastThroughDeath();
		}
		world.playersInside.add(player);
		world.addAllowed(player.getObjectId());
		teleportPlayer(player, ENTER_LOC[getRandom(ENTER_LOC.length)], world.getInstanceId(), false);
	}
	
	private boolean checkConditions(L2PcInstance player)
	{
		final L2Party party = player.getParty();
		final L2CommandChannel channel = party != null ? party.getCommandChannel() : null;
		
		if (player.isGM() && player.canOverrideCond(PcCondOverride.INSTANCE_CONDITIONS))
		{
			return true;
		}
		
		if (party == null)
		{
			player.sendPacket(SystemMessageId.NOT_IN_PARTY_CANT_ENTER);
			return false;
		}
		else if (channel == null)
		{
			player.sendPacket(SystemMessageId.NOT_IN_COMMAND_CHANNEL_CANT_ENTER);
			return false;
		}
		else if (player != channel.getLeader())
		{
			player.sendPacket(SystemMessageId.ONLY_PARTY_LEADER_CAN_ENTER);
			return false;
		}
		else if (channel.getMemberCount() < MIN_PLAYERS || channel.getMemberCount() > MAX_PLAYERS)
		{
			player.sendPacket(SystemMessageId.PARTY_EXCEEDED_THE_LIMIT_CANT_ENTER);
			return false;
		}
		for (L2PcInstance channelMember : channel.getMembers())
		{
			if (channelMember.getLevel() < MIN_LEVEL)
			{
				SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_LEVEL_REQUIREMENT_NOT_SUFFICIENT);
				sm.addPcName(channelMember);
				party.broadcastPacket(sm);
				return false;
			}
			else 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);
				return false;
			}
			else if (System.currentTimeMillis() < InstanceManager.getInstance().getInstanceTime(channelMember.getObjectId(), TEMPLATE_ID))
			{
				SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_MAY_NOT_REENTER_YET);
				sm.addPcName(channelMember);
				party.broadcastPacket(sm);
				return false;
			}
		}
		return true;
	}
	
	private void manageRandomAttack(IQCNBWorld world, L2Attackable mob)
	{
		final List<L2PcInstance> players = new ArrayList<>();
		for (L2PcInstance player : world.playersInside)
		{
			if (player != null && !player.isDead() && player.getInstanceId() == world.getInstanceId() && !player.isInvisible())
			{
				players.add(player);
			}
		}
		
		if (players.size() > 0)
		{
			final L2PcInstance target = players.get(Rnd.get(players.size()));
			mob.addDamageHate(target, 0, 999);
			mob.setIsRunning(true);
			mob.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target);
		}
		else
		{
			startQuestTimer("FIND_TARGET", 10000, mob, null);
		}
	}
	
	private void manageDespawnMinions(IQCNBWorld world)
	{
		assert world.canSpawnMobs == false;
		for (L2Attackable mob : world.spawnedMobs)/*18853決氷石|18854氷宮の息吹|18855氷宮の騎士*/
		{
			if (mob != null)
			{
				cancelQuestTimers(mob);	//+[JOJO] "ICE_RUPTURE"@18855氷宮の騎士
				if (!mob.isDead())
				{
					mob.doDie(null);
				}
			}
		}
	}
	
	private void manageTimer(IQCNBWorld world, int time)
	{
		for (L2PcInstance player : world.playersInside)
		{
			if (player != null && player.getInstanceId() == world.getInstanceId())
			{
				player.sendPacket(new ExSendUIEvent(player, false, false, time, 0, NpcStringId.TIME_REMAINING_UNTIL_NEXT_BATTLE));
			}
		}
	}
	
	private void manageScreenMsg(IQCNBWorld world, NpcStringId stringId)
	{
		L2GameServerPacket packet = new ExShowScreenMessage(stringId, 2, 6000);
		for (L2PcInstance player : world.playersInside)
		{
			if (player != null && player.getInstanceId() == world.getInstanceId())
			{
				player.sendPacket(packet);
			}
		}
	}
	
	private void manageMovie(IQCNBWorld world, int movie)
	{
		for (L2PcInstance player : world.playersInside)
		{
			if (player != null && player.getInstanceId() == world.getInstanceId())
			{
				player.showQuestMovie(movie);
			}
		}
	}
	
	public static void main(String[] args)
	{
		new IceQueensCastleNormalBattle();
	}
}