Antharas.java 28 KB

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