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.



  • Posts

    • This post originally appeared on zupyak.   If you're diving into MLB The Show 25, you know how essential stubs are for building a powerhouse team. Whether you're aiming to snag elite players, upgrade your roster, or stock up on packs, stubs are the key to success. The good news? You don't need to spend real money to earn them. With a little strategy and effort, you can rake in stubs and dominate the diamond.  Here are the top five strategies to maximize your MLB The Show stub earnings and create the ultimate team without breaking the bank.    1. Earning Stubs with Diamond Quest Diamond Quest is a goldmine for stubs. By completing challenges in this mode, you can earn Diamond cards, which often have high sell values. Once you've earned these cards, sell them in the in-game Marketplace for a quick influx of stubs. Additionally, the packs you earn from Diamond Quest can be opened for more cards to sell or use in collections.   2. Completing Conquest Maps Conquest Maps are another excellent way to rack up stubs. Focus on capturing territories and completing map-specific goals. Many maps offer hidden rewards, including packs and stubs, which can significantly boost your earnings. You don't always need to conquer Strongholds—simply taking over territories can yield great rewards.   3. Flipping Cards in the Marketplace The Marketplace is your playground for flipping cards. Look for cards with a significant gap between their "Buy Now" and "Sell Now" prices. Place a Buy Order slightly above the current "Sell Now" price, then list the card for a "Sell Order" just below the "Buy Now" price. After the 10% Marketplace tax, you'll still make a profit. This strategy works best with high-value cards but requires patience and consistency.     4. Leveraging Player Exchanges Player Exchanges are an underrated method for earning stubs. Purchase cheap Silver cards near their quick-sell value, then exchange them for Gold players. These Gold players can either be used in your lineup or sold for a profit. This method is especially effective early in the game when Gold cards hold higher value.   5. Selling Things You Don't Need Don't let unused items clutter your inventory. Regularly check for duplicate cards, equipment, or other items you don't need. Sell these through the Marketplace to free up space and earn extra stubs. Even Bronze and Silver cards can add up over time, so don't overlook them. With these strategies, you'll be well on your way to building a dream team without spending real money. Let me know if you'd like to dive deeper into any of these methods!   Final Thoughts Building your dream team in MLB The Show 25 doesn't have to cost real money. With these five strategies—earning rewards through Diamond Quest, conquering Conquest Maps, flipping cards in the Marketplace, leveraging Player Exchanges, and selling unused items—you'll be well on your way to amassing stubs and creating a roster that rivals even the best in the game. Remember, consistency is key! Whether you're grinding through challenges or flipping cards daily, every little bit adds up over time. Stick with these methods, and soon enough, you'll have the stubs you need to dominate the diamond. Let us know which strategy works best for you—or if you've discovered any additional tips that deserve a spot on this list! Happy grinding!   
    • I don't see that ur account got unbanned https://maxcheaters.com/profile/80641-∽ave∽/  
    • Looking for gracia final/gracia epilogue server files including source.
    • Got banned for ALLEGED scamm. Unbaned because I never scammed anyone - I either deliver or refund. So You can cry as much as You like, post as much idiotic and chidlish emotes as You like, but I'm not a scammer. So...get a life kid, and fuck off Cuntw0lf. There is a reason You have "0" in Your nickname. You are a zero 😎
    • talk in the mirror 🖕  🤏 in some of those urls you are banned for scam     definition of scam for you is not include delivery we all know scammer once scammer always i cant understand why you talk to me only and ignore the others? why nobody else triggers you like that
  • Topics

×
×
  • Create New...