Jump to content

Recommended Posts

Posted (edited)

I share this piece code here as it will be likely end up declined and then pushed from some-one else.
The code resembles retail-like implementation of tears and cystal golems AI.
Improves over-all experience by resolving notable number of issues and formatted for readability.
NOTE: Kechi's henchmen requires AI implementation, poison traps at Dernel and exploding traps at Steam Corridor must be implemented.
This code is improved version and will try and keep it up to date,

original release can be found on the following link.
https://bitbucket.org/l2jserver/l2j-server-datapack/pull-requests/90
Simple adaption should do for most L2J Projects.

 

/*
 * Copyright © 2004-2022 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 com.l2jserver.datapack.instances.CrystalCaverns;

import com.l2jserver.datapack.instances.AbstractInstance;
import com.l2jserver.datapack.quests.Q00131_BirdInACage.Q00131_BirdInACage;
import com.l2jserver.gameserver.GeoData;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.enums.TrapAction;
import com.l2jserver.gameserver.instancemanager.InstanceManager;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.L2Party;
import com.l2jserver.gameserver.model.L2World;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.PcCondOverride;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.L2Summon;
import com.l2jserver.gameserver.model.actor.instance.L2DoorInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.actor.instance.L2TrapInstance;
import com.l2jserver.gameserver.model.entity.Instance;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.instancezone.InstanceWorld;
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
import com.l2jserver.gameserver.model.quest.QuestState;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.model.zone.L2ZoneType;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
import com.l2jserver.gameserver.network.serverpackets.CreatureSay;
import com.l2jserver.gameserver.network.serverpackets.FlyToLocation;
import com.l2jserver.gameserver.network.serverpackets.FlyToLocation.FlyType;
import com.l2jserver.gameserver.network.serverpackets.MagicSkillUse;
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.Util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

import static com.l2jserver.gameserver.config.Configuration.rates;

/**
 * Crystal Caverns instance zone.<br>
 * TODO: 1. Kechi's Henchmans spawn AI is missing.<br>
 * 2. Poison traps at Dernels and Explosion traps at Steam Corridor require implementation.<br>
 * 3. Baylor Raid is missing a lot of things This script takes the best elements of different versions and combines them into one script to get the most optimal and retail-like experience.<br>
 * Original sources: theone, L2JEmu, L2JOfficial, L2JFree Contributing authors: TGS, Lantoc, Janiii, Gigiikun, RosT, Cherish, Lomka.<br>
 * Please maintain consistency between the Crystal Caverns scripts.<br>
 */
public final class CrystalCaverns extends AbstractInstance {

	protected static class CrystalGolem {
		protected L2ItemInstance foodItem = null;
		protected Location newLoc = null;
		protected Location oldLoc = null;
		protected boolean golemHasBeenFed = false;
		protected boolean isAtFinalDestination = false;
	}

	private class CCWorld extends InstanceWorld {

		public Map<L2Npc, CrystalGolem> crystalGolems = new HashMap<>();
		public boolean golemIsAtFinalDestination1 = false;
		public boolean golemIsAtFinalDestination2 = false;

		// tears and world related variables
		public Map<L2Npc, Boolean> npcList1 = new HashMap<>();
		public List<L2Npc> copies = new ArrayList<>();
		private final String damageTracker = "damageTracker";
		public boolean isUsedInvulSkill = false;
		public int tearsStatus = 0;
		public long dragonScaleStart = 0;
		public int dragonScaleNeed = 0;

		public int cleanedRooms = 0;
		public long endTime = 0;

		public boolean[] oracleTriggered = {
				false,
				false,
				false
		};
		public int kechisHenchmanSpawn = 0;
		public int[] roomsStatus = {
				0,
				0,
				0,
				0
		}; // 0: not spawned, 1: spawned, 2: cleared
		public Map<L2DoorInstance, L2PcInstance> openedDoors = new ConcurrentHashMap<>();
		public Map<Integer, Map<L2Npc, Boolean>> npcList2 = new HashMap<>();
		public Map<L2Npc, L2Npc> oracles = new HashMap<>();
		public List<L2Npc> keyKeepers = new ArrayList<>();
		public List<L2Npc> guards = new ArrayList<>();
		public List<L2Npc> oracle = new ArrayList<>();
		// baylor variables
		protected final List<L2PcInstance> raiders = new ArrayList<>();
		protected int raidStatus = 0;
		protected long dragonClawStart = 0;
		protected int dragonClawNeed = 0;
		protected final List<L2Npc> animationMobs = new ArrayList<>();
		protected L2Npc camera = null;
		protected L2Npc baylor = null;
		protected L2Npc alarm = null;

		public CCWorld(Long time) {
			endTime = time;
		}
	}

	// Items
	private static final int WHITE_SEED_OF_EVIL_SHARD = 9597;
	private static final int BLACK_SEED_OF_EVIL_SHARD = 9598;
	private static final int CONTAMINATED_CRYSTAL = 9690;
	private static final int RED_CORAL = 9692;
	private static final int CRYSTAL_FRAGMENT = 9693;
	private static final int SECRET_KEY = 9694;
	private static final int BLUE_CRYSTAL = 9695;
	private static final int RED_CRYSTAL = 9696;
	private static final int CLEAR_CRYSTAL = 9697;
	private static final int BLUE_CORAL_KEY = 9698;
	private static final int RED_CORAL_KEY = 9699;

	// NPCs
	private static final int PARME = 32271;
	private static final int TREASURE_CHEST_1 = 29116;
	private static final int TREASURE_CHEST_2 = 29117;
	private static final int ORACLE_GUIDE_1 = 32281;
	private static final int ORACLE_GUIDE_2 = 32278;
	private static final int ORACLE_GUIDE_3 = 32280;
	private static final int ORACLE_GUIDE_4 = 32279;
	private static final int ORACLE_GUIDE_5 = 32275;
	private static final int ORACLE_GUIDE_6 = 32277;
	private static final int ORACLE_GUIDE_7 = 32274;
	private static final int ORACLE_GUIDE_8 = 32276;
	private static final int CRYSTALLINE_GOLEM = 32328;
	private static final int GATEKEEPER_LOHAN = 22275;
	private static final int GATEKEEPER_PROVO = 22277;
	private static final int TOURMALINE = 22292;
	private static final int TEROD = 22301;
	private static final int DOLPH = 22299;
	private static final int WEYLIN = 22298;
	private static final int GUARDIAN_OF_THE_SQUARE = 22303;
	private static final int GUARDIAN_OF_THE_EMERALD = 22304;
	private static final int TEARS = 25534;
	private static final int TEARS_COPY = 25535;
	private static final int KECHI = 25532;
	private static final int KECHIS_HENCHMAN = 25533;
	private static final int BAYLOR = 29099;
	private static final int CRYSTAL_PRISON_GUARD = 29104;
	private static final int DARNEL = 25531;
	private static final int ALARM = 18474;
	private static final int[] DOOR_OPENING_TRAP = {
			18378,
			143680,
			142608,
			-11845,
			0
	};
	private static final int[] CGMOBS = {
			22311,
			22312,
			22313,
			22314,
			22315,
			22316,
			22317
	};

	// Kechi Hencmans spawn times
	private static final int[] SPAWN = {
			60000,
			120000,
			90000,
			60000,
			50000,
			40000
	};

	private static final int[] MOBLIST = {
			22279,
			22280,
			22281,
			22282,
			22283,
			22285,
			22286,
			22287,
			22288,
			22289,
			22293,
			22294,
			22295,
			22296,
			22297,
			22305,
			22306,
			22307,
			22416,
			22418,
			22419,
			22420
	};

	// Locations
	private static final Location START_LOC = new Location(143348, 148707, -11972);
	private static final Location golemFinalDestination1 = new Location(142999, 151671, -11805);
	private static final Location golemFinalDestination2 = new Location(139494, 151668, -11805);
	private static final Location tearsSpawnLocation = new Location(144298, 154420, -11854, 32767);

	// Skills
	private static final SkillHolder BERSERK = new SkillHolder(5224);
	private static final SkillHolder INVINCIBLE = new SkillHolder(5225);
	private static final SkillHolder STRONG_PUNCH = new SkillHolder(5229);
	private static final SkillHolder EVENT_TIMER_1 = new SkillHolder(5239);
	private static final SkillHolder EVENT_TIMER_2 = new SkillHolder(5239, 2);
	private static final SkillHolder EVENT_TIMER_3 = new SkillHolder(5239, 3);
	private static final SkillHolder EVENT_TIMER_4 = new SkillHolder(5239, 4);
	private static final SkillHolder PHYSICAL_UP = new SkillHolder(5244);
	private static final SkillHolder MAGICAL_UP = new SkillHolder(5245);
	private static final SkillHolder PRESENTATION = new SkillHolder(5441);

	// Misc
	private static final int TEMPLATE_ID = 10;
	private static final int MIN_LEVEL = 78;
	private static final int DOOR1 = 24220021;
	private static final int DOOR2 = 24220024;
	private static final int DOOR3 = 24220023;
	private static final int DOOR4 = 24220061;
	private static final int DOOR5 = 24220025;
	private static final int DOOR6 = 24220022;
	private static final int DOOR7 = 24220026;
	private static final int DOOR8 = 24220005;
	private static final int DOOR9 = 24220006;
	private static final int DOOR10 = 24220000;
	private static final int DOOR11 = 24220002;
	private static final int DOOR12 = 24220003;
	private static final int DOOR13 = 24220004;
	private static final int DOOR14 = 24220004;


	private static final int[] ZONES = {
			20105,
			20106,
			20107
	};

	// @formatter:off
	private final static int[][] ALARMSPAWN =
			{
					{153572, 141277, -12738},
					{153572, 142852, -12738},
					{154358, 142075, -12738},
					{152788, 142075, -12738}
			};

