package instance; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import com.aionemu.commons.utils.Rnd; import com.aionemu.gameserver.dataholders.DataManager; import com.aionemu.gameserver.instance.handlers.GeneralInstanceHandler; import com.aionemu.gameserver.instance.handlers.InstanceID; import com.aionemu.gameserver.model.Race; import com.aionemu.gameserver.model.gameobjects.Npc; import com.aionemu.gameserver.model.gameobjects.player.Player; import com.aionemu.gameserver.model.geometry.Point3D; import com.aionemu.gameserver.model.instance.InstanceProgressionType; import com.aionemu.gameserver.model.instance.instancescore.NormalScore; import com.aionemu.gameserver.network.aion.instanceinfo.EternalBastionScoreWriter; import com.aionemu.gameserver.network.aion.serverpackets.SM_INSTANCE_SCORE; import com.aionemu.gameserver.network.aion.serverpackets.SM_SYSTEM_MESSAGE; import com.aionemu.gameserver.services.abyss.AbyssPointsService; import com.aionemu.gameserver.services.item.ItemService; import com.aionemu.gameserver.services.player.PlayerReviveService; import com.aionemu.gameserver.services.teleport.TeleportService; import com.aionemu.gameserver.skillengine.SkillEngine; import com.aionemu.gameserver.skillengine.model.Effect; import com.aionemu.gameserver.utils.PacketSendUtility; import com.aionemu.gameserver.utils.ThreadPoolManager; import com.aionemu.gameserver.world.WorldMapInstance; /** * Remaining Online Information:
* Summarized guide: Link
* Guide based on interview: Link
* Rewards: <Link
* Quick Summary: * Players need to defend the fortress commander while also progressing the instance and accumulating additional points by killing the surrounding * camp commanders. The first three phases are progressed by killing three specific commanders, whereas the fourth phase will be completed if all * five siege towers are killed.
* Killing a specific barricade or dredgion signal tower or activating the siege cannon will result in additional assault pod spawns. * Every two minutes an assault wave will spawn. It's strength, i.e. assaulter count, increases over time. Additional waves can spawn from * assault pods, siege towers or broken wall/gate.
* Players can skip specific waves by killing enough commanders and thus reducing the assault strength. They can also use the cannons or tank to * make defending/attacking easier. * * @author Cheatkiller, Estrayl */ @InstanceID(300540000) public class EternalBastionInstance extends GeneralInstanceHandler { private static final int START_DELAY = 180 * 1000; private final AtomicInteger assaultPower = new AtomicInteger(12); // Retail private final AtomicInteger progressionKills = new AtomicInteger(); private final AtomicBoolean isRaceSet = new AtomicBoolean(); private final List> spawnTasks = new ArrayList<>(); private Future instanceTimerTask, assaultWaveTask; private int waveCount; private long startTime; private NormalScore instanceReward; public EternalBastionInstance(WorldMapInstance instance) { super(instance); } @Override public void onDie(Npc npc) { super.onDie(npc); switch (npc.getNpcId()) { case 231168: // Pashid Scout Commander Azute case 231169: // Pashid Scout Commander Zest case 231170: // Pashid Scout Commander Sartas case 231171: // Pashid Infantry Commander Matuk case 231172: // Pashid Assault Commander Badute case 231173: // Pashid Assault Commander Katsu case 231174: // Pashid Artillery Commander Murat case 231175: // Pashid Artillery Commander Kaimdu case 231176: // Pashid Artillery Commander Nirta addPoints(npc, 1880); checkProgress(progressionKills.incrementAndGet()); break; case 231143: // Pashid Siege Tower case 231152: // Pashid Siege Tower case 231153: // Pashid Siege Tower case 231154: // Pashid Siege Tower case 231155: // Pashid Siege Tower addPoints(npc, 334); checkProgress(progressionKills.incrementAndGet()); break; case 231177: // Deathbringer Tariksha addPoints(npc, 1880); break; case 231178: // Commander Hakunta case 231179: // Commander Rakunta addPoints(npc, 1880); assaultPower.addAndGet(-2); // Retail break; case 230784: // Pashid Snare Turret case 230785: // Pashid Assault Flamethrower case 231137: // Pashid Danuar Turret case 231138: // Pashid Danuar Turret case 231140: // Pashid Assault Pod case 231141: // Pashid Siege Drop Pod case 231144: // Pashid Siege Cannon case 231156: // Pashid Assault Pod case 231157: // Pashid Assault Pod case 231158: // Pashid Assault Pod case 231159: // Pashid Assault Pod case 231160: // Pashid Assault Pod case 231162: // Pashid Assault Pod case 231163: // Pashid Siege Drop Pod case 231164: // Pashid Siege Drop Pod case 231165: // Pashid Siege Drop Pod case 231167: // Pashid Siege Drop Pod case 231180: // Dredgion Signal Tower addPoints(npc, 334); break; case 231148: // Dredgion Signal Tower addPoints(npc, 334); PacketSendUtility.broadcastToMap(npc, SM_SYSTEM_MESSAGE.STR_MSG_IDLDF5b_TD_AddWave_03()); spawnWithDelay(231157, 778.845f, 323.282f, 253.434f, (byte) 40, 30000); spawnWithDelay(231159, 697.564f, 305.424f, 249.303f, (byte) 100, 30000); break; case 231149: // Pashid Army Barricade addPoints(npc, 266); PacketSendUtility.broadcastToMap(npc, SM_SYSTEM_MESSAGE.STR_MSG_IDLDF5b_TD_AddWave_02()); spawnWithDelay(231164, 667.350f, 281.046f, 225.698f, (byte) 33, 30000); // Pashid Assault Pod spawnWithDelay(231165, 721.498f, 358.172f, 230.940f, (byte) 0, 30000); case 231181: // Pashid Army Barricade addPoints(npc, 266); break; case 230746: // Pashid Assault Tribuni Sentry case 230753: // Pashid Assault Rider case 230754: // Pashid Assault Gunner case 230756: // Pashid Assault Supply Officer case 230757: // Pashid Assault Dragon addPoints(npc, 1002); assaultPower.decrementAndGet(); sendMsg(SM_SYSTEM_MESSAGE.STR_MSG_IDLDF5b_TD_Notice_06()); break; case 230744: // Pashid Assault Tribuni Combatant case 230745: // Pashid Assault Tribuni Protector case 230749: // Pashid Assault Tribuni Marksman case 231131: // Pashid Siege Dragon case 231132: // Pashid Siege Dragon case 231133: // Pashid Siege Dragon case 231134: // Pashid Siege Dragon addPoints(npc, 1002); break; case 831333: // Castle Wall addPoints(npc, -150); deleteAliveNpcs(831332); // Right Castle Gate deleteAliveNpcs(231150); // Drill sendMsg(SM_SYSTEM_MESSAGE.STR_MSG_IDLDF5b_TD_Notice_04()); break; case 831335: // Inner Water Gate addPoints(npc, -150); sendMsg(SM_SYSTEM_MESSAGE.STR_MSG_IDLDF5b_TD_Notice_02()); break; case 209516: // Commander Lysander case 209517: // Commander Granir addPoints(npc, -100000); // Retail endInstance(); break; case 209555: // Lysander's Disciple case 209557: // Granir's Disciple addPoints(npc, -50); break; case 231130: // Grand Commander Pashid addPoints(npc, 24000); endInstance(); break; case 231117: // Pashid Elite Siege Combatant case 231118: // Pashid Elite Siege Protector case 231119: // Pashid Elite Siege Ambusher case 231120: // Pashid Elite Siege Troublemaker case 231122: // Pashid Elite Siege Marksman case 231123: // Pashid Elite Siege Rampager case 231124: // Pashid Elite Siege Magus case 231125: // Pashid Elite Siege Summoner case 231126: // Pashid Elite Siege Cavalry case 231127: // Pashid Elite Siege Striker case 231128: // Pashid Elite Siege Medic case 233310: // Pashid Siege Cavalry case 233311: // Pashid Siege Engineer addPoints(npc, 42); break; case 233312: // Pashid Siege Healer case 233314: // Pashid Elite Siege Defender case 233315: // Pashid Elite Siege Gunner addPoints(npc, 36); break; case 231115: // Pashid Siege Soldier case 231116: // Pashid Siege Mage case 233309: // Pashid Siege Ambusher addPoints(npc, 33); break; case 233313: addPoints(npc, 20); break; } } private void checkProgress(int progressionKills) { switch (progressionKills) { case 3 -> { Npc outerWaterGate = getNpc(831334); if (outerWaterGate != null) outerWaterGate.getController().deleteIfAliveOrCancelRespawn(); spawn(233314, 575.858f, 146.753f, 221.351f, (byte) 33); // Pashid Elite Siege Defender spawn(233314, 587.445f, 152.020f, 218.004f, (byte) 63); spawn(233314, 609.691f, 187.747f, 216.455f, (byte) 87); spawn(233314, 630.440f, 192.271f, 219.763f, (byte) 40); spawn(233315, 598.051f, 160.956f, 216.754f, (byte) 100); // Pashid Elite Siege Gunner spawn(233315, 609.099f, 150.973f, 216.063f, (byte) 57); spawn(233315, 637.820f, 203.284f, 222.032f, (byte) 77); spawn(233315, 641.959f, 197.833f, 221.788f, (byte) 77); spawnTasks.add(ThreadPoolManager.getInstance().schedule(() -> { sendMsg(SM_SYSTEM_MESSAGE.STR_MSG_IDLDF5b_TD_MainWave_02()); spawn(231171, 655.755f, 212.606f, 223.931f, (byte) 80); // Pashid Infantry Commander Matuk spawnWithWalker(231142, 604.397f, 170.492f, 216.042f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_Z1_S2_D1"); // Pashid Siege Volatile spawnWithWalker(231142, 605.397f, 171.492f, 216.092f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_Z1_S2_D1"); spawnWithWalker(231142, 603.397f, 171.492f, 216.085f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_Z1_S2_D1"); spawnWithWalker(231173, 657.052f, 465.173f, 225.052f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_Z1_S2_B2F2"); // Pashid Assault Commander Katsu spawnWithWalker(233313, 659.052f, 467.173f, 225.000f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_Z1_S2_B2F2"); spawnWithWalker(233313, 655.052f, 467.173f, 225.133f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_Z1_S2_B2F2"); spawnWithWalker(231172, 604.429f, 413.910f, 223.782f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_Z1_S2_B1F2"); // Pashid Assault Commander Badute spawnWithWalker(233313, 606.429f, 411.910f, 224.027f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_Z1_S2_B1F2"); spawnWithWalker(233313, 602.429f, 411.910f, 223.756f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_Z1_S2_B1F2"); }, 90, TimeUnit.SECONDS)); } case 6 -> spawnTasks.add(ThreadPoolManager.getInstance().schedule(() -> { sendMsg(SM_SYSTEM_MESSAGE.STR_MSG_IDLDF5b_TD_MainWave_03()); spawn(233313, 572.428f, 368.118f, 226.464f, (byte) 113); // Pashid Siege Combatant spawn(233313, 577.691f, 374.779f, 226.077f, (byte) 110); spawn(233313, 583.372f, 380.359f, 225.562f, (byte) 107); spawn(233313, 590.788f, 386.729f, 224.273f, (byte) 100); spawn(233313, 652.680f, 456.840f, 225.698f, (byte) 110); spawn(233313, 660.402f, 469.521f, 225.095f, (byte) 113); spawn(233313, 670.701f, 477.320f, 225.120f, (byte) 100); spawn(233313, 681.626f, 481.653f, 224.853f, (byte) 100); spawn(231137, 569.389f, 374.023f, 228.221f, (byte) 110); // Pashid Danuar Turret spawn(231137, 576.424f, 381.682f, 226.099f, (byte) 107); spawn(231137, 584.247f, 388.219f, 225.080f, (byte) 103); spawn(231138, 650.886f, 466.252f, 225.282f, (byte) 110); spawn(231138, 661.941f, 478.229f, 226.286f, (byte) 103); spawn(231138, 673.506f, 486.307f, 225.869f, (byte) 100); spawn(231140, 635.426f, 243.117f, 238.075f, (byte) 33); // Pashid Assault Pods spawn(231141, 666.361f, 294.435f, 225.698f, (byte) 20); spawn(231158, 768.339f, 390.709f, 243.356f, (byte) 40); spawn(231174, 669.851f, 468.267f, 225.250f, (byte) 107); // Pashid Artillery Commander Murat spawn(231175, 583.830f, 373.812f, 225.280f, (byte) 107); // Pashid Artillery Commander Kaimdu spawn(231176, 760.219f, 392.471f, 243.354f, (byte) 50); // Pashid Infantry Commander Nirta }, 90, TimeUnit.SECONDS)); case 9 -> spawnTasks.add(ThreadPoolManager.getInstance().schedule(() -> { sendMsg(SM_SYSTEM_MESSAGE.STR_MSG_IDLDF5b_TD_MainWave_04()); spawn(231143, 613.231f, 262.163f, 227.255f, (byte) 3); spawn(231152, 608.371f, 303.514f, 226.295f, (byte) 113); spawn(231153, 625.244f, 352.624f, 226.295f, (byte) 113); spawn(231154, 668.864f, 405.970f, 228.500f, (byte) 83); spawn(231155, 691.536f, 409.367f, 231.720f, (byte) 98); }, 90, TimeUnit.SECONDS)); case 14 -> spawnTasks.add(ThreadPoolManager.getInstance().schedule(() -> { sendMsg(SM_SYSTEM_MESSAGE.STR_MSG_IDLDF5b_TD_MainWave_05()); spawn(231130, 740.668f, 298.082f, 233.889f, (byte) 100); // Commander Pashid spawn(231131, 686.574f, 358.216f, 243.386f, (byte) 100); // Pashid Siege Dragons spawn(231131, 655.856f, 351.118f, 241.595f, (byte) 20); spawn(231131, 732.982f, 371.320f, 230.942f, (byte) 106); spawn(231132, 582.631f, 376.172f, 225.461f, (byte) 100); spawn(231133, 745.820f, 322.916f, 249.287f, (byte) 86); spawn(231133, 713.242f, 289.971f, 249.285f, (byte) 0); spawn(231134, 668.732f, 473.705f, 225.159f, (byte) 100); spawn(231156, 641.551f, 339.264f, 238.075f, (byte) 20); // Pashid Assault Pods spawn(231163, 727.175f, 364.431f, 230.941f, (byte) 7); }, 90, TimeUnit.SECONDS)); } } @Override public void onEnterInstance(Player player) { if (!instanceReward.isRewarded()) sendPacket(); if (isRaceSet.compareAndSet(false, true)) { spawnRaceGuards(player.getRace()); if (Rnd.nextBoolean()) { spawn(231177, 821.146f, 607.305f, 239.703f, (byte) 73); // Deathbringer Tariksha spawn(230746, 551.146f, 412.105f, 222.760f, (byte) 30); // Pashid Assault Tribuni Sentry spawn(231149, 702.116f, 552.614f, 232.423f, (byte) 110); // Pashid Army Barricade (Assault Pod Trigger) spawn(231181, 564.414f, 250.835f, 233.198f, (byte) 110); // Pashid Army Barricade } else { spawn(230746, 821.146f, 607.305f, 239.703f, (byte) 73); // Pashid Assault Tribuni Sentry spawn(231177, 551.146f, 412.105f, 222.760f, (byte) 30); // Deathbringer Tariksha spawn(231181, 702.116f, 552.614f, 232.423f, (byte) 110); // Pashid Army Barricade spawn(231149, 564.414f, 250.835f, 233.198f, (byte) 110); // Pashid Army Barricade (Assault Pod Trigger) } } } private void spawnRaceGuards(Race race) { int guardId = race == Race.ELYOS ? 209555 : 209557; spawn(race == Race.ELYOS ? 209516 : 209517, 750.205f, 285.880f, 233.752f, (byte) 40); // Commander spawn(race == Race.ELYOS ? 701923 : 701924, 744.174f, 292.949f, 233.698f, (byte) 40); // Flag spawn(race == Race.ELYOS ? 701625 : 701922, 640.862f, 412.784f, 243.940f, (byte) 40); // Siege Cannon spawn(guardId, 595.476f, 284.680f, 226.375f, (byte) 40); spawn(guardId, 598.868f, 284.201f, 226.424f, (byte) 40); spawn(guardId, 602.328f, 340.964f, 225.794f, (byte) 40); spawn(guardId, 605.731f, 343.153f, 225.448f, (byte) 40); spawn(guardId, 607.450f, 387.642f, 223.353f, (byte) 40); spawn(guardId, 611.817f, 388.865f, 223.500f, (byte) 40); spawn(guardId, 681.742f, 444.580f, 226.818f, (byte) 40); spawn(guardId, 684.437f, 447.848f, 226.787f, (byte) 40); spawn(guardId, 690.046f, 351.800f, 244.744f, (byte) 40); spawn(guardId, 690.220f, 341.532f, 228.674f, (byte) 40); spawn(guardId, 692.778f, 337.952f, 228.674f, (byte) 40); spawn(guardId, 693.082f, 354.432f, 244.733f, (byte) 40); spawn(guardId, 715.405f, 427.312f, 230.025f, (byte) 40); spawn(guardId, 719.378f, 428.101f, 230.112f, (byte) 40); spawn(guardId, 748.146f, 361.345f, 230.945f, (byte) 40); spawn(guardId, 749.389f, 364.988f, 230.945f, (byte) 40); if (race == Race.ELYOS) { spawn(701596, 617.501f, 248.196f, 235.740f, (byte) 60); // Cannons spawn(701597, 612.806f, 275.206f, 235.740f, (byte) 67); spawn(701598, 616.159f, 313.939f, 235.740f, (byte) 53); spawn(701599, 625.603f, 339.608f, 235.734f, (byte) 53); spawn(701600, 650.914f, 372.932f, 238.607f, (byte) 53); spawn(701601, 677.853f, 396.203f, 238.632f, (byte) 40); spawn(701602, 710.145f, 410.661f, 241.014f, (byte) 30); spawn(701603, 736.803f, 414.121f, 241.017f, (byte) 40); spawn(701604, 772.961f, 410.834f, 241.014f, (byte) 20); spawn(701605, 798.383f, 401.605f, 241.015f, (byte) 30); spawn(701606, 709.602f, 313.531f, 254.216f, (byte) 40); spawn(701607, 726.757f, 327.932f, 254.216f, (byte) 50); } else { spawn(701610, 617.501f, 248.196f, 235.740f, (byte) 60); // Cannons spawn(701611, 612.806f, 275.206f, 235.740f, (byte) 67); spawn(701612, 616.159f, 313.939f, 235.740f, (byte) 53); spawn(701613, 625.603f, 339.608f, 235.734f, (byte) 53); spawn(701614, 650.914f, 372.932f, 238.607f, (byte) 53); spawn(701615, 677.853f, 396.203f, 238.632f, (byte) 40); spawn(701616, 710.145f, 410.661f, 241.014f, (byte) 30); spawn(701617, 736.803f, 414.121f, 241.017f, (byte) 40); spawn(701618, 772.961f, 410.834f, 241.014f, (byte) 20); spawn(701619, 798.383f, 401.605f, 241.015f, (byte) 30); spawn(701620, 709.602f, 313.531f, 254.216f, (byte) 40); spawn(701621, 726.757f, 327.932f, 254.216f, (byte) 50); } } @Override public void onInstanceCreate() { instanceReward = new NormalScore(); instanceReward.setInstanceProgressionType(InstanceProgressionType.PREPARING); instanceReward.setPoints(20000); startTime = System.currentTimeMillis(); instanceTimerTask = ThreadPoolManager.getInstance().schedule(this::onStart, START_DELAY); } private void onStart() { startTime = System.currentTimeMillis(); instanceReward.setInstanceProgressionType(InstanceProgressionType.START_PROGRESS); sendPacket(); instance.forEachDoor(door -> door.setOpen(true)); assaultWaveTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(this::spawnAssaultWave, 60000, 60000); instanceTimerTask = ThreadPoolManager.getInstance().schedule(this::onTimeOut, 30, TimeUnit.MINUTES); sendMsg(SM_SYSTEM_MESSAGE.STR_MSG_IDLDF5b_TD_MainWave_01()); spawn(233313, 584.013f, 371.221f, 225.374f, (byte) 110); // Pashid Siege Fighter spawn(233313, 588.725f, 377.543f, 225.221f, (byte) 110); spawn(233313, 655.190f, 454.515f, 225.936f, (byte) 110); spawn(233313, 659.293f, 461.406f, 225.449f, (byte) 110); spawn(233313, 795.178f, 462.909f, 225.853f, (byte) 118); spawn(233313, 804.449f, 461.860f, 227.897f, (byte) 58); spawn(233315, 572.093f, 377.641f, 227.147f, (byte) 110); // Pashid Elite Siege Gunner spawn(233315, 580.561f, 387.814f, 225.668f, (byte) 110); spawn(233315, 646.597f, 458.471f, 225.575f, (byte) 117); spawn(233315, 652.617f, 467.432f, 225.265f, (byte) 113); spawn(233315, 794.179f, 474.019f, 225.361f, (byte) 88); spawn(233315, 806.574f, 473.837f, 227.837f, (byte) 98); spawn(231168, 652.191f, 461.264f, 225.095f, (byte) 110); // Pashid Scout Commander Azute spawn(231169, 581.777f, 377.664f, 225.528f, (byte) 110); // Pashid Scout Commander Zest spawn(231170, 800.515f, 469.416f, 228.586f, (byte) 88); // Pashid Scout Commander Sartas spawn(831334, 569.772f, 162.763f, 220.048f, (byte) 53, 271); // Outer Water Gate spawnWithDelay(231167, 735.282f, 295.307f, 233.752f, (byte) 115, 9000); // Pashid Assault Pods spawnWithDelay(231162, 747.273f, 300.182f, 233.752f, (byte) 97, 6000); } private void spawnAssaultWave() { switch (++waveCount) { case 1, 5, 13, 17, 25 -> spawnAssaultPodWave(); case 2 -> spawnEasternWaveOne(); case 4 -> { spawnEasternWaveOne(); spawnNorthernWaveOne(); } case 6 -> { spawnEasternWaveOne(); spawnNorthernWaveOne(); spawnEasternWaveTwo(); spawnCanalWave(); spawnSiegeTowerWave(); } case 8 -> { spawnEasternWaveOne(); spawnNorthernWaveOne(); spawnEasternWaveTwo(); spawnWesternWave(); } case 9, 21 -> { spawnAssaultPodWave(); spawnSiegeTowerWave(); } case 10 -> { spawnEasternWaveOne(); spawnNorthernWaveOne(); spawnEasternWaveTwo(); spawnWesternWave(); spawnNorthernWaveTwo(); spawnCanalWave(); if (assaultPower.get() >= 8) { spawnWithWalker(231142, 795.579f, 478.629f, 225.086f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S38"); // Pashid Siege Volatile spawnWithWalker(231142, 798.579f, 479.629f, 225.221f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S38"); spawnWithWalker(231142, 792.579f, 479.629f, 224.934f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S38"); spawnWithWalker(231142, 801.579f, 481.629f, 225.845f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S38"); spawnWithWalker(231142, 789.579f, 481.629f, 224.622f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S38"); } } case 12 -> { spawnEasternWaveOne(); spawnNorthernWaveOne(); spawnEasternWaveTwo(); spawnWesternWave(); spawnNorthernWaveTwo(); spawnEasternWaveThree(); spawnSiegeTowerWave(); } case 14 -> { spawnEasternWaveOne(); spawnNorthernWaveOne(); spawnEasternWaveTwo(); spawnWesternWave(); spawnNorthernWaveTwo(); spawnEasternWaveThree(); spawnCanalWave(); } case 15 -> { spawnCanalWave(); spawnSiegeTowerWave(); if (assaultPower.get() >= 7 && getNpc(831333) != null) spawnWithWalker(231150, 798.563f, 477.952f, 225.231f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S73"); // Pashid Siege Ram } case 16 -> { if (assaultPower.get() >= 11) spawnEasternWaveOne(); spawnNorthernWaveOne(); spawnEasternWaveTwo(); if (assaultPower.get() >= 12) spawnWesternWave(); spawnNorthernWaveTwo(); spawnEasternWaveThree(); } case 18 -> { spawnEasternWaveOne(); spawnNorthernWaveOne(); if (assaultPower.get() >= 10) spawnEasternWaveTwo(); spawnWesternWave(); if (assaultPower.get() >= 9) spawnNorthernWaveTwo(); spawnEasternWaveThree(); spawnCanalWave(); spawnSouthernWave(); spawnSiegeTowerWave(); } case 20 -> { spawnEasternWaveOne(); spawnNorthernWaveOne(); spawnEasternWaveTwo(); spawnWesternWave(); spawnNorthernWaveTwo(); spawnEasternWaveThree(); } case 22 -> { spawnEasternWaveOne(); spawnNorthernWaveOne(); spawnEasternWaveTwo(); spawnWesternWave(); spawnNorthernWaveTwo(); spawnEasternWaveThree(); spawnCanalWave(); spawnSouthernWave(); } case 24 -> { if (assaultPower.get() >= 5) spawnEasternWaveOne(); spawnNorthernWaveOne(); spawnEasternWaveTwo(); if (assaultPower.get() >= 6) spawnWesternWave(); spawnNorthernWaveTwo(); spawnEasternWaveThree(); spawnSiegeTowerWave(); } case 26 -> { spawnEasternWaveOne(); if (assaultPower.get() >= 3) spawnNorthernWaveOne(); spawnEasternWaveTwo(); spawnWesternWave(); spawnNorthernWaveTwo(); if (assaultPower.get() >= 4) spawnEasternWaveThree(); spawnCanalWave(); spawnSouthernWave(); } case 28 -> { spawnEasternWaveOne(); spawnNorthernWaveOne(); if (assaultPower.get() >= 1) spawnEasternWaveTwo(); spawnWesternWave(); if (assaultPower.get() >= 2) spawnNorthernWaveTwo(); spawnEasternWaveThree(); } } } private void spawnEasternWaveOne() { spawnWithWalker(231113, 652.071f, 475.738f, 226.125f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S46"); // East 1 spawnWithWalker(231110, 655.071f, 478.738f, 226.125f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S46"); spawnWithWalker(231110, 649.071f, 478.738f, 226.125f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S46"); } private void spawnEasternWaveTwo() { spawnWithWalker(231114, 671.857f, 480.417f, 225.195f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S32"); // East 2 spawnWithWalker(231112, 674.857f, 483.417f, 225.337f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S32"); spawnWithWalker(231112, 668.857f, 483.417f, 226.457f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S32"); } private void spawnEasternWaveThree() { spawnWithWalker(231113, 632.525f, 451.311f, 223.422f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S34"); // East 3 spawnWithWalker(231111, 635.525f, 454.311f, 223.193f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S34"); spawnWithWalker(231111, 629.525f, 454.311f, 220.445f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S34"); } private void spawnNorthernWaveOne() { spawnWithWalker(231113, 598.026f, 411.715f, 223.784f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S71"); // North 1 spawnWithWalker(231110, 601.026f, 414.715f, 223.519f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S71"); spawnWithWalker(231110, 595.026f, 414.715f, 223.552f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S71"); } private void spawnNorthernWaveTwo() { spawnWithWalker(231113, 569.237f, 387.007f, 227.533f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S36"); // North 2 spawnWithWalker(231111, 572.237f, 390.007f, 227.905f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S36"); spawnWithWalker(231111, 566.237f, 390.007f, 228.194f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S36"); } private void spawnWesternWave() { spawnWithWalker(231114, 587.952f, 239.621f, 229.530f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S44"); // West spawnWithWalker(231112, 590.952f, 242.621f, 229.152f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S44"); spawnWithWalker(231112, 584.952f, 242.621f, 229.822f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S44"); } private void spawnSouthernWave() { if (getNpc(831333) == null) { spawnWithWalker(231113, 794.134f, 483.021f, 224.756f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S39"); // South Wall spawnWithWalker(231113, 796.134f, 481.021f, 225.008f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S39"); spawnWithWalker(231113, 792.134f, 481.021f, 224.820f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_S39"); } } private void spawnCanalWave() { if (getNpc(831335) == null) { spawnWithWalker(231110, 610.571f, 189.724f, 216.509f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_Z1_S2_T1"); // Canal spawnWithWalker(231108, 612.571f, 191.724f, 216.589f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_Z1_S2_T1"); spawnWithWalker(231108, 608.571f, 187.724f, 216.574f, (byte) 100, "NPCPathIDLDF5b_TD_Mob_Z1_S2_T1"); } } private void spawnAssaultPodWave() { if (getNpc(231140) != null) { spawnWithWalker(231106, 633.457f, 245.792f, 238.075f, (byte) 33, "NPCPathIDLDF5b_TD_Mob_Z1_S3_POD01"); spawnWithWalker(231108, 635.457f, 247.792f, 238.075f, (byte) 33, "NPCPathIDLDF5b_TD_Mob_Z1_S3_POD01"); spawnWithWalker(231108, 631.457f, 247.792f, 238.075f, (byte) 33, "NPCPathIDLDF5b_TD_Mob_Z1_S3_POD01"); } if (getNpc(231156) != null) { spawnWithWalker(231106, 642.871f, 343.420f, 238.075f, (byte) 20, "NPCPathIDLDF5b_TD_Z1_S5_POD01"); spawnWithWalker(231108, 644.871f, 345.420f, 238.075f, (byte) 20, "NPCPathIDLDF5b_TD_Z1_S5_POD01"); spawnWithWalker(231108, 640.871f, 345.420f, 238.075f, (byte) 20, "NPCPathIDLDF5b_TD_Z1_S5_POD01"); } if (getNpc(231157) != null) { spawnWithWalker(231106, 776.242f, 326.041f, 253.434f, (byte) 40, "NPCPathIDLDF5b_TD_Z4_POD02"); spawnWithWalker(231108, 778.242f, 328.041f, 253.434f, (byte) 40, "NPCPathIDLDF5b_TD_Z4_POD02"); spawnWithWalker(231108, 774.242f, 328.041f, 253.434f, (byte) 40, "NPCPathIDLDF5b_TD_Z4_POD02"); } if (getNpc(231158) != null) { spawnWithWalker(231106, 765.481f, 393.614f, 243.354f, (byte) 40, "NPCPathIDLDF5b_TD_Mob_Z1_S3_POD3"); spawnWithWalker(231108, 767.481f, 395.614f, 243.354f, (byte) 40, "NPCPathIDLDF5b_TD_Mob_Z1_S3_POD3"); spawnWithWalker(231108, 763.481f, 395.614f, 243.354f, (byte) 40, "NPCPathIDLDF5b_TD_Mob_Z1_S3_POD3"); } if (getNpc(231141) != null) { spawnWithWalker(231105, 667.631f, 297.565f, 225.700f, (byte) 20, "NPCPathIDLDF5b_TD_Mob_Z1_S3_POD2"); spawnWithWalker(231107, 669.631f, 299.565f, 225.700f, (byte) 20, "NPCPathIDLDF5b_TD_Mob_Z1_S3_POD2"); spawnWithWalker(231107, 665.631f, 299.565f, 225.700f, (byte) 20, "NPCPathIDLDF5b_TD_Mob_Z1_S3_POD2"); } if (getNpc(231163) != null) { spawnWithWalker(231105, 731.089f, 365.461f, 230.941f, (byte) 7, "NPCPathIDLDF5b_TD_Z1_S5_POD02"); spawnWithWalker(231107, 731.089f, 365.461f, 230.941f, (byte) 7, "NPCPathIDLDF5b_TD_Z1_S5_POD02"); spawnWithWalker(231107, 731.089f, 365.461f, 230.941f, (byte) 7, "NPCPathIDLDF5b_TD_Z1_S5_POD02"); } if (getNpc(231159) != null) { spawnWithWalker(231106, 699.760f, 302.938f, 249.303f, (byte) 100, "NPCPathIDLDF5b_TD_Z4_POD01"); spawnWithWalker(231108, 701.760f, 304.938f, 249.303f, (byte) 100, "NPCPathIDLDF5b_TD_Z4_POD01"); spawnWithWalker(231108, 697.760f, 304.938f, 249.303f, (byte) 100, "NPCPathIDLDF5b_TD_Z4_POD01"); } if (getNpc(231162) != null) { // Could be a bug on retail, but anyway spawnWithWalker(231106, 724.927f, 359.346f, 230.941f, (byte) 0, "NPCPathIDLDF5b_TD_Z3_POD02"); spawnWithWalker(231108, 726.927f, 361.346f, 230.941f, (byte) 0, "NPCPathIDLDF5b_TD_Z3_POD02"); spawnWithWalker(231108, 722.927f, 361.346f, 230.941f, (byte) 0, "NPCPathIDLDF5b_TD_Z3_POD02"); } if (getNpc(231164) != null) { spawnWithWalker(231106, 724.927f, 359.346f, 230.941f, (byte) 0, "NPCPathIDLDF5b_TD_Z3_POD02"); spawnWithWalker(231108, 726.927f, 361.346f, 230.941f, (byte) 0, "NPCPathIDLDF5b_TD_Z3_POD02"); spawnWithWalker(231108, 722.927f, 361.346f, 230.941f, (byte) 0, "NPCPathIDLDF5b_TD_Z3_POD02"); } if (getNpc(231165) != null) { spawnWithWalker(231106, 724.927f, 359.346f, 230.941f, (byte) 0, "NPCPathIDLDF5b_TD_Z3_POD02"); spawnWithWalker(231108, 726.927f, 361.346f, 230.941f, (byte) 0, "NPCPathIDLDF5b_TD_Z3_POD02"); spawnWithWalker(231108, 722.927f, 361.346f, 230.941f, (byte) 0, "NPCPathIDLDF5b_TD_Z3_POD02"); } } private void spawnSiegeTowerWave() { if (getNpc(230783) != null) { spawnWithWalker(231107, 623.235f, 263.392f, 238.484f, (byte) 3, "NPCPathIDLDF5b_TD_Z1_S4_T1"); spawnWithWalker(231105, 625.235f, 265.392f, 238.484f, (byte) 3, "NPCPathIDLDF5b_TD_Z1_S4_T1"); spawnWithWalker(231105, 621.235f, 265.392f, 238.484f, (byte) 3, "NPCPathIDLDF5b_TD_Z1_S4_T1"); } if (getNpc(231152) != null) { spawnWithWalker(231107, 621.920f, 298.179f, 238.075f, (byte) 113, "NPCPathIDLDF5b_TD_Z1_S4_T2"); spawnWithWalker(231105, 623.920f, 300.179f, 238.075f, (byte) 113, "NPCPathIDLDF5b_TD_Z1_S4_T2"); spawnWithWalker(231105, 619.920f, 300.179f, 238.075f, (byte) 113, "NPCPathIDLDF5b_TD_Z1_S4_T2"); } if (getNpc(231153) != null) { spawnWithWalker(231107, 644.089f, 351.522f, 239.764f, (byte) 113, "NPCPathIDLDF5b_TD_Z1_S4_T3"); spawnWithWalker(231105, 646.089f, 353.522f, 241.151f, (byte) 113, "NPCPathIDLDF5b_TD_Z1_S4_T3"); spawnWithWalker(231105, 642.089f, 353.522f, 239.809f, (byte) 113, "NPCPathIDLDF5b_TD_Z1_S4_T3"); } if (getNpc(231154) != null) { spawnWithWalker(231107, 664.091f, 394.303f, 240.223f, (byte) 83, "NPCPathIDLDF5b_TD_Z1_S4_T4"); spawnWithWalker(231105, 666.091f, 396.303f, 240.223f, (byte) 83, "NPCPathIDLDF5b_TD_Z1_S4_T4"); spawnWithWalker(231105, 662.091f, 396.303f, 240.223f, (byte) 83, "NPCPathIDLDF5b_TD_Z1_S4_T4"); } if (getNpc(231155) != null) { spawnWithWalker(231107, 692.867f, 396.708f, 241.594f, (byte) 85, "NPCPathIDLDF5b_TD_Z1_S4_T5"); spawnWithWalker(231105, 694.867f, 398.708f, 242.018f, (byte) 85, "NPCPathIDLDF5b_TD_Z1_S4_T5"); spawnWithWalker(231105, 690.867f, 398.708f, 241.594f, (byte) 85, "NPCPathIDLDF5b_TD_Z1_S4_T5"); } } private void onTimeOut() { sendMsg(SM_SYSTEM_MESSAGE.STR_MSG_IDLDF5b_TD_MainWave_06()); endInstance(); } /* * Original points for ranks: * 92,000 = S-Rank * 84,000 = A-Rank * 76,000 = B-Rank * 50,000 = C-Rank * 10,000 = D-Rank */ private void endInstance() { cancelTasks(); instanceReward.setInstanceProgressionType(InstanceProgressionType.END_PROGRESS); int rank = getFinalRank(); switch (rank) { case 1 -> { instanceReward.setFinalAp(35000); instanceReward.setRewardItem1(186000242); // Ceramium Medal instanceReward.setRewardItem1Count(4); instanceReward.setRewardItem2(188052596); // Highest Grade Material Support Bundle instanceReward.setRewardItem2Count(1); instanceReward.setRewardItem3(188052594); // Highest Grade Material Box instanceReward.setRewardItem3Count(1); } case 2 -> { instanceReward.setFinalAp(25000); instanceReward.setRewardItem1(186000242); // Ceramium Medal instanceReward.setRewardItem1Count(2); instanceReward.setRewardItem2(188052594); // Highest Grade Material Box instanceReward.setRewardItem2Count(1); instanceReward.setRewardItem3(188052597); // High Grade Material Support Bundle instanceReward.setRewardItem3Count(1); } case 3 -> { // B-Rank instanceReward.setFinalAp(15000); instanceReward.setRewardItem1(186000242); // Ceramium Medal instanceReward.setRewardItem1Count(1); instanceReward.setRewardItem2(188052595); // High Grade Material Box instanceReward.setRewardItem2Count(1); instanceReward.setRewardItem3(188052598); // Low Grade Material Support Bundle instanceReward.setRewardItem3Count(1); } case 4 -> { // C-Rank instanceReward.setFinalAp(11000); instanceReward.setRewardItem1(188052598); // Low Grade Material Support Bundle instanceReward.setRewardItem1Count(1); } case 5 -> instanceReward.setFinalAp(7000); // D-Rank } instanceReward.setInstanceProgressionType(InstanceProgressionType.END_PROGRESS); instanceReward.setRank(rank); instance.forEachNpc(npc -> npc.getController().delete()); sendPacket(); instance.forEachPlayer(this::distributeRewards); spawnFinalChest(rank); spawn(730871, 766.458f, 263.157f, 233.498f, (byte) 100); // Exit log.info("[{}] Instance completed with {} points resulting in {}-Rank. Player(s) in instance: {}", DataManager.WORLD_MAPS_DATA.getTemplate(mapId).getName(), instanceReward.getPoints(), getRankNameById(rank), instance.getPlayersInside().stream().map(p -> String.format("%s (ID:%d)", p.getName(), p.getObjectId())).collect(Collectors.joining(", "))); } private int getFinalRank() { if (instanceReward.getPoints() >= 90000) { // S-Rank return 1; } else if (instanceReward.getPoints() >= 82000) { // A-Rank return 2; } else if (instanceReward.getPoints() >= 60000) { // B-Rank return 3; } else if (instanceReward.getPoints() >= 30000) { // C-Rank return 4; } else if (instanceReward.getPoints() >= 5000) { // D-Rank return 5; } else { return 8; } } private void spawnFinalChest(int rank) { switch (rank) { case 1 -> spawn(701913, 744.167f, 292.860f, 233.702f, (byte) 100); // Biggest in model size case 2 -> spawn(701914, 744.167f, 292.860f, 233.702f, (byte) 100); case 3 -> spawn(701915, 744.167f, 292.860f, 233.702f, (byte) 100); case 4 -> spawn(701916, 744.167f, 292.860f, 233.702f, (byte) 100); case 5 -> spawn(701917, 744.167f, 292.860f, 233.702f, (byte) 100); // Smallest in model size } } private void distributeRewards(Player player) { AbyssPointsService.addAp(player, instanceReward.getFinalAp()); if (instanceReward.getRewardItem1() > 0) ItemService.addItem(player, instanceReward.getRewardItem1(), instanceReward.getRewardItem1Count(), true); if (instanceReward.getRewardItem2() > 0) ItemService.addItem(player, instanceReward.getRewardItem2(), instanceReward.getRewardItem2Count(), true); if (instanceReward.getRewardItem3() > 0) ItemService.addItem(player, instanceReward.getRewardItem3(), instanceReward.getRewardItem3Count(), true); if (instanceReward.getRewardItem4() > 0) ItemService.addItem(player, instanceReward.getRewardItem4(), instanceReward.getRewardItem4Count(), true); } @Override public void handleUseItemFinish(Player player, Npc npc) { if (npc.getNpcId() == 701625 || npc.getNpcId() == 701922) { SkillEngine.getInstance().getSkill(npc, 21069, 1, npc).useSkill(); ThreadPoolManager.getInstance().schedule(() -> npc.getController().delete(), 3000); sendMsg(SM_SYSTEM_MESSAGE.STR_MSG_IDLDF5b_TD_AddWave_01(), 3000); spawnWithDelay(231160, 707.703f, 259.173f, 253.038f, (byte) 40, 33000); // Assault Pod } } @Override public void onEndEffect(Effect effect) { if (effect.getEffected()instanceof Player player && !player.isDead() && !player.getLifeStats().isAboutToDie()) { switch (effect.getSkillId()) { case 21138, 21139 -> { // Cannons respawn if not killed Point3D pos = new Point3D(player.getX(), player.getY(), player.getZ()); Race race = player.getRace(); spawnTasks.add(ThreadPoolManager.getInstance().schedule(() -> { if (instanceReward.getInstanceProgressionType() == InstanceProgressionType.START_PROGRESS) spawn(race == Race.ELYOS ? 701596 : 701610, pos.getX(), pos.getY(), pos.getZ(), (byte) 50); }, 10, TimeUnit.SECONDS)); } } } } @Override public void onInstanceDestroy() { cancelTasks(); } @Override public boolean onReviveEvent(Player player) { PlayerReviveService.revive(player, 100, 100, false, 0); player.getGameStats().updateStatsAndSpeedVisually(); TeleportService.teleportTo(player, instance, 449.581f, 448.846f, 270.747f, (byte) 70); return true; } private void cancelTasks() { spawnTasks.forEach(task -> { if (task != null && !task.isDone()) task.cancel(false); }); if (instanceTimerTask != null && !instanceTimerTask.isCancelled()) instanceTimerTask.cancel(false); if (assaultWaveTask != null && !assaultWaveTask.isCancelled()) assaultWaveTask.cancel(false); } private void spawnWithDelay(int npcId, float x, float y, float z, byte h, int delay) { spawnTasks.add(ThreadPoolManager.getInstance().schedule(() -> spawn(npcId, x, y, z, h), delay)); } private void spawnWithWalker(int npcId, float x, float y, float z, byte h, final String walker) { spawn(npcId, x, y, z, h).getSpawn().setWalkerId(walker); } private void addPoints(Npc npc, int points) { if (instanceReward.getInstanceProgressionType() == InstanceProgressionType.START_PROGRESS) { instanceReward.addPoints(points); PacketSendUtility.broadcastToMap(instance, SM_SYSTEM_MESSAGE.STR_MSG_GET_SCORE(npc.getObjectTemplate().getL10n(), points)); sendPacket(); } } private int getTime() { int current = (int) (System.currentTimeMillis() - startTime); return instanceReward.getInstanceProgressionType() == InstanceProgressionType.PREPARING ? 180000 - current : Math.max(1800000 - current, 0); } private void sendPacket() { PacketSendUtility.broadcastToMap(instance, new SM_INSTANCE_SCORE(instance.getMapId(), new EternalBastionScoreWriter(instanceReward), getTime())); } @Override public void leaveInstance(Player player) { if (instanceReward.getInstanceProgressionType() == InstanceProgressionType.END_PROGRESS) TeleportService.moveToInstanceExit(player, mapId, player.getRace()); } private String getRankNameById(int rank) { return switch (rank) { case 1 -> "S"; case 2 -> "A"; case 3 -> "B"; case 4 -> "C"; case 5 -> "D"; default -> "F"; }; } @Override public boolean isBoss(Npc npc) { return switch (npc.getNpcId()) { case 209516, 209517, 231168, 231169, 231170, 231171, 231172, 231173, 231174, 231175, 231176, 231130 -> true; default -> false; }; } }