Advertisement
Guest User

Untitled

a guest
Nov 16th, 2015
221
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 33.39 KB | None | 0 0
  1. package l2e.scripts.ai.individual.raidbosses;
  2.  
  3. import l2e.config.Config;
  4. import l2e.gameserver.ThreadPoolManager;
  5. import l2e.gameserver.engine.hookengine.AbstractHookImpl;
  6. import l2e.gameserver.engine.hookengine.HookType;
  7. import l2e.gameserver.instancemanager.GrandBossManager;
  8. import l2e.gameserver.instancemanager.ZoneManager;
  9. import l2e.gameserver.model.actor.L2Character;
  10. import l2e.gameserver.model.actor.L2Npc;
  11. import l2e.gameserver.model.actor.L2Object;
  12. import l2e.gameserver.model.actor.instance.L2GrandBossInstance;
  13. import l2e.gameserver.model.actor.instance.L2GuardInstance;
  14. import l2e.gameserver.model.actor.instance.L2MonsterInstance;
  15. import l2e.gameserver.model.actor.instance.L2PcInstance;
  16. import l2e.gameserver.model.skills.SkillTable;
  17. import l2e.gameserver.model.skills.base.L2Skill;
  18. import l2e.gameserver.model.skills.stats.StatsSet;
  19. import l2e.gameserver.model.world.quest.Quest;
  20. import l2e.gameserver.model.world.zone.L2ZoneType;
  21. import l2e.gameserver.model.world.zone.Location;
  22. import l2e.gameserver.model.world.zone.type.L2BossZone;
  23. import l2e.gameserver.network.game.components.NpcStringId;
  24. import l2e.gameserver.network.game.serverpackets.EarthQuake;
  25. import l2e.gameserver.network.game.serverpackets.EventTrigger;
  26. import l2e.gameserver.network.game.serverpackets.L2GameServerPacket;
  27. import l2e.gameserver.network.game.serverpackets.SocialAction;
  28. import l2e.gameserver.network.game.serverpackets.packet.ex.ExSendUIEvent;
  29. import l2e.gameserver.network.game.serverpackets.packet.ex.ExStartScenePlayer;
  30. import l2e.gameserver.network.game.serverpackets.packet.info.ExNpcInfo;
  31. import l2e.gameserver.network.game.serverpackets.packet.show.ExShowScreenMessage;
  32. import l2e.gameserver.util.Broadcast;
  33. import l2e.gameserver.util.Rnd;
  34.  
  35. import java.util.ArrayList;
  36. import java.util.List;
  37. import java.util.concurrent.ScheduledFuture;
  38.  
  39. /**
  40.  * User: Mifesto
  41.  * Date: 15:04 / 30.11.2014
  42.  * Team: http://mmo-core.ru/
  43.  * На юге города Руна, в Лесу Неупокоенных находится Жертвенный Алтарь.
  44.  * С помощью него можно зайти в Рейдовую Зону к Линдвиору.
  45.  * Бросить вызов одному из сильнейших рейдовых боссов могут только персонажи 99 уровня,
  46.  * для входа к РБ нужно 49-112 человек (7-16 полных групп) находящиеся в составе командного канала.
  47.  * Внутрь сможет попасть только 1 командный канал.
  48.  * <p>
  49.  * ZONE - 44269 -26152 -1405
  50.  * <p>
  51.  * Рейд - Линдвиор
  52.  * Уровень - 99
  53.  * Количество человек - 49-112(7-16 групп)
  54.  * NPC -Kato Sycamore Maynooth (Като Сиканус) id=33881
  55.  * Примечание - 1 Командный канал (2ая или соло бомжи немогут зайти)
  56.  * <p>
  57.  * Генератор - id=19426
  58.  * Генератор - id=19477
  59.  * Схема генератора - id=19479
  60.  * Линдрако - id=25895(мелкий ползающий) id=29243(летающий) id=29242 id=29241 id=25897 id=25896
  61.  * Линдрако (маленький) - id=19476
  62.  * <p>
  63.  * Система оптимизации графики
  64.  * При походе на Линдвиора, что бы увеличить FPS (количество кадров в секунду),
  65.  * автоматически включается единая система оптимизации.
  66.  * У всех персонажей броня и оружие, кроме головных уборов, становятся одинаковыми.
  67.  * Если у вас нет необходимости в оптимизации графики, то отключите систему, нажав кнопку на мини-карте.
  68.  * <p>
  69.  * Защита
  70.  * Алтарь Жертвоприношений - это огромное круглое здание, в центре которого находится большая башня,
  71.  * а вокруг неё 4 энергоблока. Линдвиор посылает своих бойцов, чтобы уничтожить Энергоблоки,
  72.  * а игроки не должны позволить сломать их.
  73.  * Когда Энергоблоки зарядятся до конца, пушки выстрелят по летающему Линдвиору,
  74.  * и он упадет на землю, после этого начинается фарм Эпического Босса.
  75.  * <p>
  76.  * <p>
  77.  * 1 Этап
  78.  * Первый этап начинается когда Линдвиор спускается на землю, и до того как у него не станет 80% HP.
  79.  * Если стоять перед драконом, можно получить урон от удара ветром, а если стоять со спины,
  80.  * то вы получите урон от удара хвостом.
  81.  * Дракон будет использовать умение Дыхание Ветра - оно наносит урон и отбрасывает спереди дракона,
  82.  * и умение Body Slam, которое наносит урон и оглушает цели вокруг.
  83.  * Во время фарма Линдвиор будет призывать рейдовых бойцов (А).
  84.  * После того, как вы отнимите первые 20% HP у Линдвиора, он взлетит в воздух и использует умение Ярость,
  85.  * которое будет отнимать у всех персонажей по 2500 HP за тик.
  86.  * <p>
  87.  * Используемые умения:
  88.  * - Сотрясение Тела (15271)
  89.  * - Шквальный Ветер (15274)
  90.  * - Прыжок Линдвиора (15430)
  91.  * - Натиск Ветра (15591)
  92.  * <p>
  93.  * Линдрако - id=25895 id=29243 id=29242 id=29241 id=25897 id=25896
  94.  * <p>
  95.  * 2 Этап
  96.  * Сообщение перед взлетом: От линдвиора веет силой
  97.  * Когда HP Линдвиора меньше 80%, он поднимается в воздух и перемещается по всему Алтарю Жертвоприношения,
  98.  * нанося мега удары ветром.
  99.  * С небольшой вероятностью появляются вихри, которые будут затягивать персонажей и наносить урон.
  100.  * Когда HP Линдвиора снизится до 75%, он вызовет огромный вихрь, который будет перемещаться по всей локации.
  101.  * Если вы попадете в гигантский вихрь, ваше HP, MP, CP опустится до 1.
  102.  * Линдвиор также призывает новых рейдовых бойцов (B).
  103.  * Линдрако - id=25895 id=29243 id=29242 id=29241 id=25897 id=25896
  104.  * <p>
  105.  * Используемые умения:
  106.  * - Бешенство Линдвиора (15269)
  107.  * - Шквальный Ветер (15274)
  108.  * <p>
  109.  * <p>
  110.  * 3 Этап
  111.  * Когда HP Линдвиора спускается ниже 60%, он спускается на землю.
  112.  * Он начинает использовать такие же умения, как и на 1 этапе,
  113.  * и дополнительно использует умение Тёмный Ветер - он отражает урон.
  114.  * Это умение легко заметить - Линдвиор потемнеет при его использовании.
  115.  * Также появляются новые рейдовые бойцы (C)
  116.  * Линдрако - id=25895 id=29243 id=29242 id=29241 id=25897 id=25896
  117.  * <p>
  118.  * Используемые умения:
  119.  * - Бешенство Линдвиора (15269)
  120.  * - Дыхание Ветра (15272)
  121.  * - Шквальный Ветер (15274)
  122.  * - Прыжок Линдвиора (15430)
  123.  * <p>
  124.  * 4 Этап
  125.  * HP Линдвиора спускается до 40%, и он опять поднимается в воздух.
  126.  * Этот этап похож на 2 стадию. Когда HP спустится ниже 35%, Рейд Босс призовет Малые Вихри.
  127.  * <p>
  128.  * <p>
  129.  * Используемые умения:
  130.  * - Шквальный Ветер (15274)
  131.  * <p>
  132.  * 5 Этап
  133.  * HP Дракона спускается ниже 20%.
  134.  * Теперь, вам дается 10 минут, чтобы убить Линдвиора.
  135.  * Он использует умение Ярость, и урон по нему снизится.
  136.  * Если вы не успеете убить его за 10 минут, то всех выкинет из рейд зоны.
  137.  * На последнем Этапе Lindvior призывает рейдовых бойцов и вихри, использует умения как на 1 этапе,
  138.  * кроме этого, если вы попадёте в вихрь, то ваша скорость снизится и вас отбросит.
  139.  * <p>
  140.  * Используемые умения:
  141.  * - Шквальный Ветер (15274)
  142.  * - Прыжок Линдвиора (15430)
  143.  * <p>
  144.  * зависимости от HP Линдвиора игрок получает Чешуйки Линдвиора.
  145.  * HP ниже 80%: 1 Чешуйка Линдвиора
  146.  * HP ниже 60%: 2 Чешуйки Линдвиора
  147.  * HP ниже 40%: 3 Чешуйки Линдвиора
  148.  * HP ниже 20%: 4 Чешуйки Линдвиора
  149.  * Чтобы получать Чешуйки Линдвиора, нужно заключить союз с НПЦ в Руне,
  150.  * если расформировать союз или выйти из него, то награду получить нельзя.
  151.  * 100 Чешуек Линдвиора можно обменять на книгу для изучения умения езды на Линдвиоре.
  152.  * <p>
  153.  * http://www.youtube.com/watch?v=hurIT0lyJ70
  154.  */
  155. public class Lindvior extends Quest
  156. {
  157.     //Lindvior Status Tracking :
  158.     private static final byte DORMANT = 0;        //Lindvior is spawned and no one has entered yet.
  159.     // Entry is unlocked
  160.     private static final byte FIGHTING = 1;        //Lindvior is engaged in battle,
  161.     // annihilating his foes. Entry is locked
  162.     private static final byte DEAD = 2;            //Lindvior has been killed. Entry is locked
  163.     // Config
  164.     private static final int ACTIVITYTIMEOFLINDVIOR = 120;
  165.     private static final int INACTIVITYTIME = 900000;           // 15 min
  166.     private static final boolean EARTH_QUAKE_ON_SPAWN = true;
  167.     // Монстры
  168.     private static final int LINDVIOR_FAKE = 19423;
  169.     private static final int LINDVIOR_GROUND = 25899;
  170.     private static final int LINDVIOR_RAID = 29240;
  171.     private static final int LINDVIOR_FLY = 19424;
  172.     private static final int[] LINDVIOR_SERVITOR = {25895, 29243, 29242, 29241, 25897, 25896};
  173.     // НПЦ
  174.     private static final int NPC_GENERATOR = 19477;
  175.     private static final int NPC_SCHEME_GENERATOR = 19479;
  176.     private static final int NPC_ATTACKER_GENERATORS = 25897;
  177.     private static final int eventTriggerFirstStage = 21170112;
  178.  
  179.     // zone triggrs
  180.     //private static final int[] EventTriggerRecharge = Util.createRangeArray(21170102, 21170110);
  181.     //private static final int[] EventTriggerCannonShoot = { 21170120, 21170124, 21170130, 21170100 };
  182.     private static final int eventTriggerSecondStage = 21170100;
  183.     // Локации
  184.     private static final Location CENTER_LOCATION = new Location(46424, -26200, -1430);
  185.     // Умения
  186.     private static final L2Skill SKILL = SkillTable.getInstance().getInfo(15605, 1);
  187.     private static final L2GameServerPacket[] GENERATOR_MESSAGES = {
  188.             new ExShowScreenMessage(NpcStringId.YOU_MUST_ACTIVATE_THE_4_GENERATORS, ExShowScreenMessage.TOP_CENTER,
  189.                     7000),
  190.             new ExShowScreenMessage(NpcStringId.PROTECT_THE_GENERATOR, ExShowScreenMessage.TOP_CENTER, 7000)
  191.     };
  192.     private static final Location[] CONTROL_GENERATOR_SPAWNS = {
  193.             new Location(45288, -30360, -1432, 0),
  194.             new Location(48520, -27176, -1438, 0),
  195.             new Location(45272, -23976, -1432, 0),
  196.             new Location(42088, -27160, -1432, 0)
  197.     };
  198.     private static final Location[] SCHEME_GENERATOR_SPAWNS = {
  199.             new Location(48440, -26824, -1438, 0),
  200.             new Location(48392, -27448, -1438, 0),
  201.             new Location(42136, -27480, -1438, 0),
  202.             new Location(42136, -26840, -1438, 0),
  203.             new Location(44936, -24024, -1438, 0),
  204.             new Location(45592, -24008, -1438, 0),
  205.             new Location(45608, -30312, -1438, 0),
  206.             new Location(44984, -30360, -1438, 0)
  207.     };
  208.     private static final Location[] ATTACKER_GENERATOR_SPAWNS = {
  209.             new Location(44863, -24272, -1413, 33713),
  210.             new Location(45675, -24272, -1413, 33713),
  211.             new Location(45675, -30057, -1413, 64987),
  212.             new Location(44863, -30057, -1413, 64987),
  213.             new Location(42350, -27563, -1413, 46871),
  214.             new Location(42350, -26809, -1413, 46871),
  215.             new Location(48220, -26809, -1413, 16383),
  216.             new Location(48220, -27563, -1413, 16383)
  217.     };
  218.     private static final int[][] generatorTriggers = {
  219.             {21170102, 21170103}, {21170104, 21170105}, {21170106, 21170107}, {21170108, 21170109}
  220.     };
  221.     // Зоны
  222.     private final static int ZONE_ID = 12015;
  223.     private static Lindvior _instance;
  224.     protected final int _chargedValues[] = new int[]{0, 0, 0, 0};
  225.     // Spawn data of monsters.
  226.     protected List<L2Npc> _monsterSpawn = new ArrayList<>();
  227.     protected List<L2GuardInstance> _generatorSpawn = new ArrayList<>();
  228.     // Tasks.
  229.     protected ScheduledFuture<?> _socialTask;
  230.     protected ScheduledFuture<?> _announceTask;
  231.     protected ScheduledFuture<?> _skillCastTask;
  232.     protected ScheduledFuture<?> _mobsSpawnTask;
  233.     protected ScheduledFuture<?> _collapseTask;
  234.     protected ScheduledFuture<?> _bigVortexesTask;
  235.     protected ScheduledFuture<?> _smallVortexesTask;
  236.     protected L2GrandBossInstance _lindvior = null;
  237.     protected L2Npc _lindvior2 = null;
  238.     protected L2BossZone _zoneLair;
  239.     protected OnHpChange _hpChange;
  240.     protected int _activeMask = 0;
  241.     protected int _chargedMask = 0;
  242.     protected int _status = 0;
  243.  
  244.     public Lindvior()
  245.     {
  246.         super();
  247.  
  248.         addEnterZoneId(ZONE_ID);
  249.         addExitZoneId(ZONE_ID);
  250.  
  251.         addAskId(NPC_GENERATOR, -1007);
  252.         addFirstTalkId(NPC_GENERATOR);
  253.  
  254.         registerMobs(NPC_GENERATOR, NPC_ATTACKER_GENERATORS, NPC_SCHEME_GENERATOR, LINDVIOR_FAKE, LINDVIOR_GROUND,
  255.                 LINDVIOR_FLY, LINDVIOR_RAID);
  256.  
  257.         init();
  258.     }
  259.  
  260.     private static boolean hasFlag(int val, int flag)
  261.     {
  262.         return (val & flag) == flag;
  263.     }
  264.  
  265.     public static void main(String[] args)
  266.     {
  267.         _instance = new Lindvior();
  268.     }
  269.  
  270.     public static Lindvior getInstance()
  271.     {
  272.         return _instance;
  273.     }
  274.  
  275.     private void init()
  276.     {
  277.         _hpChange = new OnHpChange();
  278.         _zoneLair = ZoneManager.getInstance().getZoneById(ZONE_ID, L2BossZone.class);
  279.  
  280.         StatsSet info = GrandBossManager.getInstance().getStatsSet(LINDVIOR_RAID);
  281.         if (info == null)
  282.         {
  283.             info = new StatsSet();
  284.             info.set("respawn_time", 0);
  285.  
  286.             GrandBossManager.getInstance().setStatsSet(LINDVIOR_RAID, info);
  287.         }
  288.  
  289.         int status = GrandBossManager.getInstance().getBossStatus(LINDVIOR_RAID);
  290.  
  291.         Long respawnTime = info.getLong("respawn_time");
  292.         if (status == FIGHTING || status == DEAD && respawnTime <= System.currentTimeMillis())
  293.         {
  294.             GrandBossManager.getInstance().setBossStatus(LINDVIOR_RAID, DORMANT);
  295.         }
  296.         else if (status == DEAD)
  297.         {
  298.             ThreadPoolManager.getInstance().scheduleGeneral(new UnlockLindvior(),
  299.                     respawnTime - System.currentTimeMillis());
  300.         }
  301.     }
  302.  
  303.     public void setLindviorSpawnTask()
  304.     {
  305.         synchronized (this)
  306.         {
  307.             if (_socialTask == null)
  308.             {
  309.                 GrandBossManager.getInstance().setBossStatus(LINDVIOR_RAID, FIGHTING);
  310.  
  311.                 _socialTask = ThreadPoolManager.getInstance().scheduleGeneral(() -> nextStage(1), 1000);
  312.             }
  313.         }
  314.     }
  315.  
  316.     protected void Clean()
  317.     {
  318.         _status = 0;
  319.  
  320.         if (_socialTask != null)
  321.         {
  322.             _socialTask.cancel(false);
  323.             _socialTask = null;
  324.         }
  325.  
  326.         if (_announceTask != null)
  327.         {
  328.             _announceTask.cancel(false);
  329.             _announceTask = null;
  330.         }
  331.  
  332.         if (_skillCastTask != null)
  333.         {
  334.             _skillCastTask.cancel(false);
  335.             _skillCastTask = null;
  336.         }
  337.  
  338.         if (_mobsSpawnTask != null)
  339.         {
  340.             _mobsSpawnTask.cancel(false);
  341.             _mobsSpawnTask = null;
  342.         }
  343.  
  344.         if (_collapseTask != null)
  345.         {
  346.             _collapseTask.cancel(false);
  347.             _collapseTask = null;
  348.         }
  349.  
  350.         if (_bigVortexesTask != null)
  351.         {
  352.             _bigVortexesTask.cancel(false);
  353.             _bigVortexesTask = null;
  354.         }
  355.  
  356.         if (_smallVortexesTask != null)
  357.         {
  358.             _smallVortexesTask.cancel(false);
  359.             _smallVortexesTask = null;
  360.         }
  361.  
  362.         _zoneLair.getCharactersInside().forEach(mob -> {
  363.             if (mob.isNpc())
  364.             {
  365.                 mob.onDelete();
  366.                 mob.setIsDead(true);
  367.             }
  368.         });
  369.     }
  370.  
  371.     private void Fail(boolean clean)
  372.     {
  373.         if (clean)
  374.         {
  375.             Clean();
  376.         }
  377.  
  378.         _zoneLair.oustAllPlayers();
  379.  
  380.         GrandBossManager.getInstance().setBossStatus(LINDVIOR_RAID, DORMANT);
  381.     }
  382.  
  383.     @Override
  384.     public String onAsk(L2PcInstance player, L2Npc npc, int ask, int reply)
  385.     {
  386.         if (reply == 1)
  387.         {
  388.             int index = npc.getAiVarInt("index");
  389.             if (!hasFlag(_activeMask, 1 << index))
  390.             {
  391.                 _activeMask |= 1 << index;
  392.  
  393.                 npc.setDisplayEffect(0x02);
  394.  
  395.                 sendEventTrigger(true, generatorTriggers[index]);
  396.  
  397.                 if (hasFlag(_activeMask, 0xf))
  398.                 {
  399.                     nextStage(2);
  400.                 }
  401.             }
  402.         }
  403.  
  404.         return null;
  405.     }
  406.  
  407.     @Override
  408.     public synchronized String onSkillSee(L2Npc npc, L2PcInstance caster, L2Skill skill, L2Object[] targets,
  409.                                           boolean isPet)
  410.     {
  411.         if (skill.getId() == 15606 && npc.getNpcId() == NPC_GENERATOR)
  412.         {
  413.             synchronized (_chargedValues)
  414.             {
  415.                 int index = npc.getAiVarInt("index");
  416.                 if (!hasFlag(_chargedMask, 1 << index))
  417.                 {
  418.                     _chargedValues[index] += 30;
  419.                     _chargedValues[index] = Math.min(_chargedValues[index], 120);
  420.  
  421.                     npc.getKnownList().getKnownPlayersInRadius(1000).forEach(player -> {
  422.                         player.sendPacket(new ExShowScreenMessage(NpcStringId.S1_HAS_CHARGED_THE_CANNON,
  423.                                 ExShowScreenMessage.TOP_CENTER, 10000, caster.getName()));
  424.                         player.sendPacket(new ExSendUIEvent(player, 5, 5000, _chargedValues[index], 0,
  425.                                 NpcStringId.CHARGING.getId()));
  426.                     });
  427.  
  428.                     if (_chargedValues[index] >= 120)
  429.                     {
  430.                         _chargedMask |= 1 << index;
  431.                         _chargedValues[index] = 0;
  432.                     }
  433.  
  434.                     if (hasFlag(_chargedMask, 0xf))
  435.                     {
  436.                         nextStage(3);
  437.                     }
  438.                 }
  439.             }
  440.         }
  441.  
  442.         return null;
  443.     }
  444.  
  445.     @Override
  446.     public String onSpawn(L2Npc npc)
  447.     {
  448.         switch (npc.getNpcId())
  449.         {
  450.             case NPC_ATTACKER_GENERATORS:
  451.             {
  452.                 npc.getKnownList().getKnownNpcInRadius(1500).forEach(cha -> {
  453.                     if (cha.getNpcId() == NPC_SCHEME_GENERATOR)
  454.                     {
  455.                         ((L2MonsterInstance) npc).attackCharacter(cha);
  456.                         ((L2GuardInstance) cha).attackCharacter(npc);
  457.                     }
  458.  
  459.                     if (cha.getNpcId() == NPC_GENERATOR)
  460.                     {
  461.                         ((L2MonsterInstance) npc).addDamageHate(cha, 0, 98);
  462.                     }
  463.                 });
  464.                 break;
  465.             }
  466.             case NPC_SCHEME_GENERATOR:
  467.             {
  468.                 ((L2GuardInstance) npc).setCanAttackPlayer(false);
  469.                 ((L2GuardInstance) npc).setCanAttackGuard(false);
  470.                 break;
  471.             }
  472.         }
  473.  
  474.         return super.onSpawn(npc);
  475.     }
  476.  
  477.     @Override
  478.     public String onNpcDie(L2Npc npc, L2Character killer)
  479.     {
  480.         if (npc.getNpcId() == LINDVIOR_RAID)
  481.         {
  482.             if (_mobsSpawnTask != null)
  483.             {
  484.                 _mobsSpawnTask.cancel(true);
  485.                 _mobsSpawnTask = null;
  486.             }
  487.  
  488.             _zoneLair.broadcastPacket(new ExShowScreenMessage(NpcStringId
  489.                     .HONORABLE_WARRIORS_HAVE_DRIVEN_OFF_LINDVIOR_THE_EVIL_WIND_DRAGON, ExShowScreenMessage.TOP_CENTER,
  490.                     5000));
  491.  
  492.             GrandBossManager.getInstance().setBossStatus(LINDVIOR_RAID, DEAD);
  493.  
  494.             long respawnTime = Config.INTERVAL_OF_LINDVIOR_SPAWN + Rnd.get(Config.RANDOM_OF_LINDVIOR_SPAWN);
  495.  
  496.             // also save the respawn time so that the info is maintained past reboots
  497.             StatsSet info = GrandBossManager.getInstance().getStatsSet(LINDVIOR_RAID);
  498.  
  499.             info.set("respawn_time", (System.currentTimeMillis() + respawnTime));
  500.  
  501.             GrandBossManager.getInstance().setStatsSet(LINDVIOR_RAID, info);
  502.  
  503.             _zoneLair.getCharactersInside().stream().filter(L2Character::isNpc).forEach(mob -> mob
  504.                     .getLocationController().delete());
  505.  
  506.             ThreadPoolManager.getInstance().scheduleGeneral(() -> npc.getLocationController().decay(), 10000L);
  507.             ThreadPoolManager.getInstance().scheduleGeneral(new UnlockLindvior(), respawnTime);
  508.         }
  509.         else if (npc.getNpcId() == NPC_GENERATOR)
  510.         {
  511.             _zoneLair.broadcastPacket(new ExShowScreenMessage(NpcStringId.THE_GENERATOR_HAS_BEEN_DESTROYED,
  512.                     ExShowScreenMessage.TOP_CENTER, 5000));
  513.  
  514.             Clean();
  515.  
  516.             _collapseTask = ThreadPoolManager.getInstance().scheduleGeneral(() -> Fail(false), 20000L);
  517.         }
  518.  
  519.         return super.onNpcDie(npc, killer);
  520.     }
  521.  
  522.     @Override
  523.     public String onFirstTalk(L2Npc npc, L2PcInstance player)
  524.     {
  525.         int index = npc.getAiVarInt("index");
  526.         if (hasFlag(_activeMask, 1 << index))
  527.         {
  528.             return "19477-1.htm";
  529.         }
  530.  
  531.         return "19477.htm";
  532.     }
  533.  
  534.     @Override
  535.     public String onEnterZone(L2Character character, L2ZoneType zone)
  536.     {
  537.         if (zone.getId() == ZONE_ID)
  538.         {
  539.             if (_collapseTask != null)
  540.             {
  541.                 _collapseTask.cancel(true);
  542.                 _collapseTask = null;
  543.             }
  544.         }
  545.  
  546.         return super.onEnterZone(character, zone);
  547.     }
  548.  
  549.     @Override
  550.     public String onExitZone(L2Character character, L2ZoneType zone)
  551.     {
  552.         if (zone.getId() == ZONE_ID)
  553.         {
  554.             if (zone.getPlayersInside().isEmpty())
  555.             {
  556.                 _collapseTask = ThreadPoolManager.getInstance().scheduleGeneral(() -> Fail(true), INACTIVITYTIME);
  557.             }
  558.         }
  559.  
  560.         return super.onExitZone(character, zone);
  561.     }
  562.  
  563.     private void nextStage(int _taskId)
  564.     {
  565.         switch (_taskId)
  566.         {
  567.             case 1: // Спавним генераторы, схемы и аттакеров
  568.             {
  569.                 _zoneLair.broadcastPacket(new EventTrigger(eventTriggerFirstStage, true));
  570.  
  571.                 int i = 0;
  572.                 L2GuardInstance guard;
  573.                 for (Location loc : CONTROL_GENERATOR_SPAWNS)
  574.                 {
  575.                     guard = (L2GuardInstance) addSpawn(NPC_GENERATOR, loc, false, true);
  576.                     guard.setDisplayEffect(0x01);
  577.                     guard.setAiVar("index", i++);
  578.  
  579.                     _monsterSpawn.add(guard);
  580.                     _generatorSpawn.add(guard);
  581.                 }
  582.  
  583.                 L2Npc npc;
  584.                 for (Location loc : SCHEME_GENERATOR_SPAWNS)
  585.                 {
  586.                     npc = addSpawn(NPC_SCHEME_GENERATOR, loc, false, true);
  587.                     npc.setIsNoRndWalk(true);
  588.  
  589.                     _monsterSpawn.add(npc);
  590.                 }
  591.  
  592.                 _mobsSpawnTask = ThreadPoolManager.getInstance().scheduleAiAtFixedRate(() -> {
  593.                     for (Location loc : ATTACKER_GENERATOR_SPAWNS)
  594.                     {
  595.                         _monsterSpawn.add(addSpawn(NPC_ATTACKER_GENERATORS, loc, false, true));
  596.                     }
  597.                 }, 20000, 60000);
  598.  
  599.                 _announceTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(() -> _zoneLair
  600.                         .getPlayersInside().forEach(player -> player.sendPacket(Rnd.get(GENERATOR_MESSAGES))), 10000,
  601.                         10000);
  602.                 break;
  603.             }
  604.             case 2: // После активации 4х генераторов, ждем их зарядки
  605.             {
  606.                 if (_announceTask != null)
  607.                 {
  608.                     _announceTask.cancel(true);
  609.                     _announceTask = null;
  610.                 }
  611.  
  612.                 _generatorSpawn.forEach(npc -> {
  613.                     npc.setDisplayEffect(0x00);
  614.                     npc.broadcastPacket(new ExNpcInfo(npc));
  615.                 });
  616.  
  617.                 _zoneLair.getPlayersInside().forEach(player -> {
  618.                     player.sendPacket(new EventTrigger(eventTriggerFirstStage, false));
  619.                     player.sendPacket(new EventTrigger(eventTriggerSecondStage, true));
  620.                     player.showQuestMovie(ExStartScenePlayer.SCENE_LINDVIOR_ARRIVE);
  621.  
  622.                     _generatorSpawn.forEach(npc -> npc.sendInfo(player));
  623.                 });
  624.  
  625.                 _lindvior2 = addSpawn(LINDVIOR_FAKE, CENTER_LOCATION, false, true);
  626.  
  627.                 _announceTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(() -> _zoneLair
  628.                         .getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId
  629.                                 .CHARGE_THE_CANNON_USING_THE_GENERATOR, ExShowScreenMessage.TOP_CENTER, 7000))),
  630.                         30000, 10000);
  631.                 _skillCastTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(() -> _generatorSpawn
  632.                         .forEach(npc -> {
  633.                     int index = npc.getAiVarInt("index");
  634.                     if (!npc.isCastingNow() && npc.getFirstEffect(SKILL) == null && !hasFlag(_chargedMask, 1 << index))
  635.                     {
  636.                         npc.doSimultaneousCast(SKILL);
  637.                     }
  638.                 }), 25000, 25000);
  639.                 break;
  640.             }
  641.             case 3: // После зарядки всех генераторов
  642.             {
  643.                 /**
  644.                  * 1 Этап
  645.                  * Первый этап начинается когда Линдвиор спускается на землю, и до того как у него не станет 80% HP.
  646.                  * Если стоять перед драконом, можно получить урон от удара ветром, а если стоять со спины,
  647.                  * то вы получите урон от удара хвостом.
  648.                  * Дракон будет использовать умение Дыхание Ветра - оно наносит урон и отбрасывает спереди дракона,
  649.                  * и умение Body Slam, которое наносит урон и оглушает цели вокруг.
  650.                  * Во время фарма Линдвиор будет призывать рейдовых бойцов.
  651.                  * Линдрако - id=25895 id=29243 id=29242 id=29241 id=25897 id=25896
  652.                  */
  653.  
  654.                 if (_announceTask != null)
  655.                 {
  656.                     _announceTask.cancel(true);
  657.                     _announceTask = null;
  658.                 }
  659.  
  660.                 if (_skillCastTask != null)
  661.                 {
  662.                     _skillCastTask.cancel(true);
  663.                     _skillCastTask = null;
  664.                 }
  665.  
  666.                 if (_mobsSpawnTask != null)
  667.                 {
  668.                     _mobsSpawnTask.cancel(true);
  669.                     _mobsSpawnTask = null;
  670.                 }
  671.  
  672.                 _monsterSpawn.forEach(npc -> {
  673.                     if (npc != null)
  674.                     {
  675.                         npc.onDelete();
  676.                     }
  677.                 });
  678.                 _monsterSpawn.clear();
  679.  
  680.                 ThreadPoolManager.getInstance().scheduleGeneral(() -> _zoneLair.broadcastPacket(new
  681.                         ExShowScreenMessage(NpcStringId.LINDVIOR_HAS_FALLEN_FROM_THE_SKY,
  682.                         ExShowScreenMessage.TOP_CENTER, 5000)), 15000);
  683.  
  684.                 if (_lindvior2 != null)
  685.                 {
  686.                     _lindvior2.onDelete();
  687.                 }
  688.  
  689.                 _lindvior = (L2GrandBossInstance) addSpawn(LINDVIOR_GROUND, CENTER_LOCATION, false, true);
  690.                 _lindvior.getHookContainer().addHook(HookType.ON_HP_CHANGED, _hpChange);
  691.  
  692.                 _zoneLair.getPlayersInside().forEach(_lindvior::sendInfo);
  693.  
  694.                 _mobsSpawnTask = ThreadPoolManager.getInstance().scheduleAiAtFixedRate(() -> spawnServitor(2, 1000,
  695.                         _lindvior.getLoc(), LINDVIOR_SERVITOR), 60000, 120000);
  696.                 break;
  697.             }
  698.         }
  699.     }
  700.  
  701.     /**
  702.      * Активируем триггеры зоны
  703.      *
  704.      * @param status   статус
  705.      * @param triggers идентификаторы
  706.      */
  707.     private void sendEventTrigger(boolean status, int... triggers)
  708.     {
  709.         L2GameServerPacket[] pakets = new L2GameServerPacket[triggers.length];
  710.  
  711.         for (int i = 0; i < triggers.length; i++)
  712.         {
  713.             pakets[i] = new EventTrigger(triggers[i], status);
  714.         }
  715.  
  716.         for (L2GameServerPacket packet : pakets)
  717.         {
  718.             _zoneLair.broadcastPacket(packet);
  719.         }
  720.     }
  721.  
  722.     /**
  723.      * Призываем монстров
  724.      *
  725.      * @param count  количество
  726.      * @param radius разброс
  727.      * @param loc    локация
  728.      * @param npcIds списко монстров
  729.      */
  730.     private void spawnServitor(int count, int radius, Location loc, int... npcIds)
  731.     {
  732.         int x = loc.getX(), y = loc.getY();
  733.         if (radius > 0)
  734.         {
  735.             x += Rnd.get(-radius, radius);
  736.             y += Rnd.get(-radius, radius);
  737.         }
  738.  
  739.         for (int i = 0; i < count; i++)
  740.         {
  741.             _monsterSpawn.add(addSpawn(Rnd.get(npcIds), x, y, loc.getZ(), loc.getHeading(), true, 0, true));
  742.         }
  743.     }
  744.  
  745.     /**
  746.      * Хит поинт Ченжер, Контролит процен ХП у боссов.
  747.      */
  748.     private class OnHpChange extends AbstractHookImpl
  749.     {
  750.         @Override
  751.         public void onHpChange(L2Character character, L2Character attacker, double damage, double fullDamage)
  752.         {
  753.             if (!character.isNpc())
  754.             {
  755.                 return;
  756.             }
  757.  
  758.             double percent = ((character.getCurrentHp() - damage) / character.getMaxHp()) * 100;
  759.             if (percent <= 20 && _status == 5)
  760.             {
  761.                 /**
  762.                  * 5 Этап
  763.                  * HP Дракона спускается ниже 20%.
  764.                  * Теперь, вам дается 10 минут, чтобы убить Линдвиора.
  765.                  * Он использует умение Ярость, и урон по нему снизится.
  766.                  * Если вы не успеете убить его за 10 минут, то всех выкинет из рейд зоны.
  767.                  * На последнем Этапе Lindvior призывает рейдовых бойцов и вихри, использует умения как на 1 этапе,
  768.                  * кроме этого, если вы попадёте в вихрь, то ваша скорость снизится и вас отбросит.
  769.                  */
  770.                 if (_smallVortexesTask != null)
  771.                 {
  772.                     _smallVortexesTask.cancel(true);
  773.                     _smallVortexesTask = null;
  774.                 }
  775.  
  776.                 _zoneLair.broadcastPacket(new ExShowScreenMessage(NpcStringId.LINDVIOR_HAS_LANDED,
  777.                         ExShowScreenMessage.TOP_CENTER, 5000));
  778.  
  779.                 _lindvior.broadcastPacket(new SocialAction(_lindvior.getObjectId(), 1));
  780.                 _lindvior.setIsDead(true);
  781.                 _lindvior.onDelete();
  782.  
  783.                 _lindvior = (L2GrandBossInstance) addSpawn(LINDVIOR_RAID, _lindvior.getLoc(), false, true);
  784.                 _lindvior.setCurrentHp(_lindvior.getMaxHp() * 0.2);
  785.                 _lindvior.getHookContainer().addHook(HookType.ON_HP_CHANGED, _hpChange);
  786.  
  787.                 _collapseTask = ThreadPoolManager.getInstance().scheduleGeneral(Lindvior.this::Clean, 10 * 60 * 1000);
  788.  
  789.                 _status = 6;
  790.             }
  791.             else if (percent <= 35 && _status == 4)
  792.             {
  793.                 /**
  794.                  * 4 Этап
  795.                  * Когда HP спустится ниже 35%, Рейд Босс призовет Малые Вихри.
  796.                  */
  797.                 _smallVortexesTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(() -> {
  798.                 }, 10000, 10000);
  799.  
  800.                 _status = 5;
  801.             }
  802.             else if (percent <= 40 && _status == 3)
  803.             {
  804.                 /**
  805.                  * 4 Этап
  806.                  * HP Линдвиора спускается до 40%, и он опять поднимается в воздух.
  807.                  */
  808.                 _lindvior.broadcastPacket(new SocialAction(_lindvior.getObjectId(), 1));
  809.                 _lindvior.setIsDead(true);
  810.                 _lindvior.onDelete();
  811.  
  812.                 _lindvior = (L2GrandBossInstance) addSpawn(LINDVIOR_FLY, _lindvior.getLoc(), false, true);
  813.                 _lindvior.setCurrentHp(_lindvior.getMaxHp() * 0.4);
  814.                 _lindvior.getHookContainer().addHook(HookType.ON_HP_CHANGED, _hpChange);
  815.  
  816.                 _status = 4;
  817.             }
  818.             else if (percent <= 60 && _status == 2)
  819.             {
  820.                 /**
  821.                  * 3 Этап
  822.                  * Когда HP Линдвиора спускается ниже 60%, он спускается на землю.
  823.                  * Он начинает использовать такие же умения, как и на 1 этапе,
  824.                  * и дополнительно использует умение Тёмный Ветер - он отражает урон.
  825.                  * Это умение легко заметить - Линдвиор потемнеет при его использовании.
  826.                  * Также появляются новые рейдовые бойцы (C)
  827.                  * Линдрако - id=25895 id=29243 id=29242 id=29241 id=25897 id=25896
  828.                  */
  829.                 _lindvior.broadcastPacket(new SocialAction(_lindvior.getObjectId(), 1));
  830.                 _lindvior.setIsDead(true);
  831.                 _lindvior.onDelete();
  832.  
  833.                 _lindvior = (L2GrandBossInstance) addSpawn(LINDVIOR_RAID, _lindvior.getLoc(), false, true);
  834.                 _lindvior.setCurrentHp(_lindvior.getMaxHp() * 0.6);
  835.                 _lindvior.getHookContainer().addHook(HookType.ON_HP_CHANGED, _hpChange);
  836.  
  837.                 _status = 3;
  838.             }
  839.             else if (percent <= 75 && _status == 1)
  840.             {
  841.                 /**
  842.                  * 2 Этап
  843.                  * Когда HP Линдвиора снизится до 75%, он вызовет огромный вихрь, который будет перемещаться по всей
  844.                  * локации.
  845.                  * Если вы попадете в гигантский вихрь, ваше HP, MP, CP опустится до 1.
  846.                  * Линдвиор также призывает новых рейдовых бойцов (B).
  847.                  * Линдрако - id=25895 id=29243 id=29242 id=29241 id=25897 id=25896
  848.                  */
  849.                 _bigVortexesTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(() -> {
  850.                 }, 10000, 10000);
  851.  
  852.                 _status = 2;
  853.             }
  854.             else if (percent <= 80 && _status == 0)
  855.             {
  856.                 /**
  857.                  * 2 Этап
  858.                  * Когда HP Линдвиора меньше 80%, он поднимается в воздух и перемещается по всему Алтарю
  859.                  * Жертвоприношения,
  860.                  * нанося мега удары ветром.
  861.                  * С небольшой вероятностью появляются вихри, которые будут затягивать персонажей и наносить урон.
  862.                  */
  863.  
  864.                 _lindvior.broadcastPacket(new SocialAction(_lindvior.getObjectId(), 1));
  865.                 _lindvior.setIsDead(true);
  866.                 _lindvior.onDelete();
  867.  
  868.                 _lindvior = (L2GrandBossInstance) addSpawn(LINDVIOR_FLY, _lindvior.getLoc(), false, true);
  869.                 _lindvior.setCurrentHp(_lindvior.getMaxHp() * 0.8);
  870.                 _lindvior.getHookContainer().addHook(HookType.ON_HP_CHANGED, _hpChange);
  871.  
  872.                 _status = 1;
  873.             }
  874.         }
  875.     }
  876.  
  877.     /**
  878.      * Обновляем статус босса при его респауне.
  879.      */
  880.     private class UnlockLindvior implements Runnable
  881.     {
  882.         @Override
  883.         public void run()
  884.         {
  885.             GrandBossManager.getInstance().setBossStatus(LINDVIOR_RAID, DORMANT);
  886.  
  887.             if (EARTH_QUAKE_ON_SPAWN)
  888.             {
  889.                 Broadcast.toAllOnlinePlayers(new EarthQuake(CENTER_LOCATION.getX(), CENTER_LOCATION.getY(),
  890.                         CENTER_LOCATION.getZ(), CENTER_LOCATION.getHeading(), 10));
  891.             }
  892.         }
  893.     }
  894. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement