CostyKiller

Etina Solo Instance script + npc helpers ai's

Apr 27th, 2021 (edited)
808
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 72.07 KB | None | 0 0
  1. Index: dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-01.html
  2. ===================================================================
  3. --- dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-01.html (nonexistent)
  4. +++ dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-01.html (working copy)
  5. @@ -0,0 +1,4 @@
  6. +<html><body>Blackbird Clan Lord Leona Blackbird:<br>
  7. +Let us defeat our enemies.<br>
  8. +Let's go to Etis van Etina, the Head of the Embryo, as fast as we can.
  9. +</body></html>
  10. \ No newline at end of file
  11. Index: dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-02.htm
  12. ===================================================================
  13. --- dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-02.htm  (nonexistent)
  14. +++ dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-02.htm  (working copy)
  15. @@ -0,0 +1,5 @@
  16. +<html><body>Blackbird Clan Lord Leona Blackbird:<br>
  17. +Thanks to you, we were able to come this far this time.<br>
  18. +But why is it so quiet? It can't be this empty...<br>
  19. +<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest EtisVanEtinaSolo startStage2">"I have a bad feeling about this."</Button>
  20. +</body></html>
  21. \ No newline at end of file
  22. Index: dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-03.html
  23. ===================================================================
  24. --- dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-03.html (nonexistent)
  25. +++ dist/game/data/scripts/instances/EtisVanEtinaSolo/34471-03.html (working copy)
  26. @@ -0,0 +1,3 @@
  27. +<html><body>Blackbird Clan Lord Leona Blackbird:<br>
  28. +You don't have to worry ab- Ah! Oh no! What's that?<br>
  29. +</body></html>
  30. \ No newline at end of file
  31. Index: dist/game/data/scripts/instances/EtisVanEtinaSolo/34471.htm
  32. ===================================================================
  33. --- dist/game/data/scripts/instances/EtisVanEtinaSolo/34471.htm (nonexistent)
  34. +++ dist/game/data/scripts/instances/EtisVanEtinaSolo/34471.htm (working copy)
  35. @@ -0,0 +1,5 @@
  36. +<html><body>Blackbird Clan Lord Leona Blackbird:<br>
  37. +This is <font color="GOLD"> the Great Etina Temple.</font> 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.<br>
  38. +Now, let's take down the Embryos and Etis van Etina before they even realize. Are you ready?<br>
  39. +<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest EtisVanEtinaSolo startStage1">"Yes, I'm ready."</Button>
  40. +</body></html>
  41. \ No newline at end of file
  42. Index: dist/game/data/scripts/instances/EtisVanEtinaSolo/34472.html
  43. ===================================================================
  44. --- dist/game/data/scripts/instances/EtisVanEtinaSolo/34472.html    (nonexistent)
  45. +++ dist/game/data/scripts/instances/EtisVanEtinaSolo/34472.html    (working copy)
  46. @@ -0,0 +1,3 @@
  47. +<html><body>Devianne:<br>
  48. +Behold the power of the Ivory Tower Wizards!<br>
  49. +</body></html>
  50. \ No newline at end of file
  51. Index: dist/game/data/scripts/instances/EtisVanEtinaSolo/34473.html
  52. ===================================================================
  53. --- dist/game/data/scripts/instances/EtisVanEtinaSolo/34473.html    (nonexistent)
  54. +++ dist/game/data/scripts/instances/EtisVanEtinaSolo/34473.html    (working copy)
  55. @@ -0,0 +1,3 @@
  56. +<html><body>Elikia:<br>
  57. +Let's take down the Embryos and Etis van Etina before they even realize.<br>
  58. +</body></html>
  59. \ No newline at end of file
  60. Index: dist/game/data/scripts/instances/EtisVanEtinaSolo/34474.html
  61. ===================================================================
  62. --- dist/game/data/scripts/instances/EtisVanEtinaSolo/34474.html    (nonexistent)
  63. +++ dist/game/data/scripts/instances/EtisVanEtinaSolo/34474.html    (working copy)
  64. @@ -0,0 +1,3 @@
  65. +<html><body>Sporcha:<br>
  66. +Are you ready to fight?<br>
  67. +</body></html>
  68. \ No newline at end of file
  69. Index: dist/game/data/scripts/instances/EtisVanEtinaSolo/34475.html
  70. ===================================================================
  71. --- dist/game/data/scripts/instances/EtisVanEtinaSolo/34475.html    (nonexistent)
  72. +++ dist/game/data/scripts/instances/EtisVanEtinaSolo/34475.html    (working copy)
  73. @@ -0,0 +1,3 @@
  74. +<html><body>Aliber:<br>
  75. +Rage against all that stands in our way!<br>
  76. +</body></html>
  77. \ No newline at end of file
  78. Index: dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperAliber.java
  79. ===================================================================
  80. --- dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperAliber.java    (nonexistent)
  81. +++ dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperAliber.java    (working copy)
  82. @@ -0,0 +1,283 @@
  83. +/*
  84. + * This file is part of the L2J Mobius project.
  85. + *
  86. + * This program is free software: you can redistribute it and/or modify
  87. + * it under the terms of the GNU General Public License as published by
  88. + * the Free Software Foundation, either version 3 of the License, or
  89. + * (at your option) any later version.
  90. + *
  91. + * This program is distributed in the hope that it will be useful,
  92. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  93. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  94. + * General Public License for more details.
  95. + *
  96. + * You should have received a copy of the GNU General Public License
  97. + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  98. + */
  99. +package instances.EtisVanEtinaSolo;
  100. +
  101. +import org.l2jmobius.commons.util.CommonUtil;
  102. +import org.l2jmobius.gameserver.ai.CtrlIntention;
  103. +import org.l2jmobius.gameserver.enums.ChatType;
  104. +import org.l2jmobius.gameserver.geoengine.GeoEngine;
  105. +import org.l2jmobius.gameserver.model.Location;
  106. +import org.l2jmobius.gameserver.model.StatSet;
  107. +import org.l2jmobius.gameserver.model.World;
  108. +import org.l2jmobius.gameserver.model.WorldObject;
  109. +import org.l2jmobius.gameserver.model.actor.Creature;
  110. +import org.l2jmobius.gameserver.model.actor.Npc;
  111. +import org.l2jmobius.gameserver.model.actor.instance.FriendlyNpcInstance;
  112. +import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
  113. +import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
  114. +import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureAttacked;
  115. +import org.l2jmobius.gameserver.model.events.impl.instance.OnInstanceStatusChange;
  116. +import org.l2jmobius.gameserver.model.holders.SkillHolder;
  117. +import org.l2jmobius.gameserver.model.instancezone.Instance;
  118. +import org.l2jmobius.gameserver.network.NpcStringId;
  119. +import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
  120. +import org.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
  121. +
  122. +import ai.AbstractNpcAI;
  123. +
  124. +/**
  125. + * Etina Helper Aliber AI.
  126. + * @author CostyKiller
  127. + */
  128. +public class EtinaHelperAliber extends AbstractNpcAI
  129. +{
  130. +   // NPCs
  131. +   private static final int ETINA_HELPER_ALIBER = 34475;
  132. +   // Corridor Mobs
  133. +   //@formatter:off
  134. +   private static final int[] CORRIDOR_MOBS_1 = {24173, 24174, 24175, 24176};
  135. +   private static final int[] CORRIDOR_MOBS_2 = {24180, 24181, 24182, 24183};
  136. +   private static final int[] CORRIDOR_MOBS_3 = {24184, 24185, 24186, 24187, 24188, 24189, 24190, 24191, 24192};
  137. +   private static final int[] NOT_ATK_NPCS =
  138. +   {
  139. +       33798, // Common Decoration - Barricade
  140. +       19677, // Seal of Gnosis
  141. +       19678, // Seal of Strife
  142. +       19679, // Seal of Avarice
  143. +       19680, // Seal of Punishment
  144. +       19681, // Seal of Awakening
  145. +       19682, // Seal of Calamity
  146. +       19683, // Seal of Destruction
  147. +   };
  148. +   private static final int[] ETINA_HELPERS =
  149. +   {
  150. +       34471, // Leona Blackbird
  151. +       34472, // Devianne
  152. +       34473, // Elikia
  153. +       34474, // Sporcha
  154. +       34475, // Aliber
  155. +   };
  156. +   // Skill Cast Locations
  157. +   private static final Location[] SKILL_CAST_LOCATIONS =
  158. +   {
  159. +       new Location(-245751, 182321, 2861, 16612), // First barricade line
  160. +       new Location(-245751, 184001, 3025, 16612), // Second barricade line
  161. +       new Location(-245751, 185298, 3031, 16612), // Third barricade line
  162. +       new Location(-245751, 186612, 3038, 16612), // Fourth barricade line
  163. +   };
  164. +   // Support Npcs Skills
  165. +   private static final SkillHolder BARRICADE_DESTRUCTION = new SkillHolder(32286, 1);
  166. +   // Misc
  167. +   private static final int[] ETINA_SOLO_INSTANCES =
  168. +   {
  169. +       292, // Fall of Etina (Solo)
  170. +       293, // Fall of Etina (Solo)
  171. +   };
  172. +  
  173. +   private EtinaHelperAliber()
  174. +   {
  175. +       setCreatureAttackedId(this::onCreatureAttacked, ETINA_HELPER_ALIBER);
  176. +       addSpellFinishedId(ETINA_HELPER_ALIBER);
  177. +       addSeeCreatureId(ETINA_HELPER_ALIBER);
  178. +       setInstanceStatusChangeId(this::onInstanceStatusChange, ETINA_SOLO_INSTANCES);
  179. +   }
  180. +  
  181. +   @Override
  182. +   public void onTimerEvent(String event, StatSet params, Npc npc, PlayerInstance player)
  183. +   {
  184. +       final Instance instance = npc.getInstanceWorld();
  185. +       if (instance != null)
  186. +       {
  187. +           switch (event)
  188. +           {
  189. +               case "CHECK_ACTION":
  190. +               {
  191. +                   final StatSet npcVars = npc.getVariables();
  192. +                   final PlayerInstance plr = npcVars.getObject("PLAYER_OBJECT", PlayerInstance.class);
  193. +                   final MonsterInstance monster = getRandomEntry(World.getInstance().getVisibleObjectsInRange(npc, MonsterInstance.class, 2500));
  194. +                   if (plr != null)
  195. +                   {
  196. +                       final double distance = npc.calculateDistance2D(plr);
  197. +                       if (!npc.isAttackingNow() && !npc.isMoving() && (distance > 250))
  198. +                       {
  199. +                           final Location loc = new Location(plr.getX(), plr.getY(), plr.getZ() + 50);
  200. +                           final Location randLoc = new Location(loc.getX() + getRandom(-100, 100), loc.getY() + getRandom(-100, 100), loc.getZ());
  201. +                           if (distance > 600)
  202. +                           {
  203. +                               npc.teleToLocation(loc);
  204. +                           }
  205. +                           else
  206. +                           {
  207. +                               npc.setRunning();
  208. +                           }
  209. +                           addMoveToDesire(npc, randLoc, 23);
  210. +                           ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
  211. +                       }
  212. +                       else if (!npc.isInCombat() || !npc.isAttackingNow() || (npc.getTarget() == null))
  213. +                       {
  214. +                           WorldObject target = npc.getTarget();
  215. +                           if (target == null)
  216. +                           {
  217. +                               npc.setTarget(monster);
  218. +                           }
  219. +                           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()))
  220. +                           {
  221. +                               npc.setInvul(true);
  222. +                               npc.setRunning();
  223. +                               ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
  224. +                               addAttackDesire(npc, (Creature) target);
  225. +                               // addSkillCastDesire(npc, target, ALIBER_SPLASH, 23);
  226. +                               // npc.reduceCurrentHp(1, monster, null);
  227. +                           }
  228. +                       }
  229. +                   }
  230. +                   break;
  231. +               }
  232. +               case "DESTROY_BARRICADES":
  233. +               {
  234. +                   final FriendlyNpcInstance _aliber = (FriendlyNpcInstance) instance.getNpc(ETINA_HELPER_ALIBER);
  235. +                   boolean BARRICADE_DESTROYED = instance.getParameters().getBoolean("BARRICADE_DESTROYED", false);
  236. +                   if (!instance.getNpcsOfGroup("BARRICADES_1").isEmpty())
  237. +                   {
  238. +                       _aliber.setRunning();
  239. +                       _aliber.setInvul(true);
  240. +                       _aliber.setCanReturnToSpawnPoint(false);
  241. +                       _aliber.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, SKILL_CAST_LOCATIONS[0]);
  242. +                       if (_aliber.getLocation().isIn2DRadius(SKILL_CAST_LOCATIONS[0], 200) && (BARRICADE_DESTROYED == false))
  243. +                       {
  244. +                           _aliber.broadcastPacket(new MagicSkillUse(_aliber, _aliber, BARRICADE_DESTRUCTION.getSkillId(), 1, 500, 0));
  245. +                           _aliber.broadcastPacket(new ExShowScreenMessage(NpcStringId.ALIBER_IS_CASTING_A_SPELL_TO_DESTROY_THE_BARRICADE, ExShowScreenMessage.TOP_CENTER, 7000, true));
  246. +                           instance.getNpcsOfGroup("BARRICADES_1").forEach(barricade ->
  247. +                           {
  248. +                               if (barricade != null)
  249. +                               {
  250. +                                   barricade.decayMe();
  251. +                               }
  252. +                           });
  253. +                           instance.getParameters().set("BARRICADE_DESTROYED", true);
  254. +                           instance.despawnGroup("BARRICADES_1");
  255. +                       }
  256. +                   }
  257. +                   else if (!instance.getNpcsOfGroup("BARRICADES_2").isEmpty() && instance.getAliveNpcs(CORRIDOR_MOBS_1).isEmpty() && instance.getNpcsOfGroup("BARRICADES_1").isEmpty())
  258. +                   {
  259. +                       _aliber.setRunning();
  260. +                       _aliber.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, SKILL_CAST_LOCATIONS[1]);
  261. +                       if (_aliber.getLocation().isIn2DRadius(SKILL_CAST_LOCATIONS[1], 200) && (BARRICADE_DESTROYED == false))
  262. +                       {
  263. +                           _aliber.broadcastPacket(new MagicSkillUse(_aliber, _aliber, BARRICADE_DESTRUCTION.getSkillId(), 1, 500, 0));
  264. +                           _aliber.broadcastPacket(new ExShowScreenMessage(NpcStringId.ALIBER_IS_CASTING_A_SPELL_TO_DESTROY_THE_BARRICADE, ExShowScreenMessage.TOP_CENTER, 7000, true));
  265. +                           instance.getNpcsOfGroup("BARRICADES_2").forEach(barricade ->
  266. +                           {
  267. +                               if (barricade != null)
  268. +                               {
  269. +                                   barricade.decayMe();
  270. +                               }
  271. +                           });
  272. +                           instance.getParameters().set("BARRICADE_DESTROYED", true);
  273. +                           instance.despawnGroup("BARRICADES_2");
  274. +                       }
  275. +                   }
  276. +                   else if (!instance.getNpcsOfGroup("BARRICADES_3").isEmpty() && instance.getAliveNpcs(CORRIDOR_MOBS_2).isEmpty() && instance.getNpcsOfGroup("BARRICADES_2").isEmpty())
  277. +                   {
  278. +                       _aliber.setRunning();
  279. +                       _aliber.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, SKILL_CAST_LOCATIONS[2]);
  280. +                       if (_aliber.getLocation().isIn2DRadius(SKILL_CAST_LOCATIONS[2], 200) && (BARRICADE_DESTROYED == false))
  281. +                       {
  282. +                           _aliber.broadcastPacket(new MagicSkillUse(_aliber, _aliber, BARRICADE_DESTRUCTION.getSkillId(), 1, 500, 0));
  283. +                           _aliber.broadcastPacket(new ExShowScreenMessage(NpcStringId.ALIBER_IS_CASTING_A_SPELL_TO_DESTROY_THE_BARRICADE, ExShowScreenMessage.TOP_CENTER, 7000, true));
  284. +                           instance.getNpcsOfGroup("BARRICADES_3").forEach(barricade ->
  285. +                           {
  286. +                               if (barricade != null)
  287. +                               {
  288. +                                   barricade.decayMe();
  289. +                               }
  290. +                           });
  291. +                           instance.getParameters().set("BARRICADE_DESTROYED", true);
  292. +                           instance.despawnGroup("BARRICADES_3");
  293. +                       }
  294. +                   }
  295. +                   else if (!instance.getNpcsOfGroup("BARRICADES_4").isEmpty() && instance.getAliveNpcs(CORRIDOR_MOBS_3).isEmpty() && instance.getNpcsOfGroup("BARRICADES_3").isEmpty())
  296. +                   {
  297. +                       _aliber.setRunning();
  298. +                       _aliber.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, SKILL_CAST_LOCATIONS[3]);
  299. +                       if (_aliber.getLocation().isIn2DRadius(SKILL_CAST_LOCATIONS[3], 200) && (BARRICADE_DESTROYED == false))
  300. +                       {
  301. +                           _aliber.broadcastPacket(new MagicSkillUse(_aliber, _aliber, BARRICADE_DESTRUCTION.getSkillId(), 1, 500, 0));
  302. +                           _aliber.broadcastPacket(new ExShowScreenMessage(NpcStringId.ALIBER_IS_CASTING_A_SPELL_TO_DESTROY_THE_BARRICADE, ExShowScreenMessage.TOP_CENTER, 7000, true));
  303. +                           instance.getNpcsOfGroup("BARRICADES_4").forEach(barricade ->
  304. +                           {
  305. +                               if (barricade != null)
  306. +                               {
  307. +                                   barricade.decayMe();
  308. +                               }
  309. +                           });
  310. +                           instance.getParameters().set("BARRICADE_DESTROYED", true);
  311. +                           instance.despawnGroup("BARRICADES_4");
  312. +                       }
  313. +                   }
  314. +               }
  315. +                   break;
  316. +           }
  317. +       }
  318. +   }
  319. +  
  320. +   public void onCreatureAttacked(OnCreatureAttacked event)
  321. +   {
  322. +       final FriendlyNpcInstance npc = (FriendlyNpcInstance) event.getTarget();
  323. +       if (npc != null)
  324. +       {
  325. +           final Instance instance = npc.getInstanceWorld();
  326. +           if ((instance != null) && !event.getAttacker().isPlayable() && !CommonUtil.contains(ETINA_HELPERS, event.getAttacker().getId()))
  327. +           {
  328. +               if (!npc.isInCombat())
  329. +               {
  330. +                   if (getRandom(50) < 5)
  331. +                   {
  332. +                       npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.RAGE_AGAINST_ALL_THAT_STANDS_IN_OUR_WAY);
  333. +                   }
  334. +               }
  335. +           }
  336. +       }
  337. +   }
  338. +  
  339. +   public void onInstanceStatusChange(OnInstanceStatusChange event)
  340. +   {
  341. +       final Instance instance = event.getWorld();
  342. +       final int status = event.getStatus();
  343. +       if ((status == 1) || (status == 2) || (status == 3))
  344. +       {
  345. +           instance.getAliveNpcs(ETINA_HELPER_ALIBER).forEach(etinaHelperAliber -> getTimers().addRepeatingTimer("CHECK_ACTION", 3000, etinaHelperAliber, null));
  346. +           instance.getAliveNpcs(ETINA_HELPER_ALIBER).forEach(etinaHelperAliber -> getTimers().addRepeatingTimer("USE_SKILL", 6000, etinaHelperAliber, null));
  347. +           instance.getAliveNpcs(ETINA_HELPER_ALIBER).forEach(etinaHelperAliber -> getTimers().addRepeatingTimer("DESTROY_BARRICADES", 5000, etinaHelperAliber, null));
  348. +       }
  349. +   }
  350. +  
  351. +   @Override
  352. +   public String onSeeCreature(Npc npc, Creature creature, boolean isSummon)
  353. +   {
  354. +       if (creature.isPlayer())
  355. +       {
  356. +           npc.getVariables().set("PLAYER_OBJECT", creature.getActingPlayer());
  357. +       }
  358. +       return super.onSeeCreature(npc, creature, isSummon);
  359. +   }
  360. +  
  361. +   public static void main(String[] args)
  362. +   {
  363. +       new EtinaHelperAliber();
  364. +   }
  365. +}
  366. \ No newline at end of file
  367. Index: dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperDevianne.java
  368. ===================================================================
  369. --- dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperDevianne.java  (nonexistent)
  370. +++ dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperDevianne.java  (working copy)
  371. @@ -0,0 +1,171 @@
  372. +/*
  373. + * This file is part of the L2J Mobius project.
  374. + *
  375. + * This program is free software: you can redistribute it and/or modify
  376. + * it under the terms of the GNU General Public License as published by
  377. + * the Free Software Foundation, either version 3 of the License, or
  378. + * (at your option) any later version.
  379. + *
  380. + * This program is distributed in the hope that it will be useful,
  381. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  382. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  383. + * General Public License for more details.
  384. + *
  385. + * You should have received a copy of the GNU General Public License
  386. + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  387. + */
  388. +package instances.EtisVanEtinaSolo;
  389. +
  390. +import org.l2jmobius.commons.util.CommonUtil;
  391. +import org.l2jmobius.gameserver.enums.ChatType;
  392. +import org.l2jmobius.gameserver.geoengine.GeoEngine;
  393. +import org.l2jmobius.gameserver.model.Location;
  394. +import org.l2jmobius.gameserver.model.StatSet;
  395. +import org.l2jmobius.gameserver.model.World;
  396. +import org.l2jmobius.gameserver.model.WorldObject;
  397. +import org.l2jmobius.gameserver.model.actor.Creature;
  398. +import org.l2jmobius.gameserver.model.actor.Npc;
  399. +import org.l2jmobius.gameserver.model.actor.instance.FriendlyNpcInstance;
  400. +import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
  401. +import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
  402. +import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureAttacked;
  403. +import org.l2jmobius.gameserver.model.events.impl.instance.OnInstanceStatusChange;
  404. +import org.l2jmobius.gameserver.model.instancezone.Instance;
  405. +import org.l2jmobius.gameserver.network.NpcStringId;
  406. +
  407. +import ai.AbstractNpcAI;
  408. +
  409. +/**
  410. + * Etina Helper Devianne AI.
  411. + * @author CostyKiller
  412. + */
  413. +public class EtinaHelperDevianne extends AbstractNpcAI
  414. +{
  415. +   // NPCs
  416. +   private static final int ETINA_HELPER_DEVIANNE = 34472;
  417. +   private static final int[] NOT_ATK_NPCS =
  418. +   {
  419. +       33798, // Common Decoration - Barricade
  420. +       19677, // Seal of Gnosis
  421. +       19678, // Seal of Strife
  422. +       19679, // Seal of Avarice
  423. +       19680, // Seal of Punishment
  424. +       19681, // Seal of Awakening
  425. +       19682, // Seal of Calamity
  426. +       19683, // Seal of Destruction
  427. +   };
  428. +   private static final int[] ETINA_HELPERS =
  429. +   {
  430. +       34471, // Leona Blackbird
  431. +       34472, // Devianne
  432. +       34473, // Elikia
  433. +       34474, // Sporcha
  434. +       34475, // Aliber
  435. +   };
  436. +   // Misc
  437. +   private static final int[] ETINA_SOLO_INSTANCES =
  438. +   {
  439. +       292, // Fall of Etina (Solo)
  440. +       293, // Fall of Etina (Solo)
  441. +   };
  442. +  
  443. +   private EtinaHelperDevianne()
  444. +   {
  445. +       setCreatureAttackedId(this::onCreatureAttacked, ETINA_HELPER_DEVIANNE);
  446. +       addSpellFinishedId(ETINA_HELPER_DEVIANNE);
  447. +       addSeeCreatureId(ETINA_HELPER_DEVIANNE);
  448. +       setInstanceStatusChangeId(this::onInstanceStatusChange, ETINA_SOLO_INSTANCES);
  449. +   }
  450. +  
  451. +   @Override
  452. +   public void onTimerEvent(String event, StatSet params, Npc npc, PlayerInstance player)
  453. +   {
  454. +       final Instance instance = npc.getInstanceWorld();
  455. +       if ((instance != null) && event.equals("CHECK_ACTION"))
  456. +       {
  457. +           final StatSet npcVars = npc.getVariables();
  458. +           final PlayerInstance plr = npcVars.getObject("PLAYER_OBJECT", PlayerInstance.class);
  459. +           final MonsterInstance monster = getRandomEntry(World.getInstance().getVisibleObjectsInRange(npc, MonsterInstance.class, 2500));
  460. +           if (plr != null)
  461. +           {
  462. +               final double distance = npc.calculateDistance2D(plr);
  463. +               if (!npc.isAttackingNow() && !npc.isMoving() && (distance > 250))
  464. +               {
  465. +                   final Location loc = new Location(plr.getX(), plr.getY(), plr.getZ() + 50);
  466. +                   final Location randLoc = new Location(loc.getX() + getRandom(-100, 100), loc.getY() + getRandom(-100, 100), loc.getZ());
  467. +                   if (distance > 600)
  468. +                   {
  469. +                       npc.teleToLocation(loc);
  470. +                   }
  471. +                   else
  472. +                   {
  473. +                       npc.setRunning();
  474. +                   }
  475. +                   addMoveToDesire(npc, randLoc, 23);
  476. +                   ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
  477. +               }
  478. +               else if (!npc.isInCombat() || !npc.isAttackingNow() || (npc.getTarget() == null))
  479. +               {
  480. +                   WorldObject target = npc.getTarget();
  481. +                   if (target == null)
  482. +                   {
  483. +                       npc.setTarget(monster);
  484. +                   }
  485. +                   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()))
  486. +                   {
  487. +                       npc.setInvul(true);
  488. +                       npc.setRunning();
  489. +                       ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
  490. +                       addAttackDesire(npc, (Creature) target);
  491. +                       // npc.reduceCurrentHp(1, monster, null);
  492. +                   }
  493. +               }
  494. +           }
  495. +       }
  496. +   }
  497. +  
  498. +   public void onCreatureAttacked(OnCreatureAttacked event)
  499. +   {
  500. +       final FriendlyNpcInstance npc = (FriendlyNpcInstance) event.getTarget();
  501. +       if (npc != null)
  502. +       {
  503. +           final Instance instance = npc.getInstanceWorld();
  504. +           if ((instance != null) && !event.getAttacker().isPlayable() && !CommonUtil.contains(ETINA_HELPERS, event.getAttacker().getId()))
  505. +           {
  506. +               if (!npc.isInCombat())
  507. +               {
  508. +                   if (getRandom(50) < 5)
  509. +                   {
  510. +                       npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.BEHOLD_THE_POWER_OF_THE_IVORY_TOWER_WIZARDS);
  511. +                   }
  512. +                  
  513. +               }
  514. +           }
  515. +       }
  516. +   }
  517. +  
  518. +   public void onInstanceStatusChange(OnInstanceStatusChange event)
  519. +   {
  520. +       final Instance instance = event.getWorld();
  521. +       final int status = event.getStatus();
  522. +       if ((status == 1) || (status == 2) || (status == 3))
  523. +       {
  524. +           instance.getAliveNpcs(ETINA_HELPER_DEVIANNE).forEach(etinaHelperDevianne -> getTimers().addRepeatingTimer("CHECK_ACTION", 3000, etinaHelperDevianne, null));
  525. +       }
  526. +   }
  527. +  
  528. +   @Override
  529. +   public String onSeeCreature(Npc npc, Creature creature, boolean isSummon)
  530. +   {
  531. +       if (creature.isPlayer())
  532. +       {
  533. +           npc.getVariables().set("PLAYER_OBJECT", creature.getActingPlayer());
  534. +       }
  535. +       return super.onSeeCreature(npc, creature, isSummon);
  536. +   }
  537. +  
  538. +   public static void main(String[] args)
  539. +   {
  540. +       new EtinaHelperDevianne();
  541. +   }
  542. +}
  543. \ No newline at end of file
  544. Index: dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperElikia.java
  545. ===================================================================
  546. --- dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperElikia.java    (nonexistent)
  547. +++ dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperElikia.java    (working copy)
  548. @@ -0,0 +1,170 @@
  549. +/*
  550. + * This file is part of the L2J Mobius project.
  551. + *
  552. + * This program is free software: you can redistribute it and/or modify
  553. + * it under the terms of the GNU General Public License as published by
  554. + * the Free Software Foundation, either version 3 of the License, or
  555. + * (at your option) any later version.
  556. + *
  557. + * This program is distributed in the hope that it will be useful,
  558. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  559. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  560. + * General Public License for more details.
  561. + *
  562. + * You should have received a copy of the GNU General Public License
  563. + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  564. + */
  565. +package instances.EtisVanEtinaSolo;
  566. +
  567. +import org.l2jmobius.commons.util.CommonUtil;
  568. +import org.l2jmobius.gameserver.enums.ChatType;
  569. +import org.l2jmobius.gameserver.geoengine.GeoEngine;
  570. +import org.l2jmobius.gameserver.model.Location;
  571. +import org.l2jmobius.gameserver.model.StatSet;
  572. +import org.l2jmobius.gameserver.model.World;
  573. +import org.l2jmobius.gameserver.model.WorldObject;
  574. +import org.l2jmobius.gameserver.model.actor.Creature;
  575. +import org.l2jmobius.gameserver.model.actor.Npc;
  576. +import org.l2jmobius.gameserver.model.actor.instance.FriendlyNpcInstance;
  577. +import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
  578. +import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
  579. +import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureAttacked;
  580. +import org.l2jmobius.gameserver.model.events.impl.instance.OnInstanceStatusChange;
  581. +import org.l2jmobius.gameserver.model.instancezone.Instance;
  582. +import org.l2jmobius.gameserver.network.NpcStringId;
  583. +
  584. +import ai.AbstractNpcAI;
  585. +
  586. +/**
  587. + * Etina Helper Elikia AI.
  588. + * @author CostyKiller
  589. + */
  590. +public class EtinaHelperElikia extends AbstractNpcAI
  591. +{
  592. +   // NPCs
  593. +   private static final int ETINA_HELPER_ELIKIA = 34473;
  594. +   private static final int[] NOT_ATK_NPCS =
  595. +   {
  596. +       33798, // Common Decoration - Barricade
  597. +       19677, // Seal of Gnosis
  598. +       19678, // Seal of Strife
  599. +       19679, // Seal of Avarice
  600. +       19680, // Seal of Punishment
  601. +       19681, // Seal of Awakening
  602. +       19682, // Seal of Calamity
  603. +       19683, // Seal of Destruction
  604. +   };
  605. +   private static final int[] ETINA_HELPERS =
  606. +   {
  607. +       34471, // Leona Blackbird
  608. +       34472, // Devianne
  609. +       34473, // Elikia
  610. +       34474, // Sporcha
  611. +       34475, // Aliber
  612. +   };
  613. +   // Misc
  614. +   private static final int[] ETINA_SOLO_INSTANCES =
  615. +   {
  616. +       292, // Fall of Etina (Solo)
  617. +       293, // Fall of Etina (Solo)
  618. +   };
  619. +  
  620. +   private EtinaHelperElikia()
  621. +   {
  622. +       setCreatureAttackedId(this::onCreatureAttacked, ETINA_HELPER_ELIKIA);
  623. +       addSpellFinishedId(ETINA_HELPER_ELIKIA);
  624. +       addSeeCreatureId(ETINA_HELPER_ELIKIA);
  625. +       setInstanceStatusChangeId(this::onInstanceStatusChange, ETINA_SOLO_INSTANCES);
  626. +   }
  627. +  
  628. +   @Override
  629. +   public void onTimerEvent(String event, StatSet params, Npc npc, PlayerInstance player)
  630. +   {
  631. +       final Instance instance = npc.getInstanceWorld();
  632. +       if ((instance != null) && event.equals("CHECK_ACTION"))
  633. +       {
  634. +           final StatSet npcVars = npc.getVariables();
  635. +           final PlayerInstance plr = npcVars.getObject("PLAYER_OBJECT", PlayerInstance.class);
  636. +           final MonsterInstance monster = getRandomEntry(World.getInstance().getVisibleObjectsInRange(npc, MonsterInstance.class, 2500));
  637. +           if (plr != null)
  638. +           {
  639. +               final double distance = npc.calculateDistance2D(plr);
  640. +               if (!npc.isAttackingNow() && !npc.isMoving() && (distance > 250))
  641. +               {
  642. +                   final Location loc = new Location(plr.getX(), plr.getY(), plr.getZ() + 50);
  643. +                   final Location randLoc = new Location(loc.getX() + getRandom(-100, 100), loc.getY() + getRandom(-100, 100), loc.getZ());
  644. +                   if (distance > 600)
  645. +                   {
  646. +                       npc.teleToLocation(loc);
  647. +                   }
  648. +                   else
  649. +                   {
  650. +                       npc.setRunning();
  651. +                   }
  652. +                   addMoveToDesire(npc, randLoc, 23);
  653. +                   ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
  654. +               }
  655. +               else if (!npc.isInCombat() || !npc.isAttackingNow() || (npc.getTarget() == null))
  656. +               {
  657. +                   WorldObject target = npc.getTarget();
  658. +                   if (target == null)
  659. +                   {
  660. +                       npc.setTarget(monster);
  661. +                   }
  662. +                   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()))
  663. +                   {
  664. +                       npc.setInvul(true);
  665. +                       npc.setRunning();
  666. +                       ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
  667. +                       addAttackDesire(npc, (Creature) target);
  668. +                       // npc.reduceCurrentHp(1, monster, null);
  669. +                   }
  670. +               }
  671. +           }
  672. +       }
  673. +   }
  674. +  
  675. +   public void onCreatureAttacked(OnCreatureAttacked event)
  676. +   {
  677. +       final FriendlyNpcInstance npc = (FriendlyNpcInstance) event.getTarget();
  678. +       if (npc != null)
  679. +       {
  680. +           final Instance instance = npc.getInstanceWorld();
  681. +           if ((instance != null) && !event.getAttacker().isPlayable() && !CommonUtil.contains(ETINA_HELPERS, event.getAttacker().getId()))
  682. +           {
  683. +               if (!npc.isInCombat())
  684. +               {
  685. +                   if (getRandom(50) < 5)
  686. +                   {
  687. +                       npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.DON_T_GET_IN_MY_WAY);
  688. +                   }
  689. +               }
  690. +           }
  691. +       }
  692. +   }
  693. +  
  694. +   public void onInstanceStatusChange(OnInstanceStatusChange event)
  695. +   {
  696. +       final Instance instance = event.getWorld();
  697. +       final int status = event.getStatus();
  698. +       if ((status == 1) || (status == 2) || (status == 3))
  699. +       {
  700. +           instance.getAliveNpcs(ETINA_HELPER_ELIKIA).forEach(etinaHelperElikia -> getTimers().addRepeatingTimer("CHECK_ACTION", 3000, etinaHelperElikia, null));
  701. +       }
  702. +   }
  703. +  
  704. +   @Override
  705. +   public String onSeeCreature(Npc npc, Creature creature, boolean isSummon)
  706. +   {
  707. +       if (creature.isPlayer())
  708. +       {
  709. +           npc.getVariables().set("PLAYER_OBJECT", creature.getActingPlayer());
  710. +       }
  711. +       return super.onSeeCreature(npc, creature, isSummon);
  712. +   }
  713. +  
  714. +   public static void main(String[] args)
  715. +   {
  716. +       new EtinaHelperElikia();
  717. +   }
  718. +}
  719. \ No newline at end of file
  720. Index: dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperLeona.java
  721. ===================================================================
  722. --- dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperLeona.java (nonexistent)
  723. +++ dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperLeona.java (working copy)
  724. @@ -0,0 +1,203 @@
  725. +/*
  726. + * This file is part of the L2J Mobius project.
  727. + *
  728. + * This program is free software: you can redistribute it and/or modify
  729. + * it under the terms of the GNU General Public License as published by
  730. + * the Free Software Foundation, either version 3 of the License, or
  731. + * (at your option) any later version.
  732. + *
  733. + * This program is distributed in the hope that it will be useful,
  734. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  735. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  736. + * General Public License for more details.
  737. + *
  738. + * You should have received a copy of the GNU General Public License
  739. + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  740. + */
  741. +package instances.EtisVanEtinaSolo;
  742. +
  743. +import org.l2jmobius.commons.util.CommonUtil;
  744. +import org.l2jmobius.gameserver.enums.ChatType;
  745. +import org.l2jmobius.gameserver.geoengine.GeoEngine;
  746. +import org.l2jmobius.gameserver.model.Location;
  747. +import org.l2jmobius.gameserver.model.StatSet;
  748. +import org.l2jmobius.gameserver.model.World;
  749. +import org.l2jmobius.gameserver.model.WorldObject;
  750. +import org.l2jmobius.gameserver.model.actor.Creature;
  751. +import org.l2jmobius.gameserver.model.actor.Npc;
  752. +import org.l2jmobius.gameserver.model.actor.instance.FriendlyNpcInstance;
  753. +import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
  754. +import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
  755. +import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureAttacked;
  756. +import org.l2jmobius.gameserver.model.events.impl.instance.OnInstanceStatusChange;
  757. +import org.l2jmobius.gameserver.model.instancezone.Instance;
  758. +import org.l2jmobius.gameserver.network.NpcStringId;
  759. +
  760. +import ai.AbstractNpcAI;
  761. +
  762. +/**
  763. + * Etina Helper Leona AI.
  764. + * @author CostyKiller
  765. + */
  766. +public class EtinaHelperLeona extends AbstractNpcAI
  767. +{
  768. +   // NPCs
  769. +   private static final int ETINA_HELPER_LEONA = 34471;
  770. +   private static final int[] NOT_ATK_NPCS =
  771. +   {
  772. +       33798, // Common Decoration - Barricade
  773. +       19677, // Seal of Gnosis
  774. +       19678, // Seal of Strife
  775. +       19679, // Seal of Avarice
  776. +       19680, // Seal of Punishment
  777. +       19681, // Seal of Awakening
  778. +       19682, // Seal of Calamity
  779. +       19683, // Seal of Destruction
  780. +   };
  781. +   private static final int[] ETINA_HELPERS =
  782. +   {
  783. +       34471, // Leona Blackbird
  784. +       34472, // Devianne
  785. +       34473, // Elikia
  786. +       34474, // Sporcha
  787. +       34475, // Aliber
  788. +   };
  789. +   // RB
  790. +   private static final int ETIS_VAN_ETINA1 = 26321;
  791. +   private static final int ETIS_VAN_ETINA2 = 26322;
  792. +   private static final int KAIN_VAN_HALTER = 26235;
  793. +   private static final int CAMILLE = 26236;
  794. +   // Misc
  795. +   private static final int[] ETINA_SOLO_INSTANCES =
  796. +   {
  797. +       292, // Fall of Etina (Solo)
  798. +       293, // Fall of Etina (Solo)
  799. +   };
  800. +  
  801. +   private EtinaHelperLeona()
  802. +   {
  803. +       setCreatureAttackedId(this::onCreatureAttacked, ETINA_HELPER_LEONA);
  804. +       addSpellFinishedId(ETINA_HELPER_LEONA);
  805. +       addSeeCreatureId(ETINA_HELPER_LEONA);
  806. +       setInstanceStatusChangeId(this::onInstanceStatusChange, ETINA_SOLO_INSTANCES);
  807. +   }
  808. +  
  809. +   @Override
  810. +   public void onTimerEvent(String event, StatSet params, Npc npc, PlayerInstance player)
  811. +   {
  812. +       final Instance instance = npc.getInstanceWorld();
  813. +       if ((instance != null) && event.equals("CHECK_ACTION"))
  814. +       {
  815. +           final StatSet npcVars = npc.getVariables();
  816. +           final PlayerInstance plr = npcVars.getObject("PLAYER_OBJECT", PlayerInstance.class);
  817. +           final MonsterInstance monster = getRandomEntry(World.getInstance().getVisibleObjectsInRange(npc, MonsterInstance.class, 2500));
  818. +           if (plr != null)
  819. +           {
  820. +               final double distance = npc.calculateDistance2D(plr);
  821. +               if (!npc.isAttackingNow() && !npc.isMoving() && (distance > 250))
  822. +               {
  823. +                   final Location loc = new Location(plr.getX(), plr.getY(), plr.getZ() + 50);
  824. +                   final Location randLoc = new Location(loc.getX() + getRandom(-100, 100), loc.getY() + getRandom(-100, 100), loc.getZ());
  825. +                   if (distance > 600)
  826. +                   {
  827. +                       npc.teleToLocation(loc);
  828. +                   }
  829. +                   else
  830. +                   {
  831. +                       npc.setRunning();
  832. +                   }
  833. +                   addMoveToDesire(npc, randLoc, 23);
  834. +                   ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
  835. +               }
  836. +               else if (!npc.isInCombat() || !npc.isAttackingNow() || (npc.getTarget() == null))
  837. +               {
  838. +                   WorldObject target = npc.getTarget();
  839. +                   if (target == null)
  840. +                   {
  841. +                       npc.setTarget(monster);
  842. +                   }
  843. +                   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()))
  844. +                   {
  845. +                       npc.setInvul(true);
  846. +                       npc.setRunning();
  847. +                       ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
  848. +                       addAttackDesire(npc, (Creature) target);
  849. +                       // npc.reduceCurrentHp(1, monster, null);
  850. +                   }
  851. +               }
  852. +           }
  853. +       }
  854. +   }
  855. +  
  856. +   public void onCreatureAttacked(OnCreatureAttacked event)
  857. +   {
  858. +       final FriendlyNpcInstance npc = (FriendlyNpcInstance) event.getTarget();
  859. +       final Npc attacker = (Npc) event.getAttacker();
  860. +       if (npc != null)
  861. +       {
  862. +           final Instance instance = npc.getInstanceWorld();
  863. +           if ((instance != null) && !event.getAttacker().isPlayable() && !CommonUtil.contains(ETINA_HELPERS, event.getAttacker().getId()))
  864. +           {
  865. +               if (!npc.isInCombat())
  866. +               {
  867. +                   switch (attacker.getId())
  868. +                   {
  869. +                       default:
  870. +                       {
  871. +                           if (getRandom(50) < 5)
  872. +                           {
  873. +                               npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.DON_T_GET_IN_MY_WAY);
  874. +                           }
  875. +                           break;
  876. +                       }
  877. +                       case CAMILLE:
  878. +                       {
  879. +                           npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.GISELLE_NO_IS_SHE_CAMILLE_IN_THAT_STATE);
  880. +                           break;
  881. +                       }
  882. +                       case KAIN_VAN_HALTER:
  883. +                       {
  884. +                           break;
  885. +                       }
  886. +                       case ETIS_VAN_ETINA1:
  887. +                       {
  888. +                           npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.EVEN_THE_MIGHTY_ETINA_SEEMS_TO_FEAR_US);
  889. +                           break;
  890. +                       }
  891. +                       case ETIS_VAN_ETINA2:
  892. +                       {
  893. +                           npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.ETIS_VAN_ETINA_WE_FINALLY_MEET);
  894. +                           break;
  895. +                       }
  896. +                   }
  897. +               }
  898. +           }
  899. +       }
  900. +   }
  901. +  
  902. +   public void onInstanceStatusChange(OnInstanceStatusChange event)
  903. +   {
  904. +       final Instance instance = event.getWorld();
  905. +       final int status = event.getStatus();
  906. +       if ((status == 1) || (status == 2) || (status == 3))
  907. +       {
  908. +           instance.getAliveNpcs(ETINA_HELPER_LEONA).forEach(etinaHelperLeona -> getTimers().addRepeatingTimer("CHECK_ACTION", 3000, etinaHelperLeona, null));
  909. +           // instance.getAliveNpcs(ETINA_HELPER_LEONA).forEach(etinaHelperLeona -> getTimers().addRepeatingTimer("USE_SKILL", 6000, etinaHelperLeona, null));
  910. +       }
  911. +   }
  912. +  
  913. +   @Override
  914. +   public String onSeeCreature(Npc npc, Creature creature, boolean isSummon)
  915. +   {
  916. +       if (creature.isPlayer())
  917. +       {
  918. +           npc.getVariables().set("PLAYER_OBJECT", creature.getActingPlayer());
  919. +       }
  920. +       return super.onSeeCreature(npc, creature, isSummon);
  921. +   }
  922. +  
  923. +   public static void main(String[] args)
  924. +   {
  925. +       new EtinaHelperLeona();
  926. +   }
  927. +}
  928. \ No newline at end of file
  929. Index: dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperSporcha.java
  930. ===================================================================
  931. --- dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperSporcha.java   (nonexistent)
  932. +++ dist/game/data/scripts/instances/EtisVanEtinaSolo/EtinaHelperSporcha.java   (working copy)
  933. @@ -0,0 +1,170 @@
  934. +/*
  935. + * This file is part of the L2J Mobius project.
  936. + *
  937. + * This program is free software: you can redistribute it and/or modify
  938. + * it under the terms of the GNU General Public License as published by
  939. + * the Free Software Foundation, either version 3 of the License, or
  940. + * (at your option) any later version.
  941. + *
  942. + * This program is distributed in the hope that it will be useful,
  943. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  944. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  945. + * General Public License for more details.
  946. + *
  947. + * You should have received a copy of the GNU General Public License
  948. + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  949. + */
  950. +package instances.EtisVanEtinaSolo;
  951. +
  952. +import org.l2jmobius.commons.util.CommonUtil;
  953. +import org.l2jmobius.gameserver.enums.ChatType;
  954. +import org.l2jmobius.gameserver.geoengine.GeoEngine;
  955. +import org.l2jmobius.gameserver.model.Location;
  956. +import org.l2jmobius.gameserver.model.StatSet;
  957. +import org.l2jmobius.gameserver.model.World;
  958. +import org.l2jmobius.gameserver.model.WorldObject;
  959. +import org.l2jmobius.gameserver.model.actor.Creature;
  960. +import org.l2jmobius.gameserver.model.actor.Npc;
  961. +import org.l2jmobius.gameserver.model.actor.instance.FriendlyNpcInstance;
  962. +import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
  963. +import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
  964. +import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureAttacked;
  965. +import org.l2jmobius.gameserver.model.events.impl.instance.OnInstanceStatusChange;
  966. +import org.l2jmobius.gameserver.model.instancezone.Instance;
  967. +import org.l2jmobius.gameserver.network.NpcStringId;
  968. +
  969. +import ai.AbstractNpcAI;
  970. +
  971. +/**
  972. + * Etina Helper Sporcha AI.
  973. + * @author CostyKiller
  974. + */
  975. +public class EtinaHelperSporcha extends AbstractNpcAI
  976. +{
  977. +   // NPCs
  978. +   private static final int ETINA_HELPER_SPORCHA = 34474;
  979. +   private static final int[] NOT_ATK_NPCS =
  980. +   {
  981. +       33798, // Common Decoration - Barricade
  982. +       19677, // Seal of Gnosis
  983. +       19678, // Seal of Strife
  984. +       19679, // Seal of Avarice
  985. +       19680, // Seal of Punishment
  986. +       19681, // Seal of Awakening
  987. +       19682, // Seal of Calamity
  988. +       19683, // Seal of Destruction
  989. +   };
  990. +   private static final int[] ETINA_HELPERS =
  991. +   {
  992. +       34471, // Leona Blackbird
  993. +       34472, // Devianne
  994. +       34473, // Elikia
  995. +       34474, // Sporcha
  996. +       34475, // Aliber
  997. +   };
  998. +   // Misc
  999. +   private static final int[] ETINA_SOLO_INSTANCES =
  1000. +   {
  1001. +       292, // Fall of Etina (Solo)
  1002. +       293, // Fall of Etina (Solo)
  1003. +   };
  1004. +  
  1005. +   private EtinaHelperSporcha()
  1006. +   {
  1007. +       setCreatureAttackedId(this::onCreatureAttacked, ETINA_HELPER_SPORCHA);
  1008. +       addSpellFinishedId(ETINA_HELPER_SPORCHA);
  1009. +       addSeeCreatureId(ETINA_HELPER_SPORCHA);
  1010. +       setInstanceStatusChangeId(this::onInstanceStatusChange, ETINA_SOLO_INSTANCES);
  1011. +   }
  1012. +  
  1013. +   @Override
  1014. +   public void onTimerEvent(String event, StatSet params, Npc npc, PlayerInstance player)
  1015. +   {
  1016. +       final Instance instance = npc.getInstanceWorld();
  1017. +       if ((instance != null) && event.equals("CHECK_ACTION"))
  1018. +       {
  1019. +           final StatSet npcVars = npc.getVariables();
  1020. +           final PlayerInstance plr = npcVars.getObject("PLAYER_OBJECT", PlayerInstance.class);
  1021. +           final MonsterInstance monster = getRandomEntry(World.getInstance().getVisibleObjectsInRange(npc, MonsterInstance.class, 2500));
  1022. +           if (plr != null)
  1023. +           {
  1024. +               final double distance = npc.calculateDistance2D(plr);
  1025. +               if (!npc.isAttackingNow() && !npc.isMoving() && (distance > 250))
  1026. +               {
  1027. +                   final Location loc = new Location(plr.getX(), plr.getY(), plr.getZ() + 50);
  1028. +                   final Location randLoc = new Location(loc.getX() + getRandom(-100, 100), loc.getY() + getRandom(-100, 100), loc.getZ());
  1029. +                   if (distance > 600)
  1030. +                   {
  1031. +                       npc.teleToLocation(loc);
  1032. +                   }
  1033. +                   else
  1034. +                   {
  1035. +                       npc.setRunning();
  1036. +                   }
  1037. +                   addMoveToDesire(npc, randLoc, 23);
  1038. +                   ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
  1039. +               }
  1040. +               else if (!npc.isInCombat() || !npc.isAttackingNow() || (npc.getTarget() == null))
  1041. +               {
  1042. +                   WorldObject target = npc.getTarget();
  1043. +                   if (target == null)
  1044. +                   {
  1045. +                       npc.setTarget(monster);
  1046. +                   }
  1047. +                   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()))
  1048. +                   {
  1049. +                       npc.setInvul(true);
  1050. +                       npc.setRunning();
  1051. +                       ((FriendlyNpcInstance) npc).setCanReturnToSpawnPoint(false);
  1052. +                       addAttackDesire(npc, (Creature) target);
  1053. +                       // npc.reduceCurrentHp(1, monster, null);
  1054. +                   }
  1055. +               }
  1056. +           }
  1057. +       }
  1058. +   }
  1059. +  
  1060. +   public void onCreatureAttacked(OnCreatureAttacked event)
  1061. +   {
  1062. +       final FriendlyNpcInstance npc = (FriendlyNpcInstance) event.getTarget();
  1063. +       if (npc != null)
  1064. +       {
  1065. +           final Instance instance = npc.getInstanceWorld();
  1066. +           if ((instance != null) && !event.getAttacker().isPlayable() && !CommonUtil.contains(ETINA_HELPERS, event.getAttacker().getId()))
  1067. +           {
  1068. +               if (!npc.isInCombat())
  1069. +               {
  1070. +                   if (getRandom(50) < 5)
  1071. +                   {
  1072. +                       npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.DON_T_GET_IN_MY_WAY);
  1073. +                   }
  1074. +               }
  1075. +           }
  1076. +       }
  1077. +   }
  1078. +  
  1079. +   public void onInstanceStatusChange(OnInstanceStatusChange event)
  1080. +   {
  1081. +       final Instance instance = event.getWorld();
  1082. +       final int status = event.getStatus();
  1083. +       if ((status == 1) || (status == 2) || (status == 3))
  1084. +       {
  1085. +           instance.getAliveNpcs(ETINA_HELPER_SPORCHA).forEach(etinaHelperSporcha -> getTimers().addRepeatingTimer("CHECK_ACTION", 3000, etinaHelperSporcha, null));
  1086. +       }
  1087. +   }
  1088. +  
  1089. +   @Override
  1090. +   public String onSeeCreature(Npc npc, Creature creature, boolean isSummon)
  1091. +   {
  1092. +       if (creature.isPlayer())
  1093. +       {
  1094. +           npc.getVariables().set("PLAYER_OBJECT", creature.getActingPlayer());
  1095. +       }
  1096. +       return super.onSeeCreature(npc, creature, isSummon);
  1097. +   }
  1098. +  
  1099. +   public static void main(String[] args)
  1100. +   {
  1101. +       new EtinaHelperSporcha();
  1102. +   }
  1103. +}
  1104. \ No newline at end of file
  1105. Index: dist/game/data/scripts/instances/EtisVanEtinaSolo/EtisVanEtinaSolo.java
  1106. ===================================================================
  1107. --- dist/game/data/scripts/instances/EtisVanEtinaSolo/EtisVanEtinaSolo.java (nonexistent)
  1108. +++ dist/game/data/scripts/instances/EtisVanEtinaSolo/EtisVanEtinaSolo.java (working copy)
  1109. @@ -0,0 +1,723 @@
  1110. +/*
  1111. + * This file is part of the L2J Mobius project.
  1112. + *
  1113. + * This program is free software: you can redistribute it and/or modify
  1114. + * it under the terms of the GNU General Public License as published by
  1115. + * the Free Software Foundation, either version 3 of the License, or
  1116. + * (at your option) any later version.
  1117. + *
  1118. + * This program is distributed in the hope that it will be useful,
  1119. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1120. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  1121. + * General Public License for more details.
  1122. + *
  1123. + * You should have received a copy of the GNU General Public License
  1124. + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  1125. + */
  1126. +package instances.EtisVanEtinaSolo;
  1127. +
  1128. +import org.l2jmobius.commons.util.CommonUtil;
  1129. +import org.l2jmobius.gameserver.enums.ChatType;
  1130. +import org.l2jmobius.gameserver.enums.Movie;
  1131. +import org.l2jmobius.gameserver.model.World;
  1132. +import org.l2jmobius.gameserver.model.actor.Attackable;
  1133. +import org.l2jmobius.gameserver.model.actor.Npc;
  1134. +import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
  1135. +import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
  1136. +import org.l2jmobius.gameserver.model.holders.SkillHolder;
  1137. +import org.l2jmobius.gameserver.model.instancezone.Instance;
  1138. +import org.l2jmobius.gameserver.model.skills.AbnormalVisualEffect;
  1139. +import org.l2jmobius.gameserver.network.NpcStringId;
  1140. +import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
  1141. +import org.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
  1142. +
  1143. +import instances.AbstractInstance;
  1144. +
  1145. +/**
  1146. + * @author CostyKiller
  1147. + * @URL: https://l2wiki.com/Fall_of_Etina_(Solo)
  1148. + * @URL: https://youtu.be/3flFpg0KGcA
  1149. + * @TODO: Add helper npcs skills
  1150. + * @TODO: Add instance buff Elikia Emblem
  1151. + */
  1152. +public class EtisVanEtinaSolo extends AbstractInstance
  1153. +{
  1154. +   // NPC
  1155. +   private static final int LEONA_OUTLET = 34426;
  1156. +   private static final int LEONA_BLACKBIRD = 34471;
  1157. +   private static final int DEVIANNE = 34472;
  1158. +   private static final int ELIKIA = 34473;
  1159. +   private static final int SPORCHA = 34474;
  1160. +   private static final int ALIBER = 34475;
  1161. +   // RB
  1162. +   private static final int ETIS_VAN_ETINA1 = 26321;
  1163. +   private static final int ETIS_VAN_ETINA2 = 26322;
  1164. +   private static final int KAIN_VAN_HALTER = 26235;
  1165. +   private static final int CAMILLE = 26236;
  1166. +   // Corridor Mobs
  1167. +   //@formatter:off
  1168. +   private static final int[] CORRIDOR_MOBS_1 = {24173, 24174, 24175, 24176};
  1169. +   private static final int[] CORRIDOR_MOBS_2 = {24180, 24181, 24182, 24183};
  1170. +   private static final int[] CORRIDOR_MOBS_3 = {24184, 24185, 24186, 24187, 24188, 24189, 24190, 24191, 24192};
  1171. +   private static final int[] CORRIDOR_MOBS_4 = {24189, 24190, 24191, 24192};
  1172. +   //@formatter:on
  1173. +   private static final int PARAGON = 24193;
  1174. +   // Seals
  1175. +   private static final int SEAL_OF_GNOSIS = 19677;
  1176. +   private static final int SEAL_OF_STRIFE = 19678;
  1177. +   private static final int SEAL_OF_AVARICE = 19679;
  1178. +   private static final int SEAL_OF_PUNISHMENT = 19680;
  1179. +   private static final int SEAL_OF_AWAKENING = 19681;
  1180. +   private static final int SEAL_OF_CALAMITY = 19682;
  1181. +   private static final int SEAL_OF_DESTRUCTION = 19683;
  1182. +   // Others
  1183. +   private static final int DOOR1 = 12230702;
  1184. +   private static final int DOOR2 = 12230704;
  1185. +   private static final int DOOR3 = 12230802;
  1186. +   private static final int DOOR4 = 12230804;
  1187. +   // Skills
  1188. +   private static final SkillHolder CALL_OF_SEVEN_SIGNS = new SkillHolder(32317, 1);
  1189. +   private static final SkillHolder CALL_OF_SEVEN_SIGNS_SEAL_N = new SkillHolder(32004, 1);
  1190. +   private static final SkillHolder ETINA_REVELATION = new SkillHolder(32014, 2);
  1191. +   private static final SkillHolder STIGMA_OF_REVELATION = new SkillHolder(32015, 1);
  1192. +   private static final SkillHolder CRY_OF_HOLY_WAR = new SkillHolder(32017, 2);
  1193. +   private static final SkillHolder STIGMA_OF_MARTYR = new SkillHolder(32018, 1);
  1194. +   private static final SkillHolder UNDEAD_CREATURE = new SkillHolder(32020, 2);
  1195. +   private static final SkillHolder ETINA_DIVINE_PUNISHMENT = new SkillHolder(32023, 2);
  1196. +   private static final SkillHolder ETINA_OBSERVATION = new SkillHolder(32024, 2);
  1197. +   private static final SkillHolder RAGE_OF_THE_OPEN_EYE = new SkillHolder(32026, 2);
  1198. +  
  1199. +   // Camille -> Horseshoe Trampling, Horizon Bash, Joust Lunge, Call of Etina (summon minions?)
  1200. +   // Misc
  1201. +   private static final int TEMPLATE_ID = 293;
  1202. +  
  1203. +   public EtisVanEtinaSolo()
  1204. +   {
  1205. +       super(TEMPLATE_ID);
  1206. +       addInstanceCreatedId(TEMPLATE_ID);
  1207. +       addStartNpc(LEONA_OUTLET);
  1208. +       addTalkId(LEONA_OUTLET, LEONA_BLACKBIRD);
  1209. +       addFirstTalkId(LEONA_BLACKBIRD, DEVIANNE, ELIKIA, SPORCHA, ALIBER);
  1210. +       addAttackId(CORRIDOR_MOBS_1);
  1211. +       addAttackId(CORRIDOR_MOBS_2);
  1212. +       addAttackId(CORRIDOR_MOBS_3);
  1213. +       addAttackId(CORRIDOR_MOBS_4);
  1214. +       addAttackId(CAMILLE, KAIN_VAN_HALTER, ETIS_VAN_ETINA1, ETIS_VAN_ETINA2);
  1215. +       addKillId(CORRIDOR_MOBS_1);
  1216. +       addKillId(CORRIDOR_MOBS_2);
  1217. +       addKillId(CORRIDOR_MOBS_3);
  1218. +       addKillId(CORRIDOR_MOBS_4);
  1219. +       addKillId(PARAGON, CAMILLE, KAIN_VAN_HALTER, ETIS_VAN_ETINA1, ETIS_VAN_ETINA2);
  1220. +   }
  1221. +  
  1222. +   @Override
  1223. +   public void onInstanceCreated(Instance world, PlayerInstance player)
  1224. +   {
  1225. +       world.setStatus(0);
  1226. +       world.getParameters().set("BARRICADE_DESTROYED", false);
  1227. +       world.getParameters().set("CORRIDOR_MOBS_1_SPAWNED", false);
  1228. +       world.getParameters().set("CORRIDOR_MOBS_2_SPAWNED", false);
  1229. +       world.getParameters().set("CORRIDOR_MOBS_3_SPAWNED", false);
  1230. +       world.getParameters().set("CORRIDOR_MOBS_4_SPAWNED", false);
  1231. +       world.getParameters().set("CAMILLE_30", false);
  1232. +       world.getParameters().set("CAMILLE_60", false);
  1233. +       world.getParameters().set("KAIN_30", false);
  1234. +       world.getParameters().set("KAIN_60", false);
  1235. +       world.getParameters().set("ETINA_80", false);
  1236. +       world.getParameters().set("ETINA_15", false);
  1237. +   }
  1238. +  
  1239. +   @Override
  1240. +   public String onAdvEvent(String event, Npc npc, PlayerInstance player)
  1241. +   {
  1242. +       switch (event)
  1243. +       {
  1244. +           case "enterInstance":
  1245. +           {
  1246. +               playMovie(player, Movie.EP5_ETINA_QST_START_A);
  1247. +               startQuestTimer("enterEtina", 20000, npc, player);
  1248. +               startQuestTimer("intro_movie", 20000, npc, player);
  1249. +               startQuestTimer("talkLeona", 25000, npc, player);
  1250. +               break;
  1251. +           }
  1252. +           case "enterEtina":
  1253. +           {
  1254. +               enterInstance(player, npc, TEMPLATE_ID);
  1255. +               break;
  1256. +           }
  1257. +           case "intro_movie":
  1258. +           {
  1259. +               final Instance world = player.getInstanceWorld();
  1260. +               if (isInInstance(world))
  1261. +               {
  1262. +                   playMovie(world.getPlayers(), Movie.EP5_ETINA_QST_START_B);
  1263. +               }
  1264. +               break;
  1265. +           }
  1266. +           case "talkLeona":
  1267. +           {
  1268. +               final Instance world = player.getInstanceWorld();
  1269. +               if (isInInstance(world))
  1270. +               {
  1271. +                   showOnScreenMsg(world, NpcStringId.TALK_TO_LEONA_BLACKBIRD_13, ExShowScreenMessage.TOP_CENTER, 10000, true);
  1272. +               }
  1273. +               break;
  1274. +           }
  1275. +           case "startStage1":
  1276. +           {
  1277. +               final Instance world = player.getInstanceWorld();
  1278. +               if (isInInstance(world))
  1279. +               {
  1280. +                   showOnScreenMsg(world, NpcStringId.ALRIGHT_LET_S_GO_DEFEAT_ETIS_VAN_ETINA, ExShowScreenMessage.TOP_CENTER, 7000, true);
  1281. +                   startQuestTimer("checkProgress", 5000, npc, player, true);
  1282. +                   world.setStatus(1);
  1283. +                   return "34471-01.html";
  1284. +               }
  1285. +               break;
  1286. +           }
  1287. +           case "checkProgress":
  1288. +           {
  1289. +               final Instance world = player.getInstanceWorld();
  1290. +               boolean CORRIDOR_MOBS_1_SPAWNED = world.getParameters().getBoolean("CORRIDOR_MOBS_1_SPAWNED", false);
  1291. +               boolean CORRIDOR_MOBS_2_SPAWNED = world.getParameters().getBoolean("CORRIDOR_MOBS_2_SPAWNED", false);
  1292. +               boolean CORRIDOR_MOBS_3_SPAWNED = world.getParameters().getBoolean("CORRIDOR_MOBS_3_SPAWNED", false);
  1293. +               boolean CORRIDOR_MOBS_4_SPAWNED = world.getParameters().getBoolean("CORRIDOR_MOBS_4_SPAWNED", false);
  1294. +               if (isInInstance(world))
  1295. +               {
  1296. +                   final MonsterInstance monsterCheck = getRandomEntry(World.getInstance().getVisibleObjectsInRange(npc, MonsterInstance.class, 2500));
  1297. +                   if (monsterCheck == null)
  1298. +                   {
  1299. +                       if (!world.getNpcsOfGroup("BARRICADES_2").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_1).isEmpty() && world.getNpcsOfGroup("BARRICADES_1").isEmpty())
  1300. +                       {
  1301. +                           world.getParameters().set("BARRICADE_DESTROYED", false);
  1302. +                       }
  1303. +                       else if (!world.getNpcsOfGroup("BARRICADES_3").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_2).isEmpty() && world.getNpcsOfGroup("BARRICADES_2").isEmpty())
  1304. +                       {
  1305. +                           world.getParameters().set("BARRICADE_DESTROYED", false);
  1306. +                       }
  1307. +                       else if (!world.getNpcsOfGroup("BARRICADES_4").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_3).isEmpty() && world.getNpcsOfGroup("BARRICADES_3").isEmpty())
  1308. +                       {
  1309. +                           world.getParameters().set("BARRICADE_DESTROYED", false);
  1310. +                       }
  1311. +                   }
  1312. +                   if (!CORRIDOR_MOBS_1_SPAWNED && world.getNpcsOfGroup("BARRICADES_1").isEmpty() && !world.getNpcsOfGroup("BARRICADES_2").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_1).isEmpty())
  1313. +                   {
  1314. +                       world.spawnGroup("CORRIDOR_MOBS_1");
  1315. +                       world.getNpcsOfGroup("CORRIDOR_MOBS_1").forEach(mob ->
  1316. +                       {
  1317. +                           if (mob != null)
  1318. +                           {
  1319. +                               mob.setRandomWalking(false);
  1320. +                           }
  1321. +                       });
  1322. +                       world.getParameters().set("CORRIDOR_MOBS_1_SPAWNED", true);
  1323. +                   }
  1324. +                   if (!CORRIDOR_MOBS_2_SPAWNED && world.getNpcsOfGroup("BARRICADES_2").isEmpty() && !world.getNpcsOfGroup("BARRICADES_3").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_2).isEmpty())
  1325. +                   {
  1326. +                       world.spawnGroup("CORRIDOR_MOBS_2");
  1327. +                       world.getNpcsOfGroup("CORRIDOR_MOBS_2").forEach(mob ->
  1328. +                       {
  1329. +                           if (mob != null)
  1330. +                           {
  1331. +                               mob.setRandomWalking(false);
  1332. +                           }
  1333. +                       });
  1334. +                       world.getParameters().set("CORRIDOR_MOBS_2_SPAWNED", true);
  1335. +                   }
  1336. +                   if (!CORRIDOR_MOBS_3_SPAWNED && world.getNpcsOfGroup("BARRICADES_3").isEmpty() && !world.getNpcsOfGroup("BARRICADES_4").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_3).isEmpty())
  1337. +                   {
  1338. +                       world.spawnGroup("CORRIDOR_MOBS_3");
  1339. +                       world.getNpcsOfGroup("CORRIDOR_MOBS_3").forEach(mob ->
  1340. +                       {
  1341. +                           if (mob != null)
  1342. +                           {
  1343. +                               mob.setRandomWalking(false);
  1344. +                           }
  1345. +                       });
  1346. +                       world.getParameters().set("CORRIDOR_MOBS_3_SPAWNED", true);
  1347. +                   }
  1348. +                   if (!CORRIDOR_MOBS_4_SPAWNED && world.getNpcsOfGroup("BARRICADES_4").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_4).isEmpty())
  1349. +                   {
  1350. +                       world.spawnGroup("CORRIDOR_MOBS_4");
  1351. +                       world.spawnGroup("PARAGON");
  1352. +                       world.getParameters().set("CORRIDOR_MOBS_4_SPAWNED", true);
  1353. +                       world.getNpcsOfGroup("CORRIDOR_MOBS_4").forEach(mob ->
  1354. +                       {
  1355. +                           if (mob != null)
  1356. +                           {
  1357. +                               mob.setRandomWalking(false);
  1358. +                           }
  1359. +                       });
  1360. +                       if (world.getNpc(PARAGON) != null)
  1361. +                       {
  1362. +                           world.getNpc(PARAGON).setInvul(true);
  1363. +                           world.getNpc(PARAGON).getEffectList().startAbnormalVisualEffect(AbnormalVisualEffect.INVINCIBILITY);
  1364. +                       }
  1365. +                       npc.broadcastPacket(new ExShowScreenMessage(NpcStringId.YOU_CAN_T_DEFEAT_PARAGON_WHILE_PARAGON_S_MINIONS_ARE_ALIVE, ExShowScreenMessage.TOP_CENTER, 7000, true));
  1366. +                   }
  1367. +                   if (world.getNpcsOfGroup("BARRICADES_4").isEmpty() && world.getAliveNpcs(CORRIDOR_MOBS_4).isEmpty())
  1368. +                   {
  1369. +                       if ((world.getNpc(PARAGON) != null) && world.getNpc(PARAGON).isInvul())
  1370. +                       {
  1371. +                           world.getNpc(PARAGON).setInvul(false);
  1372. +                           world.getNpc(PARAGON).getEffectList().stopAbnormalVisualEffect(AbnormalVisualEffect.INVINCIBILITY);
  1373. +                           showOnScreenMsg(world, NpcStringId.PARAGON_IS_NO_LONGER_INVINCIBLE, ExShowScreenMessage.TOP_CENTER, 7000, true);
  1374. +                           world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.TODAY_IS_THE_DAY_THAT_I_WILL_ENTER);
  1375. +                       }
  1376. +                   }
  1377. +                   if ((world.getStatus() == 1) && world.getNpcsOfGroup("BARRICADES_4").isEmpty() && (world.getAliveNpcs(PARAGON).isEmpty()))
  1378. +                   {
  1379. +                       startQuestTimer("openInnerDoors", 5000, null, player);
  1380. +                       cancelQuestTimer("checkProgress", npc, player);
  1381. +                   }
  1382. +               }
  1383. +               break;
  1384. +           }
  1385. +           case "openInnerDoors":
  1386. +           {
  1387. +               final Instance world = player.getInstanceWorld();
  1388. +               if (isInInstance(world))
  1389. +               {
  1390. +                   openDoor(DOOR1, world.getId());
  1391. +                   openDoor(DOOR2, world.getId());
  1392. +                   openDoor(DOOR3, world.getId());
  1393. +                   openDoor(DOOR4, world.getId());
  1394. +                   world.setStatus(2);
  1395. +                   startQuestTimer("talkLeona", 5000, null, player);
  1396. +               }
  1397. +               break;
  1398. +           }
  1399. +           case "startStage2":
  1400. +           {
  1401. +               final Instance world = player.getInstanceWorld();
  1402. +               if (isInInstance(world))
  1403. +               {
  1404. +                   startQuestTimer("show_intro_movie_camille", 5000, null, player);
  1405. +                   return "34471-03.html";
  1406. +               }
  1407. +               break;
  1408. +           }
  1409. +           case "show_intro_movie_camille":
  1410. +           {
  1411. +               final Instance world = player.getInstanceWorld();
  1412. +               if (isInInstance(world))
  1413. +               {
  1414. +                   playMovie(world.getPlayers(), Movie.SC_INZONE_CAMILLE_INTRO);
  1415. +                   startQuestTimer("spawn_camille", 5000, null, player);
  1416. +               }
  1417. +               break;
  1418. +           }
  1419. +           case "spawn_camille":
  1420. +           {
  1421. +               final Instance world = player.getInstanceWorld();
  1422. +               if (isInInstance(world))
  1423. +               {
  1424. +                   closeDoor(DOOR1, world.getId());
  1425. +                   closeDoor(DOOR2, world.getId());
  1426. +                   closeDoor(DOOR3, world.getId());
  1427. +                   closeDoor(DOOR4, world.getId());
  1428. +                   world.setStatus(3);
  1429. +                   world.spawnGroup("CAMILLE");
  1430. +                   world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.GISELLE_NO_IS_SHE_CAMILLE_IN_THAT_STATE);
  1431. +               }
  1432. +               break;
  1433. +           }
  1434. +           case "spawn_kain":
  1435. +           {
  1436. +               final Instance world = player.getInstanceWorld();
  1437. +               if (isInInstance(world))
  1438. +               {
  1439. +                   world.spawnGroup("KAIN");
  1440. +                   world.spawnGroup("ETINA_1");
  1441. +                   world.getNpc(ETIS_VAN_ETINA1).setInvul(true);
  1442. +                   world.getNpc(ETIS_VAN_ETINA1).setTargetable(false);
  1443. +                   world.getNpc(ETIS_VAN_ETINA1).setImmobilized(true);
  1444. +                   showOnScreenMsg(world, NpcStringId.ETIS_VAN_ETINA_AND_HIS_APOSTLES_HAVE_APPEARED, ExShowScreenMessage.TOP_CENTER, 7000, true);
  1445. +                   world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.EVEN_THE_MIGHTY_ETINA_SEEMS_TO_FEAR_US);
  1446. +               }
  1447. +               break;
  1448. +           }
  1449. +           case "spawnTransformedEtina":
  1450. +           {
  1451. +               final Instance world = player.getInstanceWorld();
  1452. +               if (isInInstance(world))
  1453. +               {
  1454. +                   world.spawnGroup("ETINA_2");
  1455. +                   world.spawnGroup("ETINA_MINIONS");
  1456. +                   world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.ETIS_VAN_ETINA_WE_FINALLY_MEET);
  1457. +               }
  1458. +               break;
  1459. +           }
  1460. +           case "gnosisCastTimer":
  1461. +           {
  1462. +               final Instance world = player.getInstanceWorld();
  1463. +               if (isInInstance(world))
  1464. +               {
  1465. +                   final Npc _sealOfGnosis = world.getNpc(SEAL_OF_GNOSIS);
  1466. +                   _sealOfGnosis.setDisplayEffect(3);
  1467. +                   _sealOfGnosis.broadcastPacket(new MagicSkillUse(_sealOfGnosis, _sealOfGnosis, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 1, 10000, 0));
  1468. +                   PlayerInstance member = world.getPlayers().stream().findAny().get();
  1469. +                   STIGMA_OF_REVELATION.getSkill().applyEffects(member, member);
  1470. +                   world.getNpcsOfGroup("ETINA_MINIONS").forEach(minion ->
  1471. +                   {
  1472. +                       if (minion != null)
  1473. +                       {
  1474. +                           ETINA_REVELATION.getSkill().applyEffects(minion, minion);
  1475. +                           ((Attackable) minion).addDamageHate(member, 0, 999999999);
  1476. +                       }
  1477. +                   });
  1478. +                   showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_GNOSIS_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true);
  1479. +               }
  1480. +               break;
  1481. +           }
  1482. +           case "strifeCastTimer":
  1483. +           {
  1484. +               final Instance world = player.getInstanceWorld();
  1485. +               if (isInInstance(world))
  1486. +               {
  1487. +                   final Npc _sealOfStrife = world.getNpc(SEAL_OF_STRIFE);
  1488. +                   _sealOfStrife.setDisplayEffect(3);
  1489. +                   _sealOfStrife.broadcastPacket(new MagicSkillUse(_sealOfStrife, _sealOfStrife, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 2, 10000, 0));
  1490. +                   world.getNpcsOfGroup("ETINA_MINIONS").forEach(minion ->
  1491. +                   {
  1492. +                       if (minion != null)
  1493. +                       {
  1494. +                           CRY_OF_HOLY_WAR.getSkill().applyEffects(minion, minion);
  1495. +                       }
  1496. +                   });
  1497. +                   world.getPlayers().forEach(plr -> STIGMA_OF_MARTYR.getSkill().applyEffects(player, player));
  1498. +                   showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_STRIFE_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true);
  1499. +               }
  1500. +               break;
  1501. +           }
  1502. +           case "avariceCastTimer":
  1503. +           {
  1504. +               final Instance world = player.getInstanceWorld();
  1505. +               if (isInInstance(world))
  1506. +               {
  1507. +                   final Npc _sealOfAvarice = world.getNpc(SEAL_OF_AVARICE);
  1508. +                   _sealOfAvarice.setDisplayEffect(3);
  1509. +                   _sealOfAvarice.broadcastPacket(new MagicSkillUse(_sealOfAvarice, _sealOfAvarice, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 3, 10000, 0));
  1510. +                   world.getNpcsOfGroup("ETINA_MINIONS").forEach(minion ->
  1511. +                   {
  1512. +                       if (minion != null)
  1513. +                       {
  1514. +                           UNDEAD_CREATURE.getSkill().applyEffects(minion, minion);
  1515. +                       }
  1516. +                   });
  1517. +                   showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_AVARICE_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true);
  1518. +               }
  1519. +               break;
  1520. +           }
  1521. +           case "punishmentCastTimer":
  1522. +           {
  1523. +               final Instance world = player.getInstanceWorld();
  1524. +               if (isInInstance(world))
  1525. +               {
  1526. +                   final Npc _sealOfPunishment = world.getNpc(SEAL_OF_PUNISHMENT);
  1527. +                   _sealOfPunishment.setDisplayEffect(3);
  1528. +                   _sealOfPunishment.broadcastPacket(new MagicSkillUse(_sealOfPunishment, _sealOfPunishment, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 4, 10000, 0));
  1529. +                   world.getNpcsOfGroup("ETINA_MINIONS").forEach(minion ->
  1530. +                   {
  1531. +                       if (minion != null)
  1532. +                       {
  1533. +                           ETINA_DIVINE_PUNISHMENT.getSkill().applyEffects(minion, minion);
  1534. +                       }
  1535. +                   });
  1536. +                   world.getPlayers().forEach(plr -> ETINA_OBSERVATION.getSkill().applyEffects(player, player));
  1537. +                   showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_PUNISHMENT_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true);
  1538. +               }
  1539. +               break;
  1540. +           }
  1541. +           case "awakeningCastTimer":
  1542. +           {
  1543. +               final Instance world = player.getInstanceWorld();
  1544. +               if (isInInstance(world))
  1545. +               {
  1546. +                   final Npc _sealOfAwakening = world.getNpc(SEAL_OF_AWAKENING);
  1547. +                   _sealOfAwakening.setDisplayEffect(3);
  1548. +                   _sealOfAwakening.broadcastPacket(new MagicSkillUse(_sealOfAwakening, _sealOfAwakening, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 5, 10000, 0));
  1549. +                   world.getNpcsOfGroup("ETINA_MINIONS").forEach(minion ->
  1550. +                   {
  1551. +                       if (minion != null)
  1552. +                       {
  1553. +                           RAGE_OF_THE_OPEN_EYE.getSkill().applyEffects(minion, minion);
  1554. +                       }
  1555. +                   });
  1556. +                   showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_AWAKENING_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true);
  1557. +               }
  1558. +               break;
  1559. +           }
  1560. +           case "calamityCastTimer":
  1561. +           {
  1562. +               final Instance world = player.getInstanceWorld();
  1563. +               if (isInInstance(world))
  1564. +               {
  1565. +                   final Npc _sealOfCalamity = world.getNpc(SEAL_OF_CALAMITY);
  1566. +                   _sealOfCalamity.setDisplayEffect(3);
  1567. +                   _sealOfCalamity.broadcastPacket(new MagicSkillUse(_sealOfCalamity, _sealOfCalamity, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 6, 10000, 0));
  1568. +                   showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_CALAMITY_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true);
  1569. +               }
  1570. +               break;
  1571. +           }
  1572. +           case "destructionCastTimer":
  1573. +           {
  1574. +               final Instance world = player.getInstanceWorld();
  1575. +               if (isInInstance(world))
  1576. +               {
  1577. +                   final Npc _sealOfDestruction = world.getNpc(SEAL_OF_DESTRUCTION);
  1578. +                   _sealOfDestruction.setDisplayEffect(3);
  1579. +                   _sealOfDestruction.broadcastPacket(new MagicSkillUse(_sealOfDestruction, _sealOfDestruction, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 7, 10000, 0));
  1580. +                   showOnScreenMsg(world, NpcStringId.THE_SEAL_OF_DESTRUCTION_IS_ACTIVATED_AND_ETINA_S_GRAND_TEMPLE_IS_NOW_UNDER_ITS_INFLUENCE, ExShowScreenMessage.TOP_CENTER, 7000, true);
  1581. +               }
  1582. +               break;
  1583. +           }
  1584. +       }
  1585. +       return super.onAdvEvent(event, npc, player);
  1586. +   }
  1587. +  
  1588. +   @Override
  1589. +   public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon)
  1590. +   {
  1591. +       final Instance world = attacker.getInstanceWorld();
  1592. +       if (isInInstance(world))
  1593. +       {
  1594. +           final boolean CAMILLE_30 = world.getParameters().getBoolean("CAMILLE_30", false);
  1595. +           final boolean CAMILLE_60 = world.getParameters().getBoolean("CAMILLE_60", false);
  1596. +           final boolean KAIN_30 = world.getParameters().getBoolean("KAIN_30", false);
  1597. +           final boolean KAIN_60 = world.getParameters().getBoolean("KAIN_60", false);
  1598. +           final boolean ETINA_80 = world.getParameters().getBoolean("ETINA_80", false);
  1599. +           final boolean ETINA_15 = world.getParameters().getBoolean("ETINA_15", false);
  1600. +           if (npc.getId() == CAMILLE)
  1601. +           {
  1602. +               if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.3)) && !CAMILLE_30)
  1603. +               {
  1604. +                   world.getParameters().set("CAMILLE_30", true);
  1605. +                   world.spawnGroup("CAMILLE_MINIONS");
  1606. +               }
  1607. +               else if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.6)) && !CAMILLE_60)
  1608. +               {
  1609. +                   world.getParameters().set("CAMILLE_60", true);
  1610. +                   world.spawnGroup("CAMILLE_MINIONS");
  1611. +               }
  1612. +           }
  1613. +           else if (npc.getId() == KAIN_VAN_HALTER)
  1614. +           {
  1615. +               if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.3)) && !KAIN_30)
  1616. +               {
  1617. +                   world.getParameters().set("KAIN_30", true);
  1618. +                   showOnScreenMsg(world, NpcStringId.ETIS_VAN_ETINA_SUMMONS_HIS_APOSTLES_MINIONS, ExShowScreenMessage.TOP_CENTER, 7000, true);
  1619. +                   world.spawnGroup("KAIN_MINIONS");
  1620. +               }
  1621. +               else if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.6)) && !KAIN_60)
  1622. +               {
  1623. +                   world.getParameters().set("KAIN_60", true);
  1624. +                   showOnScreenMsg(world, NpcStringId.ETIS_VAN_ETINA_SUMMONS_HIS_APOSTLES_MINIONS, ExShowScreenMessage.TOP_CENTER, 7000, true);
  1625. +                   world.spawnGroup("KAIN_MINIONS");
  1626. +               }
  1627. +           }
  1628. +           else if ((npc.getId() == ETIS_VAN_ETINA1))
  1629. +           {
  1630. +               if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.8)) && !ETINA_80)
  1631. +               {
  1632. +                   final Npc _etina1 = world.getNpc(ETIS_VAN_ETINA1);
  1633. +                   world.getParameters().set("ETINA_80", true);
  1634. +                   world.spawnGroup("ETINA_MINIONS");
  1635. +                   _etina1.abortCast();
  1636. +                   _etina1.broadcastPacket(new MagicSkillUse(_etina1, _etina1, CALL_OF_SEVEN_SIGNS.getSkillId(), CALL_OF_SEVEN_SIGNS.getSkillLevel(), 3000, 0));
  1637. +                   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);
  1638. +                   world.spawnGroup("SEALS");
  1639. +                   startQuestTimer("gnosisCastTimer", 120000, npc, attacker, true);
  1640. +                   startQuestTimer("strifeCastTimer", 120000, npc, attacker, true);
  1641. +                   startQuestTimer("avariceCastTimer", 120000, npc, attacker, true);
  1642. +                   startQuestTimer("punishmentCastTimer", 120000, npc, attacker, true);
  1643. +                   startQuestTimer("awakeningCastTimer", 120000, npc, attacker, true);
  1644. +                   startQuestTimer("calamityCastTimer", 120000, npc, attacker, true);
  1645. +                   startQuestTimer("destructionCastTimer", 120000, npc, attacker, true);
  1646. +               }
  1647. +               else if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.15)) && !ETINA_15)
  1648. +               {
  1649. +                   world.getParameters().set("ETINA_15", true);
  1650. +                   world.spawnGroup("ETINA_MINIONS");
  1651. +                   showOnScreenMsg(world, NpcStringId.ETIS_VAN_ETINA_AND_THE_POWER_OF_SIX_SEALS_ARE_WEAKENING, ExShowScreenMessage.TOP_CENTER, 7000, true);
  1652. +               }
  1653. +           }
  1654. +       }
  1655. +       return super.onAttack(npc, attacker, damage, isSummon);
  1656. +   }
  1657. +  
  1658. +   @Override
  1659. +   public String onKill(Npc npc, PlayerInstance killer, boolean isPet)
  1660. +   {
  1661. +       final Instance world = npc.getInstanceWorld();
  1662. +       if (isInInstance(world))
  1663. +       {
  1664. +           if (npc.getId() == ETIS_VAN_ETINA1)
  1665. +           {
  1666. +               playMovie(world.getPlayers(), Movie.SC_ETIS_VAN_ETINA_TRANS);
  1667. +               startQuestTimer("spawnTransformedEtina", 15000, null, killer);
  1668. +           }
  1669. +           else if (npc.getId() == ETIS_VAN_ETINA2)
  1670. +           {
  1671. +               playMovie(world.getPlayers(), Movie.SC_ETIS_VAN_ETINA_ENDING);
  1672. +               world.getAliveNpcs().forEach(mob ->
  1673. +               {
  1674. +                   mob.deleteMe();
  1675. +               });
  1676. +               if (getQuestTimer("gnosisCastTimer", npc, killer) != null)
  1677. +               {
  1678. +                   cancelQuestTimer("gnosisCastTimer", npc, killer);
  1679. +               }
  1680. +               if (getQuestTimer("trifeCastTimer", npc, killer) != null)
  1681. +               {
  1682. +                   cancelQuestTimer("strifeCastTimer", npc, killer);
  1683. +               }
  1684. +               if (getQuestTimer("avariceCastTimer", npc, killer) != null)
  1685. +               {
  1686. +                   cancelQuestTimer("avariceCastTimer", npc, killer);
  1687. +               }
  1688. +               if (getQuestTimer("punishmentCastTimer", npc, killer) != null)
  1689. +               {
  1690. +                   cancelQuestTimer("punishmentCastTimer", npc, killer);
  1691. +               }
  1692. +               if (getQuestTimer("awakeningCastTimer", npc, killer) != null)
  1693. +               {
  1694. +                   cancelQuestTimer("awakeningCastTimer", npc, killer);
  1695. +               }
  1696. +               if (getQuestTimer("calamityCastTimer", npc, killer) != null)
  1697. +               {
  1698. +                   cancelQuestTimer("calamityCastTimer", npc, killer);
  1699. +               }
  1700. +               if (getQuestTimer("destructionCastTimer", npc, killer) != null)
  1701. +               {
  1702. +                   cancelQuestTimer("destructionCastTimer", npc, killer);
  1703. +               }
  1704. +               closeDoor(DOOR1, world.getId());
  1705. +               closeDoor(DOOR2, world.getId());
  1706. +               closeDoor(DOOR3, world.getId());
  1707. +               closeDoor(DOOR4, world.getId());
  1708. +               world.finishInstance(2);
  1709. +           }
  1710. +           else if (CommonUtil.contains(CORRIDOR_MOBS_1, npc.getId()))
  1711. +           {
  1712. +               if (world.getAliveNpcs(CORRIDOR_MOBS_1).isEmpty())
  1713. +               {
  1714. +                   world.getParameters().set("BARRICADE_DESTROYED", false);
  1715. +               }
  1716. +           }
  1717. +           else if (CommonUtil.contains(CORRIDOR_MOBS_2, npc.getId()))
  1718. +           {
  1719. +               if (world.getAliveNpcs(CORRIDOR_MOBS_2).isEmpty())
  1720. +               {
  1721. +                   world.getParameters().set("BARRICADE_DESTROYED", false);
  1722. +               }
  1723. +           }
  1724. +           else if (CommonUtil.contains(CORRIDOR_MOBS_3, npc.getId()))
  1725. +           {
  1726. +               if (world.getAliveNpcs(CORRIDOR_MOBS_3).isEmpty())
  1727. +               {
  1728. +                   world.getParameters().set("BARRICADE_DESTROYED", false);
  1729. +               }
  1730. +           }
  1731. +           else if (CommonUtil.contains(CORRIDOR_MOBS_4, npc.getId()))
  1732. +           {
  1733. +               if (world.getAliveNpcs(CORRIDOR_MOBS_4).isEmpty())
  1734. +               {
  1735. +                   world.getNpc(PARAGON).setInvul(false);
  1736. +                   world.getNpc(PARAGON).getEffectList().stopAbnormalVisualEffect(AbnormalVisualEffect.INVINCIBILITY);
  1737. +                   showOnScreenMsg(world, NpcStringId.PARAGON_IS_NO_LONGER_INVINCIBLE, ExShowScreenMessage.TOP_CENTER, 7000, true);
  1738. +                   world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.TODAY_IS_THE_DAY_THAT_I_WILL_ENTER);
  1739. +               }
  1740. +           }
  1741. +           else if (npc.getId() == PARAGON)
  1742. +           {
  1743. +               startQuestTimer("openInnerDoors", 5000, null, killer);
  1744. +           }
  1745. +           else if (npc.getId() == CAMILLE)
  1746. +           {
  1747. +               world.getNpcsOfGroup("CAMILLE_MINIONS").forEach(minion ->
  1748. +               {
  1749. +                   if (minion != null)
  1750. +                   {
  1751. +                       minion.doDie(null);
  1752. +                   }
  1753. +               });
  1754. +               world.getNpc(CAMILLE).deleteMe();
  1755. +               world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.KAIN_IS_OUR_ENEMY_NOW_BE_ON_GUARD);
  1756. +               playMovie(world.getPlayers(), Movie.SC_INZONE_KAIN_INTRO);
  1757. +               startQuestTimer("spawn_kain", 5000, null, killer);
  1758. +           }
  1759. +           else if (npc.getId() == KAIN_VAN_HALTER)
  1760. +           {
  1761. +               world.getNpcsOfGroup("KAIN_MINIONS").forEach(minion ->
  1762. +               {
  1763. +                   if (minion != null)
  1764. +                   {
  1765. +                       minion.doDie(null);
  1766. +                   }
  1767. +               });
  1768. +               world.getNpc(ETIS_VAN_ETINA1).setInvul(false);
  1769. +               world.getNpc(ETIS_VAN_ETINA1).setImmobilized(false);
  1770. +               world.getNpc(ETIS_VAN_ETINA1).setTargetable(true);
  1771. +               showOnScreenMsg(world, NpcStringId.ETIS_VAN_ETINA_APPROACHES, ExShowScreenMessage.TOP_CENTER, 7000, true);
  1772. +               world.getNpc(KAIN_VAN_HALTER).deleteMe();
  1773. +               playMovie(world.getPlayers(), Movie.SC_KAIN_BOSS_ENDING);
  1774. +               world.getNpc(LEONA_BLACKBIRD).broadcastSay(ChatType.NPC_GENERAL, NpcStringId.KAIN_I_WON_T_FEEL_GUILTY_ABOUT_THIS);
  1775. +           }
  1776. +       }
  1777. +       return super.onKill(npc, killer, isPet);
  1778. +   }
  1779. +  
  1780. +   @Override
  1781. +   public String onFirstTalk(Npc npc, PlayerInstance player)
  1782. +   {
  1783. +       final Instance world = player.getInstanceWorld();
  1784. +       String htmltext = null;
  1785. +       if (isInInstance(world))
  1786. +       {
  1787. +           switch (npc.getId())
  1788. +           {
  1789. +               case DEVIANNE:
  1790. +               case ELIKIA:
  1791. +               case SPORCHA:
  1792. +               case ALIBER:
  1793. +               {
  1794. +                   htmltext = npc.getId() + ".html";
  1795. +                   break;
  1796. +               }
  1797. +               case LEONA_BLACKBIRD:
  1798. +               {
  1799. +                   switch (world.getStatus())
  1800. +                   {
  1801. +                       case 0:
  1802. +                       {
  1803. +                           htmltext = "34471.htm";
  1804. +                           break;
  1805. +                       }
  1806. +                       case 1:
  1807. +                       {
  1808. +                           htmltext = "34471-01.html";
  1809. +                           break;
  1810. +                       }
  1811. +                       case 2:
  1812. +                       {
  1813. +                           htmltext = "34471-02.htm";
  1814. +                           break;
  1815. +                       }
  1816. +                       case 3:
  1817. +                       {
  1818. +                           htmltext = "34471-03.html";
  1819. +                           break;
  1820. +                       }
  1821. +                   }
  1822. +               }
  1823. +           }
  1824. +       }
  1825. +       return htmltext;
  1826. +   }
  1827. +  
  1828. +   public static void main(String[] args)
  1829. +   {
  1830. +       new EtisVanEtinaSolo();
  1831. +   }
  1832. +}
  1833. \ No newline at end of file
  1834. Index: dist/game/data/scripts/instances/EtisVanEtinaSolo/condNoGroup.html
  1835. ===================================================================
  1836. --- dist/game/data/scripts/instances/EtisVanEtinaSolo/condNoGroup.html  (nonexistent)
  1837. +++ dist/game/data/scripts/instances/EtisVanEtinaSolo/condNoGroup.html  (working copy)
  1838. @@ -0,0 +1,3 @@
  1839. +<html><body>Leona Blackbird:<br>
  1840. +You can enter only solo.
  1841. +</body></html>
  1842. \ No newline at end of file
  1843. Index: dist/game/data/scripts/instances/EtisVanEtinaSolo/condNoLevel.html
  1844. ===================================================================
  1845. --- dist/game/data/scripts/instances/EtisVanEtinaSolo/condNoLevel.html  (nonexistent)
  1846. +++ dist/game/data/scripts/instances/EtisVanEtinaSolo/condNoLevel.html  (working copy)
  1847. @@ -0,0 +1,4 @@
  1848. +<html><body>Leona Blackbird:<br>
  1849. +I won't let you enter.<br>
  1850. +(Only players between levels 104-130 may participate.)
  1851. +</body></html>
  1852. \ No newline at end of file
  1853.  
Add Comment
Please, Sign In to add comment