/*
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package ai.individual;

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

import java.util.ArrayList;
import java.util.List;

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

import com.l2jserver.Config;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.SkillData;
import com.l2jserver.gameserver.enums.MountType;
import com.l2jserver.gameserver.instancemanager.GrandBossManager;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.L2Party;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.StatsSet;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2DecoyInstance;
import com.l2jserver.gameserver.model.actor.instance.L2GrandBossInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.itemcontainer.PcInventory;
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.model.zone.type.L2BossZone;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.CreatureSay;
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.PlaySound;
import com.l2jserver.gameserver.network.serverpackets.SocialAction;
import com.l2jserver.gameserver.network.serverpackets.SpecialCamera;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.gameserver.network.serverpackets.ValidateLocation;
import com.l2jserver.gameserver.util.Broadcast;
import com.l2jserver.gameserver.util.Util;

/**
 * Valakas AI
 * @author Kerberos
 */
public class Valakas9103 extends AbstractNpcAI
{
	final int Config_Valakas_Wait_Time = Config.VALAKAS_WAIT_TIME * 60000;	// r5833
	final int Config_Interval_Of_Valakas_Spawn = Config.VALAKAS_SPAWN_INTERVAL * 3600000;	// r5833
	final int Config_Random_Of_Valakas_Spawn = Config.VALAKAS_SPAWN_RANDOM * 3600000;	// r5833
	
	private int i_ai0 = 0;
	private int i_ai1 = 0;
	private int i_ai2 = 0;
	private int i_ai3 = 0;
	private int i_ai4 = 0;
	private int i_quest0 = 0;
	private long i_quest1 = 0; // time to tracking valakas when was last time attacked
	private int i_quest2 = 0; // hate value for 1st player
	private int i_quest3 = 0; // hate value for 2nd player
	private int i_quest4 = 0; // hate value for 3rd player
	private L2Character c_quest2 = null; // 1st most hated target
	private L2Character c_quest3 = null; // 2nd most hated target
	private L2Character c_quest4 = null; // 3rd most hated target
	
	private static final int VALAKAS = 29028;
	private static final int VALAKAS_CIRCLET = 8567;
	
	// Valakas Status Tracking :
	private static final byte DORMANT = 0; // Valakas is spawned and no one has entered yet. Entry is unlocked
	private static final byte WAITING = 1; // Valakas is spawend and someone has entered, triggering a 30 minute window for additional people to enter
	// before he unleashes his attack. Entry is unlocked
	private static final byte FIGHTING = 2; // Valakas is engaged in battle, annihilating his foes. Entry is locked
	private static final byte DEAD = 3; // Valakas has been killed. Entry is locked
	
	private static L2BossZone _Zone;
	
	// Boss: Valakas
	private Valakas9103(int id, String name, String descr)
	{
		super(id, name, descr);
		
		addMoveFinishedId(VALAKAS);
		
		int[] mob =
		{
			VALAKAS
		};
		registerMobs(mob);
		i_ai0 = 0;
		i_ai1 = 0;
		i_ai2 = 0;
		i_ai3 = 0;
		i_ai4 = 0;
		i_quest0 = 0;
		i_quest1 = System.currentTimeMillis();
		_Zone = GrandBossManager.getInstance().getZone(212852, -114842, -1632);
		StatsSet info = GrandBossManager.getInstance().getStatsSet(VALAKAS);
		int status = GrandBossManager.getInstance().getBossStatus(VALAKAS);
		if (info.getInt("loc_x") == 0 && info.getInt("loc_y") == 0) status = DEAD;	//[JOJO]
		if (status == DEAD)
		{
			// load the unlock date and time for valakas from DB
			long temp = info.getLong("respawn_time") - System.currentTimeMillis();
			// if valakas is locked until a certain time, mark it so and start the unlock timer
			// the unlock time has not yet expired. Mark valakas as currently locked. Setup a timer
			// to fire at the correct time (calculate the time between now and the unlock time,
			// setup a timer to fire after that many msec)
			if (temp > 0)
			{
				startQuestTimer("valakas_unlock", temp, null, null);
				_log.info("AI script: Next spawn date of Valakas is " + GrandBossManager.respawnTimeFormat(info) + ".");
			}
			else
			{
				// the time has already expired while the server was offline. Immediately spawn valakas in his cave.
				// also, the status needs to be changed to DORMANT
				L2GrandBossInstance valakas = (L2GrandBossInstance) addSpawn(VALAKAS, -105200, -253104, -15264, 0, false, 0);
				GrandBossManager.getInstance().setBossStatus(VALAKAS, DORMANT);
				GrandBossManager.getInstance().addBoss(valakas);
				final L2Npc _valakas = valakas;
				ThreadPoolManager.getInstance().scheduleGeneral(new Runnable()
				{
					@Override
					public void run()
					{
						try
						{
							_valakas.setIsInvul(true);
							_valakas.setRunning();
						}
						catch (Throwable e)
						{
						}
					}
				}, 100L);
			//	startQuestTimer("1003", 60000, valakas, null, true);
			}
		}
		else
		{
			int loc_x = info.getInt("loc_x");
			int loc_y = info.getInt("loc_y");
			int loc_z = info.getInt("loc_z") - com.l2jserver.Config.NPC_SPAWN_Z_MARGIN;
			int heading = info.getInt("heading");
			final int hp = info.getInt("currentHP");
			final int mp = info.getInt("currentMP");
			L2GrandBossInstance valakas = (L2GrandBossInstance) addSpawn(VALAKAS, loc_x, loc_y, loc_z, heading, false, 0);
			GrandBossManager.getInstance().addBoss(valakas);
			final L2Npc _valakas = valakas;
			final int _status = status;
			ThreadPoolManager.getInstance().scheduleGeneral(new Runnable()
			{
				@Override
				public void run()
				{
					try
					{
						_valakas.setCurrentHpMp(hp, mp);
						if (_status != FIGHTING)
						{
							_valakas.setIsInvul(true);
						}
						_valakas.setRunning();
					}
					catch (Throwable e)
					{
					}
				}
			}, 100L);
			
		//	startQuestTimer("1003", 60000, valakas, null, true);	//-[JOJO]
			if (status == WAITING)
			{
				// Start timer to lock entry after 30 minutes
				startQuestTimer("1001_3", Config_Valakas_Wait_Time - 180000, valakas, null);
			//	startQuestTimer("1001", Config_Valakas_Wait_Time, valakas, null);
			}
			else if (status == FIGHTING)
			{
				// Start repeating timer to check for inactivity
				startQuestTimer("1002", 60000, valakas, null, true);
				valakas.setIsInvul(false);
			}
		}
	}
	
