diff --git a/L2J_Mobius_Underground/dist/game/data/html/default/32011.htm b/L2J_Mobius_Underground/dist/game/data/html/default/32011.htm index 5e43c9f5e9..f7c4766873 100644 --- a/L2J_Mobius_Underground/dist/game/data/html/default/32011.htm +++ b/L2J_Mobius_Underground/dist/game/data/html/default/32011.htm @@ -1,7 +1,7 @@ I feel an invisible barrier... Some sort of Magic Force Field has been put in place...
...? The guide of the Imperial mausoleum seems to have something to say.

- + \ No newline at end of file diff --git a/L2J_Mobius_Underground/dist/game/data/instances/FinalEmperialTomb.xml b/L2J_Mobius_Underground/dist/game/data/instances/FinalEmperialTomb.xml deleted file mode 100644 index 811ae73db8..0000000000 --- a/L2J_Mobius_Underground/dist/game/data/instances/FinalEmperialTomb.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - diff --git a/L2J_Mobius_Underground/dist/game/data/instances/LastImperialTomb.xml b/L2J_Mobius_Underground/dist/game/data/instances/LastImperialTomb.xml new file mode 100644 index 0000000000..8add710d0d --- /dev/null +++ b/L2J_Mobius_Underground/dist/game/data/instances/LastImperialTomb.xml @@ -0,0 +1,208 @@ + + + + diff --git a/L2J_Mobius_Underground/dist/game/data/scripts/instances/LastImperialTomb/LastImperialTomb.java b/L2J_Mobius_Underground/dist/game/data/scripts/instances/LastImperialTomb/LastImperialTomb.java new file mode 100644 index 0000000000..c179fd2409 --- /dev/null +++ b/L2J_Mobius_Underground/dist/game/data/scripts/instances/LastImperialTomb/LastImperialTomb.java @@ -0,0 +1,908 @@ +/* + * 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 . + */ +package instances.LastImperialTomb; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.l2jmobius.commons.util.CommonUtil; +import com.l2jmobius.gameserver.ai.CtrlIntention; +import com.l2jmobius.gameserver.model.Location; +import com.l2jmobius.gameserver.model.actor.L2Npc; +import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance; +import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.model.holders.SkillHolder; +import com.l2jmobius.gameserver.model.instancezone.Instance; +import com.l2jmobius.gameserver.model.skills.Skill; +import com.l2jmobius.gameserver.network.NpcStringId; +import com.l2jmobius.gameserver.network.serverpackets.Earthquake; +import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage; +import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; +import com.l2jmobius.gameserver.network.serverpackets.MagicSkillCanceld; +import com.l2jmobius.gameserver.network.serverpackets.MagicSkillUse; +import com.l2jmobius.gameserver.network.serverpackets.NpcInfo; +import com.l2jmobius.gameserver.network.serverpackets.SocialAction; +import com.l2jmobius.gameserver.network.serverpackets.SpecialCamera; + +import instances.AbstractInstance; + +/** + * Last Imperial Tomb AI + * @author Mobius (reworked from L2J version) + */ +public final class LastImperialTomb extends AbstractInstance +{ + // NPCs + private static final int GUIDE = 32011; + private static final int CUBE = 29061; + private static final int HALL_ALARM = 18328; + private static final int HALL_KEEPER_SUICIDAL_SOLDIER = 18333; + private static final int DUMMY = 29052; + private static final int DUMMY2 = 29053; + private static final int[] PORTRAITS = + { + 29048, + 29049 + }; + private static final int[] DEMONS = + { + 29050, + 29051 + }; + private static final int FRINTEZZA = 29045; + private static final int SCARLET1 = 29046; + private static final int SCARLET2 = 29047; + private static final int[] ON_KILL_MONSTERS = + { + HALL_ALARM, + HALL_KEEPER_SUICIDAL_SOLDIER, + 18329, + 18330, + 18331, + 18334, + 18335, + 18336, + 18337, + 18338, + 18339 + + }; + // Items + private static final int DEWDROP_OF_DESTRUCTION_ITEM_ID = 8556; + private static final int FIRST_SCARLET_WEAPON = 8204; + private static final int SECOND_SCARLET_WEAPON = 7903; + // Doors + private static final int[] FIRST_ROOM_DOORS = + { + 17130051, + 17130052, + 17130053, + 17130054, + 17130055, + 17130056, + 17130057, + 17130058 + }; + private static final int[] SECOND_ROOM_DOORS = + { + 17130061, + 17130062, + 17130063, + 17130064, + 17130065, + 17130066, + 17130067, + 17130068, + 17130069, + 17130070 + }; + private static final int[] FIRST_ROUTE_DOORS = + { + 17130042, + 17130043 + }; + private static final int[] SECOND_ROUTE_DOORS = + { + 17130045, + 17130046 + }; + // Skills + private static final int DEWDROP_OF_DESTRUCTION_SKILL_ID = 2276; + private static final SkillHolder INTRO_SKILL = new SkillHolder(5004, 1); + private static final SkillHolder FIRST_MORPH_SKILL = new SkillHolder(5017, 1); + private static final Map SKILL_MSG = new HashMap<>(); + static + { + SKILL_MSG.put(1, NpcStringId.REQUIEM_OF_HATRED); + SKILL_MSG.put(2, NpcStringId.RONDO_OF_SOLITUDE); + SKILL_MSG.put(3, NpcStringId.FRENETIC_TOCCATA); + SKILL_MSG.put(4, NpcStringId.FUGUE_OF_JUBILATION); + SKILL_MSG.put(5, NpcStringId.HYPNOTIC_MAZURKA); + } + // Spawns + // @formatter:off + static final int[][] PORTRAIT_SPAWNS = + { + {29048, -89381, -153981, -9168, 3368, -89378, -153968, -9168, 3368}, + {29048, -86234, -152467, -9168, 37656, -86261, -152492, -9168, 37656}, + {29049, -89342, -152479, -9168, -5152, -89311, -152491, -9168, -5152}, + {29049, -86189, -153968, -9168, 29456, -86217, -153956, -9168, 29456}, + }; + // @formatter:on + // Misc + private static final int TEMPLATE_ID = 136; + private static final int FRINTEZZA_WAIT_TIME = 10; // minutes + private static final int RANDOM_SONG_INTERVAL = 90; // seconds + private static final int TIME_BETWEEN_DEMON_SPAWNS = 20; // seconds + private static final int MAX_DEMONS = 24; + + public LastImperialTomb() + { + addTalkId(GUIDE, CUBE); + addAttackId(SCARLET1); + addKillId(ON_KILL_MONSTERS); + addKillId(HALL_ALARM, SCARLET2); + addKillId(PORTRAITS); + addKillId(DEMONS); + addSpawnId(HALL_ALARM, DUMMY, DUMMY2); + addSpellFinishedId(HALL_KEEPER_SUICIDAL_SOLDIER); + } + + @Override + public String onAdvEvent(String event, L2Npc npc, L2PcInstance player) + { + switch (event) + { + case "FRINTEZZA_INTRO_START": + { + final Instance world = player.getInstanceWorld(); + startQuestTimer("FRINTEZZA_INTRO_1", 17000, null, player, false); + startQuestTimer("FRINTEZZA_INTRO_2", 20000, null, player, false); + broadCastPacket(world, new Earthquake(-87784, -155083, -9087, 45, 27)); + break; + } + case "FRINTEZZA_INTRO_1": + { + final Instance world = player.getInstanceWorld(); + for (int doorId : FIRST_ROOM_DOORS) + { + world.openCloseDoor(doorId, false); + } + for (int doorId : FIRST_ROUTE_DOORS) + { + world.openCloseDoor(doorId, false); + } + for (int doorId : SECOND_ROOM_DOORS) + { + world.openCloseDoor(doorId, false); + } + for (int doorId : SECOND_ROUTE_DOORS) + { + world.openCloseDoor(doorId, false); + } + addSpawn(CUBE, -87904, -141296, -9168, 0, false, 0, false, world.getId()); + break; + } + case "FRINTEZZA_INTRO_2": + { + final Instance world = player.getInstanceWorld(); + + final L2Npc frintezzaDummy = addSpawn(DUMMY, -87784, -155083, -9087, 16048, false, 0, false, world.getId()); + world.setParameter("frintezzaDummy", frintezzaDummy); + + final L2Npc overheadDummy = addSpawn(DUMMY, -87784, -153298, -9175, 16384, false, 0, false, world.getId()); + overheadDummy.setCollisionHeight(600); + broadCastPacket(world, new NpcInfo(overheadDummy)); + world.setParameter("overheadDummy", overheadDummy); + + final L2Npc portraitDummy1 = addSpawn(DUMMY, -89566, -153168, -9165, 16048, false, 0, false, world.getId()); + world.setParameter("portraitDummy1", portraitDummy1); + + final L2Npc portraitDummy3 = addSpawn(DUMMY, -86004, -153168, -9165, 16048, false, 0, false, world.getId()); + world.setParameter("portraitDummy3", portraitDummy3); + + final L2Npc scarletDummy = addSpawn(DUMMY2, -87784, -153298, -9175, 16384, false, 0, false, world.getId()); + world.setParameter("scarletDummy", scarletDummy); + + disablePlayers(world); + + broadCastPacket(world, new SpecialCamera(overheadDummy, 0, 75, -89, 0, 100, 0, 0, 1, 0, 0)); + broadCastPacket(world, new SpecialCamera(overheadDummy, 0, 75, -89, 0, 100, 0, 0, 1, 0, 0)); + broadCastPacket(world, new SpecialCamera(overheadDummy, 300, 90, -10, 6500, 7000, 0, 0, 1, 0, 0)); + + final L2Npc frintezza = addSpawn(FRINTEZZA, -87780, -155086, -9080, 16384, false, 0, false, world.getId()); + frintezza.setIsImmobilized(true); + frintezza.setIsInvul(true); + frintezza.disableAllSkills(); + world.setParameter("frintezza", frintezza); + + final List demons = new ArrayList<>(); + for (int[] element : PORTRAIT_SPAWNS) + { + final L2MonsterInstance demon = (L2MonsterInstance) addSpawn(element[0] + 2, element[5], element[6], element[7], element[8], false, 0, false, world.getId()); + demon.setIsImmobilized(true); + demon.disableAllSkills(); + demons.add(demon); + } + world.setParameter("demons", demons); + + startQuestTimer("FRINTEZZA_INTRO_3", 6500, null, player, false); + break; + } + case "FRINTEZZA_INTRO_3": + { + final Instance world = player.getInstanceWorld(); + final L2Npc frintezzaDummy = world.getParameters().getObject("frintezzaDummy", L2Npc.class); + broadCastPacket(world, new SpecialCamera(frintezzaDummy, 1800, 90, 8, 6500, 7000, 0, 0, 1, 0, 0)); + startQuestTimer("FRINTEZZA_INTRO_4", 900, null, player, false); + break; + } + case "FRINTEZZA_INTRO_4": + { + final Instance world = player.getInstanceWorld(); + final L2Npc frintezzaDummy = world.getParameters().getObject("frintezzaDummy", L2Npc.class); + broadCastPacket(world, new SpecialCamera(frintezzaDummy, 140, 90, 10, 2500, 4500, 0, 0, 1, 0, 0)); + startQuestTimer("FRINTEZZA_INTRO_5", 4000, null, player, false); + break; + } + case "FRINTEZZA_INTRO_5": + { + final Instance world = player.getInstanceWorld(); + final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class); + broadCastPacket(world, new SpecialCamera(frintezza, 40, 75, -10, 0, 1000, 0, 0, 1, 0, 0)); + broadCastPacket(world, new SpecialCamera(frintezza, 40, 75, -10, 0, 12000, 0, 0, 1, 0, 0)); + startQuestTimer("FRINTEZZA_INTRO_6", 1350, null, player, false); + break; + } + case "FRINTEZZA_INTRO_6": + { + final Instance world = player.getInstanceWorld(); + final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class); + broadCastPacket(world, new SocialAction(frintezza.getObjectId(), 2)); + final L2Npc frintezzaDummy = world.getParameters().getObject("frintezzaDummy", L2Npc.class); + frintezzaDummy.deleteMe(); + startQuestTimer("FRINTEZZA_INTRO_7", 8000, null, player, false); + break; + } + case "FRINTEZZA_INTRO_7": + { + final Instance world = player.getInstanceWorld(); + final List demons = world.getParameters().getList("demons", L2Npc.class); + broadCastPacket(world, new SocialAction(demons.get(1).getObjectId(), 1)); + broadCastPacket(world, new SocialAction(demons.get(2).getObjectId(), 1)); + startQuestTimer("FRINTEZZA_INTRO_8", 400, null, player, false); + break; + } + case "FRINTEZZA_INTRO_8": + { + final Instance world = player.getInstanceWorld(); + final List demons = world.getParameters().getList("demons", L2Npc.class); + final L2Npc portraitDummy1 = world.getParameters().getObject("portraitDummy1", L2Npc.class); + final L2Npc portraitDummy3 = world.getParameters().getObject("portraitDummy3", L2Npc.class); + broadCastPacket(world, new SocialAction(demons.get(0).getObjectId(), 1)); + broadCastPacket(world, new SocialAction(demons.get(3).getObjectId(), 1)); + sendPacketX(world, new SpecialCamera(portraitDummy1, 1000, 118, 0, 0, 1000, 0, 0, 1, 0, 0), new SpecialCamera(portraitDummy3, 1000, 62, 0, 0, 1000, 0, 0, 1, 0, 0), -87784); + sendPacketX(world, new SpecialCamera(portraitDummy1, 1000, 118, 0, 0, 10000, 0, 0, 1, 0, 0), new SpecialCamera(portraitDummy3, 1000, 62, 0, 0, 10000, 0, 0, 1, 0, 0), -87784); + startQuestTimer("FRINTEZZA_INTRO_9", 2000, null, player, false); + break; + } + case "FRINTEZZA_INTRO_9": + { + final Instance world = player.getInstanceWorld(); + final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class); + final L2Npc portraitDummy1 = world.getParameters().getObject("portraitDummy1", L2Npc.class); + final L2Npc portraitDummy3 = world.getParameters().getObject("portraitDummy3", L2Npc.class); + broadCastPacket(world, new SpecialCamera(frintezza, 240, 90, 0, 0, 1000, 0, 0, 1, 0, 0)); + broadCastPacket(world, new SpecialCamera(frintezza, 240, 90, 25, 5500, 10000, 0, 0, 1, 0, 0)); + broadCastPacket(world, new SocialAction(frintezza.getObjectId(), 3)); + portraitDummy1.deleteMe(); + portraitDummy3.deleteMe(); + startQuestTimer("FRINTEZZA_INTRO_10", 4500, null, player, false); + break; + } + case "FRINTEZZA_INTRO_10": + { + final Instance world = player.getInstanceWorld(); + final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class); + broadCastPacket(world, new SpecialCamera(frintezza, 100, 195, 35, 0, 10000, 0, 0, 1, 0, 0)); + startQuestTimer("FRINTEZZA_INTRO_11", 700, null, player, false); + break; + } + case "FRINTEZZA_INTRO_11": + { + final Instance world = player.getInstanceWorld(); + final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class); + broadCastPacket(world, new SpecialCamera(frintezza, 100, 195, 35, 0, 10000, 0, 0, 1, 0, 0)); + startQuestTimer("FRINTEZZA_INTRO_12", 1300, null, player, false); + break; + } + case "FRINTEZZA_INTRO_12": + { + final Instance world = player.getInstanceWorld(); + final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class); + broadCastPacket(world, new ExShowScreenMessage(NpcStringId.MOURNFUL_CHORALE_PRELUDE, 2, 5000)); + broadCastPacket(world, new SpecialCamera(frintezza, 120, 180, 45, 1500, 10000, 0, 0, 1, 0, 0)); + broadCastPacket(world, new MagicSkillUse(frintezza, frintezza, 5006, 1, 34000, 0)); + startQuestTimer("FRINTEZZA_INTRO_13", 1500, null, player, false); + break; + } + case "FRINTEZZA_INTRO_13": + { + final Instance world = player.getInstanceWorld(); + final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class); + broadCastPacket(world, new SpecialCamera(frintezza, 520, 135, 45, 8000, 10000, 0, 0, 1, 0, 0)); + startQuestTimer("FRINTEZZA_INTRO_14", 7500, null, player, false); + break; + } + case "FRINTEZZA_INTRO_14": + { + final Instance world = player.getInstanceWorld(); + final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class); + broadCastPacket(world, new SpecialCamera(frintezza, 1500, 110, 25, 10000, 13000, 0, 0, 1, 0, 0)); + startQuestTimer("FRINTEZZA_INTRO_15", 9500, null, player, false); + break; + } + case "FRINTEZZA_INTRO_15": + { + final Instance world = player.getInstanceWorld(); + final L2Npc overheadDummy = world.getParameters().getObject("overheadDummy", L2Npc.class); + final L2Npc scarletDummy = world.getParameters().getObject("scarletDummy", L2Npc.class); + broadCastPacket(world, new SpecialCamera(overheadDummy, 930, 160, -20, 0, 1000, 0, 0, 1, 0, 0)); + broadCastPacket(world, new SpecialCamera(overheadDummy, 600, 180, -25, 0, 10000, 0, 0, 1, 0, 0)); + broadCastPacket(world, new MagicSkillUse(scarletDummy, overheadDummy, 5004, 1, 5800, 0)); + startQuestTimer("FRINTEZZA_INTRO_16", 5000, null, player, false); + break; + } + case "FRINTEZZA_INTRO_16": + { + final Instance world = player.getInstanceWorld(); + final L2Npc scarletDummy = world.getParameters().getObject("scarletDummy", L2Npc.class); + final L2Npc activeScarlet = addSpawn(SCARLET1, -87789, -153295, -9176, 16384, false, 0, false, world.getId()); + world.setParameter("activeScarlet", activeScarlet); + activeScarlet.setRHandId(FIRST_SCARLET_WEAPON); + activeScarlet.setIsInvul(true); + activeScarlet.setIsImmobilized(true); + activeScarlet.disableAllSkills(); + broadCastPacket(world, new SocialAction(activeScarlet.getObjectId(), 3)); + broadCastPacket(world, new SpecialCamera(scarletDummy, 800, 180, 10, 1000, 10000, 0, 0, 1, 0, 0)); + startQuestTimer("FRINTEZZA_INTRO_17", 2100, null, player, false); + break; + } + case "FRINTEZZA_INTRO_17": + { + final Instance world = player.getInstanceWorld(); + final L2Npc activeScarlet = world.getParameters().getObject("activeScarlet", L2Npc.class); + broadCastPacket(world, new SpecialCamera(activeScarlet, 300, 60, 8, 0, 10000, 0, 0, 1, 0, 0)); + startQuestTimer("FRINTEZZA_INTRO_18", 2000, null, player, false); + break; + } + case "FRINTEZZA_INTRO_18": + { + final Instance world = player.getInstanceWorld(); + final L2Npc activeScarlet = world.getParameters().getObject("activeScarlet", L2Npc.class); + broadCastPacket(world, new SpecialCamera(activeScarlet, 500, 90, 10, 3000, 5000, 0, 0, 1, 0, 0)); + world.setParameter("isPlayingSong", false); + playRandomSong(world); + startQuestTimer("FRINTEZZA_INTRO_19", 3000, null, player, false); + break; + } + case "FRINTEZZA_INTRO_19": + { + final Instance world = player.getInstanceWorld(); + Map portraits = new HashMap<>(); + for (int i = 0; i < PORTRAIT_SPAWNS.length; i++) + { + final L2Npc portrait = addSpawn(PORTRAIT_SPAWNS[i][0], PORTRAIT_SPAWNS[i][1], PORTRAIT_SPAWNS[i][2], PORTRAIT_SPAWNS[i][3], PORTRAIT_SPAWNS[i][4], false, 0, false, world.getId()); + portraits.put(portrait, i); + } + world.setParameter("portraits", portraits); + final L2Npc overheadDummy = world.getParameters().getObject("overheadDummy", L2Npc.class); + final L2Npc scarletDummy = world.getParameters().getObject("scarletDummy", L2Npc.class); + overheadDummy.deleteMe(); + scarletDummy.deleteMe(); + startQuestTimer("FRINTEZZA_INTRO_20", 2000, null, player, false); + break; + } + case "FRINTEZZA_INTRO_20": + { + final Instance world = player.getInstanceWorld(); + final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class); + final L2Npc activeScarlet = world.getParameters().getObject("activeScarlet", L2Npc.class); + final List demons = world.getParameters().getList("demons", L2Npc.class); + for (L2Npc demon : demons) + { + demon.setIsImmobilized(false); + demon.enableAllSkills(); + } + activeScarlet.setIsInvul(false); + activeScarlet.setIsImmobilized(false); + activeScarlet.enableAllSkills(); + activeScarlet.setRunning(); + activeScarlet.doCast(INTRO_SKILL.getSkill()); + frintezza.enableAllSkills(); + frintezza.disableCoreAI(true); + frintezza.setIsInvul(true); + enablePlayers(world); + startQuestTimer("PLAY_RANDOM_SONG", RANDOM_SONG_INTERVAL * 1000, frintezza, null, false); + startQuestTimer("SPAWN_DEMONS", TIME_BETWEEN_DEMON_SPAWNS * 1000, null, player, false); + break; + } + case "SPAWN_DEMONS": + { + final Instance world = player.getInstanceWorld(); + final Map portraits = world.getParameters().getMap("portraits", L2Npc.class, Integer.class); + if (!portraits.isEmpty()) + { + final List demons = world.getParameters().getList("demons", L2Npc.class); + for (int i : portraits.values()) + { + if (demons.size() > MAX_DEMONS) + { + break; + } + final L2Npc demon = addSpawn(PORTRAIT_SPAWNS[i][0] + 2, PORTRAIT_SPAWNS[i][5], PORTRAIT_SPAWNS[i][6], PORTRAIT_SPAWNS[i][7], PORTRAIT_SPAWNS[i][8], false, 0, false, world.getId()); + demons.add(demon); + } + world.setParameter("demons", demons); + startQuestTimer("SPAWN_DEMONS", TIME_BETWEEN_DEMON_SPAWNS * 1000, null, player, false); + } + break; + } + case "PLAY_RANDOM_SONG": + { + if (npc != null) + { + final Instance world = npc.getInstanceWorld(); + playRandomSong(world); + startQuestTimer("PLAY_RANDOM_SONG", RANDOM_SONG_INTERVAL * 1000, null, player, false); + } + break; + } + case "SCARLET_FIRST_MORPH": + { + final Instance world = npc.getInstanceWorld(); + npc.doCast(FIRST_MORPH_SKILL.getSkill()); + playRandomSong(world); + break; + } + case "SCARLET_SECOND_MORPH": + { + final Instance world = npc.getInstanceWorld(); + disablePlayers(world); + final L2Npc activeScarlet = world.getParameters().getObject("activeScarlet", L2Npc.class); + activeScarlet.abortAttack(); + activeScarlet.abortCast(); + activeScarlet.setIsInvul(true); + activeScarlet.setIsImmobilized(true); + activeScarlet.disableAllSkills(); + playRandomSong(world); + startQuestTimer("SCARLET_SECOND_MORPH_CAMERA_1", 2000, npc, null, false); + break; + } + case "SCARLET_SECOND_MORPH_CAMERA_1": + { + final Instance world = npc.getInstanceWorld(); + final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class); + broadCastPacket(world, new SocialAction(frintezza.getObjectId(), 4)); + broadCastPacket(world, new SpecialCamera(frintezza, 250, 120, 15, 0, 1000, 0, 0, 1, 0, 0)); + broadCastPacket(world, new SpecialCamera(frintezza, 250, 120, 15, 0, 10000, 0, 0, 1, 0, 0)); + + startQuestTimer("SCARLET_SECOND_MORPH_CAMERA_2", 7000, npc, null, false); + break; + } + case "SCARLET_SECOND_MORPH_CAMERA_2": + { + final Instance world = npc.getInstanceWorld(); + final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class); + broadCastPacket(world, new MagicSkillUse(frintezza, frintezza, 5006, 1, 34000, 0)); + broadCastPacket(world, new SpecialCamera(frintezza, 500, 70, 15, 3000, 10000, 0, 0, 1, 0, 0)); + startQuestTimer("SCARLET_SECOND_MORPH_CAMERA_3", 3000, npc, null, false); + break; + } + case "SCARLET_SECOND_MORPH_CAMERA_3": + { + final Instance world = npc.getInstanceWorld(); + final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class); + broadCastPacket(world, new SpecialCamera(frintezza, 2500, 90, 12, 6000, 10000, 0, 0, 1, 0, 0)); + startQuestTimer("SCARLET_SECOND_MORPH_CAMERA_4", 3000, npc, null, false); + break; + } + case "SCARLET_SECOND_MORPH_CAMERA_4": + { + final Instance world = npc.getInstanceWorld(); + final L2Npc activeScarlet = world.getParameters().getObject("activeScarlet", L2Npc.class); + final Location scarletLocation = activeScarlet.getLocation(); + int newHeading = 0; + if (scarletLocation.getHeading() < 32768) + { + newHeading = Math.abs(180 - (int) (scarletLocation.getHeading() / 182.044444444)); + } + else + { + newHeading = Math.abs(540 - (int) (scarletLocation.getHeading() / 182.044444444)); + } + world.setParameter("scarletLocation", scarletLocation); + world.setParameter("newHeading", newHeading); + broadCastPacket(world, new SpecialCamera(activeScarlet, 250, newHeading, 12, 0, 1000, 0, 0, 1, 0, 0)); + broadCastPacket(world, new SpecialCamera(activeScarlet, 250, newHeading, 12, 0, 10000, 0, 0, 1, 0, 0)); + startQuestTimer("SCARLET_SECOND_MORPH_CAMERA_5", 500, npc, null, false); + break; + } + case "SCARLET_SECOND_MORPH_CAMERA_5": + { + final Instance world = npc.getInstanceWorld(); + final L2Npc activeScarlet = world.getParameters().getObject("activeScarlet", L2Npc.class); + final int newHeading = world.getParameters().getInt("newHeading"); + activeScarlet.doDie(activeScarlet); + broadCastPacket(world, new SpecialCamera(activeScarlet, 450, newHeading, 14, 8000, 8000, 0, 0, 1, 0, 0)); + startQuestTimer("SCARLET_SECOND_MORPH_CAMERA_6", 6250, npc, null, false); + startQuestTimer("SCARLET_SECOND_MORPH_CAMERA_7", 7200, npc, null, false); + break; + } + case "SCARLET_SECOND_MORPH_CAMERA_6": + { + final Instance world = npc.getInstanceWorld(); + final L2Npc activeScarlet = world.getParameters().getObject("activeScarlet", L2Npc.class); + activeScarlet.deleteMe(); + break; + } + case "SCARLET_SECOND_MORPH_CAMERA_7": + { + final Instance world = npc.getInstanceWorld(); + final int newHeading = world.getParameters().getInt("newHeading"); + final Location scarletLocation = world.getParameters().getLocation("scarletLocation"); + final L2Npc activeScarlet = addSpawn(SCARLET2, scarletLocation, false, 0, false, world.getId()); + world.setParameter("activeScarlet", activeScarlet); + activeScarlet.setRHandId(SECOND_SCARLET_WEAPON); + activeScarlet.setIsInvul(true); + activeScarlet.setIsImmobilized(true); + activeScarlet.disableAllSkills(); + broadCastPacket(world, new SpecialCamera(activeScarlet, 450, newHeading, 12, 500, 14000, 0, 0, 1, 0, 0)); + startQuestTimer("SCARLET_SECOND_MORPH_CAMERA_8", 8100, npc, null, false); + break; + } + case "SCARLET_SECOND_MORPH_CAMERA_8": + { + final Instance world = npc.getInstanceWorld(); + final L2Npc activeScarlet = world.getParameters().getObject("activeScarlet", L2Npc.class); + broadCastPacket(world, new SocialAction(activeScarlet.getObjectId(), 2)); + startQuestTimer("SCARLET_SECOND_MORPH_CAMERA_9", 9000, npc, null, false); + break; + } + case "SCARLET_SECOND_MORPH_CAMERA_9": + { + final Instance world = npc.getInstanceWorld(); + final L2Npc activeScarlet = world.getParameters().getObject("activeScarlet", L2Npc.class); + activeScarlet.setIsInvul(false); + activeScarlet.setIsImmobilized(false); + activeScarlet.enableAllSkills(); + enablePlayers(world); + break; + } + case "FINISH_CAMERA_1": + { + final Instance world = npc.getInstanceWorld(); + final L2Npc activeScarlet = world.getParameters().getObject("activeScarlet", L2Npc.class); + final int newHeading = world.getParameters().getInt("newHeading"); + broadCastPacket(world, new SpecialCamera(activeScarlet, 300, newHeading - 180, 5, 0, 7000, 0, 0, 1, 0, 0)); + broadCastPacket(world, new SpecialCamera(activeScarlet, 200, newHeading, 85, 4000, 10000, 0, 0, 1, 0, 0)); + startQuestTimer("FINISH_CAMERA_2", 7400, npc, null, false); + startQuestTimer("FINISH_CAMERA_3", 7500, npc, null, false); + break; + } + case "FINISH_CAMERA_2": + { + final Instance world = npc.getInstanceWorld(); + final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class); + frintezza.doDie(frintezza); + break; + } + case "FINISH_CAMERA_3": + { + final Instance world = npc.getInstanceWorld(); + final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class); + broadCastPacket(world, new SpecialCamera(frintezza, 100, 120, 5, 0, 7000, 0, 0, 1, 0, 0)); + broadCastPacket(world, new SpecialCamera(frintezza, 100, 90, 5, 5000, 15000, 0, 0, 1, 0, 0)); + startQuestTimer("FINISH_CAMERA_4", 7000, npc, null, false); + break; + } + case "FINISH_CAMERA_4": + { + final Instance world = npc.getInstanceWorld(); + final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class); + broadCastPacket(world, new SpecialCamera(frintezza, 900, 90, 25, 7000, 10000, 0, 0, 1, 0, 0)); + startQuestTimer("FINISH_CAMERA_5", 9000, npc, null, false); + break; + } + case "FINISH_CAMERA_5": + { + final Instance world = npc.getInstanceWorld(); + for (int doorId : FIRST_ROOM_DOORS) + { + world.openCloseDoor(doorId, true); + } + for (int doorId : FIRST_ROUTE_DOORS) + { + world.openCloseDoor(doorId, true); + } + for (int doorId : SECOND_ROOM_DOORS) + { + world.openCloseDoor(doorId, true); + } + for (int doorId : SECOND_ROUTE_DOORS) + { + world.openCloseDoor(doorId, true); + } + enablePlayers(world); + break; + } + } + return null; + } + + @Override + public String onTalk(L2Npc npc, L2PcInstance player) + { + if (npc.getId() == GUIDE) + { + enterInstance(player, npc, TEMPLATE_ID); + } + else // Teleport Cube + { + final Instance world = getPlayerInstance(player); + if (world != null) + { + teleportPlayerOut(player, world); + } + } + return null; + } + + @Override + public String onSpawn(L2Npc npc) + { + npc.setRandomWalking(false); + npc.setIsImmobilized(true); + if (npc.getId() == HALL_ALARM) + { + npc.disableCoreAI(true); + } + else // dummy + { + npc.setIsInvul(true); + } + return super.onSpawn(npc); + } + + @Override + public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon, Skill skill) + { + if (npc.getId() == SCARLET1) + { + if ((npc.getScriptValue() == 0) && (npc.getCurrentHp() < (npc.getMaxHp() * 0.80))) + { + npc.setScriptValue(1); + startQuestTimer("SCARLET_FIRST_MORPH", 1000, npc, null, false); + } + if ((npc.getScriptValue() == 1) && (npc.getCurrentHp() < (npc.getMaxHp() * 0.20))) + { + npc.setScriptValue(2); + startQuestTimer("SCARLET_SECOND_MORPH", 1000, npc, null, false); + } + } + if (skill != null) + { + // When Dewdrop of Destruction is used on Portraits they suicide. + if (CommonUtil.contains(PORTRAITS, npc.getId()) && (skill.getId() == DEWDROP_OF_DESTRUCTION_SKILL_ID)) + { + npc.doDie(attacker); + } + } + return null; + } + + @Override + public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill) + { + if (skill.isSuicideAttack()) + { + return onKill(npc, null, false); + } + return super.onSpellFinished(npc, player, skill); + } + + @Override + public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) + { + final Instance world = killer.getInstanceWorld(); + if ((npc.getId() == HALL_ALARM) && (world.getStatus() == 0)) + { + world.setStatus(1); + world.spawnGroup("room1"); + final List monsters = world.getAliveNpcs(L2MonsterInstance.class); + world.setParameter("monstersCount", monsters.size() - 1); + for (int doorId : FIRST_ROOM_DOORS) + { + world.openCloseDoor(doorId, true); + } + for (L2Npc monster : monsters) + { + monster.reduceCurrentHp(1, killer, null); // TODO: Find better way for attack + } + } + else if (npc.getId() == SCARLET2) + { + final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class); + broadCastPacket(world, new MagicSkillCanceld(frintezza.getObjectId())); + startQuestTimer("FINISH_CAMERA_1", 500, npc, null, false); + } + else if (CommonUtil.contains(DEMONS, npc.getId())) + { + final List demons = world.getParameters().getList("demons", L2Npc.class); + demons.remove(npc); + } + else if (CommonUtil.contains(PORTRAITS, npc.getId())) + { + final Map portraits = world.getParameters().getMap("portraits", L2Npc.class, Integer.class); + portraits.remove(npc); + } + else + { + final int killCount = world.getParameters().getInt("monstersCount"); + world.setParameter("monstersCount", killCount - 1); + if (killCount <= 0) + { + switch (world.getStatus()) + { + case 1: + { + world.setStatus(2); + world.spawnGroup("room2_part1"); + final List monsters = world.getAliveNpcs(L2MonsterInstance.class); + world.setParameter("monstersCount", monsters.size() - 1); + for (int doorId : FIRST_ROUTE_DOORS) + { + world.openCloseDoor(doorId, true); + } + break; + } + case 2: + { + world.setStatus(3); + world.spawnGroup("room2_part2"); + final List monsters = world.getAliveNpcs(L2MonsterInstance.class); + world.setParameter("monstersCount", monsters.size() - 1); + for (int doorId : SECOND_ROOM_DOORS) + { + world.openCloseDoor(doorId, true); + } + for (L2Npc monster : monsters) + { + monster.reduceCurrentHp(1, killer, null); // TODO: Find better way for attack + } + break; + } + case 3: + { + world.setStatus(4); + for (int doorId : SECOND_ROUTE_DOORS) + { + world.openCloseDoor(doorId, true); + } + startQuestTimer("FRINTEZZA_INTRO_START", FRINTEZZA_WAIT_TIME * 60 * 1000, null, killer, false); + break; + } + } + } + if (getRandom(100) < 5) + { + npc.dropItem(killer, DEWDROP_OF_DESTRUCTION_ITEM_ID, 1); + } + } + return super.onKill(npc, killer, isSummon); + } + + private void playRandomSong(Instance world) + { + final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class); + final boolean isPlayingSong = world.getParameters().getBoolean("isPlayingSong"); + if (isPlayingSong) + { + return; + } + world.setParameter("isPlayingSong", true); + final int random = getRandom(1, 5); + final SkillHolder skill = new SkillHolder(5007, random); + final SkillHolder skillEffect = new SkillHolder(5008, random); + broadCastPacket(world, new ExShowScreenMessage(2, -1, 2, 0, 0, 0, 0, true, 4000, false, null, SKILL_MSG.get(random), null)); + broadCastPacket(world, new MagicSkillUse(frintezza, frintezza, skill.getSkillId(), skill.getSkillLvl(), skill.getSkill().getHitTime(), 0)); + for (L2PcInstance player : world.getPlayers()) + { + if ((player != null) && player.isOnline()) + { + frintezza.setTarget(player); + frintezza.doCast(skillEffect.getSkill()); + } + } + world.setParameter("isPlayingSong", false); + } + + private void disablePlayers(Instance world) + { + for (L2PcInstance player : world.getPlayers()) + { + if ((player != null) && player.isOnline()) + { + player.abortAttack(); + player.abortCast(); + player.disableAllSkills(); + player.setTarget(null); + player.stopMove(null); + player.setIsImmobilized(true); + player.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); + } + } + } + + private void enablePlayers(Instance world) + { + for (L2PcInstance player : world.getPlayers()) + { + if ((player != null) && player.isOnline()) + { + player.enableAllSkills(); + player.setIsImmobilized(false); + } + } + } + + void broadCastPacket(Instance world, IClientOutgoingPacket packet) + { + for (L2PcInstance player : world.getPlayers()) + { + if ((player != null) && player.isOnline()) + { + player.sendPacket(packet); + } + } + } + + private void sendPacketX(Instance world, IClientOutgoingPacket packet1, IClientOutgoingPacket packet2, int x) + { + for (L2PcInstance player : world.getPlayers()) + { + if ((player != null) && player.isOnline()) + { + if (player.getX() < x) + { + player.sendPacket(packet1); + } + else + { + player.sendPacket(packet2); + } + } + } + } + + public static void main(String[] args) + { + new LastImperialTomb(); + } +} diff --git a/L2J_Mobius_Underground/dist/game/data/scripts/instances/LastImperialTomb/ScarletVanHalisha.java b/L2J_Mobius_Underground/dist/game/data/scripts/instances/LastImperialTomb/ScarletVanHalisha.java new file mode 100644 index 0000000000..b52c0680ff --- /dev/null +++ b/L2J_Mobius_Underground/dist/game/data/scripts/instances/LastImperialTomb/ScarletVanHalisha.java @@ -0,0 +1,282 @@ +/* + * 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 . + */ +package instances.LastImperialTomb; + +import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK; +import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_FOLLOW; +import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE; + +import java.util.ArrayList; + +import com.l2jmobius.gameserver.GeoData; +import com.l2jmobius.gameserver.data.xml.impl.SkillData; +import com.l2jmobius.gameserver.model.L2Object; +import com.l2jmobius.gameserver.model.actor.L2Character; +import com.l2jmobius.gameserver.model.actor.L2Npc; +import com.l2jmobius.gameserver.model.actor.instance.L2DecoyInstance; +import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.model.skills.Skill; +import com.l2jmobius.gameserver.util.Util; + +import ai.AbstractNpcAI; + +/** + * @author Micr0, Zerox, Mobius + */ +public final class ScarletVanHalisha extends AbstractNpcAI +{ + // NPCs + private static final int HALISHA2 = 29046; + private static final int HALISHA3 = 29047; + // Skills + private static final int FRINTEZZA_DAEMON_ATTACK = 5014; + private static final int FRINTEZZA_DAEMON_CHARGE = 5015; + private static final int YOKE_OF_SCARLET = 5016; + private static final int FRINTEZZA_DAEMON_MORPH = 5018; + private static final int FRINTEZZA_DAEMON_FIELD = 5019; + // Misc + private L2Character _target; + private Skill _skill; + private long _lastRangedSkillTime; + private final int _rangedSkillMinCoolTime = 60000; // 1 minute + + public ScarletVanHalisha() + { + addAttackId(HALISHA2, HALISHA3); + addKillId(HALISHA2, HALISHA3); + addSpellFinishedId(HALISHA2, HALISHA3); + registerMobs(HALISHA2, HALISHA3); + } + + @Override + public String onAdvEvent(String event, L2Npc npc, L2PcInstance player) + { + switch (event) + { + case "attack": + { + if (npc != null) + { + getSkillAI(npc); + } + break; + } + case "random_target": + { + _target = getRandomTarget(npc, null); + break; + } + } + return super.onAdvEvent(event, npc, player); + } + + @Override + public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill) + { + getSkillAI(npc); + return super.onSpellFinished(npc, player, skill); + } + + @Override + public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon) + { + startQuestTimer("random_Target", 5000, npc, null, true); + startQuestTimer("attack", 500, npc, null, true); + return super.onAttack(npc, attacker, damage, isSummon); + } + + @Override + public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) + { + cancelQuestTimers("attack"); + cancelQuestTimers("random_Target"); + return super.onKill(npc, killer, isSummon); + } + + private Skill getRndSkills(L2Npc npc) + { + switch (npc.getId()) + { + case HALISHA2: + { + if (getRandom(100) < 10) + { + return SkillData.getInstance().getSkill(FRINTEZZA_DAEMON_CHARGE, 2); + } + else if (getRandom(100) < 10) + { + return SkillData.getInstance().getSkill(FRINTEZZA_DAEMON_CHARGE, 5); + } + else if (getRandom(100) < 2) + { + return SkillData.getInstance().getSkill(YOKE_OF_SCARLET, 1); + } + else + { + return SkillData.getInstance().getSkill(FRINTEZZA_DAEMON_ATTACK, 2); + } + } + case HALISHA3: + { + if (getRandom(100) < 10) + { + return SkillData.getInstance().getSkill(FRINTEZZA_DAEMON_CHARGE, 3); + } + else if (getRandom(100) < 10) + { + return SkillData.getInstance().getSkill(FRINTEZZA_DAEMON_CHARGE, 6); + } + else if (getRandom(100) < 10) + { + return SkillData.getInstance().getSkill(FRINTEZZA_DAEMON_CHARGE, 2); + } + else if (((_lastRangedSkillTime + _rangedSkillMinCoolTime) < System.currentTimeMillis()) && (getRandom(100) < 10)) + { + return SkillData.getInstance().getSkill(FRINTEZZA_DAEMON_FIELD, 1); + } + else if (((_lastRangedSkillTime + _rangedSkillMinCoolTime) < System.currentTimeMillis()) && (getRandom(100) < 10)) + { + return SkillData.getInstance().getSkill(FRINTEZZA_DAEMON_MORPH, 1); + } + else if (getRandom(100) < 2) + { + return SkillData.getInstance().getSkill(YOKE_OF_SCARLET, 1); + } + else + { + return SkillData.getInstance().getSkill(FRINTEZZA_DAEMON_ATTACK, 3); + } + } + } + + return SkillData.getInstance().getSkill(FRINTEZZA_DAEMON_ATTACK, 1); + } + + private synchronized void getSkillAI(L2Npc npc) + { + if (npc.isInvul() || npc.isCastingNow()) + { + return; + } + if ((getRandom(100) < 30) || (_target == null) || _target.isDead()) + { + _skill = getRndSkills(npc); + _target = getRandomTarget(npc, _skill); + } + final L2Character target = _target; + Skill skill = _skill; + if (skill == null) + { + skill = getRndSkills(npc); + } + + if (npc.isPhysicalMuted()) + { + return; + } + + if ((target == null) || target.isDead()) + { + // npc.setIsCastingNow(false); + return; + } + + if (Util.checkIfInRange(skill.getCastRange(), npc, target, true)) + { + npc.getAI().setIntention(AI_INTENTION_IDLE); + npc.setTarget(target); + // npc.setIsCastingNow(true); + _target = null; + npc.doCast(skill); + } + else + { + npc.getAI().setIntention(AI_INTENTION_FOLLOW, target, null); + npc.getAI().setIntention(AI_INTENTION_ATTACK, target, null); + // npc.setIsCastingNow(false); + } + } + + private L2Character getRandomTarget(L2Npc npc, Skill skill) + { + final ArrayList result = new ArrayList<>(); + { + for (L2Object obj : npc.getInstanceWorld().getPlayers()) + { + if (obj.isPlayable() || (obj instanceof L2DecoyInstance)) + { + if (obj.isPlayer() && obj.getActingPlayer().isInvisible()) + { + continue; + } + + if (((((L2Character) obj).getZ() < (npc.getZ() - 100)) && (((L2Character) obj).getZ() > (npc.getZ() + 100))) || !GeoData.getInstance().canSeeTarget(((L2Character) obj).getX(), ((L2Character) obj).getY(), ((L2Character) obj).getZ(), npc.getX(), npc.getY(), npc.getZ())) + { + continue; + } + } + if (obj.isPlayable() || (obj instanceof L2DecoyInstance)) + { + int skillRange = 150; + if (skill != null) + { + switch (skill.getId()) + { + case FRINTEZZA_DAEMON_ATTACK: + { + skillRange = 150; + break; + } + case FRINTEZZA_DAEMON_CHARGE: + { + skillRange = 400; + break; + } + case YOKE_OF_SCARLET: + { + skillRange = 200; + break; + } + case FRINTEZZA_DAEMON_MORPH: + case FRINTEZZA_DAEMON_FIELD: + { + _lastRangedSkillTime = System.currentTimeMillis(); + skillRange = 550; + break; + } + } + } + if (Util.checkIfInRange(skillRange, npc, obj, true) && !((L2Character) obj).isDead()) + { + result.add((L2Character) obj); + } + } + } + } + if (!result.isEmpty() && (result.size() != 0)) + { + final Object[] characters = result.toArray(); + return (L2Character) characters[getRandom(characters.length)]; + } + return null; + } + + public static void main(String[] args) + { + new ScarletVanHalisha(); + } +} \ No newline at end of file