	// Oracle order
	private static final int[][] ordreOracle1 =
			{
					{32274, 147090, 152505, -12169, 31613},
					{32275, 147090, 152575, -12169, 31613},
					{32274, 147090, 152645, -12169, 31613},
					{32274, 147090, 152715, -12169, 31613}
			};

	private static final int[][] ordreOracle2 =
			{
					{32274, 149783, 152505, -12169, 31613},
					{32274, 149783, 152645, -12169, 31613},
					{32276, 149783, 152715, -12169, 31613}
			};

	private static final int[][] ordreOracle3 =
			{
					{32274, 152461, 152505, -12169, 31613},
					{32277, 152461, 152645, -12169, 31613},
			};

	private static int[][] HALL_SPAWNS =
			{
					{141842, 152556, -11814, 50449},
					{141503, 153395, -11814, 40738},
					{141070, 153201, -11814, 39292},
					{141371, 152986, -11814, 35575},
					{141602, 154188, -11814, 24575},
					{141382, 154719, -11814, 37640},
					{141376, 154359, -11814, 12054},
					{140895, 154383, -11814, 37508},
					{140972, 154740, -11814, 52690},
					{141045, 154504, -11814, 50674},
					{140757, 152740, -11814, 39463},
					{140406, 152376, -11814, 16599},
					{140268, 152007, -11817, 45316},
					{139996, 151485, -11814, 47403},
					{140378, 151190, -11814, 58116},
					{140521, 150711, -11815, 55997},
					{140816, 150215, -11814, 53682},
					{141528, 149909, -11814, 22020},
					{141644, 150360, -11817, 13283},
					{142048, 150695, -11815, 5929},
					{141852, 151065, -11817, 27071},
					{142408, 151211, -11815, 2402},
					{142481, 151762, -11815, 12876},
					{141929, 152193, -11815, 27511},
					{142083, 151791, -11814, 47176},
					{141435, 150402, -11814, 41798},
					{140390, 151199, -11814, 50069},
					{140557, 151849, -11814, 45293},
					{140964, 153445, -11814, 56672},
					{142851, 154109, -11814, 24920},
					{142379, 154725, -11814, 30342},
					{142816, 154712, -11814, 33193},
					{142276, 154223, -11814, 33922},
					{142459, 154490, -11814, 33184},
					{142819, 154372, -11814, 21318},
					{141157, 154541, -11814, 27090},
					{141095, 150281, -11814, 55186}
			};

	// first spawns
	private static int[][] FIRST_SPAWNS =
			{
					{22276, 148109, 149601, -12132, 34490},
					{22276, 148017, 149529, -12132, 33689},
					{22278, 148065, 151202, -12132, 35323},
					{22278, 147966, 151117, -12132, 33234},
					{22279, 144063, 150238, -12132, 29654},
					{22279, 144300, 149118, -12135, 5520},
					{22279, 144397, 149337, -12132, 644},
					{22279, 144426, 150639, -12132, 50655},
					{22282, 145841, 151097, -12132, 31810},
					{22282, 144387, 149958, -12132, 61173},
					{22282, 145821, 149498, -12132, 31490},
					{22282, 146619, 149694, -12132, 33374},
					{22282, 146669, 149244, -12132, 31360},
					{22284, 144147, 151375, -12132, 58395},
					{22284, 144485, 151067, -12132, 64786},
					{22284, 144356, 149571, -12132, 63516},
					{22285, 144151, 150962, -12132, 664},
					{22285, 146657, 151365, -12132, 33154},
					{22285, 146623, 150857, -12132, 28034},
					{22285, 147046, 151089, -12132, 32941},
					{22285, 145704, 151255, -12132, 32523},
					{22285, 145359, 151101, -12132, 32767},
					{22285, 147785, 150817, -12132, 27423},
					{22285, 147727, 151375, -12132, 37117},
					{22285, 145428, 149494, -12132, 890},
					{22285, 145601, 149682, -12132, 32442},
					{22285, 147003, 149476, -12132, 31554},
					{22285, 147738, 149210, -12132, 20971},
					{22285, 147769, 149757, -12132, 34980}
			};

	// Emerald Square
	private static int[][] EMERALD_SPAWNS =
			{
					{22280, 144437, 143395, -11969, 34248},
					{22281, 149241, 143735, -12230, 24575},
					{22281, 147917, 146861, -12289, 60306},
					{22281, 144406, 147782, -12133, 14349},
					{22281, 144960, 146881, -12039, 23881},
					{22281, 144985, 147679, -12135, 27594},
					{22283, 147784, 143540, -12222, 2058},
					{22283, 149091, 143491, -12230, 24836},
					{22287, 144479, 147569, -12133, 20723},
					{22287, 145158, 146986, -12058, 21970},
					{22287, 145142, 147175, -12092, 24420},
					{22287, 145110, 147133, -12088, 22465},
					{22287, 144664, 146604, -12028, 14861},
					{22287, 144596, 146600, -12028, 14461},
					{22288, 143925, 146773, -12037, 10813},
					{22288, 144415, 147070, -12069, 8568},
					{22288, 143794, 145584, -12027, 14849},
					{22288, 143429, 146166, -12030, 4078},
					{22288, 144477, 147009, -12056, 8752},
					{22289, 142577, 145319, -12029, 5403},
					{22289, 143831, 146902, -12051, 9717},
					{22289, 143714, 146705, -12028, 10044},
					{22289, 143937, 147134, -12078, 7517},
					{22293, 143356, 145287, -12027, 8126},
					{22293, 143462, 144352, -12008, 25905},
					{22293, 143745, 142529, -11882, 17102},
					{22293, 144574, 144032, -12005, 34668},
					{22295, 143992, 142419, -11884, 19697},
					{22295, 144671, 143966, -12004, 32088},
					{22295, 144440, 143269, -11957, 34169},
					{22295, 142642, 146362, -12028, 281},
					{22295, 143865, 142707, -11881, 21326},
					{22295, 143573, 142530, -11879, 16141},
					{22295, 143148, 146039, -12031, 65014},
					{22295, 143001, 144853, -12014, 0},
					{22296, 147505, 146580, -12260, 59041},
					{22296, 149366, 146932, -12358, 39407},
					{22296, 149284, 147029, -12352, 41120},
					{22296, 149439, 143940, -12230, 23189},
					{22296, 147698, 143995, -12220, 27028},
					{22296, 141885, 144969, -12007, 2526},
					{22296, 147843, 143763, -12220, 28386},
					{22296, 144753, 143650, -11982, 35429},
					{22296, 147613, 146760, -12271, 56296}
			};

	private static int[][] ROOM1_SPAWNS =
			{
					{22288, 143114, 140027, -11888, 15025},
					{22288, 142173, 140973, -11888, 55698},
					{22289, 143210, 140577, -11888, 17164},
					{22289, 142638, 140107, -11888, 6571},
					{22297, 142547, 140938, -11888, 48556},
					{22298, 142690, 140479, -11887, 7663}
			};

	private static int[][] ROOM2_SPAWNS =
			{
					{22303, 146276, 141483, -11880, 34643},
					{22287, 145707, 142161, -11880, 28799},
					{22288, 146857, 142129, -11880, 33647},
					{22288, 146869, 142000, -11880, 31215},
					{22289, 146897, 140880, -11880, 19210}
			};

	private static int[][] ROOM3_SPAWNS =
			{
					{22302, 145123, 143713, -12808, 65323},
					{22294, 145188, 143331, -12808, 496},
					{22294, 145181, 144104, -12808, 64415},
					{22293, 144994, 143431, -12808, 65431},
					{22293, 144976, 143915, -12808, 61461}
			};

	private static int[][] ROOM4_SPAWNS =
			{
					{22304, 150563, 142240, -12108, 16454},
					{22294, 150769, 142495, -12108, 16870},
					{22281, 150783, 141995, -12108, 20033},
					{22283, 150273, 141983, -12108, 16043},
					{22294, 150276, 142492, -12108, 13540}
			};

	// Steam Corridor
	private static int[][] STEAM1_SPAWNS =
			{
					{22305, 145260, 152387, -12165, 32767},
					{22305, 144967, 152390, -12165, 30464},
					{22305, 145610, 152586, -12165, 17107},
					{22305, 145620, 152397, -12165, 8191},
					{22418, 146081, 152847, -12165, 31396},
					{22418, 146795, 152641, -12165, 33850},

			};
	private static int[][] STEAM2_SPAWNS =
			{
					{22306, 147740, 152767, -12165, 65043},
					{22306, 148215, 152828, -12165, 970},
					{22306, 147743, 152846, -12165, 64147},
					{22418, 148207, 152725, -12165, 61801},
					{22419, 149058, 152828, -12165, 64564}
			};

	private static int[][] STEAM3_SPAWNS =
			{
					{22307, 150735, 152316, -12145, 31930},
					{22307, 150725, 152467, -12165, 33635},
					{22307, 151058, 152316, -12146, 65342},
					{22307, 151057, 152461, -12165, 2171},
			};

	private static int[][] STEAM4_SPAWNS =
			{
					{22416, 151636, 150280, -12142, 36869},
					{22416, 149893, 150232, -12165, 64258},
					{22416, 149864, 150110, -12165, 65054},
					{22416, 151926, 150218, -12165, 31613},
					{22420, 149986, 150051, -12165, 105},
					{22420, 151970, 149997, -12165, 32170},
					{22420, 150744, 150006, -12165, 63},
			};
	// @formatter:on
	private static final int DRAGONSCALETIME = 3000;
	private static final int DRAGONCLAWTIME = 3000;

	public CrystalCaverns() {
		super(CrystalCaverns.class.getSimpleName());
		addStartNpc(ORACLE_GUIDE_1, ORACLE_GUIDE_3, ORACLE_GUIDE_4);
		addTalkId(ORACLE_GUIDE_1, ORACLE_GUIDE_3, ORACLE_GUIDE_4, ORACLE_GUIDE_5, ORACLE_GUIDE_6, ORACLE_GUIDE_8);
		addFirstTalkId(ORACLE_GUIDE_1, ORACLE_GUIDE_2, ORACLE_GUIDE_3, ORACLE_GUIDE_4, ORACLE_GUIDE_5, ORACLE_GUIDE_6,  ORACLE_GUIDE_7, ORACLE_GUIDE_8, CRYSTALLINE_GOLEM);
		addKillId(TEARS, GATEKEEPER_LOHAN, GATEKEEPER_PROVO, TEROD, WEYLIN, DOLPH, DARNEL, KECHI, GUARDIAN_OF_THE_SQUARE, GUARDIAN_OF_THE_EMERALD, TOURMALINE, BAYLOR, ALARM);
		addSkillSeeId(BAYLOR, TEARS, ORACLE_GUIDE_5, ORACLE_GUIDE_6, ORACLE_GUIDE_8);
		addTrapActionId(DOOR_OPENING_TRAP[0]);
		addSpellFinishedId(BAYLOR);
		addAttackId(TEARS, TEARS_COPY);
		addKillId(MOBLIST);
		addKillId(CGMOBS);
		addEnterZoneId(ZONES);
		addExitZoneId(ZONES);
	}

