Addition of Crystal Cavern instances.
Author: St3eT Adapted from: L2jUnity free files.
This commit is contained in:
		| @@ -0,0 +1,215 @@ | ||||
| /* | ||||
|  * This file is part of the L2J Mobius project. | ||||
|  *  | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  *  | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
|  * General Public License for more details. | ||||
|  *  | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package ai.areas.Parnassus.EntrancePortalToCrystalCaverns; | ||||
|  | ||||
| import java.util.Calendar; | ||||
|  | ||||
| import org.l2jmobius.gameserver.instancemanager.QuestManager; | ||||
| import org.l2jmobius.gameserver.model.StatsSet; | ||||
| import org.l2jmobius.gameserver.model.World; | ||||
| import org.l2jmobius.gameserver.model.actor.Creature; | ||||
| import org.l2jmobius.gameserver.model.actor.Npc; | ||||
| import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; | ||||
| import org.l2jmobius.gameserver.model.quest.Quest; | ||||
| import org.l2jmobius.gameserver.network.serverpackets.OnEventTrigger; | ||||
|  | ||||
| import ai.AbstractNpcAI; | ||||
| import instances.CrystalCaverns.CrystalCavernsCoralGarden; | ||||
| import instances.CrystalCaverns.CrystalCavernsEmeraldSquare; | ||||
| import instances.CrystalCaverns.CrystalCavernsSteamCorridor; | ||||
|  | ||||
| /** | ||||
|  * Entrance Portal to Crystal Caverns AI. | ||||
|  * @author St3eT | ||||
|  */ | ||||
| public class EntrancePortalToCrystalCaverns extends AbstractNpcAI | ||||
| { | ||||
| 	// NPCs | ||||
| 	private static final int CAVERNS_ENTRACE = 33522; | ||||
| 	// Misc | ||||
| 	private static final int EMERALD_SQUARE_TEMPLATE_ID = 163; | ||||
| 	private static final int STEAM_CORRIDOR_TEMPLATE_ID = 164; | ||||
| 	private static final int CORAL_GARDEN_TEMPLATE_ID = 165; | ||||
| 	private static final int PRISON_ENTRACE_TRIGGER_1 = 24230010; | ||||
| 	private static final int PRISON_ENTRACE_TRIGGER_2 = 24230012; | ||||
| 	private static final int CAVERNS_ENTRACE_TRIGGER_1 = 24230014; | ||||
| 	private static final int CAVERNS_ENTRACE_TRIGGER_2 = 24230016; | ||||
| 	private static final int CAVERNS_ENTRACE_TRIGGER_3 = 24230018; | ||||
| 	 | ||||
| 	private EntrancePortalToCrystalCaverns() | ||||
| 	{ | ||||
| 		addStartNpc(CAVERNS_ENTRACE); | ||||
| 		addTalkId(CAVERNS_ENTRACE); | ||||
| 		addFirstTalkId(CAVERNS_ENTRACE); | ||||
| 		addSpawnId(CAVERNS_ENTRACE); | ||||
| 		addSeeCreatureId(CAVERNS_ENTRACE); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public String onAdvEvent(String event, Npc npc, PlayerInstance player) | ||||
| 	{ | ||||
| 		if (event.equals("enterInstance")) | ||||
| 		{ | ||||
| 			Quest instanceScript = null; | ||||
| 			 | ||||
| 			switch (getCurrentInstanceTemplateId()) | ||||
| 			{ | ||||
| 				case EMERALD_SQUARE_TEMPLATE_ID: | ||||
| 				{ | ||||
| 					instanceScript = QuestManager.getInstance().getQuest(CrystalCavernsEmeraldSquare.class.getSimpleName()); | ||||
| 					break; | ||||
| 				} | ||||
| 				case STEAM_CORRIDOR_TEMPLATE_ID: | ||||
| 				{ | ||||
| 					instanceScript = QuestManager.getInstance().getQuest(CrystalCavernsSteamCorridor.class.getSimpleName()); | ||||
| 					break; | ||||
| 				} | ||||
| 				case CORAL_GARDEN_TEMPLATE_ID: | ||||
| 				{ | ||||
| 					instanceScript = QuestManager.getInstance().getQuest(CrystalCavernsCoralGarden.class.getSimpleName()); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 			 | ||||
| 			if (instanceScript != null) | ||||
| 			{ | ||||
| 				instanceScript.notifyEvent(event, npc, player); | ||||
| 			} | ||||
| 		} | ||||
| 		return super.onAdvEvent(event, npc, player); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public String onFirstTalk(Npc npc, PlayerInstance player) | ||||
| 	{ | ||||
| 		return "EntrancePortal_" + getCurrentInstanceTemplateId() + ".html"; | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public String onSpawn(Npc npc) | ||||
| 	{ | ||||
| 		getTimers().addRepeatingTimer("LOOP_TIMER", 10000, npc, null); | ||||
| 		return super.onSpawn(npc); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public void onTimerEvent(String event, StatsSet params, Npc npc, PlayerInstance player) | ||||
| 	{ | ||||
| 		if (event.equals("LOOP_TIMER")) | ||||
| 		{ | ||||
| 			final int currentTemplateId = getCurrentInstanceTemplateId(); | ||||
| 			 | ||||
| 			World.getInstance().forEachVisibleObjectInRange(npc, PlayerInstance.class, 500, p -> | ||||
| 			{ | ||||
| 				updateTriggersForPlayer(player, currentTemplateId); | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public String onSeeCreature(Npc npc, Creature creature, boolean isSummon) | ||||
| 	{ | ||||
| 		if (creature.isPlayer()) | ||||
| 		{ | ||||
| 			creature.getActingPlayer().sendPacket(new OnEventTrigger(PRISON_ENTRACE_TRIGGER_1, true)); | ||||
| 			creature.getActingPlayer().sendPacket(new OnEventTrigger(PRISON_ENTRACE_TRIGGER_2, true)); | ||||
| 			updateTriggersForPlayer(creature.getActingPlayer(), getCurrentInstanceTemplateId()); | ||||
| 		} | ||||
| 		return super.onSeeCreature(npc, creature, isSummon); | ||||
| 	} | ||||
| 	 | ||||
| 	public void updateTriggersForPlayer(PlayerInstance player, int currentTemplateId) | ||||
| 	{ | ||||
| 		if (player != null) | ||||
| 		{ | ||||
| 			player.sendPacket(new OnEventTrigger(CAVERNS_ENTRACE_TRIGGER_1, false)); | ||||
| 			player.sendPacket(new OnEventTrigger(CAVERNS_ENTRACE_TRIGGER_2, false)); | ||||
| 			player.sendPacket(new OnEventTrigger(CAVERNS_ENTRACE_TRIGGER_3, false)); | ||||
| 			 | ||||
| 			switch (currentTemplateId) | ||||
| 			{ | ||||
| 				case EMERALD_SQUARE_TEMPLATE_ID: | ||||
| 				{ | ||||
| 					player.sendPacket(new OnEventTrigger(CAVERNS_ENTRACE_TRIGGER_1, true)); | ||||
| 					break; | ||||
| 				} | ||||
| 				case STEAM_CORRIDOR_TEMPLATE_ID: | ||||
| 				{ | ||||
| 					player.sendPacket(new OnEventTrigger(CAVERNS_ENTRACE_TRIGGER_2, true)); | ||||
| 					break; | ||||
| 				} | ||||
| 				case CORAL_GARDEN_TEMPLATE_ID: | ||||
| 				{ | ||||
| 					player.sendPacket(new OnEventTrigger(CAVERNS_ENTRACE_TRIGGER_3, true)); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	public int getCurrentInstanceTemplateId() | ||||
| 	{ | ||||
| 		final int day = Calendar.getInstance().get(Calendar.DAY_OF_WEEK); | ||||
| 		final int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY); | ||||
| 		int templateId = -1; | ||||
| 		 | ||||
| 		switch (day) | ||||
| 		{ | ||||
| 			case Calendar.MONDAY: | ||||
| 			{ | ||||
| 				templateId = (hour < 18) ? EMERALD_SQUARE_TEMPLATE_ID : STEAM_CORRIDOR_TEMPLATE_ID; | ||||
| 				break; | ||||
| 			} | ||||
| 			case Calendar.TUESDAY: | ||||
| 			{ | ||||
| 				templateId = (hour < 18) ? CORAL_GARDEN_TEMPLATE_ID : EMERALD_SQUARE_TEMPLATE_ID; | ||||
| 				break; | ||||
| 			} | ||||
| 			case Calendar.WEDNESDAY: | ||||
| 			{ | ||||
| 				templateId = (hour < 18) ? STEAM_CORRIDOR_TEMPLATE_ID : CORAL_GARDEN_TEMPLATE_ID; | ||||
| 				break; | ||||
| 			} | ||||
| 			case Calendar.THURSDAY: | ||||
| 			{ | ||||
| 				templateId = (hour < 18) ? EMERALD_SQUARE_TEMPLATE_ID : STEAM_CORRIDOR_TEMPLATE_ID; | ||||
| 				break; | ||||
| 			} | ||||
| 			case Calendar.FRIDAY: | ||||
| 			{ | ||||
| 				templateId = (hour < 18) ? CORAL_GARDEN_TEMPLATE_ID : EMERALD_SQUARE_TEMPLATE_ID; | ||||
| 				break; | ||||
| 			} | ||||
| 			case Calendar.SATURDAY: | ||||
| 			{ | ||||
| 				templateId = (hour < 18) ? STEAM_CORRIDOR_TEMPLATE_ID : CORAL_GARDEN_TEMPLATE_ID; | ||||
| 				break; | ||||
| 			} | ||||
| 			case Calendar.SUNDAY: | ||||
| 			{ | ||||
| 				templateId = (hour < 18) ? EMERALD_SQUARE_TEMPLATE_ID : STEAM_CORRIDOR_TEMPLATE_ID; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		return templateId; | ||||
| 	} | ||||
| 	 | ||||
| 	public static void main(String[] args) | ||||
| 	{ | ||||
| 		new EntrancePortalToCrystalCaverns(); | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,4 @@ | ||||
| <html><body>Entrance Portal to Crystal Caverns:<br> | ||||
| At this time, you can go into the <font color="LEVEL">Emerald Square</font>.<br> | ||||
| <Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest EntrancePortalToCrystalCaverns enterInstance">Enter</Button> | ||||
| </body></html> | ||||
| @@ -0,0 +1,4 @@ | ||||
| <html><body>Entrance Portal to Crystal Caverns:<br> | ||||
| At this time, you can go into the <font color="LEVEL">Steam Corridor</font>.<br> | ||||
| <Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest EntrancePortalToCrystalCaverns enterInstance">Enter</Button> | ||||
| </body></html> | ||||
| @@ -0,0 +1,4 @@ | ||||
| <html><body>Entrance Portal to Crystal Caverns:<br> | ||||
| At this time, you can go into the <font color="LEVEL">Coral Garden</font>.<br> | ||||
| <Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest EntrancePortalToCrystalCaverns enterInstance">Enter</Button> | ||||
| </body></html> | ||||
| @@ -0,0 +1,253 @@ | ||||
| /* | ||||
|  * This file is part of the L2J Mobius project. | ||||
|  *  | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  *  | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
|  * General Public License for more details. | ||||
|  *  | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package instances.CrystalCaverns; | ||||
|  | ||||
| import org.l2jmobius.gameserver.instancemanager.WalkingManager; | ||||
| import org.l2jmobius.gameserver.model.Location; | ||||
| import org.l2jmobius.gameserver.model.Spawn; | ||||
| import org.l2jmobius.gameserver.model.StatsSet; | ||||
| import org.l2jmobius.gameserver.model.actor.Npc; | ||||
| import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; | ||||
| import org.l2jmobius.gameserver.model.instancezone.Instance; | ||||
| import org.l2jmobius.gameserver.network.NpcStringId; | ||||
| import org.l2jmobius.gameserver.network.serverpackets.ExSendUIEvent; | ||||
| import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage; | ||||
|  | ||||
| import instances.AbstractInstance; | ||||
|  | ||||
| /** | ||||
|  * Crystal Caverns - Coral Garden instance zone. | ||||
|  * @author St3eT | ||||
|  */ | ||||
| public class CrystalCavernsCoralGarden extends AbstractInstance | ||||
| { | ||||
| 	// NPCs | ||||
| 	private static final int CAVERNS_ENTRACE = 33522; | ||||
| 	private static final int MICHAELA_NORMAL = 25799; | ||||
| 	private static final int MICHAELA_WISE = 26116; | ||||
| 	private static final int MICHAELA_WEALTHY = 26115; | ||||
| 	private static final int MICHAELA_ARMED = 26114; | ||||
| 	private static final int GOLEM_1 = 19013; // Crystalline Golem | ||||
| 	private static final int GOLEM_2 = 19014; // Crystalline Golem | ||||
| 	// Location | ||||
| 	private static final Location BOSS_LOC = new Location(144307, 220032, -11824); | ||||
| 	// Misc | ||||
| 	private static final int TEMPLATE_ID = 165; | ||||
| 	private static final int BOSS_DOOR_ID = 24240026; | ||||
| 	private static final int PLAYER_MAX_DISTANCE = 250; | ||||
| 	 | ||||
| 	public CrystalCavernsCoralGarden() | ||||
| 	{ | ||||
| 		super(TEMPLATE_ID); | ||||
| 		addStartNpc(CAVERNS_ENTRACE); | ||||
| 		addTalkId(CAVERNS_ENTRACE); | ||||
| 		addFirstTalkId(GOLEM_1, GOLEM_2); | ||||
| 		addKillId(MICHAELA_NORMAL, MICHAELA_WISE, MICHAELA_WEALTHY, MICHAELA_ARMED); | ||||
| 		addAttackId(MICHAELA_NORMAL, MICHAELA_WISE, MICHAELA_WEALTHY, MICHAELA_ARMED); | ||||
| 		addRouteFinishedId(GOLEM_1, GOLEM_2); | ||||
| 		addInstanceEnterId(TEMPLATE_ID); | ||||
| 		addInstanceLeaveId(TEMPLATE_ID); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public void onTimerEvent(String event, StatsSet params, Npc npc, PlayerInstance player) | ||||
| 	{ | ||||
| 		final Instance instance = npc.getInstanceWorld(); | ||||
| 		if (isInInstance(instance)) | ||||
| 		{ | ||||
| 			final StatsSet npcVars = npc.getVariables(); | ||||
| 			 | ||||
| 			switch (event) | ||||
| 			{ | ||||
| 				case "SUCCESS_TIMER": | ||||
| 				{ | ||||
| 					showOnScreenMsg(instance, NpcStringId.GOLEM_LOCATION_SUCCESSFUL_ENTRY_ACCESSED, ExShowScreenMessage.MIDDLE_CENTER, 5000); | ||||
| 					break; | ||||
| 				} | ||||
| 				case "LOOP_TIMER": | ||||
| 				{ | ||||
| 					player = npcVars.getObject("PLAYER_OBJECT", PlayerInstance.class); | ||||
| 					 | ||||
| 					if ((player != null) && (npc.calculateDistance3D(player) > PLAYER_MAX_DISTANCE) && npcVars.getBoolean("NPC_FOLLOWING", true)) | ||||
| 					{ | ||||
| 						WalkingManager.getInstance().cancelMoving(npc); | ||||
| 						addMoveToDesire(npc, new Location(npc.getX() + getRandom(-100, 100), npc.getY() + getRandom(-150, 150), npc.getZ()), 23); | ||||
| 						npc.setRunning(); | ||||
| 						npcVars.set("NPC_FOLLOWING", false); | ||||
| 						getTimers().cancelTimer("LOOP_TIMER", npc, null); | ||||
| 						getTimers().addTimer("FAIL_TIMER", 5000, npc, null); | ||||
| 					} | ||||
| 					break; | ||||
| 				} | ||||
| 				case "FAIL_TIMER": | ||||
| 				{ | ||||
| 					final Spawn spawn = npc.getSpawn(); | ||||
| 					 | ||||
| 					if (!npcVars.getBoolean("NPC_FOLLOWING", true)) | ||||
| 					{ | ||||
| 						WalkingManager.getInstance().cancelMoving(npc); | ||||
| 						npc.setWalking(); | ||||
| 						npc.teleToLocation(npc.getSpawn().getX(), npc.getSpawn().getY(), npc.getSpawn().getZ()); | ||||
| 						npc.setScriptValue(0); | ||||
| 						npc.setNameString(null); | ||||
| 						npc.setTitleString(null); | ||||
| 						npc.setTitle(null); | ||||
| 						npc.broadcastInfo(); | ||||
| 					} | ||||
| 					npcVars.set("CAN_CALL_MONSTERS", ((spawn.getX() - ((npc.getX() * spawn.getX()) - npc.getX())) + (spawn.getY() - (npc.getY() * spawn.getY()) - npc.getY())) > (200 * 200)); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public String onAdvEvent(String event, Npc npc, PlayerInstance player) | ||||
| 	{ | ||||
| 		if (event.equals("enterInstance")) | ||||
| 		{ | ||||
| 			enterInstance(player, npc, TEMPLATE_ID); | ||||
| 		} | ||||
| 		return super.onAdvEvent(event, npc, player); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public void onInstanceEnter(PlayerInstance player, Instance instance) | ||||
| 	{ | ||||
| 		final int startTime = (int) (instance.getElapsedTime() / 1000); | ||||
| 		final int endTime = (int) (instance.getRemainingTime() / 1000); | ||||
| 		player.sendPacket(new ExSendUIEvent(player, false, true, startTime, endTime, NpcStringId.ELAPSED_TIME)); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public void onInstanceLeave(PlayerInstance player, Instance instance) | ||||
| 	{ | ||||
| 		player.sendPacket(new ExSendUIEvent(player, true, true, 0, 0, NpcStringId.ELAPSED_TIME)); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public String onFirstTalk(Npc npc, PlayerInstance player) | ||||
| 	{ | ||||
| 		final Instance instance = npc.getInstanceWorld(); | ||||
| 		if (isInInstance(instance)) | ||||
| 		{ | ||||
| 			if (npc.isScriptValue(0)) | ||||
| 			{ | ||||
| 				npc.setScriptValue(1); | ||||
| 				npc.getVariables().set("PLAYER_OBJECT", player); | ||||
| 				npc.setNameString(NpcStringId.TRAITOR_CRYSTALLINE_GOLEM); | ||||
| 				npc.setTitleString(NpcStringId.GIVEN_TO_S1); | ||||
| 				npc.setTitle(player.getName()); | ||||
| 				npc.broadcastInfo(); | ||||
| 				WalkingManager.getInstance().startMoving(npc, npc.getId() == GOLEM_1 ? "gd_golem_1" : "gd_golem_2"); | ||||
| 				getTimers().addRepeatingTimer("LOOP_TIMER", 500, npc, null); | ||||
| 			} | ||||
| 		} | ||||
| 		return null; | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public void onRouteFinished(Npc npc) | ||||
| 	{ | ||||
| 		final Instance instance = npc.getInstanceWorld(); | ||||
| 		if (instance != null) | ||||
| 		{ | ||||
| 			WalkingManager.getInstance().cancelMoving(npc); | ||||
| 			showOnScreenMsg(instance, NpcStringId.GOLEM_ENTERED_THE_REQUIRED_ZONE, ExShowScreenMessage.MIDDLE_CENTER, 5000); | ||||
| 			npc.deleteMe(); | ||||
| 			 | ||||
| 			if (instance.getAliveNpcs(GOLEM_1, GOLEM_2).isEmpty()) | ||||
| 			{ | ||||
| 				instance.openCloseDoor(BOSS_DOOR_ID, true); | ||||
| 				 | ||||
| 				final int random = getRandom(100); | ||||
| 				int bossId = -1; | ||||
| 				 | ||||
| 				if (random < 55) | ||||
| 				{ | ||||
| 					bossId = MICHAELA_NORMAL; | ||||
| 				} | ||||
| 				else if (random < 80) | ||||
| 				{ | ||||
| 					bossId = MICHAELA_WISE; | ||||
| 				} | ||||
| 				else if (random < 95) | ||||
| 				{ | ||||
| 					bossId = MICHAELA_WEALTHY; | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					bossId = MICHAELA_ARMED; | ||||
| 				} | ||||
| 				 | ||||
| 				final Npc boss = addSpawn(bossId, BOSS_LOC, false, 0, false, instance.getId()); | ||||
| 				getTimers().addTimer("SUCCESS_TIMER", 5000, boss, null); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public String onKill(Npc npc, PlayerInstance killer, boolean isSummon) | ||||
| 	{ | ||||
| 		final Instance instance = npc.getInstanceWorld(); | ||||
| 		if (isInInstance(instance)) | ||||
| 		{ | ||||
| 			switch (npc.getId()) | ||||
| 			{ | ||||
| 				case MICHAELA_NORMAL: | ||||
| 				case MICHAELA_WISE: | ||||
| 				case MICHAELA_WEALTHY: | ||||
| 				case MICHAELA_ARMED: | ||||
| 				{ | ||||
| 					instance.finishInstance(); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		return super.onKill(npc, killer, isSummon); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon) | ||||
| 	{ | ||||
| 		final Instance instance = npc.getInstanceWorld(); | ||||
| 		if (isInInstance(instance)) | ||||
| 		{ | ||||
| 			switch (npc.getId()) | ||||
| 			{ | ||||
| 				case MICHAELA_NORMAL: | ||||
| 				case MICHAELA_WISE: | ||||
| 				case MICHAELA_WEALTHY: | ||||
| 				case MICHAELA_ARMED: | ||||
| 				{ | ||||
| 					if (npc.isScriptValue(0)) | ||||
| 					{ | ||||
| 						npc.setScriptValue(1); | ||||
| 						instance.openCloseDoor(BOSS_DOOR_ID, false); | ||||
| 					} | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		return super.onAttack(npc, attacker, damage, isSummon); | ||||
| 	} | ||||
| 	 | ||||
| 	public static void main(String[] args) | ||||
| 	{ | ||||
| 		new CrystalCavernsCoralGarden(); | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,424 @@ | ||||
| /* | ||||
|  * This file is part of the L2J Mobius project. | ||||
|  *  | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  *  | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
|  * General Public License for more details. | ||||
|  *  | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package instances.CrystalCaverns; | ||||
|  | ||||
| import org.l2jmobius.gameserver.model.Location; | ||||
| import org.l2jmobius.gameserver.model.StatsSet; | ||||
| import org.l2jmobius.gameserver.model.World; | ||||
| import org.l2jmobius.gameserver.model.actor.Creature; | ||||
| import org.l2jmobius.gameserver.model.actor.Npc; | ||||
| import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance; | ||||
| import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; | ||||
| import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureSee; | ||||
| import org.l2jmobius.gameserver.model.holders.SkillHolder; | ||||
| import org.l2jmobius.gameserver.model.instancezone.Instance; | ||||
| import org.l2jmobius.gameserver.model.skills.Skill; | ||||
| import org.l2jmobius.gameserver.model.stats.Stats; | ||||
| import org.l2jmobius.gameserver.network.NpcStringId; | ||||
| import org.l2jmobius.gameserver.network.serverpackets.ExSendUIEvent; | ||||
| import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage; | ||||
|  | ||||
| import instances.AbstractInstance; | ||||
|  | ||||
| /** | ||||
|  * Crystal Caverns - Emerald Square instance zone. | ||||
|  * @author St3eT | ||||
|  */ | ||||
| public class CrystalCavernsEmeraldSquare extends AbstractInstance | ||||
| { | ||||
| 	// NPCs | ||||
| 	private static final int CAVERNS_ENTRACE = 33522; | ||||
| 	private static final int VERIDAN_NORMAL = 25796; | ||||
| 	private static final int VERIDAN_WISE = 26107; | ||||
| 	private static final int VERIDAN_WEALTHY = 26106; | ||||
| 	private static final int VERIDAN_ARMED = 26105; | ||||
| 	private static final int WATER_CANNON = 19008; | ||||
| 	private static final int WATER_CANNON_SKILL = 19009; | ||||
| 	private static final int STRONGHOLD_PROTECTOR = 23012; | ||||
| 	private static final int SQUARE_INTRUDER = 23010; | ||||
| 	private static final int SQUARE_ATTACKER = 23011; | ||||
| 	// Skills | ||||
| 	private static final SkillHolder DESTROY_SKILL = new SkillHolder(12003, 1); | ||||
| 	private static final SkillHolder WATER_CANNON_SKILL_ATTACK = new SkillHolder(14179, 1); | ||||
| 	// Locations | ||||
| 	private static final Location[] BOSS_SPAWNS = | ||||
| 	{ | ||||
| 		new Location(152745, 145957, -12584, 16446), | ||||
| 		new Location(152816, 145968, -12633, 16446), | ||||
| 	}; | ||||
| 	// Misc | ||||
| 	private static final int TEMPLATE_ID = 163; | ||||
| 	private static final int RAID_DOOR_1 = 24220005; | ||||
| 	private static final int RAID_DOOR_2 = 24220006; | ||||
| 	 | ||||
| 	public CrystalCavernsEmeraldSquare() | ||||
| 	{ | ||||
| 		super(TEMPLATE_ID); | ||||
| 		addStartNpc(CAVERNS_ENTRACE); | ||||
| 		addTalkId(CAVERNS_ENTRACE); | ||||
| 		addSpawnId(WATER_CANNON); | ||||
| 		addKillId(WATER_CANNON, VERIDAN_NORMAL, VERIDAN_WISE, VERIDAN_WEALTHY, VERIDAN_ARMED); | ||||
| 		addAttackId(WATER_CANNON, VERIDAN_NORMAL, VERIDAN_WISE, VERIDAN_WEALTHY, VERIDAN_ARMED); | ||||
| 		addSpellFinishedId(WATER_CANNON_SKILL); | ||||
| 		addInstanceEnterId(TEMPLATE_ID); | ||||
| 		addInstanceLeaveId(TEMPLATE_ID); | ||||
| 		setCreatureSeeId(this::onCreatureSee, WATER_CANNON); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public String onAdvEvent(String event, Npc npc, PlayerInstance player) | ||||
| 	{ | ||||
| 		if (event.equals("enterInstance")) | ||||
| 		{ | ||||
| 			enterInstance(player, npc, TEMPLATE_ID); | ||||
| 		} | ||||
| 		return super.onAdvEvent(event, npc, player); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public void onTimerEvent(String event, StatsSet params, Npc npc, PlayerInstance player) | ||||
| 	{ | ||||
| 		final Instance instance = npc.getInstanceWorld(); | ||||
| 		if (isInInstance(instance)) | ||||
| 		{ | ||||
| 			final StatsSet npcParams = npc.getParameters(); | ||||
| 			final StatsSet npcVars = npc.getVariables(); | ||||
| 			final int baseId = npcParams.getInt("base_id", -1); | ||||
| 			 | ||||
| 			switch (event) | ||||
| 			{ | ||||
| 				case "HP_REGEN_TIMER": | ||||
| 				{ | ||||
| 					int value = ((baseId == 5) || (baseId == 6)) ? 5 : baseId; | ||||
| 					npc.getStat().addFixedValue(Stats.REGENERATE_HP_RATE, Double.valueOf(value * 1000)); | ||||
| 					break; | ||||
| 				} | ||||
| 				case "SUPPORT_SPAWN_TIMER": | ||||
| 				{ | ||||
| 					int supportVal = npcVars.getInt("SUPPORT_VALUE", 0); | ||||
| 					 | ||||
| 					if (supportVal > 3) | ||||
| 					{ | ||||
| 						return; | ||||
| 					} | ||||
| 					 | ||||
| 					if ((supportVal == 0) || (supportVal == 1) || (supportVal == 2)) | ||||
| 					{ | ||||
| 						final String spawnName = npcParams.getString("SupportMaker" + (supportVal + 1), null); | ||||
| 						if (spawnName != null) | ||||
| 						{ | ||||
| 							instance.spawnGroup(spawnName); | ||||
| 						} | ||||
| 						npcVars.increaseInt("SUPPORT_VALUE", 1); | ||||
| 					} | ||||
| 					 | ||||
| 					if (!npcVars.getBoolean("PREVIOUS_BASE_DESTROYED", false)) | ||||
| 					{ | ||||
| 						getTimers().addTimer("SUPPORT_SPAWN_TIMER", 60000, npc, null); | ||||
| 					} | ||||
| 					break; | ||||
| 				} | ||||
| 				case "CANNON_LOOP_ATTACK": | ||||
| 				{ | ||||
| 					if (npc.getCurrentHpPercent() > 30) | ||||
| 					{ | ||||
| 						if (npcVars.getBoolean("IS_DESTROY_ACTIVATED", false) || (getRandom(10) < 2)) | ||||
| 						{ | ||||
| 							final Npc cannonSkill = addSpawn(WATER_CANNON_SKILL, npc, true, 0, false, instance.getId()); | ||||
| 							addSkillCastDesire(cannonSkill, cannonSkill, WATER_CANNON_SKILL_ATTACK, 23); | ||||
| 						} | ||||
| 					} | ||||
| 					break; | ||||
| 				} | ||||
| 				case "SUICIDE_TIMER": | ||||
| 				{ | ||||
| 					npc.doDie(null); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill) | ||||
| 	{ | ||||
| 		final Instance instance = npc.getInstanceWorld(); | ||||
| 		if (isInInstance(instance)) | ||||
| 		{ | ||||
| 			final StatsSet npcVars = npc.getVariables(); | ||||
| 			 | ||||
| 			switch (npc.getId()) | ||||
| 			{ | ||||
| 				case VERIDAN_WISE: | ||||
| 				case VERIDAN_WEALTHY: | ||||
| 				case VERIDAN_ARMED: | ||||
| 				{ | ||||
| 					if (!npcVars.getBoolean("CLOSED_DOORS", false)) | ||||
| 					{ | ||||
| 						npcVars.set("CLOSED_DOORS", true); | ||||
| 						instance.openCloseDoor(RAID_DOOR_2, false); | ||||
| 					} | ||||
| 				} | ||||
| 				case WATER_CANNON: | ||||
| 				{ | ||||
| 					if ((skill != null) && (skill.getId() == DESTROY_SKILL.getSkillId()) && !npcVars.getBoolean("IS_DESTROY_ACTIVATED", false)) | ||||
| 					{ | ||||
| 						npcVars.set("IS_DESTROY_ACTIVATED", true); | ||||
| 						npc.setDisplayEffect(2); | ||||
| 						getTimers().addTimer("SUICIDE_TIMER", 60000, npc, null); | ||||
| 					} | ||||
| 					 | ||||
| 					if (npc.getCurrentHpPercent() < 30) | ||||
| 					{ | ||||
| 						if (!npcVars.getBoolean("IS_DESTROY_ACTIVATED", false)) | ||||
| 						{ | ||||
| 							npc.setDisplayEffect(3); | ||||
| 							 | ||||
| 						} | ||||
| 					} | ||||
| 					else if (!npcVars.getBoolean("IS_DESTROY_ACTIVATED", false)) | ||||
| 					{ | ||||
| 						npc.setDisplayEffect(1); | ||||
| 					} | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		return super.onAttack(npc, attacker, damage, isSummon); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public String onKill(Npc npc, PlayerInstance killer, boolean isSummon) | ||||
| 	{ | ||||
| 		final Instance instance = npc.getInstanceWorld(); | ||||
| 		if (isInInstance(instance)) | ||||
| 		{ | ||||
| 			final StatsSet npcParams = npc.getParameters(); | ||||
| 			final int baseId = npcParams.getInt("base_id", -1); | ||||
| 			 | ||||
| 			switch (npc.getId()) | ||||
| 			{ | ||||
| 				case VERIDAN_NORMAL: | ||||
| 				case VERIDAN_WISE: | ||||
| 				case VERIDAN_WEALTHY: | ||||
| 				case VERIDAN_ARMED: | ||||
| 				{ | ||||
| 					if (instance.getAliveNpcs(VERIDAN_NORMAL, VERIDAN_WISE, VERIDAN_WEALTHY, VERIDAN_ARMED).isEmpty()) | ||||
| 					{ | ||||
| 						instance.finishInstance(); | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						instance.setReenterTime(); | ||||
| 					} | ||||
| 					break; | ||||
| 				} | ||||
| 				case WATER_CANNON: | ||||
| 				{ | ||||
| 					npc.setDisplayEffect(4); | ||||
| 					showOnScreenMsg(instance, NpcStringId.SUCCESSFUL_DESTRUCTION_OF_STRONGHOLD_S1, ExShowScreenMessage.MIDDLE_CENTER, 4000, String.valueOf(npc.getParameters().getInt("base_id", -1))); | ||||
| 					 | ||||
| 					World.getInstance().forEachVisibleObjectInRange(npc, MonsterInstance.class, 400, monster -> | ||||
| 					{ | ||||
| 						if ((monster.getId() == STRONGHOLD_PROTECTOR) || (monster.getId() == SQUARE_INTRUDER) || (monster.getId() == SQUARE_ATTACKER)) | ||||
| 						{ | ||||
| 							monster.doDie(null); | ||||
| 						} | ||||
| 					}); | ||||
| 					 | ||||
| 					instance.getAliveNpcs(WATER_CANNON).forEach(cannon -> | ||||
| 					{ | ||||
| 						final int cannonBaseId = cannon.getParameters().getInt("base_id", -1); | ||||
| 						 | ||||
| 						switch (baseId) | ||||
| 						{ | ||||
| 							case 1: | ||||
| 							{ | ||||
| 								if (cannonBaseId == 2) | ||||
| 								{ | ||||
| 									cannon.getVariables().set("PREVIOUS_BASE_DESTROYED", true); | ||||
| 									cannon.setTargetable(true); | ||||
| 								} | ||||
| 								break; | ||||
| 							} | ||||
| 							case 2: | ||||
| 							{ | ||||
| 								if (cannonBaseId == 3) | ||||
| 								{ | ||||
| 									cannon.getVariables().set("PREVIOUS_BASE_DESTROYED", true); | ||||
| 									cannon.setTargetable(true); | ||||
| 								} | ||||
| 								break; | ||||
| 							} | ||||
| 							case 3: | ||||
| 							{ | ||||
| 								if (cannonBaseId == 4) | ||||
| 								{ | ||||
| 									cannon.getVariables().set("PREVIOUS_BASE_DESTROYED", true); | ||||
| 									cannon.setTargetable(true); | ||||
| 								} | ||||
| 								break; | ||||
| 							} | ||||
| 							case 4: | ||||
| 							{ | ||||
| 								if ((cannonBaseId == 5) || (cannonBaseId == 6)) | ||||
| 								{ | ||||
| 									cannon.getVariables().set("PREVIOUS_BASE_DESTROYED", true); | ||||
| 									cannon.setTargetable(true); | ||||
| 								} | ||||
| 								break; | ||||
| 							} | ||||
| 							case 5: | ||||
| 							case 6: | ||||
| 							{ | ||||
| 								if (cannonBaseId == 7) | ||||
| 								{ | ||||
| 									cannon.getVariables().set("PREVIOUS_BASE_DESTROYED", true); | ||||
| 									cannon.setTargetable(true); | ||||
| 								} | ||||
| 								break; | ||||
| 							} | ||||
| 							case 7: | ||||
| 							{ | ||||
| 								if ((cannonBaseId == 8) || (cannonBaseId == 9)) | ||||
| 								{ | ||||
| 									cannon.getVariables().set("PREVIOUS_BASE_DESTROYED", true); | ||||
| 									cannon.setTargetable(true); | ||||
| 								} | ||||
| 								break; | ||||
| 							} | ||||
| 						} | ||||
| 					}); | ||||
| 					 | ||||
| 					if ((baseId == 8) || (baseId == 9)) | ||||
| 					{ | ||||
| 						instance.getParameters().increaseInt("MAIN_TARGETS_KILLED", 0, 1); | ||||
| 						 | ||||
| 						if (instance.getParameters().getInt("MAIN_TARGETS_KILLED", 0) == 2) | ||||
| 						{ | ||||
| 							showOnScreenMsg(instance, NpcStringId.SUCCESSFUL_DESTRUCTION_OF_STRONGHOLD_ENTRY_ACCESSED, ExShowScreenMessage.MIDDLE_CENTER, 4000); | ||||
| 							instance.openCloseDoor(RAID_DOOR_1, true); | ||||
| 							instance.openCloseDoor(RAID_DOOR_2, true); | ||||
| 							 | ||||
| 							final int random = getRandom(100); | ||||
| 							int bossId = -1; | ||||
| 							 | ||||
| 							if (random < 55) | ||||
| 							{ | ||||
| 								bossId = VERIDAN_NORMAL; | ||||
| 							} | ||||
| 							else if (random < 80) | ||||
| 							{ | ||||
| 								bossId = VERIDAN_WISE; | ||||
| 							} | ||||
| 							else if (random < 95) | ||||
| 							{ | ||||
| 								bossId = VERIDAN_WEALTHY; | ||||
| 							} | ||||
| 							else | ||||
| 							{ | ||||
| 								bossId = VERIDAN_ARMED; | ||||
| 							} | ||||
| 							 | ||||
| 							for (Location loc : BOSS_SPAWNS) | ||||
| 							{ | ||||
| 								addSpawn(bossId, loc, false, 0, false, instance.getId()); | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		return super.onKill(npc, killer, isSummon); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill) | ||||
| 	{ | ||||
| 		final Instance instance = npc.getInstanceWorld(); | ||||
| 		if (isInInstance(instance) && (npc.getId() == WATER_CANNON_SKILL) && (skill.getId() == WATER_CANNON_SKILL_ATTACK.getSkillId())) | ||||
| 		{ | ||||
| 			npc.deleteMe(); | ||||
| 		} | ||||
| 		return super.onSpellFinished(npc, player, skill); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public String onSpawn(Npc npc) | ||||
| 	{ | ||||
| 		final Instance instance = npc.getInstanceWorld(); | ||||
| 		if (isInInstance(instance)) | ||||
| 		{ | ||||
| 			switch (npc.getId()) | ||||
| 			{ | ||||
| 				case WATER_CANNON: | ||||
| 				{ | ||||
| 					final StatsSet npcParams = npc.getParameters(); | ||||
| 					final int baseId = npcParams.getInt("base_id", -1); | ||||
| 					 | ||||
| 					if (baseId != 1) | ||||
| 					{ | ||||
| 						npc.setTargetable(false); | ||||
| 					} | ||||
| 					 | ||||
| 					getTimers().addTimer("HP_REGEN_TIMER", 10000, npc, null); | ||||
| 					 | ||||
| 					if (baseId > 0) | ||||
| 					{ | ||||
| 						getTimers().addTimer("SUPPORT_SPAWN_TIMER", (baseId * 60) * 1000, npc, null); | ||||
| 					} | ||||
| 					npc.initSeenCreatures(); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		return super.onSpawn(npc); | ||||
| 	} | ||||
| 	 | ||||
| 	public void onCreatureSee(OnCreatureSee event) | ||||
| 	{ | ||||
| 		final Creature creature = event.getSeen(); | ||||
| 		final Npc npc = (Npc) event.getSeer(); | ||||
| 		final Instance world = npc.getInstanceWorld(); | ||||
| 		 | ||||
| 		if ((world != null) && creature.isPlayer() && npc.isScriptValue(0)) | ||||
| 		{ | ||||
| 			npc.setScriptValue(1); | ||||
| 			npc.setDisplayEffect(1); | ||||
| 			getTimers().addRepeatingTimer("CANNON_LOOP_ATTACK", 1000, npc, null); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public void onInstanceEnter(PlayerInstance player, Instance instance) | ||||
| 	{ | ||||
| 		final int startTime = (int) (instance.getElapsedTime() / 1000); | ||||
| 		final int endTime = (int) (instance.getRemainingTime() / 1000); | ||||
| 		player.sendPacket(new ExSendUIEvent(player, false, true, startTime, endTime, NpcStringId.ELAPSED_TIME)); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public void onInstanceLeave(PlayerInstance player, Instance instance) | ||||
| 	{ | ||||
| 		player.sendPacket(new ExSendUIEvent(player, true, true, 0, 0, NpcStringId.ELAPSED_TIME)); | ||||
| 	} | ||||
| 	 | ||||
| 	public static void main(String[] args) | ||||
| 	{ | ||||
| 		new CrystalCavernsEmeraldSquare(); | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,408 @@ | ||||
| /* | ||||
|  * This file is part of the L2J Mobius project. | ||||
|  *  | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  *  | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
|  * General Public License for more details. | ||||
|  *  | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package instances.CrystalCaverns; | ||||
|  | ||||
| import org.l2jmobius.gameserver.enums.ChatType; | ||||
| import org.l2jmobius.gameserver.instancemanager.ZoneManager; | ||||
| import org.l2jmobius.gameserver.model.Location; | ||||
| import org.l2jmobius.gameserver.model.StatsSet; | ||||
| import org.l2jmobius.gameserver.model.WorldObject; | ||||
| import org.l2jmobius.gameserver.model.actor.Creature; | ||||
| import org.l2jmobius.gameserver.model.actor.Npc; | ||||
| import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; | ||||
| import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureSee; | ||||
| import org.l2jmobius.gameserver.model.holders.SkillHolder; | ||||
| import org.l2jmobius.gameserver.model.instancezone.Instance; | ||||
| import org.l2jmobius.gameserver.model.zone.ZoneType; | ||||
| import org.l2jmobius.gameserver.model.zone.type.TeleportZone; | ||||
| import org.l2jmobius.gameserver.network.NpcStringId; | ||||
| import org.l2jmobius.gameserver.network.serverpackets.ExSendUIEvent; | ||||
| import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage; | ||||
|  | ||||
| import instances.AbstractInstance; | ||||
|  | ||||
| /** | ||||
|  * Crystal Caverns - Steam Corridor instance zone. | ||||
|  * @author St3eT | ||||
|  */ | ||||
| public class CrystalCavernsSteamCorridor extends AbstractInstance | ||||
| { | ||||
| 	// NPCs | ||||
| 	private static final int CAVERNS_ENTRACE = 33522; | ||||
| 	private static final int KECHI_NORMAL = 25797; | ||||
| 	private static final int KECHI_WISE = 26113; | ||||
| 	private static final int KECHI_WEALTHY = 26112; | ||||
| 	private static final int KECHI_ARMED = 26111; | ||||
| 	private static final int VICIOUS_DUELER = 23014; | ||||
| 	private static final int VICIOUS_WARRIOR = 23016; | ||||
| 	private static final int VICIOUS_SWORDSMAN = 23015; | ||||
| 	private static final int SPIRIT_PROTECTOR = 23013; | ||||
| 	private static final int FIRE_REGION = 19161; | ||||
| 	private static final int PLAYER_DETECTOR = 19075; | ||||
| 	private static final int TRAP_1 = 19011; | ||||
| 	private static final int TRAP_2 = 19012; | ||||
| 	// Skills | ||||
| 	private static final SkillHolder FIRE_SKILL_1 = new SkillHolder(14373, 1); | ||||
| 	private static final SkillHolder FIRE_SKILL_2 = new SkillHolder(14373, 2); | ||||
| 	private static final SkillHolder FIRE_SKILL_3 = new SkillHolder(14197, 1); | ||||
| 	private static final SkillHolder TRAP_SKILL_1 = new SkillHolder(14180, 1); | ||||
| 	private static final SkillHolder TRAP_SKILL_2 = new SkillHolder(14181, 1); | ||||
| 	private static final SkillHolder TRAP_SKILL_3 = new SkillHolder(14372, 1); | ||||
| 	// Location | ||||
| 	private static final Location BOSS_LOC = new Location(154078, 215125, -12140); | ||||
| 	// Misc | ||||
| 	private static final int TEMPLATE_ID = 164; | ||||
| 	 | ||||
| 	public CrystalCavernsSteamCorridor() | ||||
| 	{ | ||||
| 		super(TEMPLATE_ID); | ||||
| 		addStartNpc(CAVERNS_ENTRACE); | ||||
| 		addTalkId(CAVERNS_ENTRACE); | ||||
| 		addAttackId(TRAP_1, TRAP_2); | ||||
| 		addKillId(VICIOUS_DUELER, VICIOUS_WARRIOR, VICIOUS_SWORDSMAN, KECHI_NORMAL, KECHI_WISE, KECHI_WEALTHY, KECHI_ARMED); | ||||
| 		addSpawnId(SPIRIT_PROTECTOR, VICIOUS_DUELER, VICIOUS_WARRIOR, VICIOUS_SWORDSMAN, FIRE_REGION, PLAYER_DETECTOR); | ||||
| 		addEventReceivedId(SPIRIT_PROTECTOR, VICIOUS_DUELER, VICIOUS_WARRIOR, VICIOUS_SWORDSMAN); | ||||
| 		addInstanceCreatedId(TEMPLATE_ID); | ||||
| 		addInstanceEnterId(TEMPLATE_ID); | ||||
| 		addInstanceLeaveId(TEMPLATE_ID); | ||||
| 		setCreatureSeeId(this::onCreatureSee, PLAYER_DETECTOR); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public void onTimerEvent(String event, StatsSet params, Npc npc, PlayerInstance player) | ||||
| 	{ | ||||
| 		final Instance instance = npc.getInstanceWorld(); | ||||
| 		if (isInInstance(instance)) | ||||
| 		{ | ||||
| 			final StatsSet npcVars = npc.getVariables(); | ||||
| 			 | ||||
| 			switch (event) | ||||
| 			{ | ||||
| 				case "FIRE_REGION_TIMER_1": | ||||
| 				{ | ||||
| 					addSkillCastDesire(npc, npc, FIRE_SKILL_1, 23); | ||||
| 					getTimers().addTimer("FIRE_REGION_TIMER_2", 10000, npc, null); | ||||
| 					break; | ||||
| 				} | ||||
| 				case "FIRE_REGION_TIMER_2": | ||||
| 				{ | ||||
| 					addSkillCastDesire(npc, npc, FIRE_SKILL_2, 23); | ||||
| 					getTimers().addTimer("FIRE_REGION_TIMER_3", 10000, npc, null); | ||||
| 					break; | ||||
| 				} | ||||
| 				case "FIRE_REGION_TIMER_3": | ||||
| 				{ | ||||
| 					addSkillCastDesire(npc, npc, FIRE_SKILL_3, 23); | ||||
| 					getTimers().addTimer("FIRE_REGION_TIMER_3", 1000, npc, null); | ||||
| 					break; | ||||
| 				} | ||||
| 				case "TRAP_REACT_TIMER": | ||||
| 				{ | ||||
| 					final int timer = npcVars.increaseInt("TIMER_VAL", -1); | ||||
| 					if (timer > 0) | ||||
| 					{ | ||||
| 						npc.broadcastSay(ChatType.NPC_GENERAL, " " + timer); | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						if (npc.getId() == TRAP_1) | ||||
| 						{ | ||||
| 							addSkillCastDesire(npc, npc, (getRandom(10) < 8 ? TRAP_SKILL_1 : TRAP_SKILL_3), 23); | ||||
| 						} | ||||
| 						else if (npc.getId() == TRAP_2) | ||||
| 						{ | ||||
| 							addSkillCastDesire(npc, npc, (getRandom(10) < 8 ? TRAP_SKILL_2 : TRAP_SKILL_3), 23); | ||||
| 						} | ||||
| 					} | ||||
| 					getTimers().addTimer("TRAP_REACT_TIMER", 1000, npc, null); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public String onAdvEvent(String event, Npc npc, PlayerInstance player) | ||||
| 	{ | ||||
| 		if (event.equals("enterInstance")) | ||||
| 		{ | ||||
| 			enterInstance(player, npc, TEMPLATE_ID); | ||||
| 		} | ||||
| 		return super.onAdvEvent(event, npc, player); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public void onInstanceCreated(Instance instance, PlayerInstance player) | ||||
| 	{ | ||||
| 		instance.setStatus(1); | ||||
| 		for (int i = 0; i < 6; i++) | ||||
| 		{ | ||||
| 			final ZoneType zone = ZoneManager.getInstance().getZoneByName("24_24_fire_telezone_0" + i, TeleportZone.class); | ||||
| 			if (zone != null) | ||||
| 			{ | ||||
| 				zone.setEnabled(false, instance.getId()); | ||||
| 			} | ||||
| 		} | ||||
| 		super.onInstanceCreated(instance, player); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public void onInstanceEnter(PlayerInstance player, Instance instance) | ||||
| 	{ | ||||
| 		final int startTime = (int) (instance.getElapsedTime() / 1000); | ||||
| 		final int endTime = (int) (instance.getRemainingTime() / 1000); | ||||
| 		player.sendPacket(new ExSendUIEvent(player, false, true, startTime, endTime, NpcStringId.ELAPSED_TIME)); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public void onInstanceLeave(PlayerInstance player, Instance instance) | ||||
| 	{ | ||||
| 		player.sendPacket(new ExSendUIEvent(player, true, true, 0, 0, NpcStringId.ELAPSED_TIME)); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public String onSpawn(Npc npc) | ||||
| 	{ | ||||
| 		final Instance instance = npc.getInstanceWorld(); | ||||
| 		if (isInInstance(instance)) | ||||
| 		{ | ||||
| 			final StatsSet npcParams = npc.getParameters(); | ||||
| 			 | ||||
| 			switch (npc.getId()) | ||||
| 			{ | ||||
| 				case SPIRIT_PROTECTOR: | ||||
| 				case VICIOUS_DUELER: | ||||
| 				case VICIOUS_WARRIOR: | ||||
| 				case VICIOUS_SWORDSMAN: | ||||
| 				{ | ||||
| 					npc.setTargetable(false); | ||||
| 					npc.disableCoreAI(true); | ||||
| 					npc.setInvisible(true); | ||||
| 					break; | ||||
| 				} | ||||
| 				case FIRE_REGION: | ||||
| 				{ | ||||
| 					final int timeLimit = npcParams.getInt("Limit_Time", 0); | ||||
| 					if (timeLimit > 0) | ||||
| 					{ | ||||
| 						getTimers().addTimer("FIRE_REGION_TIMER_1", ((timeLimit * 30) * 100), npc, null); | ||||
| 					} | ||||
| 					npc.setTargetable(false); | ||||
| 					npc.setIsInvul(true); | ||||
| 					npc.setRandomAnimation(false); | ||||
| 					npc.setRandomWalking(false); | ||||
| 					npc.disableCoreAI(true); | ||||
| 					break; | ||||
| 				} | ||||
| 				case PLAYER_DETECTOR: | ||||
| 				{ | ||||
| 					npc.initSeenCreatures(); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		return super.onSpawn(npc); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public String onEventReceived(String eventName, Npc sender, Npc receiver, WorldObject reference) | ||||
| 	{ | ||||
| 		final Instance instance = receiver.getInstanceWorld(); | ||||
| 		if (isInInstance(instance)) | ||||
| 		{ | ||||
| 			final StatsSet npcParams = receiver.getParameters(); | ||||
| 			 | ||||
| 			if (eventName.equals(String.valueOf(24220005 + npcParams.getInt("Terri_ID", 0)))) | ||||
| 			{ | ||||
| 				receiver.setTargetable(true); | ||||
| 				receiver.disableCoreAI(false); | ||||
| 				receiver.setInvisible(false); | ||||
| 			} | ||||
| 		} | ||||
| 		return super.onEventReceived(eventName, sender, receiver, reference); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon) | ||||
| 	{ | ||||
| 		final Instance instance = npc.getInstanceWorld(); | ||||
| 		if (isInInstance(instance)) | ||||
| 		{ | ||||
| 			switch (npc.getId()) | ||||
| 			{ | ||||
| 				case TRAP_1: | ||||
| 				case TRAP_2: | ||||
| 				{ | ||||
| 					if (npc.isScriptValue(0)) | ||||
| 					{ | ||||
| 						getTimers().addTimer("TRAP_REACT_TIMER", 1000, npc, null); | ||||
| 						npc.setScriptValue(1); | ||||
| 					} | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		return super.onAttack(npc, attacker, damage, isSummon); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public String onKill(Npc npc, PlayerInstance killer, boolean isSummon) | ||||
| 	{ | ||||
| 		final Instance instance = npc.getInstanceWorld(); | ||||
| 		if (isInInstance(instance)) | ||||
| 		{ | ||||
| 			final StatsSet npcParams = npc.getParameters(); | ||||
| 			final int killTarget = instance.getParameters().getInt("KILL_TARGET", 5); | ||||
| 			int currentKillCount = instance.getParameters().getInt("KILL_COUNT", 0); | ||||
| 			 | ||||
| 			switch (npc.getId()) | ||||
| 			{ | ||||
| 				case VICIOUS_DUELER: | ||||
| 				case VICIOUS_WARRIOR: | ||||
| 				case VICIOUS_SWORDSMAN: | ||||
| 				{ | ||||
| 					if (npcParams.getInt("last_checker", 0) == 1) | ||||
| 					{ | ||||
| 						currentKillCount = instance.getParameters().increaseInt("KILL_COUNT", 0, 1); | ||||
| 						 | ||||
| 						if (currentKillCount >= killTarget) | ||||
| 						{ | ||||
| 							final ZoneType zone = ZoneManager.getInstance().getZoneByName(npc.getParameters().getString("AreaTeleName"), TeleportZone.class); | ||||
| 							if (zone != null) | ||||
| 							{ | ||||
| 								zone.setEnabled(true, instance.getId()); | ||||
| 								showOnScreenMsg(instance, NpcStringId.THE_PORTAL_TO_THE_NEXT_ROOM_IS_NOW_OPEN, ExShowScreenMessage.MIDDLE_CENTER, 4000); | ||||
| 								instance.spawnGroup("innadril23_mb2422_pt" + instance.getStatus() + "m1"); | ||||
| 								instance.getParameters().set("KILL_COUNT", 0); | ||||
| 								 | ||||
| 								switch (instance.getStatus()) | ||||
| 								{ | ||||
| 									case 1: | ||||
| 									{ | ||||
| 										instance.getParameters().set("KILL_TARGET", 12); | ||||
| 										instance.setStatus(2); | ||||
| 										break; | ||||
| 									} | ||||
| 									case 2: | ||||
| 									{ | ||||
| 										instance.getParameters().set("KILL_TARGET", 3); | ||||
| 										instance.setStatus(3); | ||||
| 										break; | ||||
| 									} | ||||
| 									case 3: | ||||
| 									{ | ||||
| 										instance.getParameters().set("KILL_TARGET", 18); | ||||
| 										instance.setStatus(4); | ||||
| 										break; | ||||
| 									} | ||||
| 									case 4: | ||||
| 									{ | ||||
| 										instance.getParameters().set("KILL_TARGET", 5); | ||||
| 										instance.setStatus(5); | ||||
| 										break; | ||||
| 									} | ||||
| 									case 5: | ||||
| 									{ | ||||
| 										instance.getParameters().set("KILL_TARGET", 20); | ||||
| 										instance.setStatus(6); | ||||
| 										break; | ||||
| 									} | ||||
| 									case 6: | ||||
| 									{ | ||||
| 										final int random = getRandom(100); | ||||
| 										int bossId = -1; | ||||
| 										 | ||||
| 										if (random < 55) | ||||
| 										{ | ||||
| 											bossId = KECHI_NORMAL; | ||||
| 										} | ||||
| 										else if (random < 80) | ||||
| 										{ | ||||
| 											bossId = KECHI_WISE; | ||||
| 										} | ||||
| 										else if (random < 95) | ||||
| 										{ | ||||
| 											bossId = KECHI_WEALTHY; | ||||
| 										} | ||||
| 										else | ||||
| 										{ | ||||
| 											bossId = KECHI_ARMED; | ||||
| 										} | ||||
| 										 | ||||
| 										addSpawn(bossId, BOSS_LOC, false, 0, false, instance.getId()); | ||||
| 										break; | ||||
| 									} | ||||
| 								} | ||||
| 							} | ||||
| 							else | ||||
| 							{ | ||||
| 								LOGGER.warning("Cannot find teleport zone for Crystal Cavern: Steam Corridor instance!!!"); | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 					break; | ||||
| 				} | ||||
| 				case KECHI_NORMAL: | ||||
| 				case KECHI_WISE: | ||||
| 				case KECHI_WEALTHY: | ||||
| 				case KECHI_ARMED: | ||||
| 				{ | ||||
| 					instance.finishInstance(); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		return super.onKill(npc, killer, isSummon); | ||||
| 	} | ||||
| 	 | ||||
| 	private void onCreatureSee(OnCreatureSee event) | ||||
| 	{ | ||||
| 		final Creature creature = event.getSeen(); | ||||
| 		final Npc npc = (Npc) event.getSeer(); | ||||
| 		final Instance instance = npc.getInstanceWorld(); | ||||
| 		 | ||||
| 		if (isInInstance(instance) && creature.isPlayer()) | ||||
| 		{ | ||||
| 			final StatsSet npcParams = npc.getParameters(); | ||||
| 			 | ||||
| 			switch (npc.getId()) | ||||
| 			{ | ||||
| 				case PLAYER_DETECTOR: | ||||
| 				{ | ||||
| 					if (npc.isScriptValue(0)) | ||||
| 					{ | ||||
| 						npc.setScriptValue(1); | ||||
| 						npc.broadcastEvent(String.valueOf(24220005 + npcParams.getInt("Terri_ID", 0)), 2000, null); | ||||
| 						 | ||||
| 						for (int i = 0; i < getRandom(5); i++) | ||||
| 						{ | ||||
| 							final Npc trap = addSpawn(((npcParams.getInt("MobType", 0) == 0) ? TRAP_1 : TRAP_2), npc, true, 0, false, instance.getId()); | ||||
| 							trap.getVariables().set("TIMER_VAL", 4); | ||||
| 						} | ||||
| 						npc.deleteMe(); | ||||
| 					} | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	public static void main(String[] args) | ||||
| 	{ | ||||
| 		new CrystalCavernsSteamCorridor(); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										3
									
								
								L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/CrystalCaverns/condNoParty.html
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/CrystalCaverns/condNoParty.html
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| <html><body>Crystal Caverns Admission Portal:<br> | ||||
| You must be in a party to enter. | ||||
| </body></html> | ||||
| @@ -0,0 +1,3 @@ | ||||
| <html><body>Crystal Caverns Admission Portal:<br> | ||||
| The leader of the party should try to enter. | ||||
| </body></html> | ||||
		Reference in New Issue
	
	Block a user
	 MobiusDevelopment
					MobiusDevelopment