Antharas.java 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978
  1. /*
  2. * Copyright (C) 2004-2013 L2J DataPack
  3. *
  4. * This file is part of L2J DataPack.
  5. *
  6. * L2J DataPack is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * L2J DataPack is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package ai.individual;
  20. import java.util.Collection;
  21. import java.util.List;
  22. import java.util.Map;
  23. import java.util.concurrent.ScheduledFuture;
  24. import javolution.util.FastList;
  25. import javolution.util.FastMap;
  26. import ai.npc.AbstractNpcAI;
  27. import com.l2jserver.Config;
  28. import com.l2jserver.gameserver.GeoData;
  29. import com.l2jserver.gameserver.ThreadPoolManager;
  30. import com.l2jserver.gameserver.ai.CtrlIntention;
  31. import com.l2jserver.gameserver.datatables.NpcTable;
  32. import com.l2jserver.gameserver.datatables.SkillTable;
  33. import com.l2jserver.gameserver.datatables.SpawnTable;
  34. import com.l2jserver.gameserver.instancemanager.GrandBossManager;
  35. import com.l2jserver.gameserver.model.L2CharPosition;
  36. import com.l2jserver.gameserver.model.L2Spawn;
  37. import com.l2jserver.gameserver.model.L2World;
  38. import com.l2jserver.gameserver.model.StatsSet;
  39. import com.l2jserver.gameserver.model.actor.L2Character;
  40. import com.l2jserver.gameserver.model.actor.L2Npc;
  41. import com.l2jserver.gameserver.model.actor.instance.L2GrandBossInstance;
  42. import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
  43. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  44. import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
  45. import com.l2jserver.gameserver.model.skills.L2Skill;
  46. import com.l2jserver.gameserver.model.zone.type.L2BossZone;
  47. import com.l2jserver.gameserver.network.serverpackets.Earthquake;
  48. import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
  49. import com.l2jserver.gameserver.network.serverpackets.PlaySound;
  50. import com.l2jserver.gameserver.network.serverpackets.SpecialCamera;
  51. /**
  52. * This class ... control for sequence of fight against Antharas.
  53. * @author L2J_JP SANDMAN
  54. */
  55. public class Antharas extends AbstractNpcAI
  56. {
  57. // config
  58. private static final int FWA_ACTIVITYTIMEOFANTHARAS = 120;
  59. // private static final int FWA_APPTIMEOFANTHARAS = 1800000;
  60. private static final int FWA_INACTIVITYTIME = 900000;
  61. private static final boolean FWA_OLDANTHARAS = false;
  62. private static final boolean FWA_MOVEATRANDOM = true;
  63. private static final boolean FWA_DOSERVEREARTHQUAKE = true;
  64. private static final int FWA_LIMITOFWEAK = 45;
  65. private static final int FWA_LIMITOFNORMAL = 63;
  66. private static final int FWA_MAXMOBS = 10; // this includes Antharas itself
  67. private static final int FWA_INTERVALOFMOBSWEAK = 180000;
  68. private static final int FWA_INTERVALOFMOBSNORMAL = 150000;
  69. private static final int FWA_INTERVALOFMOBSSTRONG = 120000;
  70. private static final int FWA_PERCENTOFBEHEMOTH = 60;
  71. private static final int FWA_SELFDESTRUCTTIME = 15000;
  72. // Location of teleport cube.
  73. private final int _teleportCubeId = 31859;
  74. private final int _teleportCubeLocation[][] =
  75. {
  76. {
  77. 177615,
  78. 114941,
  79. -7709,
  80. 0
  81. }
  82. };
  83. protected List<L2Spawn> _teleportCubeSpawn = new FastList<>();
  84. protected List<L2Npc> _teleportCube = new FastList<>();
  85. // Spawn data of monsters.
  86. protected Map<Integer, L2Spawn> _monsterSpawn = new FastMap<>();
  87. // Instance of monsters.
  88. protected List<L2Npc> _monsters = new FastList<>();
  89. protected L2GrandBossInstance _antharas = null;
  90. // monstersId
  91. private static final int ANTHARASOLDID = 29019;
  92. private static final int ANTHARASWEAKID = 29066;
  93. private static final int ANTHARASNORMALID = 29067;
  94. private static final int ANTHARASSTRONGID = 29068;
  95. // Tasks.
  96. protected ScheduledFuture<?> _cubeSpawnTask = null;
  97. protected ScheduledFuture<?> _monsterSpawnTask = null;
  98. protected ScheduledFuture<?> _activityCheckTask = null;
  99. protected ScheduledFuture<?> _socialTask = null;
  100. protected ScheduledFuture<?> _mobiliseTask = null;
  101. protected ScheduledFuture<?> _mobsSpawnTask = null;
  102. protected ScheduledFuture<?> _selfDestructionTask = null;
  103. protected ScheduledFuture<?> _moveAtRandomTask = null;
  104. protected ScheduledFuture<?> _movieTask = null;
  105. // Antharas Status Tracking :
  106. private static final byte DORMANT = 0; // Antharas is spawned and no one has entered yet. Entry is unlocked
  107. private static final byte WAITING = 1; // Antharas is spawend and someone has entered, triggering a 30 minute window for additional people to enter
  108. // before he unleashes his attack. Entry is unlocked
  109. private static final byte FIGHTING = 2; // Antharas is engaged in battle, annihilating his foes. Entry is locked
  110. private static final byte DEAD = 3; // Antharas has been killed. Entry is locked
  111. protected static long _LastAction = 0;
  112. protected static L2BossZone _Zone;
  113. // Boss: Antharas
  114. private Antharas(String name, String descr)
  115. {
  116. super(name, descr);
  117. int[] mob =
  118. {
  119. ANTHARASOLDID,
  120. ANTHARASWEAKID,
  121. ANTHARASNORMALID,
  122. ANTHARASSTRONGID,
  123. 29069,
  124. 29070,
  125. 29071,
  126. 29072,
  127. 29073,
  128. 29074,
  129. 29075,
  130. 29076
  131. };
  132. registerMobs(mob);
  133. init();
  134. }
  135. // Initialize
  136. private void init()
  137. {
  138. // Setting spawn data of monsters.
  139. try
  140. {
  141. _Zone = GrandBossManager.getInstance().getZone(179700, 113800, -7709);
  142. L2NpcTemplate template1;
  143. L2Spawn tempSpawn;
  144. // Old Antharas
  145. template1 = NpcTable.getInstance().getTemplate(ANTHARASOLDID);
  146. tempSpawn = new L2Spawn(template1);
  147. tempSpawn.setLocx(181323);
  148. tempSpawn.setLocy(114850);
  149. tempSpawn.setLocz(-7623);
  150. tempSpawn.setHeading(32542);
  151. tempSpawn.setAmount(1);
  152. tempSpawn.setRespawnDelay(FWA_ACTIVITYTIMEOFANTHARAS * 2);
  153. SpawnTable.getInstance().addNewSpawn(tempSpawn, false);
  154. _monsterSpawn.put(29019, tempSpawn);
  155. // Weak Antharas
  156. template1 = NpcTable.getInstance().getTemplate(ANTHARASWEAKID);
  157. tempSpawn = new L2Spawn(template1);
  158. tempSpawn.setLocx(181323);
  159. tempSpawn.setLocy(114850);
  160. tempSpawn.setLocz(-7623);
  161. tempSpawn.setHeading(32542);
  162. tempSpawn.setAmount(1);
  163. tempSpawn.setRespawnDelay(FWA_ACTIVITYTIMEOFANTHARAS * 2);
  164. SpawnTable.getInstance().addNewSpawn(tempSpawn, false);
  165. _monsterSpawn.put(29066, tempSpawn);
  166. // Normal Antharas
  167. template1 = NpcTable.getInstance().getTemplate(ANTHARASNORMALID);
  168. tempSpawn = new L2Spawn(template1);
  169. tempSpawn.setLocx(181323);
  170. tempSpawn.setLocy(114850);
  171. tempSpawn.setLocz(-7623);
  172. tempSpawn.setHeading(32542);
  173. tempSpawn.setAmount(1);
  174. tempSpawn.setRespawnDelay(FWA_ACTIVITYTIMEOFANTHARAS * 2);
  175. SpawnTable.getInstance().addNewSpawn(tempSpawn, false);
  176. _monsterSpawn.put(29067, tempSpawn);
  177. // Strong Antharas
  178. template1 = NpcTable.getInstance().getTemplate(ANTHARASSTRONGID);
  179. tempSpawn = new L2Spawn(template1);
  180. tempSpawn.setLocx(181323);
  181. tempSpawn.setLocy(114850);
  182. tempSpawn.setLocz(-7623);
  183. tempSpawn.setHeading(32542);
  184. tempSpawn.setAmount(1);
  185. tempSpawn.setRespawnDelay(FWA_ACTIVITYTIMEOFANTHARAS * 2);
  186. SpawnTable.getInstance().addNewSpawn(tempSpawn, false);
  187. _monsterSpawn.put(29068, tempSpawn);
  188. }
  189. catch (Exception e)
  190. {
  191. _log.warning(e.getMessage());
  192. }
  193. // Setting spawn data of teleport cube.
  194. try
  195. {
  196. L2NpcTemplate Cube = NpcTable.getInstance().getTemplate(_teleportCubeId);
  197. L2Spawn spawnDat;
  198. for (int[] element : _teleportCubeLocation)
  199. {
  200. spawnDat = new L2Spawn(Cube);
  201. spawnDat.setAmount(1);
  202. spawnDat.setLocx(element[0]);
  203. spawnDat.setLocy(element[1]);
  204. spawnDat.setLocz(element[2]);
  205. spawnDat.setHeading(element[3]);
  206. spawnDat.setRespawnDelay(60);
  207. spawnDat.setLocation(0);
  208. SpawnTable.getInstance().addNewSpawn(spawnDat, false);
  209. _teleportCubeSpawn.add(spawnDat);
  210. }
  211. }
  212. catch (Exception e)
  213. {
  214. _log.warning(e.getMessage());
  215. }
  216. int status = GrandBossManager.getInstance().getBossStatus(ANTHARASOLDID);
  217. if (FWA_OLDANTHARAS || (status == WAITING))
  218. {
  219. StatsSet info = GrandBossManager.getInstance().getStatsSet(ANTHARASOLDID);
  220. Long respawnTime = info.getLong("respawn_time");
  221. if ((status == DEAD) && (respawnTime <= System.currentTimeMillis()))
  222. {
  223. // the time has already expired while the server was offline. Immediately spawn antharas in his cave.
  224. // also, the status needs to be changed to DORMANT
  225. GrandBossManager.getInstance().setBossStatus(ANTHARASOLDID, DORMANT);
  226. status = DORMANT;
  227. }
  228. else if (status == FIGHTING)
  229. {
  230. int loc_x = info.getInteger("loc_x");
  231. int loc_y = info.getInteger("loc_y");
  232. int loc_z = info.getInteger("loc_z");
  233. int heading = info.getInteger("heading");
  234. int hp = info.getInteger("currentHP");
  235. int mp = info.getInteger("currentMP");
  236. _antharas = (L2GrandBossInstance) addSpawn(ANTHARASOLDID, loc_x, loc_y, loc_z, heading, false, 0);
  237. GrandBossManager.getInstance().addBoss(_antharas);
  238. _antharas.setCurrentHpMp(hp, mp);
  239. _LastAction = System.currentTimeMillis();
  240. // Start repeating timer to check for inactivity
  241. _activityCheckTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new CheckActivity(), 60000, 60000);
  242. }
  243. else if (status == DEAD)
  244. {
  245. ThreadPoolManager.getInstance().scheduleGeneral(new UnlockAntharas(ANTHARASOLDID), respawnTime - System.currentTimeMillis());
  246. }
  247. else
  248. {
  249. setAntharasSpawnTask();
  250. }
  251. }
  252. else
  253. {
  254. int statusWeak = GrandBossManager.getInstance().getBossStatus(ANTHARASWEAKID);
  255. int statusNormal = GrandBossManager.getInstance().getBossStatus(ANTHARASNORMALID);
  256. int statusStrong = GrandBossManager.getInstance().getBossStatus(ANTHARASSTRONGID);
  257. int antharasId = 0;
  258. if ((statusWeak == FIGHTING) || (statusWeak == DEAD))
  259. {
  260. antharasId = ANTHARASWEAKID;
  261. status = statusWeak;
  262. }
  263. else if ((statusNormal == FIGHTING) || (statusNormal == DEAD))
  264. {
  265. antharasId = ANTHARASNORMALID;
  266. status = statusNormal;
  267. }
  268. else if ((statusStrong == FIGHTING) || (statusStrong == DEAD))
  269. {
  270. antharasId = ANTHARASSTRONGID;
  271. status = statusStrong;
  272. }
  273. if ((antharasId != 0) && (status == FIGHTING))
  274. {
  275. StatsSet info = GrandBossManager.getInstance().getStatsSet(antharasId);
  276. int loc_x = info.getInteger("loc_x");
  277. int loc_y = info.getInteger("loc_y");
  278. int loc_z = info.getInteger("loc_z");
  279. int heading = info.getInteger("heading");
  280. int hp = info.getInteger("currentHP");
  281. int mp = info.getInteger("currentMP");
  282. _antharas = (L2GrandBossInstance) addSpawn(antharasId, loc_x, loc_y, loc_z, heading, false, 0);
  283. GrandBossManager.getInstance().addBoss(_antharas);
  284. _antharas.setCurrentHpMp(hp, mp);
  285. _LastAction = System.currentTimeMillis();
  286. // Start repeating timer to check for inactivity
  287. _activityCheckTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new CheckActivity(), 60000, 60000);
  288. }
  289. else if ((antharasId != 0) && (status == DEAD))
  290. {
  291. StatsSet info = GrandBossManager.getInstance().getStatsSet(antharasId);
  292. Long respawnTime = info.getLong("respawn_time");
  293. if (respawnTime <= System.currentTimeMillis())
  294. {
  295. // the time has already expired while the server was offline. Immediately spawn antharas in his cave.
  296. // also, the status needs to be changed to DORMANT
  297. GrandBossManager.getInstance().setBossStatus(antharasId, DORMANT);
  298. status = DORMANT;
  299. }
  300. else
  301. {
  302. ThreadPoolManager.getInstance().scheduleGeneral(new UnlockAntharas(antharasId), respawnTime - System.currentTimeMillis());
  303. }
  304. }
  305. }
  306. }
  307. // Do spawn teleport cube.
  308. public void spawnCube()
  309. {
  310. if (_mobsSpawnTask != null)
  311. {
  312. _mobsSpawnTask.cancel(true);
  313. _mobsSpawnTask = null;
  314. }
  315. if (_selfDestructionTask != null)
  316. {
  317. _selfDestructionTask.cancel(true);
  318. _selfDestructionTask = null;
  319. }
  320. if (_activityCheckTask != null)
  321. {
  322. _activityCheckTask.cancel(false);
  323. _activityCheckTask = null;
  324. }
  325. for (L2Spawn spawnDat : _teleportCubeSpawn)
  326. {
  327. _teleportCube.add(spawnDat.doSpawn());
  328. }
  329. }
  330. // Setting Antharas spawn task.
  331. public void setAntharasSpawnTask()
  332. {
  333. if (_monsterSpawnTask == null)
  334. {
  335. synchronized (this)
  336. {
  337. if (_monsterSpawnTask == null)
  338. {
  339. GrandBossManager.getInstance().setBossStatus(ANTHARASOLDID, WAITING);
  340. _monsterSpawnTask = ThreadPoolManager.getInstance().scheduleGeneral(new AntharasSpawn(1), Config.Antharas_Wait_Time);
  341. }
  342. }
  343. }
  344. }
  345. @Override
  346. public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
  347. {
  348. if (event.equalsIgnoreCase("waiting"))
  349. {
  350. setAntharasSpawnTask();
  351. }
  352. return super.onAdvEvent(event, npc, player);
  353. }
  354. protected void startMinionSpawns(int antharasId)
  355. {
  356. int intervalOfMobs;
  357. // Interval of minions is decided by the type of Antharas
  358. // that invaded the lair.
  359. switch (antharasId)
  360. {
  361. case ANTHARASWEAKID:
  362. intervalOfMobs = FWA_INTERVALOFMOBSWEAK;
  363. break;
  364. case ANTHARASNORMALID:
  365. intervalOfMobs = FWA_INTERVALOFMOBSNORMAL;
  366. break;
  367. default:
  368. intervalOfMobs = FWA_INTERVALOFMOBSSTRONG;
  369. break;
  370. }
  371. // Spawn mobs.
  372. _mobsSpawnTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new MobsSpawn(), intervalOfMobs, intervalOfMobs);
  373. }
  374. // Do spawn Antharas.
  375. private class AntharasSpawn implements Runnable
  376. {
  377. private int _taskId = 0;
  378. private final Collection<L2Character> _players = _Zone.getCharactersInside();
  379. public AntharasSpawn(int taskId)
  380. {
  381. _taskId = taskId;
  382. }
  383. @Override
  384. public void run()
  385. {
  386. int npcId;
  387. L2Spawn antharasSpawn = null;
  388. switch (_taskId)
  389. {
  390. case 1: // Spawn.
  391. // Strength of Antharas is decided by the number of players that
  392. // invaded the lair.
  393. _monsterSpawnTask.cancel(false);
  394. _monsterSpawnTask = null;
  395. if (FWA_OLDANTHARAS)
  396. {
  397. npcId = 29019; // old
  398. }
  399. else if (_players.size() <= FWA_LIMITOFWEAK)
  400. {
  401. npcId = 29066; // weak
  402. }
  403. else if (_players.size() > FWA_LIMITOFNORMAL)
  404. {
  405. npcId = 29068; // strong
  406. }
  407. else
  408. {
  409. npcId = 29067; // normal
  410. }
  411. // Do spawn.
  412. antharasSpawn = _monsterSpawn.get(npcId);
  413. _antharas = (L2GrandBossInstance) antharasSpawn.doSpawn();
  414. GrandBossManager.getInstance().addBoss(_antharas);
  415. _monsters.add(_antharas);
  416. _antharas.setIsImmobilized(true);
  417. GrandBossManager.getInstance().setBossStatus(ANTHARASOLDID, DORMANT);
  418. GrandBossManager.getInstance().setBossStatus(npcId, FIGHTING);
  419. _LastAction = System.currentTimeMillis();
  420. // Start repeating timer to check for inactivity
  421. _activityCheckTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new CheckActivity(), 60000, 60000);
  422. // Setting 1st time of minions spawn task.
  423. if (!FWA_OLDANTHARAS)
  424. {
  425. startMinionSpawns(npcId);
  426. }
  427. // Set next task.
  428. if (_socialTask != null)
  429. {
  430. _socialTask.cancel(true);
  431. _socialTask = null;
  432. }
  433. _socialTask = ThreadPoolManager.getInstance().scheduleGeneral(new AntharasSpawn(2), 16);
  434. break;
  435. case 2:
  436. // Set camera.
  437. broadcastPacket(new SpecialCamera(_antharas.getObjectId(), 700, 13, -19, 0, 20000, 0, 0, 1, 0));
  438. // Set next task.
  439. if (_socialTask != null)
  440. {
  441. _socialTask.cancel(true);
  442. _socialTask = null;
  443. }
  444. _socialTask = ThreadPoolManager.getInstance().scheduleGeneral(new AntharasSpawn(3), 3000);
  445. break;
  446. case 3:
  447. // Do social.
  448. broadcastPacket(new SpecialCamera(_antharas.getObjectId(), 700, 13, 0, 6000, 20000, 0, 0, 1, 0));
  449. // Set next task.
  450. if (_socialTask != null)
  451. {
  452. _socialTask.cancel(true);
  453. _socialTask = null;
  454. }
  455. _socialTask = ThreadPoolManager.getInstance().scheduleGeneral(new AntharasSpawn(4), 10000);
  456. break;
  457. case 4:
  458. broadcastPacket(new SpecialCamera(_antharas.getObjectId(), 3700, 0, -3, 0, 10000, 0, 0, 1, 0));
  459. // Set next task.
  460. if (_socialTask != null)
  461. {
  462. _socialTask.cancel(true);
  463. _socialTask = null;
  464. }
  465. _socialTask = ThreadPoolManager.getInstance().scheduleGeneral(new AntharasSpawn(5), 200);
  466. break;
  467. case 5:
  468. // Do social.
  469. broadcastPacket(new SpecialCamera(_antharas.getObjectId(), 1100, 0, -3, 22000, 30000, 0, 0, 1, 0));
  470. // Set next task.
  471. if (_socialTask != null)
  472. {
  473. _socialTask.cancel(true);
  474. _socialTask = null;
  475. }
  476. _socialTask = ThreadPoolManager.getInstance().scheduleGeneral(new AntharasSpawn(6), 10800);
  477. break;
  478. case 6:
  479. // Set camera.
  480. broadcastPacket(new SpecialCamera(_antharas.getObjectId(), 1100, 0, -3, 300, 7000, 0, 0, 1, 0));
  481. // Set next task.
  482. if (_socialTask != null)
  483. {
  484. _socialTask.cancel(true);
  485. _socialTask = null;
  486. }
  487. _socialTask = ThreadPoolManager.getInstance().scheduleGeneral(new AntharasSpawn(7), 1900);
  488. break;
  489. case 7:
  490. _antharas.abortCast();
  491. _mobiliseTask = ThreadPoolManager.getInstance().scheduleGeneral(new SetMobilised(_antharas), 16);
  492. // Move at random.
  493. if (FWA_MOVEATRANDOM)
  494. {
  495. L2CharPosition pos = new L2CharPosition(getRandom(175000, 178500), getRandom(112400, 116000), -7707, 0);
  496. _moveAtRandomTask = ThreadPoolManager.getInstance().scheduleGeneral(new MoveAtRandom(_antharas, pos), 500);
  497. }
  498. if (_socialTask != null)
  499. {
  500. _socialTask.cancel(true);
  501. _socialTask = null;
  502. }
  503. break;
  504. }
  505. }
  506. }
  507. protected void broadcastPacket(L2GameServerPacket mov)
  508. {
  509. if (_Zone != null)
  510. {
  511. for (L2Character characters : _Zone.getCharactersInside())
  512. {
  513. if (characters.isPlayer())
  514. {
  515. characters.sendPacket(mov);
  516. }
  517. }
  518. }
  519. }
  520. // Do spawn Behemoth or Bomber.
  521. private class MobsSpawn implements Runnable
  522. {
  523. public MobsSpawn()
  524. {
  525. }
  526. @Override
  527. public void run()
  528. {
  529. L2NpcTemplate template1;
  530. L2Spawn tempSpawn;
  531. boolean isBehemoth = getRandom(100) < FWA_PERCENTOFBEHEMOTH;
  532. try
  533. {
  534. int mobNumber = (isBehemoth ? 2 : 3);
  535. // Set spawn.
  536. for (int i = 0; i < mobNumber; i++)
  537. {
  538. if (_monsters.size() >= FWA_MAXMOBS)
  539. {
  540. break;
  541. }
  542. int npcId;
  543. if (isBehemoth)
  544. {
  545. npcId = 29069;
  546. }
  547. else
  548. {
  549. npcId = getRandom(29070, 29076);
  550. }
  551. template1 = NpcTable.getInstance().getTemplate(npcId);
  552. tempSpawn = new L2Spawn(template1);
  553. // allocates it at random in the lair of Antharas.
  554. int tried = 0;
  555. boolean notFound = true;
  556. int x = 175000;
  557. int y = 112400;
  558. int dt = ((_antharas.getX() - x) * (_antharas.getX() - x)) + ((_antharas.getY() - y) * (_antharas.getY() - y));
  559. while ((tried++ < 25) && notFound)
  560. {
  561. int rx = getRandom(175000, 179900);
  562. int ry = getRandom(112400, 116000);
  563. int rdt = ((_antharas.getX() - rx) * (_antharas.getX() - rx)) + ((_antharas.getY() - ry) * (_antharas.getY() - ry));
  564. if (GeoData.getInstance().canSeeTarget(_antharas.getX(), _antharas.getY(), -7704, rx, ry, -7704))
  565. {
  566. if (rdt < dt)
  567. {
  568. x = rx;
  569. y = ry;
  570. dt = rdt;
  571. if (rdt <= 900000)
  572. {
  573. notFound = false;
  574. }
  575. }
  576. }
  577. }
  578. tempSpawn.setLocx(x);
  579. tempSpawn.setLocy(y);
  580. tempSpawn.setLocz(-7704);
  581. tempSpawn.setHeading(0);
  582. tempSpawn.setAmount(1);
  583. tempSpawn.setRespawnDelay(FWA_ACTIVITYTIMEOFANTHARAS * 2);
  584. SpawnTable.getInstance().addNewSpawn(tempSpawn, false);
  585. // Do spawn.
  586. _monsters.add(tempSpawn.doSpawn());
  587. }
  588. }
  589. catch (Exception e)
  590. {
  591. _log.warning(e.getMessage());
  592. }
  593. }
  594. }
  595. @Override
  596. public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isPet)
  597. {
  598. switch (npc.getNpcId())
  599. {
  600. case 29070:
  601. case 29071:
  602. case 29072:
  603. case 29073:
  604. case 29074:
  605. case 29075:
  606. case 29076:
  607. if ((_selfDestructionTask == null) && !npc.isDead())
  608. {
  609. _selfDestructionTask = ThreadPoolManager.getInstance().scheduleGeneral(new SelfDestructionOfBomber(npc), FWA_SELFDESTRUCTTIME);
  610. }
  611. break;
  612. }
  613. return super.onAggroRangeEnter(npc, player, isPet);
  614. }
  615. // Do self destruction.
  616. private class SelfDestructionOfBomber implements Runnable
  617. {
  618. private final L2Npc _bomber;
  619. public SelfDestructionOfBomber(L2Npc bomber)
  620. {
  621. _bomber = bomber;
  622. }
  623. @Override
  624. public void run()
  625. {
  626. L2Skill skill = null;
  627. switch (_bomber.getNpcId())
  628. {
  629. case 29070:
  630. case 29071:
  631. case 29072:
  632. case 29073:
  633. case 29074:
  634. case 29075:
  635. skill = SkillTable.getInstance().getInfo(5097, 1);
  636. break;
  637. case 29076:
  638. skill = SkillTable.getInstance().getInfo(5094, 1);
  639. break;
  640. }
  641. _bomber.doCast(skill);
  642. if (_selfDestructionTask != null)
  643. {
  644. _selfDestructionTask.cancel(false);
  645. _selfDestructionTask = null;
  646. }
  647. }
  648. }
  649. @Override
  650. public String onSpellFinished(L2Npc npc, L2PcInstance player, L2Skill skill)
  651. {
  652. if (npc.isInvul())
  653. {
  654. return null;
  655. }
  656. else if ((skill != null) && ((skill.getId() == 5097) || (skill.getId() == 5094)))
  657. {
  658. switch (npc.getNpcId())
  659. {
  660. case 29070:
  661. case 29071:
  662. case 29072:
  663. case 29073:
  664. case 29074:
  665. case 29075:
  666. case 29076:
  667. npc.doDie(npc);
  668. break;
  669. }
  670. }
  671. return super.onSpellFinished(npc, player, skill);
  672. }
  673. // At end of activity time.
  674. protected class CheckActivity implements Runnable
  675. {
  676. @Override
  677. public void run()
  678. {
  679. Long temp = (System.currentTimeMillis() - _LastAction);
  680. if (temp > FWA_INACTIVITYTIME)
  681. {
  682. GrandBossManager.getInstance().setBossStatus(_antharas.getNpcId(), DORMANT);
  683. setUnspawn();
  684. }
  685. }
  686. }
  687. // Clean Antharas's lair.
  688. public void setUnspawn()
  689. {
  690. // Eliminate players.
  691. _Zone.oustAllPlayers();
  692. // Not executed tasks is canceled.
  693. if (_cubeSpawnTask != null)
  694. {
  695. _cubeSpawnTask.cancel(true);
  696. _cubeSpawnTask = null;
  697. }
  698. if (_monsterSpawnTask != null)
  699. {
  700. _monsterSpawnTask.cancel(true);
  701. _monsterSpawnTask = null;
  702. }
  703. if (_activityCheckTask != null)
  704. {
  705. _activityCheckTask.cancel(false);
  706. _activityCheckTask = null;
  707. }
  708. if (_socialTask != null)
  709. {
  710. _socialTask.cancel(true);
  711. _socialTask = null;
  712. }
  713. if (_mobiliseTask != null)
  714. {
  715. _mobiliseTask.cancel(true);
  716. _mobiliseTask = null;
  717. }
  718. if (_mobsSpawnTask != null)
  719. {
  720. _mobsSpawnTask.cancel(true);
  721. _mobsSpawnTask = null;
  722. }
  723. if (_selfDestructionTask != null)
  724. {
  725. _selfDestructionTask.cancel(true);
  726. _selfDestructionTask = null;
  727. }
  728. if (_moveAtRandomTask != null)
  729. {
  730. _moveAtRandomTask.cancel(true);
  731. _moveAtRandomTask = null;
  732. }
  733. // Delete monsters.
  734. for (L2Npc mob : _monsters)
  735. {
  736. mob.getSpawn().stopRespawn();
  737. mob.deleteMe();
  738. }
  739. _monsters.clear();
  740. // Delete teleport cube.
  741. for (L2Npc cube : _teleportCube)
  742. {
  743. cube.getSpawn().stopRespawn();
  744. cube.deleteMe();
  745. }
  746. _teleportCube.clear();
  747. }
  748. // Do spawn teleport cube.
  749. private class CubeSpawn implements Runnable
  750. {
  751. private final int _type;
  752. public CubeSpawn(int type)
  753. {
  754. _type = type;
  755. }
  756. @Override
  757. public void run()
  758. {
  759. if (_type == 0)
  760. {
  761. spawnCube();
  762. _cubeSpawnTask = ThreadPoolManager.getInstance().scheduleGeneral(new CubeSpawn(1), 1800000);
  763. }
  764. else
  765. {
  766. setUnspawn();
  767. }
  768. }
  769. }
  770. // UnLock Antharas.
  771. private static class UnlockAntharas implements Runnable
  772. {
  773. private final int _bossId;
  774. public UnlockAntharas(int bossId)
  775. {
  776. _bossId = bossId;
  777. }
  778. @Override
  779. public void run()
  780. {
  781. GrandBossManager.getInstance().setBossStatus(_bossId, DORMANT);
  782. if (FWA_DOSERVEREARTHQUAKE)
  783. {
  784. for (L2PcInstance p : L2World.getInstance().getAllPlayersArray())
  785. {
  786. p.broadcastPacket(new Earthquake(185708, 114298, -8221, 20, 10));
  787. }
  788. }
  789. }
  790. }
  791. // Action is enabled the boss.
  792. private class SetMobilised implements Runnable
  793. {
  794. private final L2GrandBossInstance _boss;
  795. public SetMobilised(L2GrandBossInstance boss)
  796. {
  797. _boss = boss;
  798. }
  799. @Override
  800. public void run()
  801. {
  802. _boss.setIsImmobilized(false);
  803. // When it is possible to act, a social action is canceled.
  804. if (_socialTask != null)
  805. {
  806. _socialTask.cancel(true);
  807. _socialTask = null;
  808. }
  809. }
  810. }
  811. // Move at random on after Antharas appears.
  812. private static class MoveAtRandom implements Runnable
  813. {
  814. private final L2Npc _npc;
  815. private final L2CharPosition _pos;
  816. public MoveAtRandom(L2Npc npc, L2CharPosition pos)
  817. {
  818. _npc = npc;
  819. _pos = pos;
  820. }
  821. @Override
  822. public void run()
  823. {
  824. _npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, _pos);
  825. }
  826. }
  827. @Override
  828. public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isPet)
  829. {
  830. if ((npc.getNpcId() == 29019) || (npc.getNpcId() == 29066) || (npc.getNpcId() == 29067) || (npc.getNpcId() == 29068))
  831. {
  832. _LastAction = System.currentTimeMillis();
  833. if (GrandBossManager.getInstance().getBossStatus(_antharas.getNpcId()) != FIGHTING)
  834. {
  835. _Zone.oustAllPlayers();
  836. }
  837. else if (!FWA_OLDANTHARAS && (_mobsSpawnTask == null))
  838. {
  839. startMinionSpawns(npc.getNpcId());
  840. }
  841. }
  842. else if ((npc.getNpcId() > 29069) && (npc.getNpcId() < 29077) && (npc.getCurrentHp() <= damage))
  843. {
  844. L2Skill skill = null;
  845. switch (npc.getNpcId())
  846. {
  847. case 29070:
  848. case 29071:
  849. case 29072:
  850. case 29073:
  851. case 29074:
  852. case 29075:
  853. skill = SkillTable.getInstance().getInfo(5097, 1);
  854. break;
  855. case 29076:
  856. skill = SkillTable.getInstance().getInfo(5094, 1);
  857. break;
  858. }
  859. npc.doCast(skill);
  860. }
  861. return super.onAttack(npc, attacker, damage, isPet);
  862. }
  863. @Override
  864. public String onKill(L2Npc npc, L2PcInstance killer, boolean isPet)
  865. {
  866. if ((npc.getNpcId() == 29019) || (npc.getNpcId() == 29066) || (npc.getNpcId() == 29067) || (npc.getNpcId() == 29068))
  867. {
  868. npc.broadcastPacket(new PlaySound(1, "BS01_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
  869. _cubeSpawnTask = ThreadPoolManager.getInstance().scheduleGeneral(new CubeSpawn(0), 10000);
  870. GrandBossManager.getInstance().setBossStatus(npc.getNpcId(), DEAD);
  871. // Calculate Min and Max respawn times randomly.
  872. long respawnTime = getRandom((Config.Interval_Of_Antharas_Spawn - Config.Random_Of_Antharas_Spawn), (Config.Interval_Of_Antharas_Spawn + Config.Random_Of_Antharas_Spawn));
  873. ThreadPoolManager.getInstance().scheduleGeneral(new UnlockAntharas(npc.getNpcId()), respawnTime);
  874. // also save the respawn time so that the info is maintained past reboots
  875. StatsSet info = GrandBossManager.getInstance().getStatsSet(npc.getNpcId());
  876. info.set("respawn_time", (System.currentTimeMillis() + respawnTime));
  877. GrandBossManager.getInstance().setStatsSet(npc.getNpcId(), info);
  878. }
  879. else if (npc.getNpcId() == 29069)
  880. {
  881. int countHPHerb = getRandom(6, 18);
  882. int countMPHerb = getRandom(6, 18);
  883. for (int i = 0; i < countHPHerb; i++)
  884. {
  885. ((L2MonsterInstance) npc).dropItem(killer, 8602, 1);
  886. }
  887. for (int i = 0; i < countMPHerb; i++)
  888. {
  889. ((L2MonsterInstance) npc).dropItem(killer, 8605, 1);
  890. }
  891. }
  892. if (_monsters.contains(npc))
  893. {
  894. _monsters.remove(npc);
  895. }
  896. return super.onKill(npc, killer, isPet);
  897. }
  898. public static void main(String[] args)
  899. {
  900. new Antharas(Antharas.class.getSimpleName(), "ai");
  901. }
  902. }