	@Override
	public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
	{
		if (npc != null)
		{
			if (event.equals("1001_3")) // <<== scripts/teleports/GrandBossTeleporters/GrandBossTeleporters.java
			{
				startQuestTimer("1001_2", 180000 - 120000, npc, null);
				startQuestTimer("1001_1", 180000 -  60000, npc, null);
				startQuestTimer("1001_0", 180000 -  10000, npc, null);
				startQuestTimer("1001"  , 180000 -      0, npc, null);
				screenMessage("3分前");
				announce("ヴァラカスは噴火口の中央から登場します。");
			}
			else if (event == "1001_2")
			{
				screenMessage("2分前");
			}
			else if (event == "1001_1")
			{
				screenMessage("1分前");
			}
			else if (event == "1001_0")
			{
				_Zone.broadcastPacket(new Earthquake(212852, -114842, -1632, 40, 15));
			}
			else if (event == "1001")
			{
				((L2GrandBossInstance) npc).setIsInSocialAction(true);
				npc.setHeading(0);
				npc.teleToLocation(212852, -114842, -1632, 0, false);
				i_quest1 = System.currentTimeMillis();
				screenMessage("覚醒");
				startQuestTimer("1100",   500, npc, null);
				startQuestTimer("1101",  2000, npc, null);
				startQuestTimer("1102",  4000, npc, null);
				startQuestTimer("1103",  6000, npc, null);
				startQuestTimer("1104",  8000, npc, null);
				startQuestTimer("1105", 13000, npc, null);
				startQuestTimer("1106", 20000, npc, null);
				startQuestTimer("1107", 22000, npc, null);
				startQuestTimer("1108", 25000, npc, null);
				startQuestTimer("1109", 27000, npc, null);
				startQuestTimer("1110", 32000, npc, null);
			}
			else if (event == "1002")
			{
				long temp = System.currentTimeMillis() - i_quest1;
				if (temp > 900000)
				{
					npc.setIsInvul(true);
					npc.getAI().setIntention(AI_INTENTION_IDLE);
					npc.teleToLocation(-105200, -253104, -15264, 0, false);
					GrandBossManager.getInstance().setBossStatus(VALAKAS, DORMANT);
					npc.setCurrentHpMp(npc.getMaxHp(), npc.getMaxMp());
					_Zone.oustAllPlayers();
					cancelQuestTimer("1002", npc, null);
					cancelQuestTimer("1003", npc, null);	//+[JOJO]
					i_quest2 = i_quest3 = i_quest4 = 0;
					c_quest2 = c_quest3 = c_quest4 = null;
				}
				else if (isOutOfRange(npc))
				{
					home(npc);
				}
				else if (temp > 60000)
				{
					getRandomSkill(npc);
				}
			}
			else if (event == "1003")
			{
				getRandomSkill(npc);
			}
			else if (event == "1100")
			{
				_Zone.broadcastPacket(new SocialAction(npc, 3));
				flickPlayers(npc.getX(), npc.getY(), 1500, 5500);
			}
			else if (event == "1101")
			{
				_Zone.broadcastPacket(new SpecialCamera(npc.getObjectId(), 1300, 180, 10, 1, 15000, 0, 0, 1, 0));
			}
			else if (event == "1102")
			{
				_Zone.broadcastPacket(new PlaySound(1, "BS03_A", 1, npc.getObjectId(), 212852, -114842, -1632));
			}
			else if (event == "1103")
			{
				_Zone.broadcastPacket(new SpecialCamera(npc.getObjectId(), 1300, 180, -5, 1500, 15000, 0, -5, 1, 0));
			}
			else if (event == "1104")
			{
				_Zone.broadcastPacket(new SpecialCamera(npc.getObjectId(), 500, 180, -8, 600, 15000, 0, 60, 1, 0));
			}
			else if (event == "1105")
			{
				_Zone.broadcastPacket(new SpecialCamera(npc.getObjectId(), 800, 180, -8, 3000, 15000, 0, 30, 1, 0));
			}
			else if (event == "1106")
			{
				_Zone.broadcastPacket(new SpecialCamera(npc.getObjectId(), 700, 150, 30, 1000, 15000, -10, 60, 1, 0));
			}
			else if (event == "1107")
			{
				_Zone.broadcastPacket(new SpecialCamera(npc.getObjectId(), 1200, 150, 20, 2900, 15000, -10, 30, 1, 0));
			}
			else if (event == "1108")
			{
				_Zone.broadcastPacket(new SpecialCamera(npc.getObjectId(), 750, 170, 15, 4000, 15000, 10, -15, 1, 0));
			}
			else if (event == "1109")
			{
				for (L2Character ch : _Zone.getCharactersInside())
				{
					if (ch instanceof L2PcInstance)
					{
						L2PcInstance pc = (L2PcInstance) ch;
						pc.sendPacket(new SpecialCamera(npc.getObjectId()
								, minimax(800, (int)Math.ceil(com.l2jserver.gameserver.util.Util.calculateDistance(pc, npc, true)), 3500)
								, calcCameraYaw(pc.getX(), pc.getY(), npc.getX(), npc.getY()), -10
								, 2000, 15000, 0, -15, 1, 0));
					}
				}
			}
			else if (event == "1110")
			{
				// reset camera
				for (L2Character ch : _Zone.getCharactersInside())
				{
					if (ch instanceof L2PcInstance)
					{
						L2PcInstance pc = (L2PcInstance) ch;
						pc.sendPacket(new SpecialCamera(ch.getObjectId()
								, 10
								, calcCameraYaw(pc.getX(), pc.getY(), npc.getX(), npc.getY()), 0
								, 100, 700, 0, 0, 1, 0));
					}
				}
				GrandBossManager.getInstance().setBossStatus(VALAKAS, FIGHTING);
				L2GrandBossInstance valakas = (L2GrandBossInstance)npc;
				valakas.setIsInSocialAction(false);
				npc.setIsInvul(false);
				Broadcast.announceToOnlinePlayers("火竜ヴァラカスが登場しました。");
				announce("ヴァラカスを15分間攻撃しないでいると、巣に戻ってしまいます。");
				startQuestTimer("1002", 60000, npc, null, true);
				getRandomSkill(npc);
			}
			else if (event == "1111")
			{
				startQuestTimer("1112", 3500, npc, null);
				_Zone.broadcastPacket(new SpecialCamera(npc.getObjectId(), 1100, 210, -5, 3000, 10000, -13, 0, 1, 1));
			}
			else if (event == "1112")
			{
				startQuestTimer("1113", 4500, npc, null);
				_Zone.broadcastPacket(new SpecialCamera(npc.getObjectId(), 1300, 200, -8, 3000, 10000, 0, 15, 1, 1));
			}
			else if (event == "1113")
			{
				startQuestTimer("1114", 500, npc, null);
				_Zone.broadcastPacket(new SpecialCamera(npc.getObjectId(), 1000, 190, 0, 3000, 10000, 0, 10, 1, 1));
			}
			else if (event == "1114")
			{
				startQuestTimer("1115", 4600, npc, null);
				_Zone.broadcastPacket(new SpecialCamera(npc.getObjectId(), 1700, 120, 0, 2500, 10000, 12, 40, 1, 1));
			}
			else if (event == "1115")
			{
				startQuestTimer("1116", 750, npc, null);
				_Zone.broadcastPacket(new SpecialCamera(npc.getObjectId(), 1700, 20, 0, 3000, 10000, 10, 10, 1, 1));
			}
			else if (event == "1116")
			{
				startQuestTimer("1117", 2500, npc, null);
				_Zone.broadcastPacket(new SpecialCamera(npc.getObjectId(), 1700, 10, 0, 3000, 10000, 20, 70, 1, 1));
			}
			else if (event == "1117")
			{
				_Zone.broadcastPacket(new SpecialCamera(npc.getObjectId(), 1700, 10, 0, 3000, 250, 20, -20, 1, 1));
				addSpawn(31759, 212852, -114842, -1632, 0, false, 900000);
				final double radius = 1500;
				for (int i = 0; i < /*JOJO*/19; i++)
				{
					int x = (int) (radius * Math.cos(i * .331)); // .331~2pi/19
					int y = (int) (radius * Math.sin(i * .331));
					addSpawn(31759, 212852 + x, -114842 + y, -1632, 0, false, 900000);
				}
			//	cancelQuestTimer("1002", npc, null);
				startQuestTimer("remove_players", 900000, null, null);
				//
				screenMessage("討伐成功");
				announce("15分以内にヴァラカスの棲処から退去してください。");
			}
		}
		else
		{
			if (event == "valakas_unlock")
			{
				L2GrandBossInstance valakas = (L2GrandBossInstance) addSpawn(VALAKAS, -105200, -253104, -15264, 32768, false, 0);
				GrandBossManager.getInstance().addBoss(valakas);
				GrandBossManager.getInstance().setBossStatus(VALAKAS, DORMANT);
			}
			else if (event == "remove_players")
			{
				_Zone.oustAllPlayers();
			}
		}
		return super.onAdvEvent(event, npc, player);
	}
	