	@Override
	protected boolean checkConditions(L2PcInstance player) {
		if (player.canOverrideCond(PcCondOverride.INSTANCE_CONDITIONS)) {
			return true;
		}
		final L2Party party = player.getParty();
		if (party == null) {
			player.sendPacket(SystemMessageId.NOT_IN_PARTY_CANT_ENTER);
			return false;
		}
		if (party.getLeader() != player) {
			player.sendPacket(SystemMessageId.ONLY_PARTY_LEADER_CAN_ENTER);
			return false;
		}
		for (L2PcInstance partyMember : party.getMembers()) {
			if (partyMember.getLevel() < MIN_LEVEL) {
				SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_S_LEVEL_REQUIREMENT_IS_NOT_SUFFICIENT_AND_CANNOT_BE_ENTERED);
				sm.addPcName(partyMember);
				party.broadcastPacket(sm);
				return false;
			}
			L2ItemInstance item = partyMember.getInventory().getItemByItemId(CONTAMINATED_CRYSTAL);
			if (item == null) {
				SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_ITEM_REQUIREMENT_NOT_SUFFICIENT);
				sm.addPcName(partyMember);
				party.broadcastPacket(sm);
				return false;
			}
			if (!Util.checkIfInRange(1000, player, partyMember, true)) {
				SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_A_LOCATION_WHICH_CANNOT_BE_ENTERED_THEREFORE_IT_CANNOT_BE_PROCESSED);
				sm.addPcName(partyMember);
				party.broadcastPacket(sm);
				return false;
			}
			if (System.currentTimeMillis() < InstanceManager.getInstance().getInstanceTime(partyMember.getObjectId(), TEMPLATE_ID)) {
				SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_MAY_NOT_RE_ENTER_YET);
				sm.addPcName(partyMember);
				party.broadcastPacket(sm);
				return false;
			}
		}
		return true;
	}

	private boolean checkOracleConditions(L2PcInstance player) {
		if (player.canOverrideCond(PcCondOverride.INSTANCE_CONDITIONS)) {
			return true;
		}
		L2Party party = player.getParty();
		if (party == null) {
			player.sendPacket(SystemMessageId.NOT_IN_PARTY_CANT_ENTER);
			return false;
		}
		if (party.getLeader() != player) {
			player.sendPacket(SystemMessageId.ONLY_PARTY_LEADER_CAN_ENTER);
			return false;
		}
		for (L2PcInstance partyMember : party.getMembers()) {
			L2ItemInstance item = partyMember.getInventory().getItemByItemId(RED_CORAL);
			if (item == null) {
				SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_ITEM_REQUIREMENT_NOT_SUFFICIENT);
				sm.addPcName(partyMember);
				party.broadcastPacket(sm);
				return false;
			}
			if (!Util.checkIfInRange(1000, player, partyMember, true)) {
				SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_A_LOCATION_WHICH_CANNOT_BE_ENTERED_THEREFORE_IT_CANNOT_BE_PROCESSED);
				sm.addPcName(partyMember);
				party.broadcastPacket(sm);
				return false;
			}
		}
		return true;
	}

	private boolean checkBaylorConditions(L2PcInstance player) {
		if (player.canOverrideCond(PcCondOverride.INSTANCE_CONDITIONS)) {
			return true;
		}
		L2Party party = player.getParty();
		if (party == null) {
			player.sendPacket(SystemMessageId.NOT_IN_PARTY_CANT_ENTER);
			return false;
		}
		if (party.getLeader() != player) {
			player.sendPacket(SystemMessageId.ONLY_PARTY_LEADER_CAN_ENTER);
			return false;
		}
		for (L2PcInstance partyMember : party.getMembers()) {
			L2ItemInstance item1 = partyMember.getInventory().getItemByItemId(BLUE_CRYSTAL);
			L2ItemInstance item2 = partyMember.getInventory().getItemByItemId(RED_CRYSTAL);
			L2ItemInstance item3 = partyMember.getInventory().getItemByItemId(CLEAR_CRYSTAL);
			if ((item1 == null) || (item2 == null) || (item3 == null)) {
				SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_ITEM_REQUIREMENT_NOT_SUFFICIENT);
				sm.addPcName(partyMember);
				party.broadcastPacket(sm);
				return false;
			}
			if (!Util.checkIfInRange(1000, player, partyMember, true)) {
				SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_A_LOCATION_WHICH_CANNOT_BE_ENTERED_THEREFORE_IT_CANNOT_BE_PROCESSED);
				sm.addPcName(partyMember);
				party.broadcastPacket(sm);
				return false;
			}
		}
		return true;
	}

	// this should be handled from skill effect
	private void Throw(L2Character effector, L2Character effected) {
		// Get current position of the L2Character
		final int curX = effected.getX();
		final int curY = effected.getY();
		final int curZ = effected.getZ();

		// Calculate distance between effector and effected current position
		double dx = effector.getX() - curX;
		double dy = effector.getY() - curY;
		double dz = effector.getZ() - curZ;
		double distance = Math.sqrt((dx * dx) + (dy * dy));
		int offset = Math.min((int) distance + 300, 1400);

		double cos;
		double sin;

		// approximation for moving further when z coordinates are different
		// TODO: handle Z axis movement better
		offset += Math.abs(dz);
		if (offset < 5) {
			offset = 5;
		}

		if (distance < 1) {
			return;
		}
		// Calculate movement angles needed
		sin = dy / distance;
		cos = dx / distance;

		// Calculate the new destination with offset included
		int _x = effector.getX() - (int) (offset * cos);
		int _y = effector.getY() - (int) (offset * sin);
		int _z = effected.getZ();

		Location destination = GeoData.getInstance().moveCheck(effected.getX(), effected.getY(), effected.getZ(), _x, _y, _z, effected.getInstanceId());
		effected.broadcastPacket(new FlyToLocation(effected, destination, FlyType.THROW_UP));

		// maybe is need force set X,Y,Z
		effected.setXYZ(destination);
		effected.broadcastPacket(new ValidateLocation(effected));
	}

	@Override
	public void onEnterInstance(L2PcInstance player, InstanceWorld world, boolean firstEntrance) {
		if (firstEntrance) {
			Optional.ofNullable(player.getParty()).map(L2Party::getMembers).orElseGet(() -> List.of(player))
					.forEach(member -> {
						teleportPlayer(member, START_LOC, world.getInstanceId());
						world.addAllowed(member.getObjectId());
					});
			runOracle((CCWorld) world);
		} else {
			teleportPlayer(player, START_LOC, world.getInstanceId());
		}
	}

	protected void runOracle(CCWorld world) {
		world.setStatus(0);
		world.oracle.add(addSpawn(ORACLE_GUIDE_1, 143172, 148894, -11975, 0, false, 0, false, world.getInstanceId()));
	}

	protected void runEmerald(CCWorld world) {
		world.setStatus(1);
		runFirst(world);
		openDoor(DOOR1, world.getInstanceId());
	}

	protected void runCoral(CCWorld world) {
		world.setStatus(1);
		runHall(world);
		openDoor(DOOR2, world.getInstanceId());
		openDoor(DOOR5, world.getInstanceId());
	}

	protected void runHall(CCWorld world) {
		world.setStatus(2);
		for (int[] spawn : HALL_SPAWNS) {
			L2Npc mob = addSpawn(CGMOBS[getRandom(CGMOBS.length)], spawn[0], spawn[1], spawn[2], spawn[3], false, 0, false, world.getInstanceId());
			world.npcList1.put(mob, false);
		}
	}

	protected void runFirst(CCWorld world) {
		world.setStatus(2);
		world.keyKeepers.add(addSpawn(GATEKEEPER_LOHAN, 148206, 149486, -12140, 32308, false, 0, false, world.getInstanceId()));
		world.keyKeepers.add(addSpawn(GATEKEEPER_PROVO, 148203, 151093, -12140, 31100, false, 0, false, world.getInstanceId()));
		for (int[] spawn : FIRST_SPAWNS) {
			addSpawn(spawn[0], spawn[1], spawn[2], spawn[3], spawn[4], false, 0, false, world.getInstanceId());
		}
	}

	protected void runEmeraldSquare(CCWorld world) {
		world.setStatus(3);
		Map<L2Npc, Boolean> spawnList = new HashMap<>();
		for (int[] spawn : EMERALD_SPAWNS) {
			L2Npc mob = addSpawn(spawn[0], spawn[1], spawn[2], spawn[3], spawn[4], false, 0, false, world.getInstanceId());
			spawnList.put(mob, false);
		}
		world.npcList2.put(0, spawnList);
	}

	protected void runEmeraldRooms(CCWorld world, int[][] spawnList, int room) {
		Map<L2Npc, Boolean> spawned = new HashMap<>();
		for (int[] spawn : spawnList) {
			L2Npc mob = addSpawn(spawn[0], spawn[1], spawn[2], spawn[3], spawn[4], false, 0, false, world.getInstanceId());
			spawned.put(mob, false);
		}
		if (room == 1) {
			addSpawn(32359, 142110, 139896, -11888, 8033, false, 0, false, world.getInstanceId());
		}
		world.npcList2.put(room, spawned);
		world.roomsStatus[room - 1] = 1;
	}

	protected void runDarnel(CCWorld world) {
		world.setStatus(9);
		addSpawn(DARNEL, 152759, 145949, -12588, 21592, false, 0, false, world.getInstanceId());
		// TODO: missing traps
		openDoor(DOOR8, world.getInstanceId());
		openDoor(DOOR9, world.getInstanceId());
	}

	protected void runSteamRooms(CCWorld world, int[][] spawnList, int status) {
		world.setStatus(status);
		Map<L2Npc, Boolean> spawned = new HashMap<>();
		for (int[] spawn : spawnList) {
			L2Npc mob = addSpawn(spawn[0], spawn[1], spawn[2], spawn[3], spawn[4], false, 0, false, world.getInstanceId());
			spawned.put(mob, false);
		}
		world.npcList2.put(0, spawned);
	}

	protected void runSteamOracles(CCWorld world, int[][] oracleOrder) {
		world.oracles.clear();
		for (int[] oracle : oracleOrder) {
			world.oracles.put(addSpawn(oracle[0], oracle[1], oracle[2], oracle[3], oracle[4], false, 0, false, world.getInstanceId()), null);
		}
	}

	protected boolean checkKillProgress(int room, L2Npc mob, CCWorld world) {
		if (world.npcList2.get(room).containsKey(mob)) {
			world.npcList2.get(room).put(mob, true);
		}
		for (boolean isDead : world.npcList2.get(room).values()) {
			if (!isDead) {
				return false;
			}
		}
		return true;
	}

	@Override
	public String onFirstTalk(L2Npc npc, L2PcInstance player) {
		InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
		if (tmpworld instanceof CCWorld world) {
			CrystalGolem cryGolem = world.crystalGolems.get(npc);
			if (npc.getId() == ORACLE_GUIDE_1) {
				if ((world.getStatus() == 0) && world.oracle.contains(npc)) {
					return "32281.htm";// TODO: Missing HTML.
				}
				npc.showChatWindow(player);
				return null;
			} else if (npc.getId() == ORACLE_GUIDE_3) {
				return "32280.htm"; // TODO: Missing HTML.
			} else if ((npc.getId() >= ORACLE_GUIDE_5) && (npc.getId() <= ORACLE_GUIDE_6)) {
				if (!world.oracleTriggered[npc.getId() - ORACLE_GUIDE_5]) {
					return "no.htm"; // TODO: Missing HTML.
				}
				npc.showChatWindow(player);
				return null;
			} else if (npc.getId() == ORACLE_GUIDE_7) {
				return "no.htm"; // TODO: Missing HTML.
			} else if (npc.getId() == ORACLE_GUIDE_4) {
				final QuestState st = player.getQuestState(Q00131_BirdInACage.class.getSimpleName());
				return (st != null) && !st.isCompleted() ? "32279-01.htm" : "32279.htm";
			} else if (npc.getId() == CRYSTALLINE_GOLEM && !cryGolem.isAtFinalDestination) {
				//to be implemented dialog cooldown.
				
				broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.AH_IM_HUNGRY);
			}
		} else if (npc.getId() == ORACLE_GUIDE_1) {
			npc.showChatWindow(player);
			return null;
		}
		return "";
	}


	@Override
	public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, List<L2Object> targets, boolean isSummon) {
		boolean doReturn = true;
		for (L2Object obj : targets) {
			if (obj == npc) {
				doReturn = false;
			}
		}
		if (doReturn) {
			return super.onSkillSee(npc, caster, skill, targets, isSummon);
		}
		switch (skill.getId()) {
			case 1011:
			case 1015:
			case 1217:
			case 1218:
			case 1401:
			case 2360:
			case 2369:
			case 5146:
				doReturn = false;
				break;
			default:
				doReturn = true;
		}
		if (doReturn) {
			return super.onSkillSee(npc, caster, skill, targets, isSummon);
		}
		if ((npc.getId() >= ORACLE_GUIDE_5) && (npc.getId() <= ORACLE_GUIDE_6) && (skill.getId() != 2360) && (skill.getId() != 2369)) {
			InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
			if ((tmpworld instanceof CCWorld) && (getRandom(100) < 15)) {
				for (L2Npc oracle : ((CCWorld) tmpworld).oracles.keySet()) {
					if (oracle != npc) {
						oracle.decayMe();
					}
				}
				((CCWorld) tmpworld).oracleTriggered[npc.getId() - ORACLE_GUIDE_5] = true;
			}
		} else if (npc.isInvul() && (npc.getId() == BAYLOR) && (skill.getId() == 2360) && (caster != null)) {
			if (caster.getParty() == null) {
				return super.onSkillSee(npc, caster, skill, targets, isSummon);
			}
			InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
			if (tmpworld instanceof CCWorld world) {
				if (((world.dragonClawStart + DRAGONCLAWTIME) <= System.currentTimeMillis()) || (world.dragonClawNeed <= 0)) {
					world.dragonClawStart = System.currentTimeMillis();
					world.dragonClawNeed = caster.getParty().getMemberCount() - 1;
				} else {
					world.dragonClawNeed--;
				}
				if (world.dragonClawNeed == 0) {
					npc.stopSkillEffects(false, 5225);
					npc.broadcastPacket(new MagicSkillUse(npc, npc, 5480, 1, 4000, 0));
					if (world.raidStatus == 3) {
						world.raidStatus++;
					}
				}
			}
		} else if (npc.isInvul() && (npc.getId() == TEARS) && (skill.getId() == 2369) && (caster != null)) {
			InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
			if (tmpworld instanceof CCWorld world) {
				if (caster.getParty() == null) {
					return super.onSkillSee(npc, caster, skill, targets, isSummon);
				} else if (((world.dragonScaleStart + DRAGONSCALETIME) <= System.currentTimeMillis()) || (world.dragonScaleNeed <= 0)) {
					world.dragonScaleStart = System.currentTimeMillis();
					world.dragonScaleNeed = caster.getParty().getMemberCount() - 1;
				} else {
					world.dragonScaleNeed--;
				}
				if ((world.dragonScaleNeed == 0) && (getRandom(100) < 80)) {
					npc.setIsInvul(false);
					broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.NOYOU_KNEW_MY_WEAKNESS);
				}
			}
		}
		return super.onSkillSee(npc, caster, skill, targets, isSummon);
	}

	private static final Location[] TEARS_NEW_LOCATION = {
			new Location(144650, 154313, -11848),
			new Location(144522, 154714, -11848),
			new Location(143968, 154328, -11848),
			new Location(144654, 154536, -11848),
			new Location(144519, 154138, -11848),
			new Location(144320, 154789, -11848),
			new Location(144301, 154070, -11848),
			new Location(144089, 154142, -11848),
			new Location(143971, 154550, -11848),
			new Location(144116, 154715, -11848),
	};

	@Override
	public String onAttack(L2Npc npc, L2PcInstance player, int damage, boolean isSummon, Skill skill) {
		if (npc.getId() == TEARS) {
			InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
			if (tmpworld instanceof CCWorld world) {
				npc.getVariables().set(world.damageTracker, npc.getVariables().getInt(world.damageTracker) + damage);
				if (npc.getVariables().getInt(world.damageTracker) > 100000) {
					cancelQuestTimers("ApplyAggressionCopies");
					for (L2Npc copy : world.copies) {
						if (copy != null) {
							copy.deleteMe();
						}
					}
				}
				int maxHp = npc.getMaxHp();
				double nowHp = npc.getStatus().getCurrentHp();
				if (!world.isUsedInvulSkill) {
					if ((nowHp <= (maxHp * 0.8)) && (world.tearsStatus == 0)) {
						world.tearsStatus = 1;
						startQuestTimer("SpawnTearsCopies", 2000, npc, player);
						npc.doCast(PRESENTATION);
					} else if ((nowHp <= (maxHp * 0.6)) && (world.tearsStatus == 1)) {
						world.tearsStatus = 2;
						startQuestTimer("SpawnTearsCopies", 2000, npc, player);
						npc.doCast(PRESENTATION);
					} else if ((nowHp <= (maxHp * 0.4)) && (world.tearsStatus == 2)) {
						world.tearsStatus = 3;
						startQuestTimer("SpawnTearsCopies", 2000, npc, player);
						npc.doCast(PRESENTATION);
					} else if ((nowHp <= (maxHp * 0.2)) && (world.tearsStatus == 3)) {
						world.tearsStatus = 4;
						startQuestTimer("SpawnTearsCopies", 2000, npc, player);
						npc.doCast(PRESENTATION);
					} else if (nowHp <= (maxHp * 0.1)) {
						world.isUsedInvulSkill = true;
						npc.setIsInvul(true);
						broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.IT_WILL_NOT_BE_THAT_EASY_TO_KILL_ME);
					}
				}
			}
		} else if (npc.getId() == TEARS_COPY) {
			InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
			if (tmpworld instanceof CCWorld world) {
				npc.getVariables().set(world.damageTracker, npc.getVariables().getInt(world.damageTracker) + damage);
				if (npc.getVariables().getInt(world.damageTracker) > 50000) {
					npc.deleteMe();
				}
			}
		}
		return null;
	}

	@Override
	public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill) {
		if ((npc.getId() == BAYLOR) && (skill.getId() == 5225)) {
			InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
			if (tmpworld instanceof CCWorld) {
				((CCWorld) tmpworld).raidStatus++;
			}
		}
		return super.onSpellFinished(npc, player, skill);
	}

	@Override
	public String onAdvEvent(String event, L2Npc npc, L2PcInstance player) {
		InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
		if (tmpworld instanceof CCWorld world) {
			CrystalGolem cryGolem = world.crystalGolems.get(npc);
			if (event.equalsIgnoreCase("TeleportOut")) {
				teleportPlayer(player, new Location(149413, 173078, -5014), 0);
			} else if (event.equalsIgnoreCase("TeleportParme")) {
				teleportPlayer(player, new Location(153689, 142226, -9750), world.getInstanceId());
			} else if (event.equalsIgnoreCase("Timer2") || event.equalsIgnoreCase("Timer3") || event.equalsIgnoreCase("Timer4") || event.equalsIgnoreCase("Timer5")) {
				if (player.getInstanceId() == world.getInstanceId()) {
					teleportPlayer(player, new Location(144653, 152606, -12126), world.getInstanceId());
					player.stopSkillEffects(true, 5239);
					EVENT_TIMER_1.getSkill().applyEffects(player, player);
					startQuestTimer("Timer2", 300000, npc, player);
				}
			} else if (event.equalsIgnoreCase("Timer21") || event.equalsIgnoreCase("Timer31") || event.equalsIgnoreCase("Timer41") || event.equalsIgnoreCase("Timer51")) {
				InstanceManager.getInstance().getInstance(world.getInstanceId()).removeNpcs();
				world.npcList2.clear();
				runSteamRooms(world, STEAM1_SPAWNS, 22);
				startQuestTimer("Timer21", 300000, npc, null);
			} else if (event.equalsIgnoreCase("CheckKechiAttack")) {
				if (npc.isInCombat()) {
					startQuestTimer("SpawnGuards", SPAWN[0], npc, null);
					cancelQuestTimers("CheckKechiAttack");
					closeDoor(DOOR4, npc.getInstanceId());
					closeDoor(DOOR3, npc.getInstanceId());
				} else startQuestTimer("CheckKechiAttack", 1000, npc, null);
			} else if (event.equalsIgnoreCase("SpawnGuards")) {
				world.kechisHenchmanSpawn++;
				world.guards.add(addSpawn(KECHIS_HENCHMAN, 153622, 149699, -12131, 56890, false, 0, false, world.getInstanceId()));
				world.guards.add(addSpawn(KECHIS_HENCHMAN, 153609, 149622, -12131, 64023, false, 0, false, world.getInstanceId()));
				world.guards.add(addSpawn(KECHIS_HENCHMAN, 153606, 149428, -12131, 64541, false, 0, false, world.getInstanceId()));
				world.guards.add(addSpawn(KECHIS_HENCHMAN, 153601, 149534, -12131, 64901, false, 0, false, world.getInstanceId()));
				world.guards.add(addSpawn(KECHIS_HENCHMAN, 153620, 149354, -12131, 1164, false, 0, false, world.getInstanceId()));
				world.guards.add(addSpawn(KECHIS_HENCHMAN, 153637, 149776, -12131, 61733, false, 0, false, world.getInstanceId()));
				world.guards.add(addSpawn(KECHIS_HENCHMAN, 153638, 149292, -12131, 64071, false, 0, false, world.getInstanceId()));
				world.guards.add(addSpawn(KECHIS_HENCHMAN, 153647, 149857, -12131, 59402, false, 0, false, world.getInstanceId()));
				world.guards.add(addSpawn(KECHIS_HENCHMAN, 153661, 149227, -12131, 65275, false, 0, false, world.getInstanceId()));
				if (world.kechisHenchmanSpawn <= 5) {
					startQuestTimer("SpawnGuards", SPAWN[world.kechisHenchmanSpawn], npc, null);
				} else {
					cancelQuestTimers("SpawnGuards");
				}
			} else if (event.equalsIgnoreCase("EmeraldSteam")) {
				runEmerald(world);
				for (L2Npc oracle : world.oracle) {
					oracle.decayMe();
				}
			} else if (event.equalsIgnoreCase("CoralGarden")) {
				runCoral(world);
				for (L2Npc oracle : world.oracle) {
					oracle.decayMe();
				}
			} else if (event.equalsIgnoreCase("SpawnOracle")) {
				addSpawn(PARME, 153572, 142075, -9728, 10800, false, 0, false, world.getInstanceId());
				addSpawn((getRandom(10) < 5 ? TREASURE_CHEST_1 : TREASURE_CHEST_2), npc.getX(), npc.getY(), npc.getZ(), npc.getHeading(), false, 0, false, world.getInstanceId()); // Baylor's Chest
				addSpawn(ORACLE_GUIDE_4, 153572, 142075, -12738, 10800, false, 0, false, world.getInstanceId());
				cancelQuestTimer("BaylorDespawn", npc, null);
				cancelQuestTimers("BaylorCast");
			} else if (event.equalsIgnoreCase("BaylorEffect0")) {
				npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
				npc.broadcastSocialAction(1);
				startQuestTimer("BaylorCamera0", 11000, npc, null);
				startQuestTimer("BaylorEffect1", 19000, npc, null);
			} else if (event.equalsIgnoreCase("BaylorCamera0")) {
				npc.broadcastPacket(new SpecialCamera(npc, 500, -45, 170, 5000, 9000, 0, 0, 1, 0, 0));
			} else if (event.equalsIgnoreCase("BaylorEffect1")) {
				npc.broadcastPacket(new SpecialCamera(npc, 300, 0, 120, 2000, 5000, 0, 0, 1, 0, 0));
				npc.broadcastSocialAction(3);
				startQuestTimer("BaylorEffect2", 4000, npc, null);
			} else if (event.equalsIgnoreCase("BaylorEffect2")) {
				npc.broadcastPacket(new SpecialCamera(npc, 747, 0, 160, 2000, 3000, 0, 0, 1, 0, 0));
				npc.broadcastPacket(new MagicSkillUse(npc, npc, 5402, 1, 2000, 0));
				startQuestTimer("RaidStart", 2000, npc, null);
			} else if (event.equalsIgnoreCase("BaylorMinions")) {
				for (int i = 0; i < 10; i++) {
					int radius = 300;
					int x = (int) (radius * Math.cos(i * 0.618));
					int y = (int) (radius * Math.sin(i * 0.618));
					L2Npc mob = addSpawn(CRYSTAL_PRISON_GUARD, 153571 + x, 142075 + y, -12737, 0, false, 0, false, world.getInstanceId());
					mob.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
					world.animationMobs.add(mob);
				}
				startQuestTimer("BaylorEffect0", 200, npc, null);
			} else if (event.equalsIgnoreCase("RaidStart")) {
				world.camera.decayMe();
				world.camera = null;
				npc.stopStunning(false);
				for (L2PcInstance p : world.raiders) {
					p.stopStunning(false);
					Throw(npc, p);
					if (p.getSummon() != null) {
						Throw(npc, p.getSummon());
					}
				}
				world.raidStatus = 0;
				for (L2Npc mob : world.animationMobs) {
					mob.doDie(mob);
				}
				world.animationMobs.clear();
				startQuestTimer("BaylorDespawn", 60000, npc, null, true);
				startQuestTimer("CheckBaylorAttack", 1000, npc, null);
			} else if (event.equalsIgnoreCase("CheckBaylorAttack")) {
				if (npc.isInCombat()) {
					cancelQuestTimers("CheckBaylorAttack");
					startQuestTimer("BaylorAlarm", 40000, npc, null);
					startQuestTimer("BaylorCast", 5000, npc, null, true);
					world.raidStatus++;
				} else {
					startQuestTimer("CheckBaylorAttack", 1000, npc, null);
				}
			} else if (event.equalsIgnoreCase("BaylorAlarm")) {
				if (world.alarm == null) {
					int[] spawnLoc = ALARMSPAWN[getRandom(ALARMSPAWN.length)];
					npc.addSkill(PHYSICAL_UP.getSkill());
					npc.addSkill(MAGICAL_UP.getSkill());
					world.alarm = addSpawn(ALARM, spawnLoc[0], spawnLoc[1], spawnLoc[2], 10800, false, 0, false, world.getInstanceId());
					world.alarm.disableCoreAI(true);
					world.alarm.setIsImmobilized(true);
					world.alarm.broadcastPacket(new CreatureSay(world.alarm.getObjectId(), 1, world.alarm.getName(), NpcStringId.AN_ALARM_HAS_BEEN_SET_OFF_EVERYBODY_WILL_BE_IN_DANGER_IF_THEY_ARE_NOT_TAKEN_CARE_OF_IMMEDIATELY));
				}
			} else if (event.equalsIgnoreCase("BaylorCast")) {
				if (world.baylor == null) {
					cancelQuestTimers("BaylorCast");
				} else {
					int maxHp = npc.getMaxHp();
					double nowHp = npc.getStatus().getCurrentHp();
					int rand = getRandom(100);
					if ((nowHp < (maxHp * 0.2)) && (world.raidStatus < 3) && !npc.isAffectedBySkill(5224) && !npc.isAffectedBySkill(5225)) {
						if ((nowHp < (maxHp * 0.15)) && (world.raidStatus == 2)) {
							npc.doCast(INVINCIBLE);
							broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.DEMON_KING_BELETH_GIVE_ME_THE_POWER_AAAHH);
						} else if ((rand < 10) || (nowHp < (maxHp * 0.15))) {
							npc.doCast(INVINCIBLE);
							broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.DEMON_KING_BELETH_GIVE_ME_THE_POWER_AAAHH);
							startQuestTimer("BaylorSetVulnarable", 30000, world.baylor, null);
						}
					} else if ((nowHp < (maxHp * 0.3)) && (rand > 50) && !npc.isAffectedBySkill(5225) && !npc.isAffectedBySkill(5224)) {
						npc.doCast(BERSERK);
					} else if (rand < 33) {
						npc.setTarget(world.raiders.get(getRandom(world.raiders.size())));
						npc.doCast(STRONG_PUNCH);
					}
				}
			} else if (event.equalsIgnoreCase("BaylorSetVulnarable")) {
				npc.stopSkillEffects(false, 5225);
			} else if (event.equalsIgnoreCase("Baylor")) {
				world.baylor = addSpawn(BAYLOR, 153572, 142075, -12738, 10800, false, 0, false, world.getInstanceId());
				world.baylor.startStunning();
				world.camera = addSpawn(29120, 153273, 141400, -12738, 10800, false, 0, false, world.getInstanceId());
				world.camera.broadcastPacket(new SpecialCamera(world.camera, 700, -45, 160, 500, 15200, 0, 0, 1, 0, 0));
				startQuestTimer("baylorMinions", 2000, world.baylor, null);
			} else if (event.equalsIgnoreCase("CheckTearsAttack")) {
				if (npc.isInCombat()) {
					closeDoor(DOOR7, npc.getInstanceId());
					cancelQuestTimers("CheckTearsAttack");
				} else {
					startQuestTimer("CheckTearsAttack", 1000, npc, null);
				}
			} else if (event.equalsIgnoreCase("SpawnTearsCopies")) {
				double hpStat = (npc.getStatus().getCurrentHp()) / (npc.getMaxHp());
				Location tearsNewSpawnLoc = TEARS_NEW_LOCATION[getRandom(TEARS_NEW_LOCATION.length)];
				npc.deleteMe();
				for (int i = 0; i < 10; i++) {
					Location currentSpawnLoc = TEARS_NEW_LOCATION[i];
					if (tearsNewSpawnLoc != currentSpawnLoc) {
						L2Npc copy = addSpawn(TEARS_COPY, currentSpawnLoc, false, 0, true, player.getInstanceId());
						copy.setCurrentHp(copy.getMaxHp() * hpStat);
						copy.setIsNoRndWalk(true);
						((L2Attackable) copy).addDamageHate(player, 0, 99999);
						world.copies.add(copy);
						startQuestTimer("ApplyAggressionCopies", 3000, copy, player);
					} else {
						L2Npc realTears = addSpawn(TEARS, currentSpawnLoc, false, 0, true, player.getInstanceId());
						realTears.setCurrentHp(realTears.getMaxHp() * hpStat);
						realTears.setIsNoRndWalk(true);
						((L2Attackable) realTears).addDamageHate(player, 0, 99999);
						startQuestTimer("ApplyAggressionTears", 3000, realTears, player);
					}
				}
				cancelQuestTimers("SpawnTearsCopies");
			} else if (event.equalsIgnoreCase("ApplyAggressionCopies")) {
				npc.setRunning();
				npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, player);
			} else if (event.equalsIgnoreCase("ApplyAggressionTears")) {
				npc.setRunning();
				npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, player);
				cancelQuestTimers("ApplyAggressionTears");
				
			/*
			 * Implements Crystalline Golem
			 */
			} else if (!event.contains("Food")) {
				return "";
			} else if (event.equalsIgnoreCase("SeekForFood1") || event.equalsIgnoreCase("SeekForFood2")) {
				if (world.crystalGolems.get(npc).isAtFinalDestination) {
					return "";
				}
				for (L2Object object : L2World.getInstance().getVisibleObjects(npc, 300)) {
					if (object.isItem() && object.getInstanceId() == npc.getInstanceId() && object.getId() == CRYSTAL_FRAGMENT) {
						cryGolem.foodItem = (L2ItemInstance) object;
						if (event.equalsIgnoreCase("SeekForFood1")) {
							startQuestTimer("GoToFood1", 2000, npc, null);
						} else {
							startQuestTimer("GoToFood2", 2000, npc, null);
						}
					}
				}
				if (world.crystalGolems.get(npc).foodItem == null) {
					int rnd = getRandom(100);
					if (rnd < 20) {
						if (!cryGolem.golemHasBeenFed) {
							int rnd1 = getRandom(10);
							if (rnd1 <= 2) {
								broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.HELLO_IS_ANYONE_THERE);
							} else if (rnd1 > 2 && rnd1 <= 4) {
								broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.IF_SOMEONE_WOULD_GIVE_ME_SOME_OF_THOSE_TASTY_CRYSTAL_FRAGMENTS_I_WOULD_GLADLY_TELL_THEM_WHERE_TEARS_IS_HIDING_YUMMY_YUMMY);
							} else if (rnd1 > 4 && rnd1 <= 6) {
								broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.IS_NO_ONE_THERE_HOW_LONG_HAVE_I_BEEN_HIDING_I_HAVE_BEEN_STARVING_FOR_DAYS_AND_CANNOT_HOLD_OUT_ANYMORE);
							} else if (rnd1 > 6) {
								broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.HEY_YOU_FROM_ABOVE_THE_GROUND_LETS_SHARE_SOME_CRYSTAL_FRAGMENTS_IF_YOU_HAVE_ANY);
							}
						} else {
							int rnd2 = getRandom(5);
							if (rnd2 == 1) {
								broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.AH_IM_HUNGRY);
							} else if (rnd2 == 2) {
								broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.HOW_INSENSITIVE_ITS_NOT_NICE_TO_GIVE_ME_JUST_A_PIECE_CANT_YOU_GIVE_ME_MORE);
							} else if (rnd2 >= 3) {
								broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.SNIFF_SNIFF_GIVE_ME_MORE_CRYSTAL_FRAGMENTS);
							}
						}
					}
					if (event.equalsIgnoreCase("SeekForFood1")) {
						startQuestTimer("SeekForFood1", 2000, npc, null);
					} else {
						startQuestTimer("SeekForFood2", 2000, npc, null);
					}
				}
				return "";
			} else if (event.equalsIgnoreCase("GoToFood1") || event.equalsIgnoreCase("GoToFood2")) {
				cryGolem.newLoc = new Location(cryGolem.foodItem.getX(), cryGolem.foodItem.getY(), cryGolem.foodItem.getZ(), 0);
				cryGolem.oldLoc = new Location(npc.getX(), npc.getY(), npc.getZ(), npc.getHeading());
				npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO,cryGolem.newLoc);
				if (event.equalsIgnoreCase("GoToFood1")) {
					startQuestTimer("ReachForFood1", 2000, npc, null, true);
					cancelQuestTimers("GoToFood1");
				} else {
					startQuestTimer("ReachForFood2", 2000, npc, null, true);
					cancelQuestTimers("GoToFood2");
				}
				return "";
			} else if (event.equalsIgnoreCase("ReachForFood1") || event.equalsIgnoreCase("ReachForFood2")) {
				if((!cryGolem.foodItem.isVisible()) && !(npc.getAI().getIntention() == CtrlIntention.AI_INTENTION_REST)) {
				npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, cryGolem.oldLoc);
					if (event.equalsIgnoreCase("ReachForFood1")) {
						startQuestTimer("ReturnFromFood1", 2000, npc, null, true);
						cancelQuestTimers("ReachForFood1");
					} else {
						startQuestTimer("ReturnFromFood2", 2000, npc, null, true);
						cancelQuestTimers("ReachForFood2");
					}
					return "";
				} else if (npc.calculateDistance(cryGolem.newLoc.getLocation(), false, false) == 0) {
					npc.getAI().setIntention(CtrlIntention.AI_INTENTION_REST);
					L2World.getInstance().removeVisibleObject(cryGolem.foodItem, cryGolem.foodItem.getWorldRegion());
					L2World.getInstance().removeObject(cryGolem.foodItem);
					cryGolem.foodItem = null;
					int rnd3 = getRandom(10);
					if (!cryGolem.golemHasBeenFed) {
						cryGolem.golemHasBeenFed = true;
					} 
					if (rnd3 <= 4) {
						broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.YUMMY_THIS_IS_SO_TASTY);
					} else {
						broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.CRISPY_AND_COLD_FEELING_TEEHEE_DELICIOUS);
					}
					if (npc.calculateDistance(golemFinalDestination1, false, false) < 100 && !world.golemIsAtFinalDestination1) {
						npc.doCast(PRESENTATION);
						world.golemIsAtFinalDestination1 = true;
						cryGolem.isAtFinalDestination = true;
						if (world.golemIsAtFinalDestination2) {
							openDoor(DOOR7, world.getInstanceId());
							L2Npc tears = addSpawn(TEARS, tearsSpawnLocation, false, 0, true, world.getInstanceId());
							startQuestTimer("CheckTearsAttack", 1000, tears, null);
							world.setStatus(4);
						}
						if (event.equalsIgnoreCase("ReachForFood1")) {
							cancelQuestTimers("ReachForFood1");
						} else {
							cancelQuestTimers("ReachForFood2");
						}
					} else if (npc.calculateDistance(golemFinalDestination2, false, false) < 100 && !world.golemIsAtFinalDestination2) {
						npc.doCast(PRESENTATION);
						world.golemIsAtFinalDestination2 = true;
						cryGolem.isAtFinalDestination = true;
						if (world.golemIsAtFinalDestination1) {
							openDoor(DOOR7, world.getInstanceId());
							L2Npc tears = addSpawn(TEARS, tearsSpawnLocation, false, 0, true, world.getInstanceId());
							startQuestTimer("CheckTearsAttack", 1000, tears, null);
							world.setStatus(4);
						}
						if (event.equalsIgnoreCase("ReachForFood1")) {
							cancelQuestTimers("ReachForFood1");
						} else {
							cancelQuestTimers("ReachForFood2");
						}
					} else if (event.equalsIgnoreCase("ReachForFood1")) {
						startQuestTimer("SeekForFood1", 2000, npc, null);
						cancelQuestTimers("ReachForFood1");
					} else {
						startQuestTimer("SeekForFood2", 2000, npc, null);
						cancelQuestTimers("ReachForFood2");
					}
				}
				return "";
			} else if ((event.equalsIgnoreCase("ReturnFromFood1") || event.equalsIgnoreCase("ReturnFromFood2")) && (npc.calculateDistance(cryGolem.oldLoc.getLocation(), false, false) == 0)) {
				npc.getAI().setIntention(CtrlIntention.AI_INTENTION_REST);
				if (event.equalsIgnoreCase("ReturnFromFood1")) {
					startQuestTimer("SeekForFood1", 2000, npc, null);
					cancelQuestTimers("ReturnFromFood1");
				} else {
					startQuestTimer("SeekForFood2", 2000, npc, null);
					cancelQuestTimers("ReturnFromFood2");
				}
			}
			return "";
			
		}
		return "";
	}

	private void giveRewards(L2PcInstance player, int instanceId, int bossCry, boolean isBaylor) {
		final int num = Math.max(rates().getCorpseDropChanceMultiplier().intValue(), 1);
		L2Party party = player.getParty();
		if (party != null) {
			for (L2PcInstance partyMember : party.getMembers()) {
				if (partyMember.getInstanceId() == instanceId) {
					if (!isBaylor && hasQuestItems(partyMember, CONTAMINATED_CRYSTAL)) {
						takeItems(partyMember, CONTAMINATED_CRYSTAL, 1);
						giveItems(partyMember, bossCry, 1);
					}
					if (getRandom(10) < 5) {
						giveItems(partyMember, WHITE_SEED_OF_EVIL_SHARD, num);
					} else {
						giveItems(partyMember, BLACK_SEED_OF_EVIL_SHARD, num);
					}
				}
			}
		} else if (player.getInstanceId() == instanceId) {
			if (!isBaylor && hasQuestItems(player, CONTAMINATED_CRYSTAL)) {
				takeItems(player, CONTAMINATED_CRYSTAL, 1);
				giveItems(player, bossCry, 1);
			}
			if (getRandom(10) < 5) {
				giveItems(player, WHITE_SEED_OF_EVIL_SHARD, num);
			} else {
				giveItems(player, BLACK_SEED_OF_EVIL_SHARD, num);
			}
		}
	}

	@Override
	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
		InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
		if (tmpworld instanceof CCWorld world) {
			if ((world.getStatus() == 2) && world.npcList1.containsKey(npc)) {
				world.npcList1.put(npc, true);
				for (boolean isDead : world.npcList1.values()) {
					if (!isDead) {
						return "";
					}
				}
				world.setStatus(3);
				CrystalGolem crygolem1 = new CrystalGolem();
				CrystalGolem crygolem2 = new CrystalGolem();
				L2Npc golem1 = addSpawn(CRYSTALLINE_GOLEM, 140547, 151670, -11813, 32767, false, 0, false, world.getInstanceId());
				startQuestTimer("SeekForFood1", 2000, golem1, null);
				golem1.setRunning();
				world.crystalGolems.put(golem1, crygolem1);
				L2Npc golem2 = addSpawn(CRYSTALLINE_GOLEM, 141941, 151684, -11813, 63371, false, 0, false, world.getInstanceId());
				startQuestTimer("SeekForFood2", 2000, golem2, null);
				golem2.setRunning();
				world.crystalGolems.put(golem2, crygolem2);
			} else if ((world.getStatus() == 4) && (npc.getId() == TEARS)) {
				InstanceManager.getInstance().getInstance(world.getInstanceId()).setDuration(300000);
				addSpawn(ORACLE_GUIDE_3, 144312, 154420, -11855, 0, false, 0, false, world.getInstanceId());
				giveRewards(player, npc.getInstanceId(), CLEAR_CRYSTAL, false);
			} else if ((world.getStatus() == 2) && world.keyKeepers.contains(npc)) {
				if (npc.getId() == GATEKEEPER_LOHAN) {
					npc.dropItem(player, BLUE_CORAL_KEY, 1);
					runEmeraldSquare(world);
				} else if (npc.getId() == GATEKEEPER_PROVO) {
					npc.dropItem(player, RED_CORAL_KEY, 1);
					runSteamRooms(world, STEAM1_SPAWNS, 22);
					Optional.ofNullable(player.getParty()).map(L2Party::getMembers).orElseGet(() -> List.of(player)).stream()
							.filter(member -> member.getInstanceId() == world.getInstanceId())
							.forEach(member -> {
								EVENT_TIMER_1.getSkill().applyEffects(member, member);
								startQuestTimer("Timer2", 300000, npc, member);
							});
					startQuestTimer("Timer21", 300000, npc, null);
				}
				for (L2Npc gk : world.keyKeepers) {
					if (gk != npc) {
						gk.decayMe();
					}
				}
			} else if (world.getStatus() == 3) {
				if (checkKillProgress(0, npc, world)) {
					world.setStatus(4);
					addSpawn(TOURMALINE, 148202, 144791, -12235, 0, false, 0, false, world.getInstanceId());
				} else {
					return "";
				}
			} else if (world.getStatus() == 4) {
				if (npc.getId() == TOURMALINE) {
					world.setStatus(5);
					addSpawn(TEROD, 147777, 146780, -12281, 0, false, 0, false, world.getInstanceId());
				}
			} else if (world.getStatus() == 5) {
				if (npc.getId() == TEROD) {
					world.setStatus(6);
					addSpawn(TOURMALINE, 143694, 142659, -11882, 0, false, 0, false, world.getInstanceId());
				}
			} else if (world.getStatus() == 6) {
				if (npc.getId() == TOURMALINE) {
					world.setStatus(7);
					addSpawn(DOLPH, 142054, 143288, -11825, 0, false, 0, false, world.getInstanceId());
				}
			} else if (world.getStatus() == 7) {
				if (npc.getId() == DOLPH) {
					world.setStatus(8);
					// first door opener trap
					L2Npc trap = addTrap(DOOR_OPENING_TRAP[0], DOOR_OPENING_TRAP[1], DOOR_OPENING_TRAP[2], DOOR_OPENING_TRAP[3], DOOR_OPENING_TRAP[4], null, world.getInstanceId());
					broadcastNpcSay(trap, Say2.NPC_SHOUT, NpcStringId.YOU_HAVE_FINALLY_COME_HERE_BUT_YOU_WILL_NOT_BE_ABLE_TO_FIND_THE_SECRET_ROOM);
				}
			} else if (world.getStatus() == 8) {
				for (int i = 0; i < 4; i++) {
					if ((world.roomsStatus[i] == 1) && checkKillProgress(i + 1, npc, world)) {
						world.roomsStatus[i] = 2;
					}
					if (world.roomsStatus[i] == 2) {
						world.cleanedRooms++;
						if (world.cleanedRooms == 21) {
							runDarnel(world);
						}
					}
				}
			} else if ((world.getStatus() >= 22) && (world.getStatus() <= 25)) {
				if (npc.getId() == 22416) {
					for (L2Npc oracle : world.oracles.keySet()) {
						if (world.oracles.get(oracle) == npc) {
							world.oracles.put(oracle, null);
						}
					}
				}
				if (checkKillProgress(0, npc, world)) {
					world.npcList2.clear();
					int[][] oracleOrder;
					switch (world.getStatus()) {
						case 22:
							closeDoor(DOOR6, npc.getInstanceId());
							oracleOrder = ordreOracle1;
							break;
						case 23:
							oracleOrder = ordreOracle2;
							break;
						case 24:
							oracleOrder = ordreOracle3;
							break;
						case 25:
							world.setStatus(26);
							Optional.ofNullable(player.getParty()).map(L2Party::getMembers).orElseGet(() -> List.of(player))
									.forEach(member -> member.stopSkillEffects(true, 5239));
							cancelQuestTimers("Timer5");
							cancelQuestTimers("Timer51");
							openDoor(DOOR3, npc.getInstanceId());
							openDoor(DOOR4, npc.getInstanceId());
							L2Npc kechi = addSpawn(KECHI, 154069, 149525, -12158, 51165, false, 0, false, world.getInstanceId());
							startQuestTimer("CheckKechiAttack", 1000, kechi, null);
							return "";
						default:
							_log.warning("CrystalCavern-SteamCorridor: status " + world.getStatus() + " error. OracleOrder not found in " + world.getInstanceId());
							return "";
					}
					runSteamOracles(world, oracleOrder);
				}
			} else if (((world.getStatus() == 9) && (npc.getId() == DARNEL)) || ((world.getStatus() == 26) && (npc.getId() == KECHI))) {
				InstanceManager.getInstance().getInstance(world.getInstanceId()).setDuration(300000);
				int bossCry;
				if (npc.getId() == KECHI) {
					bossCry = RED_CRYSTAL;
					cancelQuestTimers("SpawnGuards");
					addSpawn(ORACLE_GUIDE_3, 154077, 149527, -12159, 0, false, 0, false, world.getInstanceId());
				} else if (npc.getId() == DARNEL) {
					bossCry = BLUE_CRYSTAL;
					addSpawn(ORACLE_GUIDE_3, 152761, 145950, -12588, 0, false, 0, false, world.getInstanceId());
				} else {
					// something is wrong
					return "";
				}
				giveRewards(player, npc.getInstanceId(), bossCry, false);
			}
			if (npc.getId() == ALARM) {
				world.baylor.removeSkill(PHYSICAL_UP.getSkillId());
				world.baylor.removeSkill(MAGICAL_UP.getSkillId());
				world.alarm = null;
				if ((world.baylor.getMaxHp() * 0.3) < world.baylor.getStatus().getCurrentHp()) {
					startQuestTimer("BaylorAlarm", 40000, world.baylor, null);
				}
			} else if (npc.getId() == BAYLOR) {
				world.setStatus(31);
				world.baylor = null;
				Instance baylorInstance = InstanceManager.getInstance().getInstance(npc.getInstanceId());
				baylorInstance.setDuration(300000);
				this.startQuestTimer("SpawnOracle", 1000, npc, null);
				giveRewards(player, npc.getInstanceId(), -1, true);
			}
		}
		return "";
	}

	@Override
	public String onTalk(L2Npc npc, L2PcInstance player) {
		int npcId = npc.getId();
		QuestState st = getQuestState(player, false);
		if (st == null) {
			st = newQuestState(player);
		}
		if (npcId == ORACLE_GUIDE_1) {
			enterInstance(player, new CCWorld(System.currentTimeMillis() + 5400000), "CrystalCaverns.xml", TEMPLATE_ID);
			return "";
		}
		InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
		if (tmpworld instanceof CCWorld world) {
			if ((npc.getId() >= ORACLE_GUIDE_5) && (npc.getId() <= ORACLE_GUIDE_6) && world.oracleTriggered[npc.getId() - ORACLE_GUIDE_5]) {
				boolean doTeleport = false;
				Location loc = null;
				L2Party party = player.getParty();
				doTeleport = true;
				switch (npc.getId()) {
					case ORACLE_GUIDE_5:
						if (world.getStatus() == 22) {
							runSteamRooms(world, STEAM2_SPAWNS, 23);
						}
						loc = new Location(147529, 152587, -12169);
						cancelQuestTimers("Timer2");
						cancelQuestTimers("Timer21");
						Optional.ofNullable(player.getParty()).map(L2Party::getMembers).orElseGet(() -> List.of(player)).stream()
								.filter(member -> member.getInstanceId() == world.getInstanceId())
								.forEach(member -> {
									member.stopSkillEffects(true, 5239);
									EVENT_TIMER_2.getSkill().applyEffects(member, member);
									startQuestTimer("Timer3", 600000, npc, member);
								});
						startQuestTimer("Timer31", 600000, npc, null);
						break;
					case ORACLE_GUIDE_8:
						if (world.getStatus() == 23) {
							runSteamRooms(world, STEAM3_SPAWNS, 24);
						}
						loc = new Location(150194, 152610, -12169);
						cancelQuestTimers("Timer3");
						cancelQuestTimers("Timer31");
						if (party != null) {
							for (L2PcInstance partyMember : party.getMembers()) {
								if (partyMember.getInstanceId() == world.getInstanceId()) {
									partyMember.stopSkillEffects(true, 5239);
									EVENT_TIMER_4.getSkill().applyEffects(partyMember, partyMember);
									startQuestTimer("Timer4", 1200000, npc, partyMember);
								}
							}
						} else {
							player.stopSkillEffects(true, 5239);
							EVENT_TIMER_4.getSkill().applyEffects(player, player);
							startQuestTimer("Timer4", 1200000, npc, player);
						}
						startQuestTimer("Timer41", 1200000, npc, null);
						break;
					case ORACLE_GUIDE_6:
						if (world.getStatus() == 24) {
							runSteamRooms(world, STEAM4_SPAWNS, 25);
						}
						loc = new Location(149743, 149986, -12141);
						cancelQuestTimers("Timer4");
						cancelQuestTimers("Timer41");
						if (party != null) {
							for (L2PcInstance partyMember : party.getMembers()) {
								if (partyMember.getInstanceId() == world.getInstanceId()) {
									partyMember.stopSkillEffects(true, 5239);
									EVENT_TIMER_3.getSkill().applyEffects(partyMember, partyMember);
									startQuestTimer("Timer5", 900000, npc, partyMember);
								}
							}
						} else {
							player.stopSkillEffects(true, 5239);
							EVENT_TIMER_3.getSkill().applyEffects(player, player);
							startQuestTimer("Timer5", 900000, npc, player);
						}
						startQuestTimer("Timer51", 900000, npc, null);
						break;
					default:
						// something is wrong
						doTeleport = false;
				}
				if (doTeleport && (loc != null)) {
					if (!checkOracleConditions(player)) {
						return "";
					} else if (party != null) {
						for (L2PcInstance partyMember : party.getMembers()) {
							partyMember.destroyItemByItemId("Quest", RED_CORAL, 1, player, true);
							teleportPlayer(partyMember, loc, npc.getInstanceId());
						}
					} else {
						teleportPlayer(player, loc, npc.getInstanceId());
					}
				}
			} else if (npc.getId() == ORACLE_GUIDE_3) {
				if ((world.getStatus() < 30) && checkBaylorConditions(player)) {
					world.raiders.clear();
					world.raiders.addAll(Optional.ofNullable(player.getParty()).map(L2Party::getMembers).orElseGet(() -> List.of(player)));
				} else {
					return "";
				}
				world.setStatus(30);
				long time = world.endTime - System.currentTimeMillis();
				Instance baylorInstance = InstanceManager.getInstance().getInstance(world.getInstanceId());
				baylorInstance.setDuration((int) time);
				int radius = 150;
				int i = 0;
				int members = world.raiders.size();
				for (L2PcInstance p : world.raiders) {
					int x = (int) (radius * Math.cos((i * 2 * Math.PI) / members));
					int y = (int) (radius * Math.sin((i++ * 2 * Math.PI) / members));
					p.teleToLocation(new Location(153571 + x, 142075 + y, -12737));
					L2Summon pet = p.getSummon();
					if (pet != null) {
						pet.teleToLocation(new Location(153571 + x, 142075 + y, -12737), true);
						pet.broadcastPacket(new ValidateLocation(pet));
					}
					p.startStunning();
					p.broadcastPacket(new ValidateLocation(p));
				}
				startQuestTimer("Baylor", 30000, npc, null);
			} else if ((npc.getId() == ORACLE_GUIDE_4) && (world.getStatus() == 31)) {
				teleportPlayer(player, new Location(153522, 144212, -9747), npc.getInstanceId());
			}
		}
		return "";
	}

	@Override
	public String onTrapAction(L2TrapInstance trap, L2Character trigger, TrapAction action) {
		InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(trap.getInstanceId());
		if (tmpworld instanceof CCWorld world) {
			switch (action) {
				case TRAP_DISARMED:
					if (trap.getId() == DOOR_OPENING_TRAP[0]) {
						openDoor(DOOR14, world.getInstanceId());
						runEmeraldRooms(world, ROOM1_SPAWNS, 1);
					}
					break;
			}
		}
		return null;
	}

	@Override
	public String onEnterZone(L2Character character, L2ZoneType zone) {
		if (character instanceof L2PcInstance) {
			InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(character.getInstanceId());
			if (tmpworld instanceof CCWorld world) {
				if (world.getStatus() == 8) {
					int room;
					int[][] spawns;
					switch (zone.getId()) {
						case 20105:
							spawns = ROOM2_SPAWNS;
							room = 2;
							break;
						case 20106:
							spawns = ROOM3_SPAWNS;
							room = 3;
							break;
						case 20107:
							spawns = ROOM4_SPAWNS;
							room = 4;
							break;
						default:
							return super.onEnterZone(character, zone);
					}
					for (L2DoorInstance door : InstanceManager.getInstance().getInstance(world.getInstanceId()).getDoors()) {
						if (door.getId() == (room + DOOR10)) {
							if (door.getOpen()) {
								return "";
							}
							if (!hasQuestItems((L2PcInstance) character, SECRET_KEY)) {
								return "";
							}
							if (world.roomsStatus[zone.getId() - 20104] == 0) {
								runEmeraldRooms(world, spawns, room);
							}
							door.openMe();
							takeItems((L2PcInstance) character, SECRET_KEY, 1);
							world.openedDoors.put(door, (L2PcInstance) character);
							break;
						}
					}
				}
			}
		}
		return super.onEnterZone(character, zone);
	}

	@Override
	public String onExitZone(L2Character character, L2ZoneType zone) {
		if (character instanceof L2PcInstance) {
			InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(character.getInstanceId());
			if (tmpworld instanceof CCWorld world) {
				if (world.getStatus() == 8) {
					int doorId;
					switch (zone.getId()) {
						case 20105:
							doorId = DOOR11;
							break;
						case 20106:
							doorId = DOOR12;
							break;
						case 20107:
							doorId = DOOR13;
							break;
						default:
							return super.onExitZone(character, zone);
					}
					for (L2DoorInstance door : InstanceManager.getInstance().getInstance(world.getInstanceId()).getDoors()) {
						if (door.getId() == doorId) {
							if (door.getOpen() && (world.openedDoors.get(door) == character)) {
								door.closeMe();
								world.openedDoors.remove(door);
							}
							break;
						}
					}
				}
			}
		}
		return super.onExitZone(character, zone);
	}
}

 

Edited by Cherish
  • Thanks 1

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...