diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/instances/EtisVanEtinaSolo.xml b/L2J_Mobius_8.0_Homunculus/dist/game/data/instances/EtisVanEtinaSolo.xml
new file mode 100644
index 0000000000..64f03d23d9
--- /dev/null
+++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/instances/EtisVanEtinaSolo.xml
@@ -0,0 +1,196 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-01.html b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-01.html
new file mode 100644
index 0000000000..3d860da0ab
--- /dev/null
+++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-01.html
@@ -0,0 +1,4 @@
+
Blackbird Clan Lord Leona Blackbird:
+Let us defeat our enemies.
+Let's go to Etis van Etina, the Head of the Embryo, as fast as we can.
+
\ No newline at end of file
diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-02.htm b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-02.htm
new file mode 100644
index 0000000000..7a02b2ead9
--- /dev/null
+++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-02.htm
@@ -0,0 +1,5 @@
+Blackbird Clan Lord Leona Blackbird:
+Thanks to you, we were able to come this far this time.
+But why is it so quiet? It can't be this empty...
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-03.html b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-03.html
new file mode 100644
index 0000000000..528abbaadb
--- /dev/null
+++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-03.html
@@ -0,0 +1,3 @@
+Blackbird Clan Lord Leona Blackbird:
+You don't have to worry ab- Ah! Oh no! What's that?
+
\ No newline at end of file
diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471.htm b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471.htm
new file mode 100644
index 0000000000..fa5014df9f
--- /dev/null
+++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471.htm
@@ -0,0 +1,5 @@
+Blackbird Clan Lord Leona Blackbird:
+This is the Great Etina Temple. Setting foot in this place again reminds me of old memories. I used my new power to sneak in so the enemy should be unaware of our presence.
+Now, let's take down the Embryos and Etis van Etina before they even realize. Are you ready?
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34472.html b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34472.html
new file mode 100644
index 0000000000..cbc5604977
--- /dev/null
+++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34472.html
@@ -0,0 +1,3 @@
+Devianne:
+Behold the power of the Ivory Tower Wizards!
+
\ No newline at end of file
diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34473.html b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34473.html
new file mode 100644
index 0000000000..eef8b17456
--- /dev/null
+++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34473.html
@@ -0,0 +1,3 @@
+Elikia:
+Let's take down the Embryos and Etis van Etina before they even realize.
+
\ No newline at end of file
diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34474.html b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34474.html
new file mode 100644
index 0000000000..9c0807c63a
--- /dev/null
+++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34474.html
@@ -0,0 +1,3 @@
+Sporcha:
+Are you ready to fight?
+
\ No newline at end of file
diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34475.html b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34475.html
new file mode 100644
index 0000000000..ec99f9f6d0
--- /dev/null
+++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/34475.html
@@ -0,0 +1,3 @@
+Aliber:
+Rage against all that stands in our way!
+
\ No newline at end of file
diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperAliber.java b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperAliber.java
new file mode 100644
index 0000000000..df86f9ab85
--- /dev/null
+++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperAliber.java
@@ -0,0 +1,283 @@
+/*
+ * 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.EtisVanEtinaSolo;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.ai.CtrlIntention;
+import org.l2jmobius.gameserver.enums.ChatType;
+import org.l2jmobius.gameserver.geoengine.GeoEngine;
+import org.l2jmobius.gameserver.model.Location;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.World;
+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.FriendlyNpcInstance;
+import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureAttacked;
+import org.l2jmobius.gameserver.model.events.impl.instance.OnInstanceStatusChange;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.instancezone.Instance;
+import org.l2jmobius.gameserver.network.NpcStringId;
+import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
+import org.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
+
+import ai.AbstractNpcAI;
+
+/**
+ * Etina Helper Aliber AI.
+ * @author CostyKiller
+ */
+public class EtinaHelperAliber extends AbstractNpcAI
+{
+ // NPCs
+ private static final int ETINA_HELPER_ALIBER = 34475;
+ // Corridor Mobs
+ //@formatter:off
+ private static final int[] CORRIDOR_MOBS_1 = {24173, 24174, 24175, 24176};
+ private static final int[] CORRIDOR_MOBS_2 = {24180, 24181, 24182, 24183};
+ private static final int[] CORRIDOR_MOBS_3 = {24184, 24185, 24186, 24187, 24188, 24189, 24190, 24191, 24192};
+ private static final int[] NOT_ATK_NPCS =
+ {
+ 33798, // Common Decoration - Barricade
+ 19677, // Seal of Gnosis
+ 19678, // Seal of Strife
+ 19679, // Seal of Avarice
+ 19680, // Seal of Punishment
+ 19681, // Seal of Awakening
+ 19682, // Seal of Calamity
+ 19683, // Seal of Destruction
+ };
+ private static final int[] ETINA_HELPERS =
+ {
+ 34471, // Leona Blackbird
+ 34472, // Devianne
+ 34473, // Elikia
+ 34474, // Sporcha
+ 34475, // Aliber
+ };
+ // Skill Cast Locations
+ private static final Location[] SKILL_CAST_LOCATIONS =
+ {
+ new Location(-245751, 182321, 2861, 16612), // First barricade line
+ new Location(-245751, 184001, 3025, 16612), // Second barricade line
+ new Location(-245751, 185298, 3031, 16612), // Third barricade line
+ new Location(-245751, 186612, 3038, 16612), // Fourth barricade line
+ };
+ // Support Npcs Skills
+ private static final SkillHolder BARRICADE_DESTRUCTION = new SkillHolder(32286, 1);
+ // Misc
+ private static final int[] ETINA_SOLO_INSTANCES =
+ {
+ 292, // Fall of Etina (Solo)
+ 293, // Fall of Etina (Solo)
+ };
+
+ private EtinaHelperAliber()
+ {
+ setCreatureAttackedId(this::onCreatureAttacked, ETINA_HELPER_ALIBER);
+ addSpellFinishedId(ETINA_HELPER_ALIBER);
+ addSeeCreatureId(ETINA_HELPER_ALIBER);
+ setInstanceStatusChangeId(this::onInstanceStatusChange, ETINA_SOLO_INSTANCES);
+ }
+
+ @Override
+ public void onTimerEvent(String event, StatSet params, Npc npc, PlayerInstance player)
+ {
+ final Instance instance = npc.getInstanceWorld();
+ if (instance != null)
+ {
+ switch (event)
+ {
+ case "CHECK_ACTION":
+ {
+ final StatSet npcVars = npc.getVariables();
+ final PlayerInstance plr = npcVars.getObject("PLAYER_OBJECT", PlayerInstance.class);
+ final MonsterInstance monster = getRandomEntry(World.getInstance().getVisibleObjectsInRange(npc, MonsterInstance.class, 2500));
+ if (plr != null)
+ {
+ final double distance = npc.calculateDistance2D(plr);
+ if (!npc.isAttackingNow() && !npc.isMoving() && (distance > 250))
+ {
+ final Location loc = new Location(plr.getX(), plr.getY(), plr.getZ() + 50);
+ final Location randLoc = new Location(loc.getX() + getRandom(-100, 100), loc.getY() + getRandom(-100, 100), loc.getZ());
+ if (distance > 600)
+ {
+ npc.teleToLocation(loc);
+ }
+ else
+ {
+ npc.setRunning();
+ }
+ addMoveToDesire(npc, randLoc, 23);
+ ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
+ }
+ else if (!npc.isInCombat() || !npc.isAttackingNow() || (npc.getTarget() == null))
+ {
+ WorldObject target = npc.getTarget();
+ if (target == null)
+ {
+ npc.setTarget(monster);
+ }
+ if ((target != null) && !target.isInvul() && target.isTargetable() && GeoEngine.getInstance().canSeeTarget(npc, target) && !CommonUtil.contains(NOT_ATK_NPCS, target.getId()) && !CommonUtil.contains(ETINA_HELPERS, target.getId()))
+ {
+ npc.setInvul(true);
+ npc.setRunning();
+ ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
+ addAttackDesire(npc, (Creature) target);
+ // addSkillCastDesire(npc, target, ALIBER_SPLASH, 23);
+ // npc.reduceCurrentHp(1, monster, null);
+ }
+ }
+ }
+ break;
+ }
+ case "DESTROY_BARRICADES":
+ {
+ final FriendlyNpcInstance _aliber = (FriendlyNpcInstance) instance.getNpc(ETINA_HELPER_ALIBER);
+ boolean BARRICADE_DESTROYED = instance.getParameters().getBoolean("BARRICADE_DESTROYED", false);
+ if (!instance.getNpcsOfGroup("BARRICADES_1").isEmpty())
+ {
+ _aliber.setRunning();
+ _aliber.setInvul(true);
+ _aliber.setCanReturnToSpawnPoint(false);
+ _aliber.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, SKILL_CAST_LOCATIONS[0]);
+ if (_aliber.getLocation().isIn2DRadius(SKILL_CAST_LOCATIONS[0], 200) && (BARRICADE_DESTROYED == false))
+ {
+ _aliber.broadcastPacket(new MagicSkillUse(_aliber, _aliber, BARRICADE_DESTRUCTION.getSkillId(), 1, 500, 0));
+ _aliber.broadcastPacket(new ExShowScreenMessage(NpcStringId.ALIBER_IS_CASTING_A_SPELL_TO_DESTROY_THE_BARRICADE, ExShowScreenMessage.TOP_CENTER, 7000, true));
+ instance.getNpcsOfGroup("BARRICADES_1").forEach(barricade ->
+ {
+ if (barricade != null)
+ {
+ barricade.decayMe();
+ }
+ });
+ instance.getParameters().set("BARRICADE_DESTROYED", true);
+ instance.despawnGroup("BARRICADES_1");
+ }
+ }
+ else if (!instance.getNpcsOfGroup("BARRICADES_2").isEmpty() && instance.getAliveNpcs(CORRIDOR_MOBS_1).isEmpty() && instance.getNpcsOfGroup("BARRICADES_1").isEmpty())
+ {
+ _aliber.setRunning();
+ _aliber.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, SKILL_CAST_LOCATIONS[1]);
+ if (_aliber.getLocation().isIn2DRadius(SKILL_CAST_LOCATIONS[1], 200) && (BARRICADE_DESTROYED == false))
+ {
+ _aliber.broadcastPacket(new MagicSkillUse(_aliber, _aliber, BARRICADE_DESTRUCTION.getSkillId(), 1, 500, 0));
+ _aliber.broadcastPacket(new ExShowScreenMessage(NpcStringId.ALIBER_IS_CASTING_A_SPELL_TO_DESTROY_THE_BARRICADE, ExShowScreenMessage.TOP_CENTER, 7000, true));
+ instance.getNpcsOfGroup("BARRICADES_2").forEach(barricade ->
+ {
+ if (barricade != null)
+ {
+ barricade.decayMe();
+ }
+ });
+ instance.getParameters().set("BARRICADE_DESTROYED", true);
+ instance.despawnGroup("BARRICADES_2");
+ }
+ }
+ else if (!instance.getNpcsOfGroup("BARRICADES_3").isEmpty() && instance.getAliveNpcs(CORRIDOR_MOBS_2).isEmpty() && instance.getNpcsOfGroup("BARRICADES_2").isEmpty())
+ {
+ _aliber.setRunning();
+ _aliber.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, SKILL_CAST_LOCATIONS[2]);
+ if (_aliber.getLocation().isIn2DRadius(SKILL_CAST_LOCATIONS[2], 200) && (BARRICADE_DESTROYED == false))
+ {
+ _aliber.broadcastPacket(new MagicSkillUse(_aliber, _aliber, BARRICADE_DESTRUCTION.getSkillId(), 1, 500, 0));
+ _aliber.broadcastPacket(new ExShowScreenMessage(NpcStringId.ALIBER_IS_CASTING_A_SPELL_TO_DESTROY_THE_BARRICADE, ExShowScreenMessage.TOP_CENTER, 7000, true));
+ instance.getNpcsOfGroup("BARRICADES_3").forEach(barricade ->
+ {
+ if (barricade != null)
+ {
+ barricade.decayMe();
+ }
+ });
+ instance.getParameters().set("BARRICADE_DESTROYED", true);
+ instance.despawnGroup("BARRICADES_3");
+ }
+ }
+ else if (!instance.getNpcsOfGroup("BARRICADES_4").isEmpty() && instance.getAliveNpcs(CORRIDOR_MOBS_3).isEmpty() && instance.getNpcsOfGroup("BARRICADES_3").isEmpty())
+ {
+ _aliber.setRunning();
+ _aliber.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, SKILL_CAST_LOCATIONS[3]);
+ if (_aliber.getLocation().isIn2DRadius(SKILL_CAST_LOCATIONS[3], 200) && (BARRICADE_DESTROYED == false))
+ {
+ _aliber.broadcastPacket(new MagicSkillUse(_aliber, _aliber, BARRICADE_DESTRUCTION.getSkillId(), 1, 500, 0));
+ _aliber.broadcastPacket(new ExShowScreenMessage(NpcStringId.ALIBER_IS_CASTING_A_SPELL_TO_DESTROY_THE_BARRICADE, ExShowScreenMessage.TOP_CENTER, 7000, true));
+ instance.getNpcsOfGroup("BARRICADES_4").forEach(barricade ->
+ {
+ if (barricade != null)
+ {
+ barricade.decayMe();
+ }
+ });
+ instance.getParameters().set("BARRICADE_DESTROYED", true);
+ instance.despawnGroup("BARRICADES_4");
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ public void onCreatureAttacked(OnCreatureAttacked event)
+ {
+ final FriendlyNpcInstance npc = (FriendlyNpcInstance) event.getTarget();
+ if (npc != null)
+ {
+ final Instance instance = npc.getInstanceWorld();
+ if ((instance != null) && !event.getAttacker().isPlayable() && !CommonUtil.contains(ETINA_HELPERS, event.getAttacker().getId()))
+ {
+ if (!npc.isInCombat())
+ {
+ if (getRandom(50) < 5)
+ {
+ npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.RAGE_AGAINST_ALL_THAT_STANDS_IN_OUR_WAY);
+ }
+ }
+ }
+ }
+ }
+
+ public void onInstanceStatusChange(OnInstanceStatusChange event)
+ {
+ final Instance instance = event.getWorld();
+ final int status = event.getStatus();
+ if ((status == 1) || (status == 2) || (status == 3))
+ {
+ instance.getAliveNpcs(ETINA_HELPER_ALIBER).forEach(etinaHelperAliber -> getTimers().addRepeatingTimer("CHECK_ACTION", 3000, etinaHelperAliber, null));
+ instance.getAliveNpcs(ETINA_HELPER_ALIBER).forEach(etinaHelperAliber -> getTimers().addRepeatingTimer("USE_SKILL", 6000, etinaHelperAliber, null));
+ instance.getAliveNpcs(ETINA_HELPER_ALIBER).forEach(etinaHelperAliber -> getTimers().addRepeatingTimer("DESTROY_BARRICADES", 5000, etinaHelperAliber, null));
+ }
+ }
+
+ @Override
+ public String onSeeCreature(Npc npc, Creature creature, boolean isSummon)
+ {
+ if (creature.isPlayer())
+ {
+ npc.getVariables().set("PLAYER_OBJECT", creature.getActingPlayer());
+ }
+ return super.onSeeCreature(npc, creature, isSummon);
+ }
+
+ public static void main(String[] args)
+ {
+ new EtinaHelperAliber();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperDevianne.java b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperDevianne.java
new file mode 100644
index 0000000000..258d606210
--- /dev/null
+++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperDevianne.java
@@ -0,0 +1,171 @@
+/*
+ * 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.EtisVanEtinaSolo;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.enums.ChatType;
+import org.l2jmobius.gameserver.geoengine.GeoEngine;
+import org.l2jmobius.gameserver.model.Location;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.World;
+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.FriendlyNpcInstance;
+import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureAttacked;
+import org.l2jmobius.gameserver.model.events.impl.instance.OnInstanceStatusChange;
+import org.l2jmobius.gameserver.model.instancezone.Instance;
+import org.l2jmobius.gameserver.network.NpcStringId;
+
+import ai.AbstractNpcAI;
+
+/**
+ * Etina Helper Devianne AI.
+ * @author CostyKiller
+ */
+public class EtinaHelperDevianne extends AbstractNpcAI
+{
+ // NPCs
+ private static final int ETINA_HELPER_DEVIANNE = 34472;
+ private static final int[] NOT_ATK_NPCS =
+ {
+ 33798, // Common Decoration - Barricade
+ 19677, // Seal of Gnosis
+ 19678, // Seal of Strife
+ 19679, // Seal of Avarice
+ 19680, // Seal of Punishment
+ 19681, // Seal of Awakening
+ 19682, // Seal of Calamity
+ 19683, // Seal of Destruction
+ };
+ private static final int[] ETINA_HELPERS =
+ {
+ 34471, // Leona Blackbird
+ 34472, // Devianne
+ 34473, // Elikia
+ 34474, // Sporcha
+ 34475, // Aliber
+ };
+ // Misc
+ private static final int[] ETINA_SOLO_INSTANCES =
+ {
+ 292, // Fall of Etina (Solo)
+ 293, // Fall of Etina (Solo)
+ };
+
+ private EtinaHelperDevianne()
+ {
+ setCreatureAttackedId(this::onCreatureAttacked, ETINA_HELPER_DEVIANNE);
+ addSpellFinishedId(ETINA_HELPER_DEVIANNE);
+ addSeeCreatureId(ETINA_HELPER_DEVIANNE);
+ setInstanceStatusChangeId(this::onInstanceStatusChange, ETINA_SOLO_INSTANCES);
+ }
+
+ @Override
+ public void onTimerEvent(String event, StatSet params, Npc npc, PlayerInstance player)
+ {
+ final Instance instance = npc.getInstanceWorld();
+ if ((instance != null) && event.equals("CHECK_ACTION"))
+ {
+ final StatSet npcVars = npc.getVariables();
+ final PlayerInstance plr = npcVars.getObject("PLAYER_OBJECT", PlayerInstance.class);
+ final MonsterInstance monster = getRandomEntry(World.getInstance().getVisibleObjectsInRange(npc, MonsterInstance.class, 2500));
+ if (plr != null)
+ {
+ final double distance = npc.calculateDistance2D(plr);
+ if (!npc.isAttackingNow() && !npc.isMoving() && (distance > 250))
+ {
+ final Location loc = new Location(plr.getX(), plr.getY(), plr.getZ() + 50);
+ final Location randLoc = new Location(loc.getX() + getRandom(-100, 100), loc.getY() + getRandom(-100, 100), loc.getZ());
+ if (distance > 600)
+ {
+ npc.teleToLocation(loc);
+ }
+ else
+ {
+ npc.setRunning();
+ }
+ addMoveToDesire(npc, randLoc, 23);
+ ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
+ }
+ else if (!npc.isInCombat() || !npc.isAttackingNow() || (npc.getTarget() == null))
+ {
+ WorldObject target = npc.getTarget();
+ if (target == null)
+ {
+ npc.setTarget(monster);
+ }
+ if ((target != null) && !target.isInvul() && target.isTargetable() && GeoEngine.getInstance().canSeeTarget(npc, target) && !CommonUtil.contains(NOT_ATK_NPCS, target.getId()) && !CommonUtil.contains(ETINA_HELPERS, target.getId()))
+ {
+ npc.setInvul(true);
+ npc.setRunning();
+ ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
+ addAttackDesire(npc, (Creature) target);
+ // npc.reduceCurrentHp(1, monster, null);
+ }
+ }
+ }
+ }
+ }
+
+ public void onCreatureAttacked(OnCreatureAttacked event)
+ {
+ final FriendlyNpcInstance npc = (FriendlyNpcInstance) event.getTarget();
+ if (npc != null)
+ {
+ final Instance instance = npc.getInstanceWorld();
+ if ((instance != null) && !event.getAttacker().isPlayable() && !CommonUtil.contains(ETINA_HELPERS, event.getAttacker().getId()))
+ {
+ if (!npc.isInCombat())
+ {
+ if (getRandom(50) < 5)
+ {
+ npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.BEHOLD_THE_POWER_OF_THE_IVORY_TOWER_WIZARDS);
+ }
+
+ }
+ }
+ }
+ }
+
+ public void onInstanceStatusChange(OnInstanceStatusChange event)
+ {
+ final Instance instance = event.getWorld();
+ final int status = event.getStatus();
+ if ((status == 1) || (status == 2) || (status == 3))
+ {
+ instance.getAliveNpcs(ETINA_HELPER_DEVIANNE).forEach(etinaHelperDevianne -> getTimers().addRepeatingTimer("CHECK_ACTION", 3000, etinaHelperDevianne, null));
+ }
+ }
+
+ @Override
+ public String onSeeCreature(Npc npc, Creature creature, boolean isSummon)
+ {
+ if (creature.isPlayer())
+ {
+ npc.getVariables().set("PLAYER_OBJECT", creature.getActingPlayer());
+ }
+ return super.onSeeCreature(npc, creature, isSummon);
+ }
+
+ public static void main(String[] args)
+ {
+ new EtinaHelperDevianne();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperElikia.java b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperElikia.java
new file mode 100644
index 0000000000..ff41fcd13e
--- /dev/null
+++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperElikia.java
@@ -0,0 +1,170 @@
+/*
+ * 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.EtisVanEtinaSolo;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.enums.ChatType;
+import org.l2jmobius.gameserver.geoengine.GeoEngine;
+import org.l2jmobius.gameserver.model.Location;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.World;
+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.FriendlyNpcInstance;
+import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureAttacked;
+import org.l2jmobius.gameserver.model.events.impl.instance.OnInstanceStatusChange;
+import org.l2jmobius.gameserver.model.instancezone.Instance;
+import org.l2jmobius.gameserver.network.NpcStringId;
+
+import ai.AbstractNpcAI;
+
+/**
+ * Etina Helper Elikia AI.
+ * @author CostyKiller
+ */
+public class EtinaHelperElikia extends AbstractNpcAI
+{
+ // NPCs
+ private static final int ETINA_HELPER_ELIKIA = 34473;
+ private static final int[] NOT_ATK_NPCS =
+ {
+ 33798, // Common Decoration - Barricade
+ 19677, // Seal of Gnosis
+ 19678, // Seal of Strife
+ 19679, // Seal of Avarice
+ 19680, // Seal of Punishment
+ 19681, // Seal of Awakening
+ 19682, // Seal of Calamity
+ 19683, // Seal of Destruction
+ };
+ private static final int[] ETINA_HELPERS =
+ {
+ 34471, // Leona Blackbird
+ 34472, // Devianne
+ 34473, // Elikia
+ 34474, // Sporcha
+ 34475, // Aliber
+ };
+ // Misc
+ private static final int[] ETINA_SOLO_INSTANCES =
+ {
+ 292, // Fall of Etina (Solo)
+ 293, // Fall of Etina (Solo)
+ };
+
+ private EtinaHelperElikia()
+ {
+ setCreatureAttackedId(this::onCreatureAttacked, ETINA_HELPER_ELIKIA);
+ addSpellFinishedId(ETINA_HELPER_ELIKIA);
+ addSeeCreatureId(ETINA_HELPER_ELIKIA);
+ setInstanceStatusChangeId(this::onInstanceStatusChange, ETINA_SOLO_INSTANCES);
+ }
+
+ @Override
+ public void onTimerEvent(String event, StatSet params, Npc npc, PlayerInstance player)
+ {
+ final Instance instance = npc.getInstanceWorld();
+ if ((instance != null) && event.equals("CHECK_ACTION"))
+ {
+ final StatSet npcVars = npc.getVariables();
+ final PlayerInstance plr = npcVars.getObject("PLAYER_OBJECT", PlayerInstance.class);
+ final MonsterInstance monster = getRandomEntry(World.getInstance().getVisibleObjectsInRange(npc, MonsterInstance.class, 2500));
+ if (plr != null)
+ {
+ final double distance = npc.calculateDistance2D(plr);
+ if (!npc.isAttackingNow() && !npc.isMoving() && (distance > 250))
+ {
+ final Location loc = new Location(plr.getX(), plr.getY(), plr.getZ() + 50);
+ final Location randLoc = new Location(loc.getX() + getRandom(-100, 100), loc.getY() + getRandom(-100, 100), loc.getZ());
+ if (distance > 600)
+ {
+ npc.teleToLocation(loc);
+ }
+ else
+ {
+ npc.setRunning();
+ }
+ addMoveToDesire(npc, randLoc, 23);
+ ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
+ }
+ else if (!npc.isInCombat() || !npc.isAttackingNow() || (npc.getTarget() == null))
+ {
+ WorldObject target = npc.getTarget();
+ if (target == null)
+ {
+ npc.setTarget(monster);
+ }
+ if ((target != null) && !target.isInvul() && target.isTargetable() && GeoEngine.getInstance().canSeeTarget(npc, target) && !CommonUtil.contains(NOT_ATK_NPCS, target.getId()) && !CommonUtil.contains(ETINA_HELPERS, target.getId()))
+ {
+ npc.setInvul(true);
+ npc.setRunning();
+ ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
+ addAttackDesire(npc, (Creature) target);
+ // npc.reduceCurrentHp(1, monster, null);
+ }
+ }
+ }
+ }
+ }
+
+ public void onCreatureAttacked(OnCreatureAttacked event)
+ {
+ final FriendlyNpcInstance npc = (FriendlyNpcInstance) event.getTarget();
+ if (npc != null)
+ {
+ final Instance instance = npc.getInstanceWorld();
+ if ((instance != null) && !event.getAttacker().isPlayable() && !CommonUtil.contains(ETINA_HELPERS, event.getAttacker().getId()))
+ {
+ if (!npc.isInCombat())
+ {
+ if (getRandom(50) < 5)
+ {
+ npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.DON_T_GET_IN_MY_WAY);
+ }
+ }
+ }
+ }
+ }
+
+ public void onInstanceStatusChange(OnInstanceStatusChange event)
+ {
+ final Instance instance = event.getWorld();
+ final int status = event.getStatus();
+ if ((status == 1) || (status == 2) || (status == 3))
+ {
+ instance.getAliveNpcs(ETINA_HELPER_ELIKIA).forEach(etinaHelperElikia -> getTimers().addRepeatingTimer("CHECK_ACTION", 3000, etinaHelperElikia, null));
+ }
+ }
+
+ @Override
+ public String onSeeCreature(Npc npc, Creature creature, boolean isSummon)
+ {
+ if (creature.isPlayer())
+ {
+ npc.getVariables().set("PLAYER_OBJECT", creature.getActingPlayer());
+ }
+ return super.onSeeCreature(npc, creature, isSummon);
+ }
+
+ public static void main(String[] args)
+ {
+ new EtinaHelperElikia();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperLeona.java b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperLeona.java
new file mode 100644
index 0000000000..21f0035a18
--- /dev/null
+++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperLeona.java
@@ -0,0 +1,203 @@
+/*
+ * 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.EtisVanEtinaSolo;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.enums.ChatType;
+import org.l2jmobius.gameserver.geoengine.GeoEngine;
+import org.l2jmobius.gameserver.model.Location;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.World;
+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.FriendlyNpcInstance;
+import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureAttacked;
+import org.l2jmobius.gameserver.model.events.impl.instance.OnInstanceStatusChange;
+import org.l2jmobius.gameserver.model.instancezone.Instance;
+import org.l2jmobius.gameserver.network.NpcStringId;
+
+import ai.AbstractNpcAI;
+
+/**
+ * Etina Helper Leona AI.
+ * @author CostyKiller
+ */
+public class EtinaHelperLeona extends AbstractNpcAI
+{
+ // NPCs
+ private static final int ETINA_HELPER_LEONA = 34471;
+ private static final int[] NOT_ATK_NPCS =
+ {
+ 33798, // Common Decoration - Barricade
+ 19677, // Seal of Gnosis
+ 19678, // Seal of Strife
+ 19679, // Seal of Avarice
+ 19680, // Seal of Punishment
+ 19681, // Seal of Awakening
+ 19682, // Seal of Calamity
+ 19683, // Seal of Destruction
+ };
+ private static final int[] ETINA_HELPERS =
+ {
+ 34471, // Leona Blackbird
+ 34472, // Devianne
+ 34473, // Elikia
+ 34474, // Sporcha
+ 34475, // Aliber
+ };
+ // RB
+ private static final int ETIS_VAN_ETINA1 = 26321;
+ private static final int ETIS_VAN_ETINA2 = 26322;
+ private static final int KAIN_VAN_HALTER = 26235;
+ private static final int CAMILLE = 26236;
+ // Misc
+ private static final int[] ETINA_SOLO_INSTANCES =
+ {
+ 292, // Fall of Etina (Solo)
+ 293, // Fall of Etina (Solo)
+ };
+
+ private EtinaHelperLeona()
+ {
+ setCreatureAttackedId(this::onCreatureAttacked, ETINA_HELPER_LEONA);
+ addSpellFinishedId(ETINA_HELPER_LEONA);
+ addSeeCreatureId(ETINA_HELPER_LEONA);
+ setInstanceStatusChangeId(this::onInstanceStatusChange, ETINA_SOLO_INSTANCES);
+ }
+
+ @Override
+ public void onTimerEvent(String event, StatSet params, Npc npc, PlayerInstance player)
+ {
+ final Instance instance = npc.getInstanceWorld();
+ if ((instance != null) && event.equals("CHECK_ACTION"))
+ {
+ final StatSet npcVars = npc.getVariables();
+ final PlayerInstance plr = npcVars.getObject("PLAYER_OBJECT", PlayerInstance.class);
+ final MonsterInstance monster = getRandomEntry(World.getInstance().getVisibleObjectsInRange(npc, MonsterInstance.class, 2500));
+ if (plr != null)
+ {
+ final double distance = npc.calculateDistance2D(plr);
+ if (!npc.isAttackingNow() && !npc.isMoving() && (distance > 250))
+ {
+ final Location loc = new Location(plr.getX(), plr.getY(), plr.getZ() + 50);
+ final Location randLoc = new Location(loc.getX() + getRandom(-100, 100), loc.getY() + getRandom(-100, 100), loc.getZ());
+ if (distance > 600)
+ {
+ npc.teleToLocation(loc);
+ }
+ else
+ {
+ npc.setRunning();
+ }
+ addMoveToDesire(npc, randLoc, 23);
+ ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
+ }
+ else if (!npc.isInCombat() || !npc.isAttackingNow() || (npc.getTarget() == null))
+ {
+ WorldObject target = npc.getTarget();
+ if (target == null)
+ {
+ npc.setTarget(monster);
+ }
+ if ((target != null) && !target.isInvul() && target.isTargetable() && GeoEngine.getInstance().canSeeTarget(npc, target) && !CommonUtil.contains(NOT_ATK_NPCS, target.getId()) && !CommonUtil.contains(ETINA_HELPERS, target.getId()))
+ {
+ npc.setInvul(true);
+ npc.setRunning();
+ ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
+ addAttackDesire(npc, (Creature) target);
+ // npc.reduceCurrentHp(1, monster, null);
+ }
+ }
+ }
+ }
+ }
+
+ public void onCreatureAttacked(OnCreatureAttacked event)
+ {
+ final FriendlyNpcInstance npc = (FriendlyNpcInstance) event.getTarget();
+ final Npc attacker = (Npc) event.getAttacker();
+ if (npc != null)
+ {
+ final Instance instance = npc.getInstanceWorld();
+ if ((instance != null) && !event.getAttacker().isPlayable() && !CommonUtil.contains(ETINA_HELPERS, event.getAttacker().getId()))
+ {
+ if (!npc.isInCombat())
+ {
+ switch (attacker.getId())
+ {
+ default:
+ {
+ if (getRandom(50) < 5)
+ {
+ npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.DON_T_GET_IN_MY_WAY);
+ }
+ break;
+ }
+ case CAMILLE:
+ {
+ npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.GISELLE_NO_IS_SHE_CAMILLE_IN_THAT_STATE);
+ break;
+ }
+ case KAIN_VAN_HALTER:
+ {
+ break;
+ }
+ case ETIS_VAN_ETINA1:
+ {
+ npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.EVEN_THE_MIGHTY_ETINA_SEEMS_TO_FEAR_US);
+ break;
+ }
+ case ETIS_VAN_ETINA2:
+ {
+ npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.ETIS_VAN_ETINA_WE_FINALLY_MEET);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void onInstanceStatusChange(OnInstanceStatusChange event)
+ {
+ final Instance instance = event.getWorld();
+ final int status = event.getStatus();
+ if ((status == 1) || (status == 2) || (status == 3))
+ {
+ instance.getAliveNpcs(ETINA_HELPER_LEONA).forEach(etinaHelperLeona -> getTimers().addRepeatingTimer("CHECK_ACTION", 3000, etinaHelperLeona, null));
+ // instance.getAliveNpcs(ETINA_HELPER_LEONA).forEach(etinaHelperLeona -> getTimers().addRepeatingTimer("USE_SKILL", 6000, etinaHelperLeona, null));
+ }
+ }
+
+ @Override
+ public String onSeeCreature(Npc npc, Creature creature, boolean isSummon)
+ {
+ if (creature.isPlayer())
+ {
+ npc.getVariables().set("PLAYER_OBJECT", creature.getActingPlayer());
+ }
+ return super.onSeeCreature(npc, creature, isSummon);
+ }
+
+ public static void main(String[] args)
+ {
+ new EtinaHelperLeona();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperSporcha.java b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperSporcha.java
new file mode 100644
index 0000000000..929fbe07ce
--- /dev/null
+++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperSporcha.java
@@ -0,0 +1,170 @@
+/*
+ * 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.EtisVanEtinaSolo;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.enums.ChatType;
+import org.l2jmobius.gameserver.geoengine.GeoEngine;
+import org.l2jmobius.gameserver.model.Location;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.World;
+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.FriendlyNpcInstance;
+import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureAttacked;
+import org.l2jmobius.gameserver.model.events.impl.instance.OnInstanceStatusChange;
+import org.l2jmobius.gameserver.model.instancezone.Instance;
+import org.l2jmobius.gameserver.network.NpcStringId;
+
+import ai.AbstractNpcAI;
+
+/**
+ * Etina Helper Sporcha AI.
+ * @author CostyKiller
+ */
+public class EtinaHelperSporcha extends AbstractNpcAI
+{
+ // NPCs
+ private static final int ETINA_HELPER_SPORCHA = 34474;
+ private static final int[] NOT_ATK_NPCS =
+ {
+ 33798, // Common Decoration - Barricade
+ 19677, // Seal of Gnosis
+ 19678, // Seal of Strife
+ 19679, // Seal of Avarice
+ 19680, // Seal of Punishment
+ 19681, // Seal of Awakening
+ 19682, // Seal of Calamity
+ 19683, // Seal of Destruction
+ };
+ private static final int[] ETINA_HELPERS =
+ {
+ 34471, // Leona Blackbird
+ 34472, // Devianne
+ 34473, // Elikia
+ 34474, // Sporcha
+ 34475, // Aliber
+ };
+ // Misc
+ private static final int[] ETINA_SOLO_INSTANCES =
+ {
+ 292, // Fall of Etina (Solo)
+ 293, // Fall of Etina (Solo)
+ };
+
+ private EtinaHelperSporcha()
+ {
+ setCreatureAttackedId(this::onCreatureAttacked, ETINA_HELPER_SPORCHA);
+ addSpellFinishedId(ETINA_HELPER_SPORCHA);
+ addSeeCreatureId(ETINA_HELPER_SPORCHA);
+ setInstanceStatusChangeId(this::onInstanceStatusChange, ETINA_SOLO_INSTANCES);
+ }
+
+ @Override
+ public void onTimerEvent(String event, StatSet params, Npc npc, PlayerInstance player)
+ {
+ final Instance instance = npc.getInstanceWorld();
+ if ((instance != null) && event.equals("CHECK_ACTION"))
+ {
+ final StatSet npcVars = npc.getVariables();
+ final PlayerInstance plr = npcVars.getObject("PLAYER_OBJECT", PlayerInstance.class);
+ final MonsterInstance monster = getRandomEntry(World.getInstance().getVisibleObjectsInRange(npc, MonsterInstance.class, 2500));
+ if (plr != null)
+ {
+ final double distance = npc.calculateDistance2D(plr);
+ if (!npc.isAttackingNow() && !npc.isMoving() && (distance > 250))
+ {
+ final Location loc = new Location(plr.getX(), plr.getY(), plr.getZ() + 50);
+ final Location randLoc = new Location(loc.getX() + getRandom(-100, 100), loc.getY() + getRandom(-100, 100), loc.getZ());
+ if (distance > 600)
+ {
+ npc.teleToLocation(loc);
+ }
+ else
+ {
+ npc.setRunning();
+ }
+ addMoveToDesire(npc, randLoc, 23);
+ ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
+ }
+ else if (!npc.isInCombat() || !npc.isAttackingNow() || (npc.getTarget() == null))
+ {
+ WorldObject target = npc.getTarget();
+ if (target == null)
+ {
+ npc.setTarget(monster);
+ }
+ if ((target != null) && !target.isInvul() && target.isTargetable() && GeoEngine.getInstance().canSeeTarget(npc, target) && !CommonUtil.contains(NOT_ATK_NPCS, target.getId()) && !CommonUtil.contains(ETINA_HELPERS, target.getId()))
+ {
+ npc.setInvul(true);
+ npc.setRunning();
+ ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
+ addAttackDesire(npc, (Creature) target);
+ // npc.reduceCurrentHp(1, monster, null);
+ }
+ }
+ }
+ }
+ }
+
+ public void onCreatureAttacked(OnCreatureAttacked event)
+ {
+ final FriendlyNpcInstance npc = (FriendlyNpcInstance) event.getTarget();
+ if (npc != null)
+ {
+ final Instance instance = npc.getInstanceWorld();
+ if ((instance != null) && !event.getAttacker().isPlayable() && !CommonUtil.contains(ETINA_HELPERS, event.getAttacker().getId()))
+ {
+ if (!npc.isInCombat())
+ {
+ if (getRandom(50) < 5)
+ {
+ npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.DON_T_GET_IN_MY_WAY);
+ }
+ }
+ }
+ }
+ }
+
+ public void onInstanceStatusChange(OnInstanceStatusChange event)
+ {
+ final Instance instance = event.getWorld();
+ final int status = event.getStatus();
+ if ((status == 1) || (status == 2) || (status == 3))
+ {
+ instance.getAliveNpcs(ETINA_HELPER_SPORCHA).forEach(etinaHelperSporcha -> getTimers().addRepeatingTimer("CHECK_ACTION", 3000, etinaHelperSporcha, null));
+ }
+ }
+
+ @Override
+ public String onSeeCreature(Npc npc, Creature creature, boolean isSummon)
+ {
+ if (creature.isPlayer())
+ {
+ npc.getVariables().set("PLAYER_OBJECT", creature.getActingPlayer());
+ }
+ return super.onSeeCreature(npc, creature, isSummon);
+ }
+
+ public static void main(String[] args)
+ {
+ new EtinaHelperSporcha();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtisVanEtinaSolo.java b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtisVanEtinaSolo.java
new file mode 100644
index 0000000000..8f1db0d8d6
--- /dev/null
+++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtisVanEtinaSolo.java
@@ -0,0 +1,723 @@
+/*
+ * 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.EtisVanEtinaSolo;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.enums.ChatType;
+import org.l2jmobius.gameserver.enums.Movie;
+import org.l2jmobius.gameserver.model.World;
+import org.l2jmobius.gameserver.model.actor.Attackable;
+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.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.instancezone.Instance;
+import org.l2jmobius.gameserver.model.skills.AbnormalVisualEffect;
+import org.l2jmobius.gameserver.network.NpcStringId;
+import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
+import org.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
+
+import instances.AbstractInstance;
+
+/**
+ * @author CostyKiller
+ * @URL: https://l2wiki.com/Fall_of_Etina_(Solo)
+ * @URL: https://youtu.be/3flFpg0KGcA
+ * @TODO: Add helper npcs skills
+ * @TODO: Add instance buff Elikia Emblem
+ */
+public class EtisVanEtinaSolo extends AbstractInstance
+{
+ // NPC
+ private static final int LEONA_OUTLET = 34426;
+ private static final int LEONA_BLACKBIRD = 34471;
+ private static final int DEVIANNE = 34472;
+ private static final int ELIKIA = 34473;
+ private static final int SPORCHA = 34474;
+ private static final int ALIBER = 34475;
+ // RB
+ private static final int ETIS_VAN_ETINA1 = 26321;
+ private static final int ETIS_VAN_ETINA2 = 26322;
+ private static final int KAIN_VAN_HALTER = 26235;
+ private static final int CAMILLE = 26236;
+ // Corridor Mobs
+ //@formatter:off
+ private static final int[] CORRIDOR_MOBS_1 = {24173, 24174, 24175, 24176};
+ private static final int[] CORRIDOR_MOBS_2 = {24180, 24181, 24182, 24183};
+ private static final int[] CORRIDOR_MOBS_3 = {24184, 24185, 24186, 24187, 24188, 24189, 24190, 24191, 24192};
+ private static final int[] CORRIDOR_MOBS_4 = {24189, 24190, 24191, 24192};
+ //@formatter:on
+ private static final int PARAGON = 24193;
+ // Seals
+ private static final int SEAL_OF_GNOSIS = 19677;
+ private static final int SEAL_OF_STRIFE = 19678;
+ private static final int SEAL_OF_AVARICE = 19679;
+ private static final int SEAL_OF_PUNISHMENT = 19680;
+ private static final int SEAL_OF_AWAKENING = 19681;
+ private static final int SEAL_OF_CALAMITY = 19682;
+ private static final int SEAL_OF_DESTRUCTION = 19683;
+ // Others
+ private static final int DOOR1 = 12230702;
+ private static final int DOOR2 = 12230704;
+ private static final int DOOR3 = 12230802;
+ private static final int DOOR4 = 12230804;
+ // Skills
+ private static final SkillHolder CALL_OF_SEVEN_SIGNS = new SkillHolder(32317, 1);
+ private static final SkillHolder CALL_OF_SEVEN_SIGNS_SEAL_N = new SkillHolder(32004, 1);
+ private static final SkillHolder ETINA_REVELATION = new SkillHolder(32014, 2);
+ private static final SkillHolder STIGMA_OF_REVELATION = new SkillHolder(32015, 1);
+ private static final SkillHolder CRY_OF_HOLY_WAR = new SkillHolder(32017, 2);
+ private static final SkillHolder STIGMA_OF_MARTYR = new SkillHolder(32018, 1);
+ private static final SkillHolder UNDEAD_CREATURE = new SkillHolder(32020, 2);
+ private static final SkillHolder ETINA_DIVINE_PUNISHMENT = new SkillHolder(32023, 2);
+ private static final SkillHolder ETINA_OBSERVATION = new SkillHolder(32024, 2);
+ private static final SkillHolder RAGE_OF_THE_OPEN_EYE = new SkillHolder(32026, 2);
+
+ // Camille -> Horseshoe Trampling, Horizon Bash, Joust Lunge, Call of Etina (summon minions?)
+ // Misc
+ private static final int TEMPLATE_ID = 293;
+
+ public EtisVanEtinaSolo()
+ {
+ super(TEMPLATE_ID);
+ addInstanceCreatedId(TEMPLATE_ID);
+ addStartNpc(LEONA_OUTLET);
+ addTalkId(LEONA_OUTLET, LEONA_BLACKBIRD);
+ addFirstTalkId(LEONA_BLACKBIRD, DEVIANNE, ELIKIA, SPORCHA, ALIBER);
+ addAttackId(CORRIDOR_MOBS_1);
+ addAttackId(CORRIDOR_MOBS_2);
+ addAttackId(CORRIDOR_MOBS_3);
+ addAttackId(CORRIDOR_MOBS_4);
+ addAttackId(CAMILLE, KAIN_VAN_HALTER, ETIS_VAN_ETINA1, ETIS_VAN_ETINA2);
+ addKillId(CORRIDOR_MOBS_1);
+ addKillId(CORRIDOR_MOBS_2);
+ addKillId(CORRIDOR_MOBS_3);
+ addKillId(CORRIDOR_MOBS_4);
+ addKillId(PARAGON, CAMILLE, KAIN_VAN_HALTER, ETIS_VAN_ETINA1, ETIS_VAN_ETINA2);
+ }
+
+ @Override
+ public void onInstanceCreated(Instance world, PlayerInstance player)
+ {
+ world.setStatus(0);
+ world.getParameters().set("BARRICADE_DESTROYED", false);
+ world.getParameters().set("CORRIDOR_MOBS_1_SPAWNED", false);
+ world.getParameters().set("CORRIDOR_MOBS_2_SPAWNED", false);
+ world.getParameters().set("CORRIDOR_MOBS_3_SPAWNED", false);
+ world.getParameters().set("CORRIDOR_MOBS_4_SPAWNED", false);
+ world.getParameters().set("CAMILLE_30", false);
+ world.getParameters().set("CAMILLE_60", false);
+ world.getParameters().set("KAIN_30", false);
+ world.getParameters().set("KAIN_60", false);
+ world.getParameters().set("ETINA_80", false);
+ world.getParameters().set("ETINA_15", false);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "enterInstance":
+ {
+ playMovie(player, Movie.EP5_ETINA_QST_START_A);
+ startQuestTimer("enterEtina", 20000, npc, player);
+ startQuestTimer("intro_movie", 20000, npc, player);
+ startQuestTimer("talkLeona", 25000, npc, player);
+ break;
+ }
+ case "enterEtina":
+ {
+ enterInstance(player, npc, TEMPLATE_ID);
+ break;
+ }
+ case "intro_movie":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ playMovie(world.getPlayers(), Movie.EP5_ETINA_QST_START_B);
+ }
+ break;
+ }
+ case "talkLeona":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ showOnScreenMsg(world, NpcStringId.TALK_TO_LEONA_BLACKBIRD_13, ExShowScreenMessage.TOP_CENTER, 10000, true);
+ }
+ break;
+ }
+ case "startStage1":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ showOnScreenMsg(world, NpcStringId.ALRIGHT_LET_S_GO_DEFEAT_ETIS_VAN_ETINA, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ startQuestTimer("checkProgress", 5000, npc, player, true);
+ world.setStatus(1);
+ return "34471-01.html";
+ }
+ break;
+ }
+ case "checkProgress":
+ {
+ final Instance world = player.getInstanceWorld();
+ boolean CORRIDOR_MOBS_1_SPAWNED = world.getParameters().getBoolean("CORRIDOR_MOBS_1_SPAWNED", false);
+ boolean CORRIDOR_MOBS_2_SPAWNED = world.getParameters().getBoolean("CORRIDOR_MOBS_2_SPAWNED", false);
+ boolean CORRIDOR_MOBS_3_SPAWNED = world.getParameters().getBoolean("CORRIDOR_MOBS_3_SPAWNED", false);
+ boolean CORRIDOR_MOBS_4_SPAWNED = world.getParameters().getBoolean("CORRIDOR_MOBS_4_SPAWNED", false);
+ if (isInInstance(world))
+ {
+ final MonsterInstance monsterCheck = getRandomEntry(World.getInstance().getVisibleObjectsInRange(npc, MonsterInstance.class, 2500));
+ if (monsterCheck == null)
+ {
+ if (!world.getNpcsOfGroup("BARRICADES_2").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_1).isEmpty() && world.getNpcsOfGroup("BARRICADES_1").isEmpty())
+ {
+ world.getParameters().set("BARRICADE_DESTROYED", false);
+ }
+ else if (!world.getNpcsOfGroup("BARRICADES_3").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_2).isEmpty() && world.getNpcsOfGroup("BARRICADES_2").isEmpty())
+ {
+ world.getParameters().set("BARRICADE_DESTROYED", false);
+ }
+ else if (!world.getNpcsOfGroup("BARRICADES_4").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_3).isEmpty() && world.getNpcsOfGroup("BARRICADES_3").isEmpty())
+ {
+ world.getParameters().set("BARRICADE_DESTROYED", false);
+ }
+ }
+ if (!CORRIDOR_MOBS_1_SPAWNED && world.getNpcsOfGroup("BARRICADES_1").isEmpty() && !world.getNpcsOfGroup("BARRICADES_2").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_1).isEmpty())
+ {
+ world.spawnGroup("CORRIDOR_MOBS_1");
+ world.getNpcsOfGroup("CORRIDOR_MOBS_1").forEach(mob ->
+ {
+ if (mob != null)
+ {
+ mob.setRandomWalking(false);
+ }
+ });
+ world.getParameters().set("CORRIDOR_MOBS_1_SPAWNED", true);
+ }
+ if (!CORRIDOR_MOBS_2_SPAWNED && world.getNpcsOfGroup("BARRICADES_2").isEmpty() && !world.getNpcsOfGroup("BARRICADES_3").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_2).isEmpty())
+ {
+ world.spawnGroup("CORRIDOR_MOBS_2");
+ world.getNpcsOfGroup("CORRIDOR_MOBS_2").forEach(mob ->
+ {
+ if (mob != null)
+ {
+ mob.setRandomWalking(false);
+ }
+ });
+ world.getParameters().set("CORRIDOR_MOBS_2_SPAWNED", true);
+ }
+ if (!CORRIDOR_MOBS_3_SPAWNED && world.getNpcsOfGroup("BARRICADES_3").isEmpty() && !world.getNpcsOfGroup("BARRICADES_4").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_3).isEmpty())
+ {
+ world.spawnGroup("CORRIDOR_MOBS_3");
+ world.getNpcsOfGroup("CORRIDOR_MOBS_3").forEach(mob ->
+ {
+ if (mob != null)
+ {
+ mob.setRandomWalking(false);
+ }
+ });
+ world.getParameters().set("CORRIDOR_MOBS_3_SPAWNED", true);
+ }
+ if (!CORRIDOR_MOBS_4_SPAWNED && world.getNpcsOfGroup("BARRICADES_4").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_4).isEmpty())
+ {
+ world.spawnGroup("CORRIDOR_MOBS_4");
+ world.spawnGroup("PARAGON");
+ world.getParameters().set("CORRIDOR_MOBS_4_SPAWNED", true);
+ world.getNpcsOfGroup("CORRIDOR_MOBS_4").forEach(mob ->
+ {
+ if (mob != null)
+ {
+ mob.setRandomWalking(false);
+ }
+ });
+ if (world.getNpc(PARAGON) != null)
+ {
+ world.getNpc(PARAGON).setInvul(true);
+ world.getNpc(PARAGON).getEffectList().startAbnormalVisualEffect(AbnormalVisualEffect.INVINCIBILITY);
+ }
+ npc.broadcastPacket(new ExShowScreenMessage(NpcStringId.YOU_CAN_T_DEFEAT_PARAGON_WHILE_PARAGON_S_MINIONS_ARE_ALIVE, ExShowScreenMessage.TOP_CENTER, 7000, true));
+ }
+ if (world.getNpcsOfGroup("BARRICADES_4").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_4).isEmpty())
+ {
+ if ((world.getNpc(PARAGON) != null) && world.getNpc(PARAGON).isInvul())
+ {
+ world.getNpc(PARAGON).setInvul(false);
+ world.getNpc(PARAGON).getEffectList().stopAbnormalVisualEffect(AbnormalVisualEffect.INVINCIBILITY);
+ showOnScreenMsg(world, NpcStringId.PARAGON_IS_NO_LONGER_INVINCIBLE, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.TODAY_IS_THE_DAY_THAT_I_WILL_ENTER);
+ }
+ }
+ if ((world.getStatus() == 1) && world.getNpcsOfGroup("BARRICADES_4").isEmpty() && (world.getAliveNpcs(PARAGON).isEmpty()))
+ {
+ startQuestTimer("openInnerDoors", 5000, null, player);
+ cancelQuestTimer("checkProgress", npc, player);
+ }
+ }
+ break;
+ }
+ case "openInnerDoors":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ openDoor(DOOR1, world.getId());
+ openDoor(DOOR2, world.getId());
+ openDoor(DOOR3, world.getId());
+ openDoor(DOOR4, world.getId());
+ world.setStatus(2);
+ startQuestTimer("talkLeona", 5000, null, player);
+ }
+ break;
+ }
+ case "startStage2":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ startQuestTimer("show_intro_movie_camille", 5000, null, player);
+ return "34471-03.html";
+ }
+ break;
+ }
+ case "show_intro_movie_camille":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ playMovie(world.getPlayers(), Movie.SC_INZONE_CAMILLE_INTRO);
+ startQuestTimer("spawn_camille", 5000, null, player);
+ }
+ break;
+ }
+ case "spawn_camille":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ closeDoor(DOOR1, world.getId());
+ closeDoor(DOOR2, world.getId());
+ closeDoor(DOOR3, world.getId());
+ closeDoor(DOOR4, world.getId());
+ world.setStatus(3);
+ world.spawnGroup("CAMILLE");
+ world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.GISELLE_NO_IS_SHE_CAMILLE_IN_THAT_STATE);
+ }
+ break;
+ }
+ case "spawn_kain":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ world.spawnGroup("KAIN");
+ world.spawnGroup("ETINA_1");
+ world.getNpc(ETIS_VAN_ETINA1).setInvul(true);
+ world.getNpc(ETIS_VAN_ETINA1).setTargetable(false);
+ world.getNpc(ETIS_VAN_ETINA1).setImmobilized(true);
+ showOnScreenMsg(world, NpcStringId.ETIS_VAN_ETINA_AND_HIS_APOSTLES_HAVE_APPEARED, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.EVEN_THE_MIGHTY_ETINA_SEEMS_TO_FEAR_US);
+ }
+ break;
+ }
+ case "spawnTransformedEtina":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ world.spawnGroup("ETINA_2");
+ world.spawnGroup("ETINA_MINIONS");
+ world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.ETIS_VAN_ETINA_WE_FINALLY_MEET);
+ }
+ break;
+ }
+ case "gnosisCastTimer":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ final Npc _sealOfGnosis = world.getNpc(SEAL_OF_GNOSIS);
+ _sealOfGnosis.setDisplayEffect(3);
+ _sealOfGnosis.broadcastPacket(new MagicSkillUse(_sealOfGnosis, _sealOfGnosis, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 1, 10000, 0));
+ PlayerInstance member = world.getPlayers().stream().findAny().get();
+ STIGMA_OF_REVELATION.getSkill().applyEffects(member, member);
+ world.getNpcsOfGroup("ETINA_MINIONS").forEach(minion ->
+ {
+ if (minion != null)
+ {
+ ETINA_REVELATION.getSkill().applyEffects(minion, minion);
+ ((Attackable) minion).addDamageHate(member, 0, 999999999);
+ }
+ });
+ showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_GNOSIS_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ }
+ break;
+ }
+ case "strifeCastTimer":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ final Npc _sealOfStrife = world.getNpc(SEAL_OF_STRIFE);
+ _sealOfStrife.setDisplayEffect(3);
+ _sealOfStrife.broadcastPacket(new MagicSkillUse(_sealOfStrife, _sealOfStrife, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 2, 10000, 0));
+ world.getNpcsOfGroup("ETINA_MINIONS").forEach(minion ->
+ {
+ if (minion != null)
+ {
+ CRY_OF_HOLY_WAR.getSkill().applyEffects(minion, minion);
+ }
+ });
+ world.getPlayers().forEach(plr -> STIGMA_OF_MARTYR.getSkill().applyEffects(player, player));
+ showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_STRIFE_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ }
+ break;
+ }
+ case "avariceCastTimer":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ final Npc _sealOfAvarice = world.getNpc(SEAL_OF_AVARICE);
+ _sealOfAvarice.setDisplayEffect(3);
+ _sealOfAvarice.broadcastPacket(new MagicSkillUse(_sealOfAvarice, _sealOfAvarice, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 3, 10000, 0));
+ world.getNpcsOfGroup("ETINA_MINIONS").forEach(minion ->
+ {
+ if (minion != null)
+ {
+ UNDEAD_CREATURE.getSkill().applyEffects(minion, minion);
+ }
+ });
+ showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_AVARICE_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ }
+ break;
+ }
+ case "punishmentCastTimer":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ final Npc _sealOfPunishment = world.getNpc(SEAL_OF_PUNISHMENT);
+ _sealOfPunishment.setDisplayEffect(3);
+ _sealOfPunishment.broadcastPacket(new MagicSkillUse(_sealOfPunishment, _sealOfPunishment, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 4, 10000, 0));
+ world.getNpcsOfGroup("ETINA_MINIONS").forEach(minion ->
+ {
+ if (minion != null)
+ {
+ ETINA_DIVINE_PUNISHMENT.getSkill().applyEffects(minion, minion);
+ }
+ });
+ world.getPlayers().forEach(plr -> ETINA_OBSERVATION.getSkill().applyEffects(player, player));
+ showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_PUNISHMENT_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ }
+ break;
+ }
+ case "awakeningCastTimer":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ final Npc _sealOfAwakening = world.getNpc(SEAL_OF_AWAKENING);
+ _sealOfAwakening.setDisplayEffect(3);
+ _sealOfAwakening.broadcastPacket(new MagicSkillUse(_sealOfAwakening, _sealOfAwakening, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 5, 10000, 0));
+ world.getNpcsOfGroup("ETINA_MINIONS").forEach(minion ->
+ {
+ if (minion != null)
+ {
+ RAGE_OF_THE_OPEN_EYE.getSkill().applyEffects(minion, minion);
+ }
+ });
+ showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_AWAKENING_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ }
+ break;
+ }
+ case "calamityCastTimer":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ final Npc _sealOfCalamity = world.getNpc(SEAL_OF_CALAMITY);
+ _sealOfCalamity.setDisplayEffect(3);
+ _sealOfCalamity.broadcastPacket(new MagicSkillUse(_sealOfCalamity, _sealOfCalamity, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 6, 10000, 0));
+ showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_CALAMITY_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ }
+ break;
+ }
+ case "destructionCastTimer":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ final Npc _sealOfDestruction = world.getNpc(SEAL_OF_DESTRUCTION);
+ _sealOfDestruction.setDisplayEffect(3);
+ _sealOfDestruction.broadcastPacket(new MagicSkillUse(_sealOfDestruction, _sealOfDestruction, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 7, 10000, 0));
+ showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_DESTRUCTION_IS_ACTIVATED_AND_ETINA_S_GRAND_TEMPLE_IS_NOW_UNDER_ITS_INFLUENCE, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon)
+ {
+ final Instance world = attacker.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ final boolean CAMILLE_30 = world.getParameters().getBoolean("CAMILLE_30", false);
+ final boolean CAMILLE_60 = world.getParameters().getBoolean("CAMILLE_60", false);
+ final boolean KAIN_30 = world.getParameters().getBoolean("KAIN_30", false);
+ final boolean KAIN_60 = world.getParameters().getBoolean("KAIN_60", false);
+ final boolean ETINA_80 = world.getParameters().getBoolean("ETINA_80", false);
+ final boolean ETINA_15 = world.getParameters().getBoolean("ETINA_15", false);
+ if (npc.getId() == CAMILLE)
+ {
+ if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.3)) && !CAMILLE_30)
+ {
+ world.getParameters().set("CAMILLE_30", true);
+ world.spawnGroup("CAMILLE_MINIONS");
+ }
+ else if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.6)) && !CAMILLE_60)
+ {
+ world.getParameters().set("CAMILLE_60", true);
+ world.spawnGroup("CAMILLE_MINIONS");
+ }
+ }
+ else if (npc.getId() == KAIN_VAN_HALTER)
+ {
+ if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.3)) && !KAIN_30)
+ {
+ world.getParameters().set("KAIN_30", true);
+ showOnScreenMsg(world, NpcStringId.ETIS_VAN_ETINA_SUMMONS_HIS_APOSTLES_MINIONS, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ world.spawnGroup("KAIN_MINIONS");
+ }
+ else if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.6)) && !KAIN_60)
+ {
+ world.getParameters().set("KAIN_60", true);
+ showOnScreenMsg(world, NpcStringId.ETIS_VAN_ETINA_SUMMONS_HIS_APOSTLES_MINIONS, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ world.spawnGroup("KAIN_MINIONS");
+ }
+ }
+ else if ((npc.getId() == ETIS_VAN_ETINA1))
+ {
+ if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.8)) && !ETINA_80)
+ {
+ final Npc _etina1 = world.getNpc(ETIS_VAN_ETINA1);
+ world.getParameters().set("ETINA_80", true);
+ world.spawnGroup("ETINA_MINIONS");
+ _etina1.abortCast();
+ _etina1.broadcastPacket(new MagicSkillUse(_etina1, _etina1, CALL_OF_SEVEN_SIGNS.getSkillId(), CALL_OF_SEVEN_SIGNS.getSkillLevel(), 3000, 0));
+ showOnScreenMsg(world, NpcStringId.ETIS_VAN_ETINA_USES_THE_POWER_OF_THE_SEVEN_SIGNS_TO_SUMMON_ALL_7_SEALS_INSIDE_THE_TEMPLE, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ world.spawnGroup("SEALS");
+ startQuestTimer("gnosisCastTimer", 120000, npc, attacker, true);
+ startQuestTimer("strifeCastTimer", 120000, npc, attacker, true);
+ startQuestTimer("avariceCastTimer", 120000, npc, attacker, true);
+ startQuestTimer("punishmentCastTimer", 120000, npc, attacker, true);
+ startQuestTimer("awakeningCastTimer", 120000, npc, attacker, true);
+ startQuestTimer("calamityCastTimer", 120000, npc, attacker, true);
+ startQuestTimer("destructionCastTimer", 120000, npc, attacker, true);
+ }
+ else if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.15)) && !ETINA_15)
+ {
+ world.getParameters().set("ETINA_15", true);
+ world.spawnGroup("ETINA_MINIONS");
+ showOnScreenMsg(world, NpcStringId.ETIS_VAN_ETINA_AND_THE_POWER_OF_SIX_SEALS_ARE_WEAKENING, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ }
+ }
+ }
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ @Override
+ public String onKill(Npc npc, PlayerInstance killer, boolean isPet)
+ {
+ final Instance world = npc.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ if (npc.getId() == ETIS_VAN_ETINA1)
+ {
+ playMovie(world.getPlayers(), Movie.SC_ETIS_VAN_ETINA_TRANS);
+ startQuestTimer("spawnTransformedEtina", 15000, null, killer);
+ }
+ else if (npc.getId() == ETIS_VAN_ETINA2)
+ {
+ playMovie(world.getPlayers(), Movie.SC_ETIS_VAN_ETINA_ENDING);
+ world.getAliveNpcs().forEach(mob ->
+ {
+ mob.deleteMe();
+ });
+ if (getQuestTimer("gnosisCastTimer", npc, killer) != null)
+ {
+ cancelQuestTimer("gnosisCastTimer", npc, killer);
+ }
+ if (getQuestTimer("trifeCastTimer", npc, killer) != null)
+ {
+ cancelQuestTimer("strifeCastTimer", npc, killer);
+ }
+ if (getQuestTimer("avariceCastTimer", npc, killer) != null)
+ {
+ cancelQuestTimer("avariceCastTimer", npc, killer);
+ }
+ if (getQuestTimer("punishmentCastTimer", npc, killer) != null)
+ {
+ cancelQuestTimer("punishmentCastTimer", npc, killer);
+ }
+ if (getQuestTimer("awakeningCastTimer", npc, killer) != null)
+ {
+ cancelQuestTimer("awakeningCastTimer", npc, killer);
+ }
+ if (getQuestTimer("calamityCastTimer", npc, killer) != null)
+ {
+ cancelQuestTimer("calamityCastTimer", npc, killer);
+ }
+ if (getQuestTimer("destructionCastTimer", npc, killer) != null)
+ {
+ cancelQuestTimer("destructionCastTimer", npc, killer);
+ }
+ closeDoor(DOOR1, world.getId());
+ closeDoor(DOOR2, world.getId());
+ closeDoor(DOOR3, world.getId());
+ closeDoor(DOOR4, world.getId());
+ world.finishInstance(2);
+ }
+ else if (CommonUtil.contains(CORRIDOR_MOBS_1, npc.getId()))
+ {
+ if (world.getAliveNpcs(CORRIDOR_MOBS_1).isEmpty())
+ {
+ world.getParameters().set("BARRICADE_DESTROYED", false);
+ }
+ }
+ else if (CommonUtil.contains(CORRIDOR_MOBS_2, npc.getId()))
+ {
+ if (world.getAliveNpcs(CORRIDOR_MOBS_2).isEmpty())
+ {
+ world.getParameters().set("BARRICADE_DESTROYED", false);
+ }
+ }
+ else if (CommonUtil.contains(CORRIDOR_MOBS_3, npc.getId()))
+ {
+ if (world.getAliveNpcs(CORRIDOR_MOBS_3).isEmpty())
+ {
+ world.getParameters().set("BARRICADE_DESTROYED", false);
+ }
+ }
+ else if (CommonUtil.contains(CORRIDOR_MOBS_4, npc.getId()))
+ {
+ if (world.getAliveNpcs(CORRIDOR_MOBS_4).isEmpty())
+ {
+ world.getNpc(PARAGON).setInvul(false);
+ world.getNpc(PARAGON).getEffectList().stopAbnormalVisualEffect(AbnormalVisualEffect.INVINCIBILITY);
+ showOnScreenMsg(world, NpcStringId.PARAGON_IS_NO_LONGER_INVINCIBLE, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.TODAY_IS_THE_DAY_THAT_I_WILL_ENTER);
+ }
+ }
+ else if (npc.getId() == PARAGON)
+ {
+ startQuestTimer("openInnerDoors", 5000, null, killer);
+ }
+ else if (npc.getId() == CAMILLE)
+ {
+ world.getNpcsOfGroup("CAMILLE_MINIONS").forEach(minion ->
+ {
+ if (minion != null)
+ {
+ minion.doDie(null);
+ }
+ });
+ world.getNpc(CAMILLE).deleteMe();
+ world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.KAIN_IS_OUR_ENEMY_NOW_BE_ON_GUARD);
+ playMovie(world.getPlayers(), Movie.SC_INZONE_KAIN_INTRO);
+ startQuestTimer("spawn_kain", 5000, null, killer);
+ }
+ else if (npc.getId() == KAIN_VAN_HALTER)
+ {
+ world.getNpcsOfGroup("KAIN_MINIONS").forEach(minion ->
+ {
+ if (minion != null)
+ {
+ minion.doDie(null);
+ }
+ });
+ world.getNpc(ETIS_VAN_ETINA1).setInvul(false);
+ world.getNpc(ETIS_VAN_ETINA1).setImmobilized(false);
+ world.getNpc(ETIS_VAN_ETINA1).setTargetable(true);
+ showOnScreenMsg(world, NpcStringId.ETIS_VAN_ETINA_APPROACHES, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ world.getNpc(KAIN_VAN_HALTER).deleteMe();
+ playMovie(world.getPlayers(), Movie.SC_KAIN_BOSS_ENDING);
+ world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.KAIN_I_WON_T_FEEL_GUILTY_ABOUT_THIS);
+ }
+ }
+ return super.onKill(npc, killer, isPet);
+ }
+
+ @Override
+ public String onFirstTalk(Npc npc, PlayerInstance player)
+ {
+ final Instance world = player.getInstanceWorld();
+ String htmltext = null;
+ if (isInInstance(world))
+ {
+ switch (npc.getId())
+ {
+ case DEVIANNE:
+ case ELIKIA:
+ case SPORCHA:
+ case ALIBER:
+ {
+ htmltext = npc.getId() + ".html";
+ break;
+ }
+ case LEONA_BLACKBIRD:
+ {
+ switch (world.getStatus())
+ {
+ case 0:
+ {
+ htmltext = "34471.htm";
+ break;
+ }
+ case 1:
+ {
+ htmltext = "34471-01.html";
+ break;
+ }
+ case 2:
+ {
+ htmltext = "34471-02.htm";
+ break;
+ }
+ case 3:
+ {
+ htmltext = "34471-03.html";
+ break;
+ }
+ }
+ }
+ }
+ }
+ return htmltext;
+ }
+
+ public static void main(String[] args)
+ {
+ new EtisVanEtinaSolo();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/condNoGroup.html b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/condNoGroup.html
new file mode 100644
index 0000000000..a34d6f3c14
--- /dev/null
+++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/condNoGroup.html
@@ -0,0 +1,3 @@
+Leona Blackbird:
+You can enter only solo.
+
\ No newline at end of file
diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/condNoLevel.html b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/condNoLevel.html
new file mode 100644
index 0000000000..5a53e17332
--- /dev/null
+++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/scripts/instances/EtisVanEtinaSolo/condNoLevel.html
@@ -0,0 +1,4 @@
+Leona Blackbird:
+I won't let you enter.
+(Only players between levels 104-130 may participate.)
+
\ No newline at end of file
diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/npcs/24100-24199.xml b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/npcs/24100-24199.xml
index 4421f21547..1fe8ac7fb3 100644
--- a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/npcs/24100-24199.xml
+++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/npcs/24100-24199.xml
@@ -2270,6 +2270,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2296,6 +2301,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2322,6 +2332,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2348,6 +2363,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2373,6 +2393,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2398,6 +2423,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2423,6 +2453,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2448,6 +2483,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2473,6 +2513,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2498,6 +2543,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2523,6 +2573,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2548,6 +2603,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2573,6 +2633,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2598,6 +2663,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2609,7 +2679,7 @@
-
+
HUMANOID
FEMALE
@@ -2622,6 +2692,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2634,7 +2709,7 @@
-
+
DEMONIC
MALE
@@ -2647,6 +2722,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -3102,6 +3182,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -3127,6 +3212,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -3152,6 +3242,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -3163,24 +3258,34 @@
-
-
+
ETC
FEMALE
-
+
+
+
-
-
-
+
+
+
+ ETINA_SOLO
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/npcs/26300-26399.xml b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/npcs/26300-26399.xml
index 4ea02626c1..050c98e131 100644
--- a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/npcs/26300-26399.xml
+++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/npcs/26300-26399.xml
@@ -509,43 +509,103 @@
-
-
- ETC
- FEMALE
+
+ HUMANOID
+ MALE
-
+
+
+
-
-
-
+
+
+
+ ETINA_SOLO
+
+
+
+
+
+
+
+
-
-
- ETC
- FEMALE
+
+ HUMANOID
+ MALE
+
-
+
+
+
-
-
-
+
+
+
+ ETINA_SOLO
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
DEMONIC
@@ -560,6 +620,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -585,6 +650,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -610,6 +680,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -635,6 +710,11 @@
+
+
+ ETINA_SOLO
+
+
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/instances/EtisVanEtinaSolo.xml b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/instances/EtisVanEtinaSolo.xml
new file mode 100644
index 0000000000..64f03d23d9
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/instances/EtisVanEtinaSolo.xml
@@ -0,0 +1,196 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-01.html b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-01.html
new file mode 100644
index 0000000000..3d860da0ab
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-01.html
@@ -0,0 +1,4 @@
+Blackbird Clan Lord Leona Blackbird:
+Let us defeat our enemies.
+Let's go to Etis van Etina, the Head of the Embryo, as fast as we can.
+
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-02.htm b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-02.htm
new file mode 100644
index 0000000000..7a02b2ead9
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-02.htm
@@ -0,0 +1,5 @@
+Blackbird Clan Lord Leona Blackbird:
+Thanks to you, we were able to come this far this time.
+But why is it so quiet? It can't be this empty...
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-03.html b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-03.html
new file mode 100644
index 0000000000..528abbaadb
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-03.html
@@ -0,0 +1,3 @@
+Blackbird Clan Lord Leona Blackbird:
+You don't have to worry ab- Ah! Oh no! What's that?
+
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471.htm b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471.htm
new file mode 100644
index 0000000000..fa5014df9f
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34471.htm
@@ -0,0 +1,5 @@
+Blackbird Clan Lord Leona Blackbird:
+This is the Great Etina Temple. Setting foot in this place again reminds me of old memories. I used my new power to sneak in so the enemy should be unaware of our presence.
+Now, let's take down the Embryos and Etis van Etina before they even realize. Are you ready?
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34472.html b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34472.html
new file mode 100644
index 0000000000..cbc5604977
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34472.html
@@ -0,0 +1,3 @@
+Devianne:
+Behold the power of the Ivory Tower Wizards!
+
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34473.html b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34473.html
new file mode 100644
index 0000000000..eef8b17456
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34473.html
@@ -0,0 +1,3 @@
+Elikia:
+Let's take down the Embryos and Etis van Etina before they even realize.
+
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34474.html b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34474.html
new file mode 100644
index 0000000000..9c0807c63a
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34474.html
@@ -0,0 +1,3 @@
+Sporcha:
+Are you ready to fight?
+
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34475.html b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34475.html
new file mode 100644
index 0000000000..ec99f9f6d0
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/34475.html
@@ -0,0 +1,3 @@
+Aliber:
+Rage against all that stands in our way!
+
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperAliber.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperAliber.java
new file mode 100644
index 0000000000..df86f9ab85
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperAliber.java
@@ -0,0 +1,283 @@
+/*
+ * 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.EtisVanEtinaSolo;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.ai.CtrlIntention;
+import org.l2jmobius.gameserver.enums.ChatType;
+import org.l2jmobius.gameserver.geoengine.GeoEngine;
+import org.l2jmobius.gameserver.model.Location;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.World;
+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.FriendlyNpcInstance;
+import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureAttacked;
+import org.l2jmobius.gameserver.model.events.impl.instance.OnInstanceStatusChange;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.instancezone.Instance;
+import org.l2jmobius.gameserver.network.NpcStringId;
+import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
+import org.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
+
+import ai.AbstractNpcAI;
+
+/**
+ * Etina Helper Aliber AI.
+ * @author CostyKiller
+ */
+public class EtinaHelperAliber extends AbstractNpcAI
+{
+ // NPCs
+ private static final int ETINA_HELPER_ALIBER = 34475;
+ // Corridor Mobs
+ //@formatter:off
+ private static final int[] CORRIDOR_MOBS_1 = {24173, 24174, 24175, 24176};
+ private static final int[] CORRIDOR_MOBS_2 = {24180, 24181, 24182, 24183};
+ private static final int[] CORRIDOR_MOBS_3 = {24184, 24185, 24186, 24187, 24188, 24189, 24190, 24191, 24192};
+ private static final int[] NOT_ATK_NPCS =
+ {
+ 33798, // Common Decoration - Barricade
+ 19677, // Seal of Gnosis
+ 19678, // Seal of Strife
+ 19679, // Seal of Avarice
+ 19680, // Seal of Punishment
+ 19681, // Seal of Awakening
+ 19682, // Seal of Calamity
+ 19683, // Seal of Destruction
+ };
+ private static final int[] ETINA_HELPERS =
+ {
+ 34471, // Leona Blackbird
+ 34472, // Devianne
+ 34473, // Elikia
+ 34474, // Sporcha
+ 34475, // Aliber
+ };
+ // Skill Cast Locations
+ private static final Location[] SKILL_CAST_LOCATIONS =
+ {
+ new Location(-245751, 182321, 2861, 16612), // First barricade line
+ new Location(-245751, 184001, 3025, 16612), // Second barricade line
+ new Location(-245751, 185298, 3031, 16612), // Third barricade line
+ new Location(-245751, 186612, 3038, 16612), // Fourth barricade line
+ };
+ // Support Npcs Skills
+ private static final SkillHolder BARRICADE_DESTRUCTION = new SkillHolder(32286, 1);
+ // Misc
+ private static final int[] ETINA_SOLO_INSTANCES =
+ {
+ 292, // Fall of Etina (Solo)
+ 293, // Fall of Etina (Solo)
+ };
+
+ private EtinaHelperAliber()
+ {
+ setCreatureAttackedId(this::onCreatureAttacked, ETINA_HELPER_ALIBER);
+ addSpellFinishedId(ETINA_HELPER_ALIBER);
+ addSeeCreatureId(ETINA_HELPER_ALIBER);
+ setInstanceStatusChangeId(this::onInstanceStatusChange, ETINA_SOLO_INSTANCES);
+ }
+
+ @Override
+ public void onTimerEvent(String event, StatSet params, Npc npc, PlayerInstance player)
+ {
+ final Instance instance = npc.getInstanceWorld();
+ if (instance != null)
+ {
+ switch (event)
+ {
+ case "CHECK_ACTION":
+ {
+ final StatSet npcVars = npc.getVariables();
+ final PlayerInstance plr = npcVars.getObject("PLAYER_OBJECT", PlayerInstance.class);
+ final MonsterInstance monster = getRandomEntry(World.getInstance().getVisibleObjectsInRange(npc, MonsterInstance.class, 2500));
+ if (plr != null)
+ {
+ final double distance = npc.calculateDistance2D(plr);
+ if (!npc.isAttackingNow() && !npc.isMoving() && (distance > 250))
+ {
+ final Location loc = new Location(plr.getX(), plr.getY(), plr.getZ() + 50);
+ final Location randLoc = new Location(loc.getX() + getRandom(-100, 100), loc.getY() + getRandom(-100, 100), loc.getZ());
+ if (distance > 600)
+ {
+ npc.teleToLocation(loc);
+ }
+ else
+ {
+ npc.setRunning();
+ }
+ addMoveToDesire(npc, randLoc, 23);
+ ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
+ }
+ else if (!npc.isInCombat() || !npc.isAttackingNow() || (npc.getTarget() == null))
+ {
+ WorldObject target = npc.getTarget();
+ if (target == null)
+ {
+ npc.setTarget(monster);
+ }
+ if ((target != null) && !target.isInvul() && target.isTargetable() && GeoEngine.getInstance().canSeeTarget(npc, target) && !CommonUtil.contains(NOT_ATK_NPCS, target.getId()) && !CommonUtil.contains(ETINA_HELPERS, target.getId()))
+ {
+ npc.setInvul(true);
+ npc.setRunning();
+ ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
+ addAttackDesire(npc, (Creature) target);
+ // addSkillCastDesire(npc, target, ALIBER_SPLASH, 23);
+ // npc.reduceCurrentHp(1, monster, null);
+ }
+ }
+ }
+ break;
+ }
+ case "DESTROY_BARRICADES":
+ {
+ final FriendlyNpcInstance _aliber = (FriendlyNpcInstance) instance.getNpc(ETINA_HELPER_ALIBER);
+ boolean BARRICADE_DESTROYED = instance.getParameters().getBoolean("BARRICADE_DESTROYED", false);
+ if (!instance.getNpcsOfGroup("BARRICADES_1").isEmpty())
+ {
+ _aliber.setRunning();
+ _aliber.setInvul(true);
+ _aliber.setCanReturnToSpawnPoint(false);
+ _aliber.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, SKILL_CAST_LOCATIONS[0]);
+ if (_aliber.getLocation().isIn2DRadius(SKILL_CAST_LOCATIONS[0], 200) && (BARRICADE_DESTROYED == false))
+ {
+ _aliber.broadcastPacket(new MagicSkillUse(_aliber, _aliber, BARRICADE_DESTRUCTION.getSkillId(), 1, 500, 0));
+ _aliber.broadcastPacket(new ExShowScreenMessage(NpcStringId.ALIBER_IS_CASTING_A_SPELL_TO_DESTROY_THE_BARRICADE, ExShowScreenMessage.TOP_CENTER, 7000, true));
+ instance.getNpcsOfGroup("BARRICADES_1").forEach(barricade ->
+ {
+ if (barricade != null)
+ {
+ barricade.decayMe();
+ }
+ });
+ instance.getParameters().set("BARRICADE_DESTROYED", true);
+ instance.despawnGroup("BARRICADES_1");
+ }
+ }
+ else if (!instance.getNpcsOfGroup("BARRICADES_2").isEmpty() && instance.getAliveNpcs(CORRIDOR_MOBS_1).isEmpty() && instance.getNpcsOfGroup("BARRICADES_1").isEmpty())
+ {
+ _aliber.setRunning();
+ _aliber.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, SKILL_CAST_LOCATIONS[1]);
+ if (_aliber.getLocation().isIn2DRadius(SKILL_CAST_LOCATIONS[1], 200) && (BARRICADE_DESTROYED == false))
+ {
+ _aliber.broadcastPacket(new MagicSkillUse(_aliber, _aliber, BARRICADE_DESTRUCTION.getSkillId(), 1, 500, 0));
+ _aliber.broadcastPacket(new ExShowScreenMessage(NpcStringId.ALIBER_IS_CASTING_A_SPELL_TO_DESTROY_THE_BARRICADE, ExShowScreenMessage.TOP_CENTER, 7000, true));
+ instance.getNpcsOfGroup("BARRICADES_2").forEach(barricade ->
+ {
+ if (barricade != null)
+ {
+ barricade.decayMe();
+ }
+ });
+ instance.getParameters().set("BARRICADE_DESTROYED", true);
+ instance.despawnGroup("BARRICADES_2");
+ }
+ }
+ else if (!instance.getNpcsOfGroup("BARRICADES_3").isEmpty() && instance.getAliveNpcs(CORRIDOR_MOBS_2).isEmpty() && instance.getNpcsOfGroup("BARRICADES_2").isEmpty())
+ {
+ _aliber.setRunning();
+ _aliber.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, SKILL_CAST_LOCATIONS[2]);
+ if (_aliber.getLocation().isIn2DRadius(SKILL_CAST_LOCATIONS[2], 200) && (BARRICADE_DESTROYED == false))
+ {
+ _aliber.broadcastPacket(new MagicSkillUse(_aliber, _aliber, BARRICADE_DESTRUCTION.getSkillId(), 1, 500, 0));
+ _aliber.broadcastPacket(new ExShowScreenMessage(NpcStringId.ALIBER_IS_CASTING_A_SPELL_TO_DESTROY_THE_BARRICADE, ExShowScreenMessage.TOP_CENTER, 7000, true));
+ instance.getNpcsOfGroup("BARRICADES_3").forEach(barricade ->
+ {
+ if (barricade != null)
+ {
+ barricade.decayMe();
+ }
+ });
+ instance.getParameters().set("BARRICADE_DESTROYED", true);
+ instance.despawnGroup("BARRICADES_3");
+ }
+ }
+ else if (!instance.getNpcsOfGroup("BARRICADES_4").isEmpty() && instance.getAliveNpcs(CORRIDOR_MOBS_3).isEmpty() && instance.getNpcsOfGroup("BARRICADES_3").isEmpty())
+ {
+ _aliber.setRunning();
+ _aliber.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, SKILL_CAST_LOCATIONS[3]);
+ if (_aliber.getLocation().isIn2DRadius(SKILL_CAST_LOCATIONS[3], 200) && (BARRICADE_DESTROYED == false))
+ {
+ _aliber.broadcastPacket(new MagicSkillUse(_aliber, _aliber, BARRICADE_DESTRUCTION.getSkillId(), 1, 500, 0));
+ _aliber.broadcastPacket(new ExShowScreenMessage(NpcStringId.ALIBER_IS_CASTING_A_SPELL_TO_DESTROY_THE_BARRICADE, ExShowScreenMessage.TOP_CENTER, 7000, true));
+ instance.getNpcsOfGroup("BARRICADES_4").forEach(barricade ->
+ {
+ if (barricade != null)
+ {
+ barricade.decayMe();
+ }
+ });
+ instance.getParameters().set("BARRICADE_DESTROYED", true);
+ instance.despawnGroup("BARRICADES_4");
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ public void onCreatureAttacked(OnCreatureAttacked event)
+ {
+ final FriendlyNpcInstance npc = (FriendlyNpcInstance) event.getTarget();
+ if (npc != null)
+ {
+ final Instance instance = npc.getInstanceWorld();
+ if ((instance != null) && !event.getAttacker().isPlayable() && !CommonUtil.contains(ETINA_HELPERS, event.getAttacker().getId()))
+ {
+ if (!npc.isInCombat())
+ {
+ if (getRandom(50) < 5)
+ {
+ npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.RAGE_AGAINST_ALL_THAT_STANDS_IN_OUR_WAY);
+ }
+ }
+ }
+ }
+ }
+
+ public void onInstanceStatusChange(OnInstanceStatusChange event)
+ {
+ final Instance instance = event.getWorld();
+ final int status = event.getStatus();
+ if ((status == 1) || (status == 2) || (status == 3))
+ {
+ instance.getAliveNpcs(ETINA_HELPER_ALIBER).forEach(etinaHelperAliber -> getTimers().addRepeatingTimer("CHECK_ACTION", 3000, etinaHelperAliber, null));
+ instance.getAliveNpcs(ETINA_HELPER_ALIBER).forEach(etinaHelperAliber -> getTimers().addRepeatingTimer("USE_SKILL", 6000, etinaHelperAliber, null));
+ instance.getAliveNpcs(ETINA_HELPER_ALIBER).forEach(etinaHelperAliber -> getTimers().addRepeatingTimer("DESTROY_BARRICADES", 5000, etinaHelperAliber, null));
+ }
+ }
+
+ @Override
+ public String onSeeCreature(Npc npc, Creature creature, boolean isSummon)
+ {
+ if (creature.isPlayer())
+ {
+ npc.getVariables().set("PLAYER_OBJECT", creature.getActingPlayer());
+ }
+ return super.onSeeCreature(npc, creature, isSummon);
+ }
+
+ public static void main(String[] args)
+ {
+ new EtinaHelperAliber();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperDevianne.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperDevianne.java
new file mode 100644
index 0000000000..258d606210
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperDevianne.java
@@ -0,0 +1,171 @@
+/*
+ * 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.EtisVanEtinaSolo;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.enums.ChatType;
+import org.l2jmobius.gameserver.geoengine.GeoEngine;
+import org.l2jmobius.gameserver.model.Location;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.World;
+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.FriendlyNpcInstance;
+import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureAttacked;
+import org.l2jmobius.gameserver.model.events.impl.instance.OnInstanceStatusChange;
+import org.l2jmobius.gameserver.model.instancezone.Instance;
+import org.l2jmobius.gameserver.network.NpcStringId;
+
+import ai.AbstractNpcAI;
+
+/**
+ * Etina Helper Devianne AI.
+ * @author CostyKiller
+ */
+public class EtinaHelperDevianne extends AbstractNpcAI
+{
+ // NPCs
+ private static final int ETINA_HELPER_DEVIANNE = 34472;
+ private static final int[] NOT_ATK_NPCS =
+ {
+ 33798, // Common Decoration - Barricade
+ 19677, // Seal of Gnosis
+ 19678, // Seal of Strife
+ 19679, // Seal of Avarice
+ 19680, // Seal of Punishment
+ 19681, // Seal of Awakening
+ 19682, // Seal of Calamity
+ 19683, // Seal of Destruction
+ };
+ private static final int[] ETINA_HELPERS =
+ {
+ 34471, // Leona Blackbird
+ 34472, // Devianne
+ 34473, // Elikia
+ 34474, // Sporcha
+ 34475, // Aliber
+ };
+ // Misc
+ private static final int[] ETINA_SOLO_INSTANCES =
+ {
+ 292, // Fall of Etina (Solo)
+ 293, // Fall of Etina (Solo)
+ };
+
+ private EtinaHelperDevianne()
+ {
+ setCreatureAttackedId(this::onCreatureAttacked, ETINA_HELPER_DEVIANNE);
+ addSpellFinishedId(ETINA_HELPER_DEVIANNE);
+ addSeeCreatureId(ETINA_HELPER_DEVIANNE);
+ setInstanceStatusChangeId(this::onInstanceStatusChange, ETINA_SOLO_INSTANCES);
+ }
+
+ @Override
+ public void onTimerEvent(String event, StatSet params, Npc npc, PlayerInstance player)
+ {
+ final Instance instance = npc.getInstanceWorld();
+ if ((instance != null) && event.equals("CHECK_ACTION"))
+ {
+ final StatSet npcVars = npc.getVariables();
+ final PlayerInstance plr = npcVars.getObject("PLAYER_OBJECT", PlayerInstance.class);
+ final MonsterInstance monster = getRandomEntry(World.getInstance().getVisibleObjectsInRange(npc, MonsterInstance.class, 2500));
+ if (plr != null)
+ {
+ final double distance = npc.calculateDistance2D(plr);
+ if (!npc.isAttackingNow() && !npc.isMoving() && (distance > 250))
+ {
+ final Location loc = new Location(plr.getX(), plr.getY(), plr.getZ() + 50);
+ final Location randLoc = new Location(loc.getX() + getRandom(-100, 100), loc.getY() + getRandom(-100, 100), loc.getZ());
+ if (distance > 600)
+ {
+ npc.teleToLocation(loc);
+ }
+ else
+ {
+ npc.setRunning();
+ }
+ addMoveToDesire(npc, randLoc, 23);
+ ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
+ }
+ else if (!npc.isInCombat() || !npc.isAttackingNow() || (npc.getTarget() == null))
+ {
+ WorldObject target = npc.getTarget();
+ if (target == null)
+ {
+ npc.setTarget(monster);
+ }
+ if ((target != null) && !target.isInvul() && target.isTargetable() && GeoEngine.getInstance().canSeeTarget(npc, target) && !CommonUtil.contains(NOT_ATK_NPCS, target.getId()) && !CommonUtil.contains(ETINA_HELPERS, target.getId()))
+ {
+ npc.setInvul(true);
+ npc.setRunning();
+ ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
+ addAttackDesire(npc, (Creature) target);
+ // npc.reduceCurrentHp(1, monster, null);
+ }
+ }
+ }
+ }
+ }
+
+ public void onCreatureAttacked(OnCreatureAttacked event)
+ {
+ final FriendlyNpcInstance npc = (FriendlyNpcInstance) event.getTarget();
+ if (npc != null)
+ {
+ final Instance instance = npc.getInstanceWorld();
+ if ((instance != null) && !event.getAttacker().isPlayable() && !CommonUtil.contains(ETINA_HELPERS, event.getAttacker().getId()))
+ {
+ if (!npc.isInCombat())
+ {
+ if (getRandom(50) < 5)
+ {
+ npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.BEHOLD_THE_POWER_OF_THE_IVORY_TOWER_WIZARDS);
+ }
+
+ }
+ }
+ }
+ }
+
+ public void onInstanceStatusChange(OnInstanceStatusChange event)
+ {
+ final Instance instance = event.getWorld();
+ final int status = event.getStatus();
+ if ((status == 1) || (status == 2) || (status == 3))
+ {
+ instance.getAliveNpcs(ETINA_HELPER_DEVIANNE).forEach(etinaHelperDevianne -> getTimers().addRepeatingTimer("CHECK_ACTION", 3000, etinaHelperDevianne, null));
+ }
+ }
+
+ @Override
+ public String onSeeCreature(Npc npc, Creature creature, boolean isSummon)
+ {
+ if (creature.isPlayer())
+ {
+ npc.getVariables().set("PLAYER_OBJECT", creature.getActingPlayer());
+ }
+ return super.onSeeCreature(npc, creature, isSummon);
+ }
+
+ public static void main(String[] args)
+ {
+ new EtinaHelperDevianne();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperElikia.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperElikia.java
new file mode 100644
index 0000000000..ff41fcd13e
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperElikia.java
@@ -0,0 +1,170 @@
+/*
+ * 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.EtisVanEtinaSolo;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.enums.ChatType;
+import org.l2jmobius.gameserver.geoengine.GeoEngine;
+import org.l2jmobius.gameserver.model.Location;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.World;
+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.FriendlyNpcInstance;
+import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureAttacked;
+import org.l2jmobius.gameserver.model.events.impl.instance.OnInstanceStatusChange;
+import org.l2jmobius.gameserver.model.instancezone.Instance;
+import org.l2jmobius.gameserver.network.NpcStringId;
+
+import ai.AbstractNpcAI;
+
+/**
+ * Etina Helper Elikia AI.
+ * @author CostyKiller
+ */
+public class EtinaHelperElikia extends AbstractNpcAI
+{
+ // NPCs
+ private static final int ETINA_HELPER_ELIKIA = 34473;
+ private static final int[] NOT_ATK_NPCS =
+ {
+ 33798, // Common Decoration - Barricade
+ 19677, // Seal of Gnosis
+ 19678, // Seal of Strife
+ 19679, // Seal of Avarice
+ 19680, // Seal of Punishment
+ 19681, // Seal of Awakening
+ 19682, // Seal of Calamity
+ 19683, // Seal of Destruction
+ };
+ private static final int[] ETINA_HELPERS =
+ {
+ 34471, // Leona Blackbird
+ 34472, // Devianne
+ 34473, // Elikia
+ 34474, // Sporcha
+ 34475, // Aliber
+ };
+ // Misc
+ private static final int[] ETINA_SOLO_INSTANCES =
+ {
+ 292, // Fall of Etina (Solo)
+ 293, // Fall of Etina (Solo)
+ };
+
+ private EtinaHelperElikia()
+ {
+ setCreatureAttackedId(this::onCreatureAttacked, ETINA_HELPER_ELIKIA);
+ addSpellFinishedId(ETINA_HELPER_ELIKIA);
+ addSeeCreatureId(ETINA_HELPER_ELIKIA);
+ setInstanceStatusChangeId(this::onInstanceStatusChange, ETINA_SOLO_INSTANCES);
+ }
+
+ @Override
+ public void onTimerEvent(String event, StatSet params, Npc npc, PlayerInstance player)
+ {
+ final Instance instance = npc.getInstanceWorld();
+ if ((instance != null) && event.equals("CHECK_ACTION"))
+ {
+ final StatSet npcVars = npc.getVariables();
+ final PlayerInstance plr = npcVars.getObject("PLAYER_OBJECT", PlayerInstance.class);
+ final MonsterInstance monster = getRandomEntry(World.getInstance().getVisibleObjectsInRange(npc, MonsterInstance.class, 2500));
+ if (plr != null)
+ {
+ final double distance = npc.calculateDistance2D(plr);
+ if (!npc.isAttackingNow() && !npc.isMoving() && (distance > 250))
+ {
+ final Location loc = new Location(plr.getX(), plr.getY(), plr.getZ() + 50);
+ final Location randLoc = new Location(loc.getX() + getRandom(-100, 100), loc.getY() + getRandom(-100, 100), loc.getZ());
+ if (distance > 600)
+ {
+ npc.teleToLocation(loc);
+ }
+ else
+ {
+ npc.setRunning();
+ }
+ addMoveToDesire(npc, randLoc, 23);
+ ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
+ }
+ else if (!npc.isInCombat() || !npc.isAttackingNow() || (npc.getTarget() == null))
+ {
+ WorldObject target = npc.getTarget();
+ if (target == null)
+ {
+ npc.setTarget(monster);
+ }
+ if ((target != null) && !target.isInvul() && target.isTargetable() && GeoEngine.getInstance().canSeeTarget(npc, target) && !CommonUtil.contains(NOT_ATK_NPCS, target.getId()) && !CommonUtil.contains(ETINA_HELPERS, target.getId()))
+ {
+ npc.setInvul(true);
+ npc.setRunning();
+ ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
+ addAttackDesire(npc, (Creature) target);
+ // npc.reduceCurrentHp(1, monster, null);
+ }
+ }
+ }
+ }
+ }
+
+ public void onCreatureAttacked(OnCreatureAttacked event)
+ {
+ final FriendlyNpcInstance npc = (FriendlyNpcInstance) event.getTarget();
+ if (npc != null)
+ {
+ final Instance instance = npc.getInstanceWorld();
+ if ((instance != null) && !event.getAttacker().isPlayable() && !CommonUtil.contains(ETINA_HELPERS, event.getAttacker().getId()))
+ {
+ if (!npc.isInCombat())
+ {
+ if (getRandom(50) < 5)
+ {
+ npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.DON_T_GET_IN_MY_WAY);
+ }
+ }
+ }
+ }
+ }
+
+ public void onInstanceStatusChange(OnInstanceStatusChange event)
+ {
+ final Instance instance = event.getWorld();
+ final int status = event.getStatus();
+ if ((status == 1) || (status == 2) || (status == 3))
+ {
+ instance.getAliveNpcs(ETINA_HELPER_ELIKIA).forEach(etinaHelperElikia -> getTimers().addRepeatingTimer("CHECK_ACTION", 3000, etinaHelperElikia, null));
+ }
+ }
+
+ @Override
+ public String onSeeCreature(Npc npc, Creature creature, boolean isSummon)
+ {
+ if (creature.isPlayer())
+ {
+ npc.getVariables().set("PLAYER_OBJECT", creature.getActingPlayer());
+ }
+ return super.onSeeCreature(npc, creature, isSummon);
+ }
+
+ public static void main(String[] args)
+ {
+ new EtinaHelperElikia();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperLeona.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperLeona.java
new file mode 100644
index 0000000000..21f0035a18
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperLeona.java
@@ -0,0 +1,203 @@
+/*
+ * 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.EtisVanEtinaSolo;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.enums.ChatType;
+import org.l2jmobius.gameserver.geoengine.GeoEngine;
+import org.l2jmobius.gameserver.model.Location;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.World;
+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.FriendlyNpcInstance;
+import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureAttacked;
+import org.l2jmobius.gameserver.model.events.impl.instance.OnInstanceStatusChange;
+import org.l2jmobius.gameserver.model.instancezone.Instance;
+import org.l2jmobius.gameserver.network.NpcStringId;
+
+import ai.AbstractNpcAI;
+
+/**
+ * Etina Helper Leona AI.
+ * @author CostyKiller
+ */
+public class EtinaHelperLeona extends AbstractNpcAI
+{
+ // NPCs
+ private static final int ETINA_HELPER_LEONA = 34471;
+ private static final int[] NOT_ATK_NPCS =
+ {
+ 33798, // Common Decoration - Barricade
+ 19677, // Seal of Gnosis
+ 19678, // Seal of Strife
+ 19679, // Seal of Avarice
+ 19680, // Seal of Punishment
+ 19681, // Seal of Awakening
+ 19682, // Seal of Calamity
+ 19683, // Seal of Destruction
+ };
+ private static final int[] ETINA_HELPERS =
+ {
+ 34471, // Leona Blackbird
+ 34472, // Devianne
+ 34473, // Elikia
+ 34474, // Sporcha
+ 34475, // Aliber
+ };
+ // RB
+ private static final int ETIS_VAN_ETINA1 = 26321;
+ private static final int ETIS_VAN_ETINA2 = 26322;
+ private static final int KAIN_VAN_HALTER = 26235;
+ private static final int CAMILLE = 26236;
+ // Misc
+ private static final int[] ETINA_SOLO_INSTANCES =
+ {
+ 292, // Fall of Etina (Solo)
+ 293, // Fall of Etina (Solo)
+ };
+
+ private EtinaHelperLeona()
+ {
+ setCreatureAttackedId(this::onCreatureAttacked, ETINA_HELPER_LEONA);
+ addSpellFinishedId(ETINA_HELPER_LEONA);
+ addSeeCreatureId(ETINA_HELPER_LEONA);
+ setInstanceStatusChangeId(this::onInstanceStatusChange, ETINA_SOLO_INSTANCES);
+ }
+
+ @Override
+ public void onTimerEvent(String event, StatSet params, Npc npc, PlayerInstance player)
+ {
+ final Instance instance = npc.getInstanceWorld();
+ if ((instance != null) && event.equals("CHECK_ACTION"))
+ {
+ final StatSet npcVars = npc.getVariables();
+ final PlayerInstance plr = npcVars.getObject("PLAYER_OBJECT", PlayerInstance.class);
+ final MonsterInstance monster = getRandomEntry(World.getInstance().getVisibleObjectsInRange(npc, MonsterInstance.class, 2500));
+ if (plr != null)
+ {
+ final double distance = npc.calculateDistance2D(plr);
+ if (!npc.isAttackingNow() && !npc.isMoving() && (distance > 250))
+ {
+ final Location loc = new Location(plr.getX(), plr.getY(), plr.getZ() + 50);
+ final Location randLoc = new Location(loc.getX() + getRandom(-100, 100), loc.getY() + getRandom(-100, 100), loc.getZ());
+ if (distance > 600)
+ {
+ npc.teleToLocation(loc);
+ }
+ else
+ {
+ npc.setRunning();
+ }
+ addMoveToDesire(npc, randLoc, 23);
+ ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
+ }
+ else if (!npc.isInCombat() || !npc.isAttackingNow() || (npc.getTarget() == null))
+ {
+ WorldObject target = npc.getTarget();
+ if (target == null)
+ {
+ npc.setTarget(monster);
+ }
+ if ((target != null) && !target.isInvul() && target.isTargetable() && GeoEngine.getInstance().canSeeTarget(npc, target) && !CommonUtil.contains(NOT_ATK_NPCS, target.getId()) && !CommonUtil.contains(ETINA_HELPERS, target.getId()))
+ {
+ npc.setInvul(true);
+ npc.setRunning();
+ ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
+ addAttackDesire(npc, (Creature) target);
+ // npc.reduceCurrentHp(1, monster, null);
+ }
+ }
+ }
+ }
+ }
+
+ public void onCreatureAttacked(OnCreatureAttacked event)
+ {
+ final FriendlyNpcInstance npc = (FriendlyNpcInstance) event.getTarget();
+ final Npc attacker = (Npc) event.getAttacker();
+ if (npc != null)
+ {
+ final Instance instance = npc.getInstanceWorld();
+ if ((instance != null) && !event.getAttacker().isPlayable() && !CommonUtil.contains(ETINA_HELPERS, event.getAttacker().getId()))
+ {
+ if (!npc.isInCombat())
+ {
+ switch (attacker.getId())
+ {
+ default:
+ {
+ if (getRandom(50) < 5)
+ {
+ npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.DON_T_GET_IN_MY_WAY);
+ }
+ break;
+ }
+ case CAMILLE:
+ {
+ npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.GISELLE_NO_IS_SHE_CAMILLE_IN_THAT_STATE);
+ break;
+ }
+ case KAIN_VAN_HALTER:
+ {
+ break;
+ }
+ case ETIS_VAN_ETINA1:
+ {
+ npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.EVEN_THE_MIGHTY_ETINA_SEEMS_TO_FEAR_US);
+ break;
+ }
+ case ETIS_VAN_ETINA2:
+ {
+ npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.ETIS_VAN_ETINA_WE_FINALLY_MEET);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void onInstanceStatusChange(OnInstanceStatusChange event)
+ {
+ final Instance instance = event.getWorld();
+ final int status = event.getStatus();
+ if ((status == 1) || (status == 2) || (status == 3))
+ {
+ instance.getAliveNpcs(ETINA_HELPER_LEONA).forEach(etinaHelperLeona -> getTimers().addRepeatingTimer("CHECK_ACTION", 3000, etinaHelperLeona, null));
+ // instance.getAliveNpcs(ETINA_HELPER_LEONA).forEach(etinaHelperLeona -> getTimers().addRepeatingTimer("USE_SKILL", 6000, etinaHelperLeona, null));
+ }
+ }
+
+ @Override
+ public String onSeeCreature(Npc npc, Creature creature, boolean isSummon)
+ {
+ if (creature.isPlayer())
+ {
+ npc.getVariables().set("PLAYER_OBJECT", creature.getActingPlayer());
+ }
+ return super.onSeeCreature(npc, creature, isSummon);
+ }
+
+ public static void main(String[] args)
+ {
+ new EtinaHelperLeona();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperSporcha.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperSporcha.java
new file mode 100644
index 0000000000..929fbe07ce
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperSporcha.java
@@ -0,0 +1,170 @@
+/*
+ * 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.EtisVanEtinaSolo;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.enums.ChatType;
+import org.l2jmobius.gameserver.geoengine.GeoEngine;
+import org.l2jmobius.gameserver.model.Location;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.World;
+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.FriendlyNpcInstance;
+import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureAttacked;
+import org.l2jmobius.gameserver.model.events.impl.instance.OnInstanceStatusChange;
+import org.l2jmobius.gameserver.model.instancezone.Instance;
+import org.l2jmobius.gameserver.network.NpcStringId;
+
+import ai.AbstractNpcAI;
+
+/**
+ * Etina Helper Sporcha AI.
+ * @author CostyKiller
+ */
+public class EtinaHelperSporcha extends AbstractNpcAI
+{
+ // NPCs
+ private static final int ETINA_HELPER_SPORCHA = 34474;
+ private static final int[] NOT_ATK_NPCS =
+ {
+ 33798, // Common Decoration - Barricade
+ 19677, // Seal of Gnosis
+ 19678, // Seal of Strife
+ 19679, // Seal of Avarice
+ 19680, // Seal of Punishment
+ 19681, // Seal of Awakening
+ 19682, // Seal of Calamity
+ 19683, // Seal of Destruction
+ };
+ private static final int[] ETINA_HELPERS =
+ {
+ 34471, // Leona Blackbird
+ 34472, // Devianne
+ 34473, // Elikia
+ 34474, // Sporcha
+ 34475, // Aliber
+ };
+ // Misc
+ private static final int[] ETINA_SOLO_INSTANCES =
+ {
+ 292, // Fall of Etina (Solo)
+ 293, // Fall of Etina (Solo)
+ };
+
+ private EtinaHelperSporcha()
+ {
+ setCreatureAttackedId(this::onCreatureAttacked, ETINA_HELPER_SPORCHA);
+ addSpellFinishedId(ETINA_HELPER_SPORCHA);
+ addSeeCreatureId(ETINA_HELPER_SPORCHA);
+ setInstanceStatusChangeId(this::onInstanceStatusChange, ETINA_SOLO_INSTANCES);
+ }
+
+ @Override
+ public void onTimerEvent(String event, StatSet params, Npc npc, PlayerInstance player)
+ {
+ final Instance instance = npc.getInstanceWorld();
+ if ((instance != null) && event.equals("CHECK_ACTION"))
+ {
+ final StatSet npcVars = npc.getVariables();
+ final PlayerInstance plr = npcVars.getObject("PLAYER_OBJECT", PlayerInstance.class);
+ final MonsterInstance monster = getRandomEntry(World.getInstance().getVisibleObjectsInRange(npc, MonsterInstance.class, 2500));
+ if (plr != null)
+ {
+ final double distance = npc.calculateDistance2D(plr);
+ if (!npc.isAttackingNow() && !npc.isMoving() && (distance > 250))
+ {
+ final Location loc = new Location(plr.getX(), plr.getY(), plr.getZ() + 50);
+ final Location randLoc = new Location(loc.getX() + getRandom(-100, 100), loc.getY() + getRandom(-100, 100), loc.getZ());
+ if (distance > 600)
+ {
+ npc.teleToLocation(loc);
+ }
+ else
+ {
+ npc.setRunning();
+ }
+ addMoveToDesire(npc, randLoc, 23);
+ ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
+ }
+ else if (!npc.isInCombat() || !npc.isAttackingNow() || (npc.getTarget() == null))
+ {
+ WorldObject target = npc.getTarget();
+ if (target == null)
+ {
+ npc.setTarget(monster);
+ }
+ if ((target != null) && !target.isInvul() && target.isTargetable() && GeoEngine.getInstance().canSeeTarget(npc, target) && !CommonUtil.contains(NOT_ATK_NPCS, target.getId()) && !CommonUtil.contains(ETINA_HELPERS, target.getId()))
+ {
+ npc.setInvul(true);
+ npc.setRunning();
+ ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
+ addAttackDesire(npc, (Creature) target);
+ // npc.reduceCurrentHp(1, monster, null);
+ }
+ }
+ }
+ }
+ }
+
+ public void onCreatureAttacked(OnCreatureAttacked event)
+ {
+ final FriendlyNpcInstance npc = (FriendlyNpcInstance) event.getTarget();
+ if (npc != null)
+ {
+ final Instance instance = npc.getInstanceWorld();
+ if ((instance != null) && !event.getAttacker().isPlayable() && !CommonUtil.contains(ETINA_HELPERS, event.getAttacker().getId()))
+ {
+ if (!npc.isInCombat())
+ {
+ if (getRandom(50) < 5)
+ {
+ npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.DON_T_GET_IN_MY_WAY);
+ }
+ }
+ }
+ }
+ }
+
+ public void onInstanceStatusChange(OnInstanceStatusChange event)
+ {
+ final Instance instance = event.getWorld();
+ final int status = event.getStatus();
+ if ((status == 1) || (status == 2) || (status == 3))
+ {
+ instance.getAliveNpcs(ETINA_HELPER_SPORCHA).forEach(etinaHelperSporcha -> getTimers().addRepeatingTimer("CHECK_ACTION", 3000, etinaHelperSporcha, null));
+ }
+ }
+
+ @Override
+ public String onSeeCreature(Npc npc, Creature creature, boolean isSummon)
+ {
+ if (creature.isPlayer())
+ {
+ npc.getVariables().set("PLAYER_OBJECT", creature.getActingPlayer());
+ }
+ return super.onSeeCreature(npc, creature, isSummon);
+ }
+
+ public static void main(String[] args)
+ {
+ new EtinaHelperSporcha();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtisVanEtinaSolo.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtisVanEtinaSolo.java
new file mode 100644
index 0000000000..8f1db0d8d6
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/EtisVanEtinaSolo.java
@@ -0,0 +1,723 @@
+/*
+ * 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.EtisVanEtinaSolo;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.enums.ChatType;
+import org.l2jmobius.gameserver.enums.Movie;
+import org.l2jmobius.gameserver.model.World;
+import org.l2jmobius.gameserver.model.actor.Attackable;
+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.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.instancezone.Instance;
+import org.l2jmobius.gameserver.model.skills.AbnormalVisualEffect;
+import org.l2jmobius.gameserver.network.NpcStringId;
+import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
+import org.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
+
+import instances.AbstractInstance;
+
+/**
+ * @author CostyKiller
+ * @URL: https://l2wiki.com/Fall_of_Etina_(Solo)
+ * @URL: https://youtu.be/3flFpg0KGcA
+ * @TODO: Add helper npcs skills
+ * @TODO: Add instance buff Elikia Emblem
+ */
+public class EtisVanEtinaSolo extends AbstractInstance
+{
+ // NPC
+ private static final int LEONA_OUTLET = 34426;
+ private static final int LEONA_BLACKBIRD = 34471;
+ private static final int DEVIANNE = 34472;
+ private static final int ELIKIA = 34473;
+ private static final int SPORCHA = 34474;
+ private static final int ALIBER = 34475;
+ // RB
+ private static final int ETIS_VAN_ETINA1 = 26321;
+ private static final int ETIS_VAN_ETINA2 = 26322;
+ private static final int KAIN_VAN_HALTER = 26235;
+ private static final int CAMILLE = 26236;
+ // Corridor Mobs
+ //@formatter:off
+ private static final int[] CORRIDOR_MOBS_1 = {24173, 24174, 24175, 24176};
+ private static final int[] CORRIDOR_MOBS_2 = {24180, 24181, 24182, 24183};
+ private static final int[] CORRIDOR_MOBS_3 = {24184, 24185, 24186, 24187, 24188, 24189, 24190, 24191, 24192};
+ private static final int[] CORRIDOR_MOBS_4 = {24189, 24190, 24191, 24192};
+ //@formatter:on
+ private static final int PARAGON = 24193;
+ // Seals
+ private static final int SEAL_OF_GNOSIS = 19677;
+ private static final int SEAL_OF_STRIFE = 19678;
+ private static final int SEAL_OF_AVARICE = 19679;
+ private static final int SEAL_OF_PUNISHMENT = 19680;
+ private static final int SEAL_OF_AWAKENING = 19681;
+ private static final int SEAL_OF_CALAMITY = 19682;
+ private static final int SEAL_OF_DESTRUCTION = 19683;
+ // Others
+ private static final int DOOR1 = 12230702;
+ private static final int DOOR2 = 12230704;
+ private static final int DOOR3 = 12230802;
+ private static final int DOOR4 = 12230804;
+ // Skills
+ private static final SkillHolder CALL_OF_SEVEN_SIGNS = new SkillHolder(32317, 1);
+ private static final SkillHolder CALL_OF_SEVEN_SIGNS_SEAL_N = new SkillHolder(32004, 1);
+ private static final SkillHolder ETINA_REVELATION = new SkillHolder(32014, 2);
+ private static final SkillHolder STIGMA_OF_REVELATION = new SkillHolder(32015, 1);
+ private static final SkillHolder CRY_OF_HOLY_WAR = new SkillHolder(32017, 2);
+ private static final SkillHolder STIGMA_OF_MARTYR = new SkillHolder(32018, 1);
+ private static final SkillHolder UNDEAD_CREATURE = new SkillHolder(32020, 2);
+ private static final SkillHolder ETINA_DIVINE_PUNISHMENT = new SkillHolder(32023, 2);
+ private static final SkillHolder ETINA_OBSERVATION = new SkillHolder(32024, 2);
+ private static final SkillHolder RAGE_OF_THE_OPEN_EYE = new SkillHolder(32026, 2);
+
+ // Camille -> Horseshoe Trampling, Horizon Bash, Joust Lunge, Call of Etina (summon minions?)
+ // Misc
+ private static final int TEMPLATE_ID = 293;
+
+ public EtisVanEtinaSolo()
+ {
+ super(TEMPLATE_ID);
+ addInstanceCreatedId(TEMPLATE_ID);
+ addStartNpc(LEONA_OUTLET);
+ addTalkId(LEONA_OUTLET, LEONA_BLACKBIRD);
+ addFirstTalkId(LEONA_BLACKBIRD, DEVIANNE, ELIKIA, SPORCHA, ALIBER);
+ addAttackId(CORRIDOR_MOBS_1);
+ addAttackId(CORRIDOR_MOBS_2);
+ addAttackId(CORRIDOR_MOBS_3);
+ addAttackId(CORRIDOR_MOBS_4);
+ addAttackId(CAMILLE, KAIN_VAN_HALTER, ETIS_VAN_ETINA1, ETIS_VAN_ETINA2);
+ addKillId(CORRIDOR_MOBS_1);
+ addKillId(CORRIDOR_MOBS_2);
+ addKillId(CORRIDOR_MOBS_3);
+ addKillId(CORRIDOR_MOBS_4);
+ addKillId(PARAGON, CAMILLE, KAIN_VAN_HALTER, ETIS_VAN_ETINA1, ETIS_VAN_ETINA2);
+ }
+
+ @Override
+ public void onInstanceCreated(Instance world, PlayerInstance player)
+ {
+ world.setStatus(0);
+ world.getParameters().set("BARRICADE_DESTROYED", false);
+ world.getParameters().set("CORRIDOR_MOBS_1_SPAWNED", false);
+ world.getParameters().set("CORRIDOR_MOBS_2_SPAWNED", false);
+ world.getParameters().set("CORRIDOR_MOBS_3_SPAWNED", false);
+ world.getParameters().set("CORRIDOR_MOBS_4_SPAWNED", false);
+ world.getParameters().set("CAMILLE_30", false);
+ world.getParameters().set("CAMILLE_60", false);
+ world.getParameters().set("KAIN_30", false);
+ world.getParameters().set("KAIN_60", false);
+ world.getParameters().set("ETINA_80", false);
+ world.getParameters().set("ETINA_15", false);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "enterInstance":
+ {
+ playMovie(player, Movie.EP5_ETINA_QST_START_A);
+ startQuestTimer("enterEtina", 20000, npc, player);
+ startQuestTimer("intro_movie", 20000, npc, player);
+ startQuestTimer("talkLeona", 25000, npc, player);
+ break;
+ }
+ case "enterEtina":
+ {
+ enterInstance(player, npc, TEMPLATE_ID);
+ break;
+ }
+ case "intro_movie":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ playMovie(world.getPlayers(), Movie.EP5_ETINA_QST_START_B);
+ }
+ break;
+ }
+ case "talkLeona":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ showOnScreenMsg(world, NpcStringId.TALK_TO_LEONA_BLACKBIRD_13, ExShowScreenMessage.TOP_CENTER, 10000, true);
+ }
+ break;
+ }
+ case "startStage1":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ showOnScreenMsg(world, NpcStringId.ALRIGHT_LET_S_GO_DEFEAT_ETIS_VAN_ETINA, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ startQuestTimer("checkProgress", 5000, npc, player, true);
+ world.setStatus(1);
+ return "34471-01.html";
+ }
+ break;
+ }
+ case "checkProgress":
+ {
+ final Instance world = player.getInstanceWorld();
+ boolean CORRIDOR_MOBS_1_SPAWNED = world.getParameters().getBoolean("CORRIDOR_MOBS_1_SPAWNED", false);
+ boolean CORRIDOR_MOBS_2_SPAWNED = world.getParameters().getBoolean("CORRIDOR_MOBS_2_SPAWNED", false);
+ boolean CORRIDOR_MOBS_3_SPAWNED = world.getParameters().getBoolean("CORRIDOR_MOBS_3_SPAWNED", false);
+ boolean CORRIDOR_MOBS_4_SPAWNED = world.getParameters().getBoolean("CORRIDOR_MOBS_4_SPAWNED", false);
+ if (isInInstance(world))
+ {
+ final MonsterInstance monsterCheck = getRandomEntry(World.getInstance().getVisibleObjectsInRange(npc, MonsterInstance.class, 2500));
+ if (monsterCheck == null)
+ {
+ if (!world.getNpcsOfGroup("BARRICADES_2").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_1).isEmpty() && world.getNpcsOfGroup("BARRICADES_1").isEmpty())
+ {
+ world.getParameters().set("BARRICADE_DESTROYED", false);
+ }
+ else if (!world.getNpcsOfGroup("BARRICADES_3").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_2).isEmpty() && world.getNpcsOfGroup("BARRICADES_2").isEmpty())
+ {
+ world.getParameters().set("BARRICADE_DESTROYED", false);
+ }
+ else if (!world.getNpcsOfGroup("BARRICADES_4").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_3).isEmpty() && world.getNpcsOfGroup("BARRICADES_3").isEmpty())
+ {
+ world.getParameters().set("BARRICADE_DESTROYED", false);
+ }
+ }
+ if (!CORRIDOR_MOBS_1_SPAWNED && world.getNpcsOfGroup("BARRICADES_1").isEmpty() && !world.getNpcsOfGroup("BARRICADES_2").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_1).isEmpty())
+ {
+ world.spawnGroup("CORRIDOR_MOBS_1");
+ world.getNpcsOfGroup("CORRIDOR_MOBS_1").forEach(mob ->
+ {
+ if (mob != null)
+ {
+ mob.setRandomWalking(false);
+ }
+ });
+ world.getParameters().set("CORRIDOR_MOBS_1_SPAWNED", true);
+ }
+ if (!CORRIDOR_MOBS_2_SPAWNED && world.getNpcsOfGroup("BARRICADES_2").isEmpty() && !world.getNpcsOfGroup("BARRICADES_3").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_2).isEmpty())
+ {
+ world.spawnGroup("CORRIDOR_MOBS_2");
+ world.getNpcsOfGroup("CORRIDOR_MOBS_2").forEach(mob ->
+ {
+ if (mob != null)
+ {
+ mob.setRandomWalking(false);
+ }
+ });
+ world.getParameters().set("CORRIDOR_MOBS_2_SPAWNED", true);
+ }
+ if (!CORRIDOR_MOBS_3_SPAWNED && world.getNpcsOfGroup("BARRICADES_3").isEmpty() && !world.getNpcsOfGroup("BARRICADES_4").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_3).isEmpty())
+ {
+ world.spawnGroup("CORRIDOR_MOBS_3");
+ world.getNpcsOfGroup("CORRIDOR_MOBS_3").forEach(mob ->
+ {
+ if (mob != null)
+ {
+ mob.setRandomWalking(false);
+ }
+ });
+ world.getParameters().set("CORRIDOR_MOBS_3_SPAWNED", true);
+ }
+ if (!CORRIDOR_MOBS_4_SPAWNED && world.getNpcsOfGroup("BARRICADES_4").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_4).isEmpty())
+ {
+ world.spawnGroup("CORRIDOR_MOBS_4");
+ world.spawnGroup("PARAGON");
+ world.getParameters().set("CORRIDOR_MOBS_4_SPAWNED", true);
+ world.getNpcsOfGroup("CORRIDOR_MOBS_4").forEach(mob ->
+ {
+ if (mob != null)
+ {
+ mob.setRandomWalking(false);
+ }
+ });
+ if (world.getNpc(PARAGON) != null)
+ {
+ world.getNpc(PARAGON).setInvul(true);
+ world.getNpc(PARAGON).getEffectList().startAbnormalVisualEffect(AbnormalVisualEffect.INVINCIBILITY);
+ }
+ npc.broadcastPacket(new ExShowScreenMessage(NpcStringId.YOU_CAN_T_DEFEAT_PARAGON_WHILE_PARAGON_S_MINIONS_ARE_ALIVE, ExShowScreenMessage.TOP_CENTER, 7000, true));
+ }
+ if (world.getNpcsOfGroup("BARRICADES_4").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_4).isEmpty())
+ {
+ if ((world.getNpc(PARAGON) != null) && world.getNpc(PARAGON).isInvul())
+ {
+ world.getNpc(PARAGON).setInvul(false);
+ world.getNpc(PARAGON).getEffectList().stopAbnormalVisualEffect(AbnormalVisualEffect.INVINCIBILITY);
+ showOnScreenMsg(world, NpcStringId.PARAGON_IS_NO_LONGER_INVINCIBLE, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.TODAY_IS_THE_DAY_THAT_I_WILL_ENTER);
+ }
+ }
+ if ((world.getStatus() == 1) && world.getNpcsOfGroup("BARRICADES_4").isEmpty() && (world.getAliveNpcs(PARAGON).isEmpty()))
+ {
+ startQuestTimer("openInnerDoors", 5000, null, player);
+ cancelQuestTimer("checkProgress", npc, player);
+ }
+ }
+ break;
+ }
+ case "openInnerDoors":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ openDoor(DOOR1, world.getId());
+ openDoor(DOOR2, world.getId());
+ openDoor(DOOR3, world.getId());
+ openDoor(DOOR4, world.getId());
+ world.setStatus(2);
+ startQuestTimer("talkLeona", 5000, null, player);
+ }
+ break;
+ }
+ case "startStage2":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ startQuestTimer("show_intro_movie_camille", 5000, null, player);
+ return "34471-03.html";
+ }
+ break;
+ }
+ case "show_intro_movie_camille":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ playMovie(world.getPlayers(), Movie.SC_INZONE_CAMILLE_INTRO);
+ startQuestTimer("spawn_camille", 5000, null, player);
+ }
+ break;
+ }
+ case "spawn_camille":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ closeDoor(DOOR1, world.getId());
+ closeDoor(DOOR2, world.getId());
+ closeDoor(DOOR3, world.getId());
+ closeDoor(DOOR4, world.getId());
+ world.setStatus(3);
+ world.spawnGroup("CAMILLE");
+ world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.GISELLE_NO_IS_SHE_CAMILLE_IN_THAT_STATE);
+ }
+ break;
+ }
+ case "spawn_kain":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ world.spawnGroup("KAIN");
+ world.spawnGroup("ETINA_1");
+ world.getNpc(ETIS_VAN_ETINA1).setInvul(true);
+ world.getNpc(ETIS_VAN_ETINA1).setTargetable(false);
+ world.getNpc(ETIS_VAN_ETINA1).setImmobilized(true);
+ showOnScreenMsg(world, NpcStringId.ETIS_VAN_ETINA_AND_HIS_APOSTLES_HAVE_APPEARED, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.EVEN_THE_MIGHTY_ETINA_SEEMS_TO_FEAR_US);
+ }
+ break;
+ }
+ case "spawnTransformedEtina":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ world.spawnGroup("ETINA_2");
+ world.spawnGroup("ETINA_MINIONS");
+ world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.ETIS_VAN_ETINA_WE_FINALLY_MEET);
+ }
+ break;
+ }
+ case "gnosisCastTimer":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ final Npc _sealOfGnosis = world.getNpc(SEAL_OF_GNOSIS);
+ _sealOfGnosis.setDisplayEffect(3);
+ _sealOfGnosis.broadcastPacket(new MagicSkillUse(_sealOfGnosis, _sealOfGnosis, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 1, 10000, 0));
+ PlayerInstance member = world.getPlayers().stream().findAny().get();
+ STIGMA_OF_REVELATION.getSkill().applyEffects(member, member);
+ world.getNpcsOfGroup("ETINA_MINIONS").forEach(minion ->
+ {
+ if (minion != null)
+ {
+ ETINA_REVELATION.getSkill().applyEffects(minion, minion);
+ ((Attackable) minion).addDamageHate(member, 0, 999999999);
+ }
+ });
+ showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_GNOSIS_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ }
+ break;
+ }
+ case "strifeCastTimer":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ final Npc _sealOfStrife = world.getNpc(SEAL_OF_STRIFE);
+ _sealOfStrife.setDisplayEffect(3);
+ _sealOfStrife.broadcastPacket(new MagicSkillUse(_sealOfStrife, _sealOfStrife, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 2, 10000, 0));
+ world.getNpcsOfGroup("ETINA_MINIONS").forEach(minion ->
+ {
+ if (minion != null)
+ {
+ CRY_OF_HOLY_WAR.getSkill().applyEffects(minion, minion);
+ }
+ });
+ world.getPlayers().forEach(plr -> STIGMA_OF_MARTYR.getSkill().applyEffects(player, player));
+ showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_STRIFE_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ }
+ break;
+ }
+ case "avariceCastTimer":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ final Npc _sealOfAvarice = world.getNpc(SEAL_OF_AVARICE);
+ _sealOfAvarice.setDisplayEffect(3);
+ _sealOfAvarice.broadcastPacket(new MagicSkillUse(_sealOfAvarice, _sealOfAvarice, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 3, 10000, 0));
+ world.getNpcsOfGroup("ETINA_MINIONS").forEach(minion ->
+ {
+ if (minion != null)
+ {
+ UNDEAD_CREATURE.getSkill().applyEffects(minion, minion);
+ }
+ });
+ showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_AVARICE_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ }
+ break;
+ }
+ case "punishmentCastTimer":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ final Npc _sealOfPunishment = world.getNpc(SEAL_OF_PUNISHMENT);
+ _sealOfPunishment.setDisplayEffect(3);
+ _sealOfPunishment.broadcastPacket(new MagicSkillUse(_sealOfPunishment, _sealOfPunishment, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 4, 10000, 0));
+ world.getNpcsOfGroup("ETINA_MINIONS").forEach(minion ->
+ {
+ if (minion != null)
+ {
+ ETINA_DIVINE_PUNISHMENT.getSkill().applyEffects(minion, minion);
+ }
+ });
+ world.getPlayers().forEach(plr -> ETINA_OBSERVATION.getSkill().applyEffects(player, player));
+ showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_PUNISHMENT_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ }
+ break;
+ }
+ case "awakeningCastTimer":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ final Npc _sealOfAwakening = world.getNpc(SEAL_OF_AWAKENING);
+ _sealOfAwakening.setDisplayEffect(3);
+ _sealOfAwakening.broadcastPacket(new MagicSkillUse(_sealOfAwakening, _sealOfAwakening, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 5, 10000, 0));
+ world.getNpcsOfGroup("ETINA_MINIONS").forEach(minion ->
+ {
+ if (minion != null)
+ {
+ RAGE_OF_THE_OPEN_EYE.getSkill().applyEffects(minion, minion);
+ }
+ });
+ showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_AWAKENING_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ }
+ break;
+ }
+ case "calamityCastTimer":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ final Npc _sealOfCalamity = world.getNpc(SEAL_OF_CALAMITY);
+ _sealOfCalamity.setDisplayEffect(3);
+ _sealOfCalamity.broadcastPacket(new MagicSkillUse(_sealOfCalamity, _sealOfCalamity, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 6, 10000, 0));
+ showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_CALAMITY_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ }
+ break;
+ }
+ case "destructionCastTimer":
+ {
+ final Instance world = player.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ final Npc _sealOfDestruction = world.getNpc(SEAL_OF_DESTRUCTION);
+ _sealOfDestruction.setDisplayEffect(3);
+ _sealOfDestruction.broadcastPacket(new MagicSkillUse(_sealOfDestruction, _sealOfDestruction, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 7, 10000, 0));
+ showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_DESTRUCTION_IS_ACTIVATED_AND_ETINA_S_GRAND_TEMPLE_IS_NOW_UNDER_ITS_INFLUENCE, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon)
+ {
+ final Instance world = attacker.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ final boolean CAMILLE_30 = world.getParameters().getBoolean("CAMILLE_30", false);
+ final boolean CAMILLE_60 = world.getParameters().getBoolean("CAMILLE_60", false);
+ final boolean KAIN_30 = world.getParameters().getBoolean("KAIN_30", false);
+ final boolean KAIN_60 = world.getParameters().getBoolean("KAIN_60", false);
+ final boolean ETINA_80 = world.getParameters().getBoolean("ETINA_80", false);
+ final boolean ETINA_15 = world.getParameters().getBoolean("ETINA_15", false);
+ if (npc.getId() == CAMILLE)
+ {
+ if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.3)) && !CAMILLE_30)
+ {
+ world.getParameters().set("CAMILLE_30", true);
+ world.spawnGroup("CAMILLE_MINIONS");
+ }
+ else if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.6)) && !CAMILLE_60)
+ {
+ world.getParameters().set("CAMILLE_60", true);
+ world.spawnGroup("CAMILLE_MINIONS");
+ }
+ }
+ else if (npc.getId() == KAIN_VAN_HALTER)
+ {
+ if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.3)) && !KAIN_30)
+ {
+ world.getParameters().set("KAIN_30", true);
+ showOnScreenMsg(world, NpcStringId.ETIS_VAN_ETINA_SUMMONS_HIS_APOSTLES_MINIONS, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ world.spawnGroup("KAIN_MINIONS");
+ }
+ else if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.6)) && !KAIN_60)
+ {
+ world.getParameters().set("KAIN_60", true);
+ showOnScreenMsg(world, NpcStringId.ETIS_VAN_ETINA_SUMMONS_HIS_APOSTLES_MINIONS, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ world.spawnGroup("KAIN_MINIONS");
+ }
+ }
+ else if ((npc.getId() == ETIS_VAN_ETINA1))
+ {
+ if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.8)) && !ETINA_80)
+ {
+ final Npc _etina1 = world.getNpc(ETIS_VAN_ETINA1);
+ world.getParameters().set("ETINA_80", true);
+ world.spawnGroup("ETINA_MINIONS");
+ _etina1.abortCast();
+ _etina1.broadcastPacket(new MagicSkillUse(_etina1, _etina1, CALL_OF_SEVEN_SIGNS.getSkillId(), CALL_OF_SEVEN_SIGNS.getSkillLevel(), 3000, 0));
+ showOnScreenMsg(world, NpcStringId.ETIS_VAN_ETINA_USES_THE_POWER_OF_THE_SEVEN_SIGNS_TO_SUMMON_ALL_7_SEALS_INSIDE_THE_TEMPLE, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ world.spawnGroup("SEALS");
+ startQuestTimer("gnosisCastTimer", 120000, npc, attacker, true);
+ startQuestTimer("strifeCastTimer", 120000, npc, attacker, true);
+ startQuestTimer("avariceCastTimer", 120000, npc, attacker, true);
+ startQuestTimer("punishmentCastTimer", 120000, npc, attacker, true);
+ startQuestTimer("awakeningCastTimer", 120000, npc, attacker, true);
+ startQuestTimer("calamityCastTimer", 120000, npc, attacker, true);
+ startQuestTimer("destructionCastTimer", 120000, npc, attacker, true);
+ }
+ else if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.15)) && !ETINA_15)
+ {
+ world.getParameters().set("ETINA_15", true);
+ world.spawnGroup("ETINA_MINIONS");
+ showOnScreenMsg(world, NpcStringId.ETIS_VAN_ETINA_AND_THE_POWER_OF_SIX_SEALS_ARE_WEAKENING, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ }
+ }
+ }
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ @Override
+ public String onKill(Npc npc, PlayerInstance killer, boolean isPet)
+ {
+ final Instance world = npc.getInstanceWorld();
+ if (isInInstance(world))
+ {
+ if (npc.getId() == ETIS_VAN_ETINA1)
+ {
+ playMovie(world.getPlayers(), Movie.SC_ETIS_VAN_ETINA_TRANS);
+ startQuestTimer("spawnTransformedEtina", 15000, null, killer);
+ }
+ else if (npc.getId() == ETIS_VAN_ETINA2)
+ {
+ playMovie(world.getPlayers(), Movie.SC_ETIS_VAN_ETINA_ENDING);
+ world.getAliveNpcs().forEach(mob ->
+ {
+ mob.deleteMe();
+ });
+ if (getQuestTimer("gnosisCastTimer", npc, killer) != null)
+ {
+ cancelQuestTimer("gnosisCastTimer", npc, killer);
+ }
+ if (getQuestTimer("trifeCastTimer", npc, killer) != null)
+ {
+ cancelQuestTimer("strifeCastTimer", npc, killer);
+ }
+ if (getQuestTimer("avariceCastTimer", npc, killer) != null)
+ {
+ cancelQuestTimer("avariceCastTimer", npc, killer);
+ }
+ if (getQuestTimer("punishmentCastTimer", npc, killer) != null)
+ {
+ cancelQuestTimer("punishmentCastTimer", npc, killer);
+ }
+ if (getQuestTimer("awakeningCastTimer", npc, killer) != null)
+ {
+ cancelQuestTimer("awakeningCastTimer", npc, killer);
+ }
+ if (getQuestTimer("calamityCastTimer", npc, killer) != null)
+ {
+ cancelQuestTimer("calamityCastTimer", npc, killer);
+ }
+ if (getQuestTimer("destructionCastTimer", npc, killer) != null)
+ {
+ cancelQuestTimer("destructionCastTimer", npc, killer);
+ }
+ closeDoor(DOOR1, world.getId());
+ closeDoor(DOOR2, world.getId());
+ closeDoor(DOOR3, world.getId());
+ closeDoor(DOOR4, world.getId());
+ world.finishInstance(2);
+ }
+ else if (CommonUtil.contains(CORRIDOR_MOBS_1, npc.getId()))
+ {
+ if (world.getAliveNpcs(CORRIDOR_MOBS_1).isEmpty())
+ {
+ world.getParameters().set("BARRICADE_DESTROYED", false);
+ }
+ }
+ else if (CommonUtil.contains(CORRIDOR_MOBS_2, npc.getId()))
+ {
+ if (world.getAliveNpcs(CORRIDOR_MOBS_2).isEmpty())
+ {
+ world.getParameters().set("BARRICADE_DESTROYED", false);
+ }
+ }
+ else if (CommonUtil.contains(CORRIDOR_MOBS_3, npc.getId()))
+ {
+ if (world.getAliveNpcs(CORRIDOR_MOBS_3).isEmpty())
+ {
+ world.getParameters().set("BARRICADE_DESTROYED", false);
+ }
+ }
+ else if (CommonUtil.contains(CORRIDOR_MOBS_4, npc.getId()))
+ {
+ if (world.getAliveNpcs(CORRIDOR_MOBS_4).isEmpty())
+ {
+ world.getNpc(PARAGON).setInvul(false);
+ world.getNpc(PARAGON).getEffectList().stopAbnormalVisualEffect(AbnormalVisualEffect.INVINCIBILITY);
+ showOnScreenMsg(world, NpcStringId.PARAGON_IS_NO_LONGER_INVINCIBLE, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.TODAY_IS_THE_DAY_THAT_I_WILL_ENTER);
+ }
+ }
+ else if (npc.getId() == PARAGON)
+ {
+ startQuestTimer("openInnerDoors", 5000, null, killer);
+ }
+ else if (npc.getId() == CAMILLE)
+ {
+ world.getNpcsOfGroup("CAMILLE_MINIONS").forEach(minion ->
+ {
+ if (minion != null)
+ {
+ minion.doDie(null);
+ }
+ });
+ world.getNpc(CAMILLE).deleteMe();
+ world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.KAIN_IS_OUR_ENEMY_NOW_BE_ON_GUARD);
+ playMovie(world.getPlayers(), Movie.SC_INZONE_KAIN_INTRO);
+ startQuestTimer("spawn_kain", 5000, null, killer);
+ }
+ else if (npc.getId() == KAIN_VAN_HALTER)
+ {
+ world.getNpcsOfGroup("KAIN_MINIONS").forEach(minion ->
+ {
+ if (minion != null)
+ {
+ minion.doDie(null);
+ }
+ });
+ world.getNpc(ETIS_VAN_ETINA1).setInvul(false);
+ world.getNpc(ETIS_VAN_ETINA1).setImmobilized(false);
+ world.getNpc(ETIS_VAN_ETINA1).setTargetable(true);
+ showOnScreenMsg(world, NpcStringId.ETIS_VAN_ETINA_APPROACHES, ExShowScreenMessage.TOP_CENTER, 7000, true);
+ world.getNpc(KAIN_VAN_HALTER).deleteMe();
+ playMovie(world.getPlayers(), Movie.SC_KAIN_BOSS_ENDING);
+ world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.KAIN_I_WON_T_FEEL_GUILTY_ABOUT_THIS);
+ }
+ }
+ return super.onKill(npc, killer, isPet);
+ }
+
+ @Override
+ public String onFirstTalk(Npc npc, PlayerInstance player)
+ {
+ final Instance world = player.getInstanceWorld();
+ String htmltext = null;
+ if (isInInstance(world))
+ {
+ switch (npc.getId())
+ {
+ case DEVIANNE:
+ case ELIKIA:
+ case SPORCHA:
+ case ALIBER:
+ {
+ htmltext = npc.getId() + ".html";
+ break;
+ }
+ case LEONA_BLACKBIRD:
+ {
+ switch (world.getStatus())
+ {
+ case 0:
+ {
+ htmltext = "34471.htm";
+ break;
+ }
+ case 1:
+ {
+ htmltext = "34471-01.html";
+ break;
+ }
+ case 2:
+ {
+ htmltext = "34471-02.htm";
+ break;
+ }
+ case 3:
+ {
+ htmltext = "34471-03.html";
+ break;
+ }
+ }
+ }
+ }
+ }
+ return htmltext;
+ }
+
+ public static void main(String[] args)
+ {
+ new EtisVanEtinaSolo();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/condNoGroup.html b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/condNoGroup.html
new file mode 100644
index 0000000000..a34d6f3c14
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/condNoGroup.html
@@ -0,0 +1,3 @@
+Leona Blackbird:
+You can enter only solo.
+
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/condNoLevel.html b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/condNoLevel.html
new file mode 100644
index 0000000000..5a53e17332
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/scripts/instances/EtisVanEtinaSolo/condNoLevel.html
@@ -0,0 +1,4 @@
+Leona Blackbird:
+I won't let you enter.
+(Only players between levels 104-130 may participate.)
+
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/npcs/24100-24199.xml b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/npcs/24100-24199.xml
index 4421f21547..1fe8ac7fb3 100644
--- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/npcs/24100-24199.xml
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/npcs/24100-24199.xml
@@ -2270,6 +2270,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2296,6 +2301,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2322,6 +2332,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2348,6 +2363,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2373,6 +2393,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2398,6 +2423,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2423,6 +2453,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2448,6 +2483,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2473,6 +2513,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2498,6 +2543,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2523,6 +2573,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2548,6 +2603,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2573,6 +2633,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2598,6 +2663,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2609,7 +2679,7 @@
-
+
HUMANOID
FEMALE
@@ -2622,6 +2692,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -2634,7 +2709,7 @@
-
+
DEMONIC
MALE
@@ -2647,6 +2722,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -3102,6 +3182,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -3127,6 +3212,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -3152,6 +3242,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -3163,24 +3258,34 @@
-
-
+
ETC
FEMALE
-
+
+
+
-
-
-
+
+
+
+ ETINA_SOLO
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/npcs/26300-26399.xml b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/npcs/26300-26399.xml
index 4ea02626c1..050c98e131 100644
--- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/npcs/26300-26399.xml
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/npcs/26300-26399.xml
@@ -509,43 +509,103 @@
-
-
- ETC
- FEMALE
+
+ HUMANOID
+ MALE
-
+
+
+
-
-
-
+
+
+
+ ETINA_SOLO
+
+
+
+
+
+
+
+
-
-
- ETC
- FEMALE
+
+ HUMANOID
+ MALE
+
-
+
+
+
-
-
-
+
+
+
+ ETINA_SOLO
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
DEMONIC
@@ -560,6 +620,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -585,6 +650,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -610,6 +680,11 @@
+
+
+ ETINA_SOLO
+
+
@@ -635,6 +710,11 @@
+
+
+ ETINA_SOLO
+
+