	@Override
	public String onSpawn(L2Npc npc)
	{
		npc.disableCoreAI(true);
		return super.onSpawn(npc);
	}
	
	@Override
	public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isPet, Skill skill)
	{
		if (npc.isInvul())
		{
			return null;
		}
		i_quest1 = System.currentTimeMillis();
 //[JOJO] 削除: ヴァラカスが死んだ瞬間、ＰＣがゴダード城の村に強制送還されてしまう。
 //		if (GrandBossManager.getInstance().getBossStatus(VALAKAS) != FIGHTING)
 //		{
 //			attacker.teleToLocation(150037, -57255, -2976);
 //		}
		if (attacker.getMountType() == MountType.STRIDER)
		{
			if (!attacker.isAffectedBySkill(getSkillId(4258)))
			{
				npc.setTarget(attacker);
				npc.doCast(SkillData.getInstance().getSkill(4258, 1));
			}
		}
		if (attacker.getZ() < (npc.getZ() + 200))
		{
			if (i_ai2 == 0)
			{
				i_ai1 = (i_ai1 + damage);
			}
			if (i_quest0 == 0)
			{
				i_ai4 = (i_ai4 + damage);
			}
			if (i_quest0 == 0)
			{
				i_ai3 = (i_ai3 + damage);
			}
			else if (i_ai2 == 0)
			{
				i_ai0 = (i_ai0 + damage);
			}
			if (i_quest0 == 0)
			{
				if ((((i_ai4 / npc.getMaxHp()) * 100)) > 1)
				{
					if (i_ai3 > (i_ai4 - i_ai3))
					{
						i_ai3 = 0;
						i_ai4 = 0;
						npc.setTarget(npc);
						npc.doCast(SkillData.getInstance().getSkill(4687, 1));
						i_quest0 = 1;
					}
				}
			}
			
		}
		int i1 = 0;
		if (skill == null)
		{
			if (attacker == c_quest2)
			{
				if (((damage * 1000) + 1000) > i_quest2)
				{
					i_quest2 = ((damage * 1000) + getRandom(3000));
				}
			}
			else if (attacker == c_quest3)
			{
				if (((damage * 1000) + 1000) > i_quest3)
				{
					i_quest3 = ((damage * 1000) + getRandom(3000));
				}
			}
			else if (attacker == c_quest4)
			{
				if (((damage * 1000) + 1000) > i_quest4)
				{
					i_quest4 = ((damage * 1000) + getRandom(3000));
				}
			}
			else if (i_quest2 > i_quest3)
			{
				i1 = 3;
			}
			else if (i_quest2 == i_quest3)
			{
				if (getRandom(100) < 50)
				{
					i1 = 2;
				}
				else
				{
					i1 = 3;
				}
			}
			else if (i_quest2 < i_quest3)
			{
				i1 = 2;
			}
			if (i1 == 2)
			{
				if (i_quest2 > i_quest4)
				{
					i1 = 4;
				}
				else if (i_quest2 == i_quest4)
				{
					if (getRandom(100) < 50)
					{
						i1 = 2;
					}
					else
					{
						i1 = 4;
					}
				}
				else if (i_quest2 < i_quest4)
				{
					i1 = 2;
				}
			}
			else if (i1 == 3)
			{
				if (i_quest3 > i_quest4)
				{
					i1 = 4;
				}
				else if (i_quest3 == i_quest4)
				{
					if (getRandom(100) < 50)
					{
						i1 = 3;
					}
					else
					{
						i1 = 4;
					}
				}
				else if (i_quest3 < i_quest4)
				{
					i1 = 3;
				}
			}
			if (i1 == 2)
			{
				i_quest2 = (damage * 1000) + getRandom(3000);
				c_quest2 = attacker;
			}
			else if (i1 == 3)
			{
				i_quest3 = (damage * 1000) + getRandom(3000);
				c_quest3 = attacker;
			}
			else if (i1 == 4)
			{
				i_quest4 = (damage * 1000) + getRandom(3000);
				c_quest4 = attacker;
			}
		}
		else if (npc.getCurrentHp() > ((npc.getMaxHp() * 1) / 4))
		{
			if (attacker == c_quest2)
			{
				if ((((damage / 30) * 1000) + 1000) > i_quest2)
				{
					i_quest2 = (((damage / 30) * 1000) + getRandom(3000));
				}
			}
			else if (attacker == c_quest3)
			{
				if ((((damage / 30) * 1000) + 1000) > i_quest3)
				{
					i_quest3 = (((damage / 30) * 1000) + getRandom(3000));
				}
			}
			else if (attacker == c_quest4)
			{
				if ((((damage / 30) * 1000) + 1000) > i_quest4)
				{
					i_quest4 = (((damage / 30) * 1000) + getRandom(3000));
				}
			}
			else if (i_quest2 > i_quest3)
			{
				i1 = 3;
			}
			else if (i_quest2 == i_quest3)
			{
				if (getRandom(100) < 50)
				{
					i1 = 2;
				}
				else
				{
					i1 = 3;
				}
			}
			else if (i_quest2 < i_quest3)
			{
				i1 = 2;
			}
			if (i1 == 2)
			{
				if (i_quest2 > i_quest4)
				{
					i1 = 4;
				}
				else if (i_quest2 == i_quest4)
				{
					if (getRandom(100) < 50)
					{
						i1 = 2;
					}
					else
					{
						i1 = 4;
					}
				}
				else if (i_quest2 < i_quest4)
				{
					i1 = 2;
				}
			}
			else if (i1 == 3)
			{
				if (i_quest3 > i_quest4)
				{
					i1 = 4;
				}
				else if (i_quest3 == i_quest4)
				{
					if (getRandom(100) < 50)
					{
						i1 = 3;
					}
					else
					{
						i1 = 4;
					}
				}
				else if (i_quest3 < i_quest4)
				{
					i1 = 3;
				}
			}
			if (i1 == 2)
			{
				i_quest2 = (((damage / 30) * 1000) + getRandom(3000));
				c_quest2 = attacker;
			}
			else if (i1 == 3)
			{
				i_quest3 = (((damage / 30) * 1000) + getRandom(3000));
				c_quest3 = attacker;
			}
			else if (i1 == 4)
			{
				i_quest4 = (((damage / 30) * 1000) + getRandom(3000));
				c_quest4 = attacker;
			}
		}
		else if (npc.getCurrentHp() > ((npc.getMaxHp() * 2) / 4))
		{
			if (attacker == c_quest2)
			{
				if ((((damage / 50) * 1000) + 1000) > i_quest2)
				{
					i_quest2 = (((damage / 50) * 1000) + getRandom(3000));
				}
			}
			else if (attacker == c_quest3)
			{
				if ((((damage / 50) * 1000) + 1000) > i_quest3)
				{
					i_quest3 = (((damage / 50) * 1000) + getRandom(3000));
				}
			}
			else if (attacker == c_quest4)
			{
				if ((((damage / 50) * 1000) + 1000) > i_quest4)
				{
					i_quest4 = (((damage / 50) * 1000) + getRandom(3000));
				}
			}
			else if (i_quest2 > i_quest3)
			{
				i1 = 3;
			}
			else if (i_quest2 == i_quest3)
			{
				if (getRandom(100) < 50)
				{
					i1 = 2;
				}
				else
				{
					i1 = 3;
				}
			}
			else if (i_quest2 < i_quest3)
			{
				i1 = 2;
			}
			if (i1 == 2)
			{
				if (i_quest2 > i_quest4)
				{
					i1 = 4;
				}
				else if (i_quest2 == i_quest4)
				{
					if (getRandom(100) < 50)
					{
						i1 = 2;
					}
					else
					{
						i1 = 4;
					}
				}
				else if (i_quest2 < i_quest4)
				{
					i1 = 2;
				}
			}
			else if (i1 == 3)
			{
				if (i_quest3 > i_quest4)
				{
					i1 = 4;
				}
				else if (i_quest3 == i_quest4)
				{
					if (getRandom(100) < 50)
					{
						i1 = 3;
					}
					else
					{
						i1 = 4;
					}
				}
				else if (i_quest3 < i_quest4)
				{
					i1 = 3;
				}
			}
			if (i1 == 2)
			{
				i_quest2 = (((damage / 50) * 1000) + getRandom(3000));
				c_quest2 = attacker;
			}
			else if (i1 == 3)
			{
				i_quest3 = (((damage / 50) * 1000) + getRandom(3000));
				c_quest3 = attacker;
			}
			else if (i1 == 4)
			{
				i_quest4 = (((damage / 50) * 1000) + getRandom(3000));
				c_quest4 = attacker;
			}
		}
		else if (npc.getCurrentHp() > ((npc.getMaxHp() * 3) / 4.0))
		{
			if (attacker == c_quest2)
			{
				if ((((damage / 100) * 1000) + 1000) > i_quest2)
				{
					i_quest2 = (((damage / 100) * 1000) + getRandom(3000));
				}
			}
			else if (attacker == c_quest3)
			{
				if ((((damage / 100) * 1000) + 1000) > i_quest3)
				{
					i_quest3 = (((damage / 100) * 1000) + getRandom(3000));
				}
			}
			else if (attacker == c_quest4)
			{
				if ((((damage / 100) * 1000) + 1000) > i_quest4)
				{
					i_quest4 = (((damage / 100) * 1000) + getRandom(3000));
				}
			}
			else if (i_quest2 > i_quest3)
			{
				i1 = 3;
			}
			else if (i_quest2 == i_quest3)
			{
				if (getRandom(100) < 50)
				{
					i1 = 2;
				}
				else
				{
					i1 = 3;
				}
			}
			else if (i_quest2 < i_quest3)
			{
				i1 = 2;
			}
			if (i1 == 2)
			{
				if (i_quest2 > i_quest4)
				{
					i1 = 4;
				}
				else if (i_quest2 == i_quest4)
				{
					if (getRandom(100) < 50)
					{
						i1 = 2;
					}
					else
					{
						i1 = 4;
					}
				}
				else if (i_quest2 < i_quest4)
				{
					i1 = 2;
				}
			}
			else if (i1 == 3)
			{
				if (i_quest3 > i_quest4)
				{
					i1 = 4;
				}
				else if (i_quest3 == i_quest4)
				{
					if (getRandom(100) < 50)
					{
						i1 = 3;
					}
					else
					{
						i1 = 4;
					}
				}
				else if (i_quest3 < i_quest4)
				{
					i1 = 3;
				}
				if (i1 == 2)
				{
					i_quest2 = (((damage / 100) * 1000) + getRandom(3000));
					c_quest2 = attacker;
				}
				else if (i1 == 3)
				{
					i_quest3 = (((damage / 100) * 1000) + getRandom(3000));
					c_quest3 = attacker;
				}
				else if (i1 == 4)
				{
					i_quest4 = (((damage / 100) * 1000) + getRandom(3000));
					c_quest4 = attacker;
				}
			}
		}
		else if (attacker == c_quest2)
		{
			if ((((damage / 150) * 1000) + 1000) > i_quest2)
			{
				i_quest2 = (((damage / 150) * 1000) + getRandom(3000));
			}
		}
		else if (attacker == c_quest3)
		{
			if ((((damage / 150) * 1000) + 1000) > i_quest3)
			{
				i_quest3 = (((damage / 150) * 1000) + getRandom(3000));
			}
		}
		else if (attacker == c_quest4)
		{
			if ((((damage / 150) * 1000) + 1000) > i_quest4)
			{
				i_quest4 = (((damage / 150) * 1000) + getRandom(3000));
			}
		}
		else if (i_quest2 > i_quest3)
		{
			i1 = 3;
		}
		else if (i_quest2 == i_quest3)
		{
			if (getRandom(100) < 50)
			{
				i1 = 2;
			}
			else
			{
				i1 = 3;
			}
		}
		else if (i_quest2 < i_quest3)
		{
			i1 = 2;
		}
		if (i1 == 2)
		{
			if (i_quest2 > i_quest4)
			{
				i1 = 4;
			}
			else if (i_quest2 == i_quest4)
			{
				if (getRandom(100) < 50)
				{
					i1 = 2;
				}
				else
				{
					i1 = 4;
				}
			}
			else if (i_quest2 < i_quest4)
			{
				i1 = 2;
			}
		}
		else if (i1 == 3)
		{
			if (i_quest3 > i_quest4)
			{
				i1 = 4;
			}
			else if (i_quest3 == i_quest4)
			{
				if (getRandom(100) < 50)
				{
					i1 = 3;
				}
				else
				{
					i1 = 4;
				}
			}
			else if (i_quest3 < i_quest4)
			{
				i1 = 3;
			}
		}
		if (i1 == 2)
		{
			i_quest2 = (((damage / 150) * 1000) + getRandom(3000));
			c_quest2 = attacker;
		}
		else if (i1 == 3)
		{
			i_quest3 = (((damage / 150) * 1000) + getRandom(3000));
			c_quest3 = attacker;
		}
		else if (i1 == 4)
		{
			i_quest4 = (((damage / 150) * 1000) + getRandom(3000));
			c_quest4 = attacker;
		}
		getRandomSkill(npc);
		return super.onAttack(npc, attacker, damage, isPet);
	}
	
	@Override
	public String onKill(L2Npc npc, L2PcInstance killer, boolean isPet)
	{
		cancelQuestTimer("1002", npc, null);	//+[JOJO]
		cancelQuestTimer("1003", npc, null);	//+[JOJO]
		i_quest2 = i_quest3 = i_quest4 = 0;
		c_quest2 = c_quest3 = c_quest4 = null;
		startQuestTimer("1111", 500, npc, null);
		_Zone.broadcastPacket(new SpecialCamera(npc.getObjectId(), 1700, 2000, 130, -1, 0, 10000, -20, 1, 1));
		_Zone.broadcastPacket(new PlaySound(1, "B03_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
		GrandBossManager.getInstance().setBossStatus(VALAKAS, DEAD);
		// Respawn time is 264 Hours - 72 Random Hours
		long respawnTime = Config_Interval_Of_Valakas_Spawn - getRandom(Config_Random_Of_Valakas_Spawn);
		startQuestTimer("valakas_unlock", respawnTime, null, null);
		// also save the respawn time so that the info is maintained past reboots
		StatsSet info = GrandBossManager.getInstance().getStatsSet(VALAKAS);
		info.set("respawn_time", System.currentTimeMillis() + respawnTime);
		GrandBossManager.getInstance().setStatsSet(VALAKAS, info);
		Broadcast.announceToOnlinePlayers("火竜ヴァラカスが死亡しました。次の復活は "+GrandBossManager.respawnTimeFormat(info)+" ごろです。");	//[JOJO]
		giveItemParty(VALAKAS_CIRCLET, killer, npc);	//+[JOJO]
		return super.onKill(npc, killer, isPet);
	}
	
	public void getRandomSkill(L2Npc npc)
	{
		if (npc.isInvul() || npc.isCastingNow())
		{
			return;
		}
		if (isOutOfRange(npc))
		{
			home(npc);
			return;
		}
		Skill skill = null;
		int i0 = 0;
		int i1 = 0;
		int i2 = 0;
		L2Character c2 = null;
		if (c_quest2 == null || c_quest2.isDead() || isOutOfRange(c_quest2))
		{
			i_quest2 = 0;
			c_quest2 = null;
		}
		if (c_quest3 == null || c_quest3.isDead() || isOutOfRange(c_quest3))
		{
			i_quest3 = 0;
			c_quest3 = null;
		}
		if (c_quest4 == null || c_quest4.isDead() || isOutOfRange(c_quest4))
		{
			i_quest4 = 0;
			c_quest4 = null;
		}
		if (i_quest2 > i_quest3)
		{
			i1 = 2;
			i2 = i_quest2;
			c2 = c_quest2;
		}
		else
		{
			i1 = 3;
			i2 = i_quest3;
			c2 = c_quest3;
		}
		if (i_quest4 > i2)
		{
			i1 = 4;
			i2 = i_quest4;
			c2 = c_quest4;
		}
		if (i2 == 0)
		{
			c2 = getRandomTarget(npc);
			if (c2 == null)
			{
				home(npc);
				return;
			}
			i2 = 500;	//TODO:
		}
		if (i2 > 0)
		{
			if (getRandom(100) < 70)
			{
				if (i1 == 2)
				{
					i_quest2 = 500;
				}
				else if (i1 == 3)
				{
					i_quest3 = 500;
				}
				else if (i1 == 4)
				{
					i_quest4 = 500;
				}
			}
			if (npc.getCurrentHp() > ((npc.getMaxHp() * 1) / 4))
			{
				i0 = 0;
				i1 = 0;
				if (Util.checkIfInRange(1423, npc, c2, true))
				{
					i0 = 1;
					i1 = 1;
				}
				if (c2.getZ() < (npc.getZ() + 200))
				{
					if (getRandom(100) < 20)
					{
						skill = SkillData.getInstance().getSkill(4690, 1);
					}
					else if (getRandom(100) < 15)
					{
						skill = SkillData.getInstance().getSkill(4689, 1);
					}
					else if ((getRandom(100) < 15) && (i0 == 1) && (i_quest0 == 1))
					{
						skill = SkillData.getInstance().getSkill(4685, 1);
						i_quest0 = 0;
					}
					else if ((getRandom(100) < 10) && (i1 == 1))
					{
						skill = SkillData.getInstance().getSkill(4688, 1);
					}
					else if (getRandom(100) < 35)
					{
						skill = SkillData.getInstance().getSkill(4683, 1);
					}
					else
					{
						if (getRandom(2) == 0)
						{
							skill = SkillData.getInstance().getSkill(4681, 1); // left hand
						}
						else
						{
							skill = SkillData.getInstance().getSkill(4682, 1); // right hand
						}
					}
				}
				else if (getRandom(100) < 20)
				{
					skill = SkillData.getInstance().getSkill(4690, 1);
				}
				else if (getRandom(100) < 15)
				{
					skill = SkillData.getInstance().getSkill(4689, 1);
				}
				else
				{
					skill = SkillData.getInstance().getSkill(4684, 1);
				}
			}
			else if (npc.getCurrentHp() > ((npc.getMaxHp() * 2) / 4))
			{
				i0 = 0;
				i1 = 0;
				if (Util.checkIfInRange(1423, npc, c2, true))
				{
					i0 = 1;
					i1 = 1;
				}
				if (c2.getZ() < (npc.getZ() + 200))
				{
					if (getRandom(100) < 5)
					{
						skill = SkillData.getInstance().getSkill(4690, 1);
					}
					else if (getRandom(100) < 10)
					{
						skill = SkillData.getInstance().getSkill(4689, 1);
					}
					else if ((getRandom(100) < 10) && (i0 == 1) && (i_quest0 == 1))
					{
						skill = SkillData.getInstance().getSkill(4685, 1);
						i_quest0 = 0;
					}
					else if ((getRandom(100) < 10) && (i1 == 1))
					{
						skill = SkillData.getInstance().getSkill(4688, 1);
					}
					else if (getRandom(100) < 20)
					{
						skill = SkillData.getInstance().getSkill(4683, 1);
					}
					else
					{
						if (getRandom(2) == 0)
						{
							skill = SkillData.getInstance().getSkill(4681, 1); // left hand
						}
						else
						{
							skill = SkillData.getInstance().getSkill(4682, 1); // right hand
						}
					}
				}
				else if (getRandom(100) < 5)
				{
					skill = SkillData.getInstance().getSkill(4690, 1);
				}
				else if (getRandom(100) < 10)
				{
					skill = SkillData.getInstance().getSkill(4689, 1);
				}
				else
				{
					skill = SkillData.getInstance().getSkill(4684, 1);
				}
			}
			else if (npc.getCurrentHp() > ((npc.getMaxHp() * 3) / 4.0))
			{
				i0 = 0;
				i1 = 0;
				if (Util.checkIfInRange(1423, npc, c2, true))
				{
					i0 = 1;
					i1 = 1;
				}
				if (c2.getZ() < (npc.getZ() + 200))
				{
					if (getRandom(100) < 0)
					{
						skill = SkillData.getInstance().getSkill(4690, 1);
					}
					else if (getRandom(100) < 5)
					{
						skill = SkillData.getInstance().getSkill(4689, 1);
					}
					else if ((getRandom(100) < 5) && (i0 == 1) && (i_quest0 == 1))
					{
						skill = SkillData.getInstance().getSkill(4685, 1);
						i_quest0 = 0;
					}
					else if ((getRandom(100) < 10) && (i1 == 1))
					{
						skill = SkillData.getInstance().getSkill(4688, 1);
					}
					else if (getRandom(100) < 15)
					{
						skill = SkillData.getInstance().getSkill(4683, 1);
					}
					else
					{
						if (getRandom(2) == 0)
						{
							skill = SkillData.getInstance().getSkill(4681, 1); // left hand
						}
						else
						{
							skill = SkillData.getInstance().getSkill(4682, 1); // right hand
						}
					}
				}
				else if (getRandom(100) < 0)
				{
					skill = SkillData.getInstance().getSkill(4690, 1);
				}
				else if (getRandom(100) < 5)
				{
					skill = SkillData.getInstance().getSkill(4689, 1);
				}
				else
				{
					skill = SkillData.getInstance().getSkill(4684, 1);
				}
			}
			else
			{
				i0 = 0;
				i1 = 0;
				if (Util.checkIfInRange(1423, npc, c2, true))
				{
					i0 = 1;
					i1 = 1;
				}
				if (c2.getZ() < (npc.getZ() + 200))
				{
					if (getRandom(100) < 0)
					{
						skill = SkillData.getInstance().getSkill(4690, 1);
					}
					else if (getRandom(100) < 10)
					{
						skill = SkillData.getInstance().getSkill(4689, 1);
					}
					else if ((getRandom(100) < 5) && (i0 == 1) && (i_quest0 == 1))
					{
						skill = SkillData.getInstance().getSkill(4685, 1);
						i_quest0 = 0;
					}
					else if ((getRandom(100) < 10) && (i1 == 1))
					{
						skill = SkillData.getInstance().getSkill(4688, 1);
					}
					else if (getRandom(100) < 15)
					{
						skill = SkillData.getInstance().getSkill(4683, 1);
					}
					else
					{
						if (getRandom(2) == 0)
						{
							skill = SkillData.getInstance().getSkill(4681, 1); // left hand
						}
						else
						{
							skill = SkillData.getInstance().getSkill(4682, 1); // right hand
						}
					}
				}
				else if (getRandom(100) < 0)
				{
					skill = SkillData.getInstance().getSkill(4690, 1);
				}
				else if (getRandom(100) < 10)
				{
					skill = SkillData.getInstance().getSkill(4689, 1);
				}
				else
				{
					skill = SkillData.getInstance().getSkill(4684, 1);
				}
			}
		}
		if (skill != null)
		{
			callSkillAI(npc, c2, skill);
		}
	}
	
	private void callSkillAI(L2Npc npc, L2Character target, Skill skill)
	{
		if (npc.isInvul())
		{
			return;
		}
		
		int range = skill.getCastRange();
		if (range <= 0) range = skill.getAffectRange();
		if (range <= 0) throw new RuntimeException();
		if (Util.checkIfInRange(range, npc, target, true))
		{
			cancelQuestTimer("1003", npc, null);
			switch (npc.getAI().getIntention())
			{
			case AI_INTENTION_ATTACK:
			case AI_INTENTION_ACTIVE:
			case AI_INTENTION_IDLE:
				break;
			default:
				npc.getAI().setIntention(AI_INTENTION_IDLE);
			}
			npc.setIsCastingNow(true);
			npc.setTarget(target);
			npc.doCast(skill);
		}
		else
		{
			if (getQuestTimer("1003", npc, null) == null)
				startQuestTimer("1003", 500, npc, null, true);
			npc.getAI().setIntention(AI_INTENTION_FOLLOW, target, null);
			npc.setIsCastingNow(false);
		}
	}
	
	public L2Character getRandomTarget(L2Npc npc)
	{
		FastList<L2Character> result = new FastList<>();
		for (L2Character target : _Zone.getCharactersInside())
		{
				if (target.isPlayer() || target.isSummon() || target instanceof L2DecoyInstance)
				{
					if (!isOutOfRange(target) && !target.isDead() && !target.isGM())
					{
						result.add(target);
					}
				}
		}
		if (result.size() == 0)
			return null;
		else
			return result.get(getRandom(result.size()));
	}
	
	@Override
	public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
	{
		if (npc.isInvul())
		{
			return null;
		}
		else if ((npc.getId() == VALAKAS) /*&& !npc.isInvul()*/)
		{
			getRandomSkill(npc);
		}
		return super.onSpellFinished(npc, player, skill);
	}
	
	@Override
	public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isPet)
	{
		int i1 = 0;
		if (GrandBossManager.getInstance().getBossStatus(VALAKAS) == FIGHTING)
		{
			if (npc.getCurrentHp() > ((npc.getMaxHp() * 1) / 4))
			{
				if (player == c_quest2)
				{
					if (((10 * 1000) + 1000) > i_quest2)
					{
						i_quest2 = ((10 * 1000) + getRandom(3000));
					}
				}
				else if (player == c_quest3)
				{
					if (((10 * 1000) + 1000) > i_quest3)
					{
						i_quest3 = ((10 * 1000) + getRandom(3000));
					}
				}
				else if (player == c_quest4)
				{
					if (((10 * 1000) + 1000) > i_quest4)
					{
						i_quest4 = ((10 * 1000) + getRandom(3000));
					}
				}
				else if (i_quest2 > i_quest3)
				{
					i1 = 3;
				}
				else if (i_quest2 == i_quest3)
				{
					if (getRandom(100) < 50)
					{
						i1 = 2;
					}
					else
					{
						i1 = 3;
					}
				}
				else if (i_quest2 < i_quest3)
				{
					i1 = 2;
				}
				if (i1 == 2)
				{
					if (i_quest2 > i_quest4)
					{
						i1 = 4;
					}
					else if (i_quest2 == i_quest4)
					{
						if (getRandom(100) < 50)
						{
							i1 = 2;
						}
						else
						{
							i1 = 4;
						}
					}
					else if (i_quest2 < i_quest4)
					{
						i1 = 2;
					}
				}
				else if (i1 == 3)
				{
					if (i_quest3 > i_quest4)
					{
						i1 = 4;
					}
					else if (i_quest3 == i_quest4)
					{
						if (getRandom(100) < 50)
						{
							i1 = 3;
						}
						else
						{
							i1 = 4;
						}
					}
					else if (i_quest3 < i_quest4)
					{
						i1 = 3;
					}
				}
				if (i1 == 2)
				{
					i_quest2 = ((10 * 1000) + getRandom(3000));
					c_quest2 = player;
				}
				else if (i1 == 3)
				{
					i_quest3 = ((10 * 1000) + getRandom(3000));
					c_quest3 = player;
				}
				else if (i1 == 4)
				{
					i_quest4 = ((10 * 1000) + getRandom(3000));
					c_quest4 = player;
				}
			}
			else if (npc.getCurrentHp() > ((npc.getMaxHp() * 2) / 4))
			{
				if (player == c_quest2)
				{
					if (((6 * 1000) + 1000) > i_quest2)
					{
						i_quest2 = ((6 * 1000) + getRandom(3000));
					}
				}
				else if (player == c_quest3)
				{
					if (((6 * 1000) + 1000) > i_quest3)
					{
						i_quest3 = ((6 * 1000) + getRandom(3000));
					}
				}
				else if (player == c_quest4)
				{
					if (((6 * 1000) + 1000) > i_quest4)
					{
						i_quest4 = ((6 * 1000) + getRandom(3000));
					}
				}
				else if (i_quest2 > i_quest3)
				{
					i1 = 3;
				}
				else if (i_quest2 == i_quest3)
				{
					if (getRandom(100) < 50)
					{
						i1 = 2;
					}
					else
					{
						i1 = 3;
					}
				}
				else if (i_quest2 < i_quest3)
				{
					i1 = 2;
				}
				if (i1 == 2)
				{
					if (i_quest2 > i_quest4)
					{
						i1 = 4;
					}
					else if (i_quest2 == i_quest4)
					{
						if (getRandom(100) < 50)
						{
							i1 = 2;
						}
						else
						{
							i1 = 4;
						}
					}
					else if (i_quest2 < i_quest4)
					{
						i1 = 2;
					}
				}
				else if (i1 == 3)
				{
					if (i_quest3 > i_quest4)
					{
						i1 = 4;
					}
					else if (i_quest3 == i_quest4)
					{
						if (getRandom(100) < 50)
						{
							i1 = 3;
						}
						else
						{
							i1 = 4;
						}
					}
					else if (i_quest3 < i_quest4)
					{
						i1 = 3;
					}
				}
				if (i1 == 2)
				{
					i_quest2 = ((6 * 1000) + getRandom(3000));
					c_quest2 = player;
				}
				else if (i1 == 3)
				{
					i_quest3 = ((6 * 1000) + getRandom(3000));
					c_quest3 = player;
				}
				else if (i1 == 4)
				{
					i_quest4 = ((6 * 1000) + getRandom(3000));
					c_quest4 = player;
				}
			}
			else if (npc.getCurrentHp() > ((npc.getMaxHp() * 3) / 4.0))
			{
				if (player == c_quest2)
				{
					if (((3 * 1000) + 1000) > i_quest2)
					{
						i_quest2 = ((3 * 1000) + getRandom(3000));
					}
				}
				else if (player == c_quest3)
				{
					if (((3 * 1000) + 1000) > i_quest3)
					{
						i_quest3 = ((3 * 1000) + getRandom(3000));
					}
				}
				else if (player == c_quest4)
				{
					if (((3 * 1000) + 1000) > i_quest4)
					{
						i_quest4 = ((3 * 1000) + getRandom(3000));
					}
				}
				else if (i_quest2 > i_quest3)
				{
					i1 = 3;
				}
				else if (i_quest2 == i_quest3)
				{
					if (getRandom(100) < 50)
					{
						i1 = 2;
					}
					else
					{
						i1 = 3;
					}
				}
				else if (i_quest2 < i_quest3)
				{
					i1 = 2;
				}
				if (i1 == 2)
				{
					if (i_quest2 > i_quest4)
					{
						i1 = 4;
					}
					else if (i_quest2 == i_quest4)
					{
						if (getRandom(100) < 50)
						{
							i1 = 2;
						}
						else
						{
							i1 = 4;
						}
					}
					else if (i_quest2 < i_quest4)
					{
						i1 = 2;
					}
				}
				else if (i1 == 3)
				{
					if (i_quest3 > i_quest4)
					{
						i1 = 4;
					}
					else if (i_quest3 == i_quest4)
					{
						if (getRandom(100) < 50)
						{
							i1 = 3;
						}
						else
						{
							i1 = 4;
						}
					}
					else if (i_quest3 < i_quest4)
					{
						i1 = 3;
					}
				}
				if (i1 == 2)
				{
					i_quest2 = ((3 * 1000) + getRandom(3000));
					c_quest2 = player;
				}
				else if (i1 == 3)
				{
					i_quest3 = ((3 * 1000) + getRandom(3000));
					c_quest3 = player;
				}
				else if (i1 == 4)
				{
					i_quest4 = ((3 * 1000) + getRandom(3000));
					c_quest4 = player;
				}
			}
			else if (player == c_quest2)
			{
				if (((2 * 1000) + 1000) > i_quest2)
				{
					i_quest2 = ((2 * 1000) + getRandom(3000));
				}
			}
			else if (player == c_quest3)
			{
				if (((2 * 1000) + 1000) > i_quest3)
				{
					i_quest3 = ((2 * 1000) + getRandom(3000));
				}
			}
			else if (player == c_quest4)
			{
				if (((2 * 1000) + 1000) > i_quest4)
				{
					i_quest4 = ((2 * 1000) + getRandom(3000));
				}
			}
			else if (i_quest2 > i_quest3)
			{
				i1 = 3;
			}
			else if (i_quest2 == i_quest3)
			{
				if (getRandom(100) < 50)
				{
					i1 = 2;
				}
				else
				{
					i1 = 3;
				}
			}
			else if (i_quest2 < i_quest3)
			{
				i1 = 2;
			}
			if (i1 == 2)
			{
				if (i_quest2 > i_quest4)
				{
					i1 = 4;
				}
				else if (i_quest2 == i_quest4)
				{
					if (getRandom(100) < 50)
					{
						i1 = 2;
					}
					else
					{
						i1 = 4;
					}
				}
				else if (i_quest2 < i_quest4)
				{
					i1 = 2;
				}
			}
			else if (i1 == 3)
			{
				if (i_quest3 > i_quest4)
				{
					i1 = 4;
				}
				else if (i_quest3 == i_quest4)
				{
					if (getRandom(100) < 50)
					{
						i1 = 3;
					}
					else
					{
						i1 = 4;
					}
				}
				else if (i_quest3 < i_quest4)
				{
					i1 = 3;
				}
			}
			if (i1 == 2)
			{
				i_quest2 = ((2 * 1000) + getRandom(3000));
				c_quest2 = player;
			}
			else if (i1 == 3)
			{
				i_quest3 = ((2 * 1000) + getRandom(3000));
				c_quest3 = player;
			}
			else if (i1 == 4)
			{
				i_quest4 = ((2 * 1000) + getRandom(3000));
				c_quest4 = player;
			}
		}
		else if (player == c_quest2)
		{
			if (((1 * 1000) + 1000) > i_quest2)
			{
				i_quest2 = ((1 * 1000) + getRandom(3000));
			}
		}
		else if (player == c_quest3)
		{
			if (((1 * 1000) + 1000) > i_quest3)
			{
				i_quest3 = ((1 * 1000) + getRandom(3000));
			}
		}
		else if (player == c_quest4)
		{
			if (((1 * 1000) + 1000) > i_quest4)
			{
				i_quest4 = ((1 * 1000) + getRandom(3000));
			}
		}
		else if (i_quest2 > i_quest3)
		{
			i1 = 3;
		}
		else if (i_quest2 == i_quest3)
		{
			if (getRandom(100) < 50)
			{
				i1 = 2;
			}
			else
			{
				i1 = 3;
			}
		}
		else if (i_quest2 < i_quest3)
		{
			i1 = 2;
		}
		if (i1 == 2)
		{
			if (i_quest2 > i_quest4)
			{
				i1 = 4;
			}
			else if (i_quest2 == i_quest4)
			{
				if (getRandom(100) < 50)
				{
					i1 = 2;
				}
				else
				{
					i1 = 4;
				}
			}
			else if (i_quest2 < i_quest4)
			{
				i1 = 2;
			}
		}
		else if (i1 == 3)
		{
			if (i_quest3 > i_quest4)
			{
				i1 = 4;
			}
			else if (i_quest3 == i_quest4)
			{
				if (getRandom(100) < 50)
				{
					i1 = 3;
				}
				else
				{
					i1 = 4;
				}
			}
			else if (i_quest3 < i_quest4)
			{
				i1 = 3;
			}
		}
		if (i1 == 2)
		{
			i_quest2 = ((1 * 1000) + getRandom(3000));
			c_quest2 = player;
		}
		else if (i1 == 3)
		{
			i_quest3 = ((1 * 1000) + getRandom(3000));
			c_quest3 = player;
		}
		else if (i1 == 4)
		{
			i_quest4 = ((1 * 1000) + getRandom(3000));
			c_quest4 = player;
		}
		if ((GrandBossManager.getInstance().getBossStatus(VALAKAS) == FIGHTING) && !npc.isInvul())
		{
			getRandomSkill(npc);
		}
		else
		{
			return null;
		}
		return super.onAggroRangeEnter(npc, player, isPet);
	}
	
	@Override
	public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, L2Object[] targets, boolean isPet)
	{
		if (npc.isInvul())
		{
			return null;
		}
		npc.setTarget(caster);
		return super.onSkillSee(npc, caster, skill, targets, isPet);
	}
	
	@Override
	public boolean onMoveFinished(L2Npc npc)
	{
		if (!npc.isVisible() || npc.isDead())
			return false;
		CtrlIntention intention;
		if ((intention = npc.getAI().getIntention()) == AI_INTENTION_MOVE_TO || intention == AI_INTENTION_FOLLOW)
		{
			startQuestTimer("1003", 500, npc, null, /**/false/**/);
			npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
			return true;
		}
		return false;
	}
	
	private void giveItemParty(int itemId, L2PcInstance player, L2Npc npc) //+[JOJO]
	{
		if (player != null)
		{
			for (L2PcInstance pc : getPartyMembers(player))
			{
				PcInventory inven = pc.getInventory();
				L2ItemInstance item;
				if ((item = inven.getItemByItemId(itemId)) == null || item.getCount() < 1)
				{
					pc.addItem("Quest", itemId, 1, npc, true);
					pc.broadcastPacket(SystemMessage.getSystemMessage(SystemMessageId.ANNOUNCEMENT_C1_PICKED_UP_S2).addCharName(pc).addItemName(itemId));
				}
			}
		}
	}
	private List<L2PcInstance> getPartyMembers(L2PcInstance player)	//+[JOJO]
	{
		L2Party party;
		if ((party = player.getParty()) != null)
			return party.getMembers();
		else
		{
			List<L2PcInstance> m = new ArrayList<>(1);
			m.add(player);
			return m;
		}
	}

	private void screenMessage(String text) //+[JOJO]
	{
		_Zone.broadcastPacket(new ExShowScreenMessage(text, 10000));
	}
	private void announce(String text) //+[JOJO]
	{
		_Zone.broadcastPacket(new CreatureSay(0, 10, "", text));
	}

	private int calcCameraYaw(int x0, int y0, int x1, int y1) //+[JOJO]
	{
		return (360 - (int)Math.round(Math.toDegrees(Math.atan2(y1 - y0, x1 - x0)))) % 360;
	}

	private int minimax(int min, int value, int max)
	{
		return value < min ? min : value > max ? max : value;
	}

	private void flickPlayers(final int mx, final int my, final double range, final long delay) //+[JOJO]
	{
		ThreadPoolManager.getInstance().scheduleGeneral(new Runnable() {
			@Override
			public void run() { flickPlayers(mx, my, range); }
		}, delay);
	}
	protected void flickPlayers(final int mx, final int my, final double range) //+[JOJO]
	{
		for (L2Character cha : _Zone.getCharactersInside())
		{
			if (true)
//			if (cha.getWalkSpeed() > 0)
//			if (cha instanceof L2PcInstance || cha instanceof L2Attackable)
			{
				final double dx = cha.getX() - mx;
				final double dy = cha.getY() - my;
				final 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 = cha.getZ();

					cha.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
					cha.abortAttack();
					cha.abortCast();

					cha.broadcastPacket(new FlyToLocation(cha, x, y, z, FlyType.THROW_UP));
					cha.setXYZ(x, y, z);
					cha.setHeading(Util.calculateHeadingFrom(x, y, mx, my));
					cha.broadcastPacket(new ValidateLocation(cha));
					cha.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_FEEL_S1_EFFECT).addSkillName(4688, 1));
				}
			}
		}
	}

	private boolean isOutOfRange(L2Object o)	//+[JOJO]簡易壁判定
	{
		return o.getX() < 209400 || o.getX() > 216600 || o.getY() < -118600 || o.getY() > -111400 || o.getZ() < -1650; //座標はL2JTWから拝借
//		return Util.calculateDistance(212852, -114842, -1632, o.getX(), o.getY(), o.getZ(), true) >= 3500;
	}
	private void home(L2Npc npc)
	{
		cancelQuestTimer("1003", npc, null);
		npc.setTarget(null);
		if (Util.calculateDistance(npc.getX(), npc.getY(), npc.getZ(), 212852, -114842, -1632, true) > 500)
		{
			npc.getAI().setIntention(AI_INTENTION_MOVE_TO, new Location(212852, -114842, -1632, 0));
			i_quest1 = System.currentTimeMillis();
		}
	}

	public static void main(String[] args)
	{
		// now call the constructor (starts up the ai)
		new Valakas9103(-1, "valakas", "ai");
	}
}
/**
SELECT npcskills.*,skillname_ja.name,skillname_ja.description FROM npcskills
 LEFT JOIN skillname_ja ON (npcskills.skillid=skillname_ja.id AND npcskills.`level`=skillname_ja.`level`)
 WHERE npcid=29028
 */

