Guest User

Untitled

a guest
Apr 15th, 2017
228
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.26 KB | None | 0 0
  1. package net.sf.l2j.gameserver.scripting.scripts.ai.individual;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. import net.sf.l2j.commons.random.Rnd;
  7.  
  8. import net.sf.l2j.Config;
  9. import net.sf.l2j.gameserver.ai.CtrlIntention;
  10. import net.sf.l2j.gameserver.datatables.SkillTable;
  11. import net.sf.l2j.gameserver.geoengine.GeoEngine;
  12. import net.sf.l2j.gameserver.instancemanager.GrandBossManager;
  13. import net.sf.l2j.gameserver.instancemanager.ZoneManager;
  14. import net.sf.l2j.gameserver.model.L2Skill;
  15. import net.sf.l2j.gameserver.model.SpawnLocation;
  16. import net.sf.l2j.gameserver.model.actor.Attackable;
  17. import net.sf.l2j.gameserver.model.actor.Character;
  18. import net.sf.l2j.gameserver.model.actor.Npc;
  19. import net.sf.l2j.gameserver.model.actor.instance.GrandBoss;
  20. import net.sf.l2j.gameserver.model.actor.instance.Monster;
  21. import net.sf.l2j.gameserver.model.actor.instance.Player;
  22. import net.sf.l2j.gameserver.model.zone.type.L2BossZone;
  23. import net.sf.l2j.gameserver.network.serverpackets.Earthquake;
  24. import net.sf.l2j.gameserver.network.serverpackets.PlaySound;
  25. import net.sf.l2j.gameserver.network.serverpackets.SocialAction;
  26. import net.sf.l2j.gameserver.scripting.EventType;
  27. import net.sf.l2j.gameserver.scripting.scripts.ai.L2AttackableAIScript;
  28. import net.sf.l2j.gameserver.templates.StatsSet;
  29. import net.sf.l2j.gameserver.util.Util;
  30.  
  31. /**
  32. * Following animations are handled in that time tempo :
  33. * <ul>
  34. * <li>wake(2), 0-13 secs</li>
  35. * <li>neck(3), 14-24 secs.</li>
  36. * <li>roar(1), 25-37 secs.</li>
  37. * </ul>
  38. * Waker's sacrifice is handled between neck and roar animation.
  39. */
  40. public class Baium extends L2AttackableAIScript
  41. {
  42. private static final L2BossZone BAIUM_LAIR = ZoneManager.getInstance().getZoneById(110002, L2BossZone.class);
  43.  
  44. private static final int STONE_BAIUM = 29025;
  45. private static final int LIVE_BAIUM = 29020;
  46. private static final int ARCHANGEL = 29021;
  47.  
  48. // Baium status tracking
  49. public static final byte ASLEEP = 0; // baium is in the stone version, waiting to be woken up. Entry is unlocked.
  50. public static final byte AWAKE = 1; // baium is awake and fighting. Entry is locked.
  51. public static final byte DEAD = 2; // baium has been killed and has not yet spawned. Entry is locked.
  52.  
  53. // Archangels spawns
  54. private static final SpawnLocation[] ANGEL_LOCATION =
  55. {
  56. new SpawnLocation(114239, 17168, 10080, 63544),
  57. new SpawnLocation(115780, 15564, 10080, 13620),
  58. new SpawnLocation(114880, 16236, 10080, 5400),
  59. new SpawnLocation(115168, 17200, 10080, 0),
  60. new SpawnLocation(115792, 16608, 10080, 0)
  61. };
  62.  
  63. private Character _actualVictim;
  64. private long _lastAttackTime = 0;
  65. private final List<Npc> _minions = new ArrayList<>(5);
  66.  
  67. public Baium()
  68. {
  69. super("ai/individual");
  70.  
  71. // Quest NPC starter initialization
  72. addStartNpc(STONE_BAIUM);
  73. addTalkId(STONE_BAIUM);
  74.  
  75. final StatsSet info = GrandBossManager.getInstance().getStatsSet(LIVE_BAIUM);
  76. final int status = GrandBossManager.getInstance().getBossStatus(LIVE_BAIUM);
  77.  
  78. if (status == DEAD)
  79. {
  80. // load the unlock date and time for baium from DB
  81. long temp = (info.getLong("respawn_time") - System.currentTimeMillis());
  82. if (temp > 0)
  83. {
  84. // The time has not yet expired. Mark Baium as currently locked (dead).
  85. startQuestTimer("baium_unlock", temp, null, null, false);
  86. }
  87. else
  88. {
  89. // The time has expired while the server was offline. Spawn the stone-baium as ASLEEP.
  90. addSpawn(STONE_BAIUM, 116033, 17447, 10104, 40188, false, 0, false);
  91. GrandBossManager.getInstance().setBossStatus(LIVE_BAIUM, ASLEEP);
  92. }
  93. }
  94. else if (status == AWAKE)
  95. {
  96. final int loc_x = info.getInteger("loc_x");
  97. final int loc_y = info.getInteger("loc_y");
  98. final int loc_z = info.getInteger("loc_z");
  99. final int heading = info.getInteger("heading");
  100. final int hp = info.getInteger("currentHP");
  101. final int mp = info.getInteger("currentMP");
  102.  
  103. final Npc baium = addSpawn(LIVE_BAIUM, loc_x, loc_y, loc_z, heading, false, 0, false);
  104. GrandBossManager.getInstance().addBoss((GrandBoss) baium);
  105.  
  106. baium.setCurrentHpMp(hp, mp);
  107. baium.setRunning();
  108.  
  109. // start monitoring baium's inactivity
  110. _lastAttackTime = System.currentTimeMillis();
  111. startQuestTimer("baium_despawn", 60000, baium, null, true);
  112. startQuestTimer("skill_range", 2000, baium, null, true);
  113.  
  114. // Spawns angels
  115. for (SpawnLocation loc : ANGEL_LOCATION)
  116. {
  117. Npc angel = addSpawn(ARCHANGEL, loc.getX(), loc.getY(), loc.getZ(), loc.getHeading(), false, 0, true);
  118. ((Attackable) angel).setIsRaidMinion(true);
  119. angel.setRunning();
  120. _minions.add(angel);
  121. }
  122.  
  123. // Angels AI
  124. startQuestTimer("angels_aggro_reconsider", 5000, null, null, true);
  125. }
  126. else
  127. addSpawn(STONE_BAIUM, 116033, 17447, 10104, 40188, false, 0, false);
  128. }
  129.  
  130. @Override
  131. protected void registerNpcs()
  132. {
  133. addEventIds(LIVE_BAIUM, EventType.ON_ATTACK, EventType.ON_KILL, EventType.ON_SPAWN);
  134. }
  135.  
  136. @Override
  137. public String onAdvEvent(String event, Npc npc, Player player)
  138. {
  139. if (npc != null && npc.getNpcId() == LIVE_BAIUM)
  140. {
  141. if (event.equalsIgnoreCase("skill_range"))
  142. {
  143. callSkillAI(npc);
  144. }
  145. else if (event.equalsIgnoreCase("baium_neck"))
  146. {
  147. npc.broadcastPacket(new SocialAction(npc, 3));
  148. }
  149. else if (event.equalsIgnoreCase("sacrifice_waker"))
  150. {
  151. if (player != null)
  152. {
  153. // If player is far of Baium, teleport him back.
  154. if (!Util.checkIfInShortRadius(300, player, npc, true))
  155. {
  156. BAIUM_LAIR.allowPlayerEntry(player, 10);
  157. player.teleToLocation(115929, 17349, 10077, 0);
  158. }
  159.  
  160. // 60% to die.
  161. if (Rnd.get(100) < 60)
  162. player.doDie(npc);
  163. }
  164. }
  165. else if (event.equalsIgnoreCase("baium_roar"))
  166. {
  167. // Roar animation
  168. npc.broadcastPacket(new SocialAction(npc, 1));
  169.  
  170. // Spawn angels
  171. for (SpawnLocation loc : ANGEL_LOCATION)
  172. {
  173. Npc angel = addSpawn(ARCHANGEL, loc.getX(), loc.getY(), loc.getZ(), loc.getHeading(), false, 0, true);
  174. ((Attackable) angel).setIsRaidMinion(true);
  175. angel.setRunning();
  176. _minions.add(angel);
  177. }
  178.  
  179. // Angels AI
  180. startQuestTimer("angels_aggro_reconsider", 5000, null, null, true);
  181. }
  182. else if (event.equalsIgnoreCase("baium_move"))
  183. {
  184. npc.setIsInvul(false);
  185. npc.setRunning();
  186.  
  187. // Start monitoring baium's inactivity and activate the AI
  188. _lastAttackTime = System.currentTimeMillis();
  189.  
  190. startQuestTimer("baium_despawn", 60000, npc, null, true);
  191. startQuestTimer("skill_range", 2000, npc, null, true);
  192. }
  193. // despawn the live baium after 30 minutes of inactivity
  194. // also check if the players are cheating, having pulled Baium outside his zone...
  195. else if (event.equalsIgnoreCase("baium_despawn"))
  196. {
  197. if (_lastAttackTime + 1800000 < System.currentTimeMillis())
  198. {
  199. // despawn the live-baium
  200. npc.deleteMe();
  201.  
  202. // Unspawn angels
  203. for (Npc minion : _minions)
  204. {
  205. minion.getSpawn().setRespawnState(false);
  206. minion.deleteMe();
  207. }
  208. _minions.clear();
  209.  
  210. addSpawn(STONE_BAIUM, 116033, 17447, 10104, 40188, false, 0, false); // spawn stone-baium
  211. GrandBossManager.getInstance().setBossStatus(LIVE_BAIUM, ASLEEP); // Baium isn't awaken anymore
  212. BAIUM_LAIR.oustAllPlayers();
  213. cancelQuestTimer("baium_despawn", npc, null);
  214. }
  215. else if ((_lastAttackTime + 300000 < System.currentTimeMillis()) && (npc.getCurrentHp() / npc.getMaxHp() < 0.75))
  216. {
  217. npc.setTarget(npc);
  218. npc.doCast(SkillTable.getInstance().getInfo(4135, 1));
  219. }
  220. else if (!BAIUM_LAIR.isInsideZone(npc))
  221. npc.teleToLocation(116033, 17447, 10104, 0);
  222. }
  223. }
  224. else if (event.equalsIgnoreCase("baium_unlock"))
  225. {
  226. GrandBossManager.getInstance().setBossStatus(LIVE_BAIUM, ASLEEP);
  227. addSpawn(STONE_BAIUM, 116033, 17447, 10104, 40188, false, 0, false);
  228. }
  229. else if (event.equalsIgnoreCase("angels_aggro_reconsider"))
  230. {
  231. boolean updateTarget = false; // Update or no the target
  232.  
  233. for (Npc minion : _minions)
  234. {
  235. Attackable angel = ((Attackable) minion);
  236. Character victim = angel.getMostHated();
  237.  
  238. if (Rnd.get(100) < 10) // Chaos time
  239. updateTarget = true;
  240. else
  241. {
  242. if (victim != null) // Target is a unarmed player ; clean aggro.
  243. {
  244. if (victim instanceof Player && victim.getActiveWeaponInstance() == null)
  245. {
  246. angel.stopHating(victim); // Clean the aggro number of previous victim.
  247. updateTarget = true;
  248. }
  249. }
  250. else
  251. // No target currently.
  252. updateTarget = true;
  253. }
  254.  
  255. if (updateTarget)
  256. {
  257. Character newVictim = getRandomTarget(minion);
  258. if (newVictim != null && victim != newVictim)
  259. {
  260. angel.addDamageHate(newVictim, 0, 10000);
  261. angel.getAI().setIntention(CtrlIntention.ATTACK, newVictim);
  262. }
  263. }
  264. }
  265. }
  266. return super.onAdvEvent(event, npc, player);
  267. }
  268.  
  269. @Override
  270. public String onTalk(Npc npc, Player player)
  271. {
  272. String htmltext = "";
  273.  
  274. if (GrandBossManager.getInstance().getBossStatus(LIVE_BAIUM) == ASLEEP)
  275. {
  276. GrandBossManager.getInstance().setBossStatus(LIVE_BAIUM, AWAKE);
  277.  
  278. final Npc baium = addSpawn(LIVE_BAIUM, npc, false, 0, false);
  279. baium.setIsInvul(true);
  280.  
  281. GrandBossManager.getInstance().addBoss((GrandBoss) baium);
  282.  
  283. // First animation
  284. baium.broadcastPacket(new SocialAction(baium, 2));
  285. baium.broadcastPacket(new Earthquake(baium.getX(), baium.getY(), baium.getZ(), 40, 10));
  286.  
  287. // Second animation, waker sacrifice, followed by angels spawn, third animation and finally movement.
  288. startQuestTimer("baium_neck", 13000, baium, null, false);
  289. startQuestTimer("sacrifice_waker", 24000, baium, player, false);
  290. startQuestTimer("baium_roar", 28000, baium, null, false);
  291. startQuestTimer("baium_move", 35000, baium, null, false);
  292.  
  293. // Delete the statue.
  294. npc.deleteMe();
  295. }
  296. return htmltext;
  297. }
  298.  
  299. @Override
  300. public String onSpawn(Npc npc)
  301. {
  302. npc.disableCoreAI(true);
  303. return super.onSpawn(npc);
  304. }
  305.  
  306. @Override
  307. public String onAttack(Npc npc, Player attacker, int damage, boolean isPet, L2Skill skill)
  308. {
  309. if (!BAIUM_LAIR.isInsideZone(attacker))
  310. {
  311. attacker.doDie(attacker);
  312. return null;
  313. }
  314.  
  315. if (npc.isInvul())
  316. return null;
  317.  
  318. if (npc.getNpcId() == LIVE_BAIUM)
  319. {
  320. if (attacker.getMountType() == 1)
  321. {
  322. final L2Skill debuff = SkillTable.getInstance().getInfo(4258, 1);
  323. if (attacker.getFirstEffect(debuff) == null)
  324. {
  325. npc.setTarget(attacker);
  326. npc.doCast(debuff);
  327. }
  328. }
  329. // update a variable with the last action against baium
  330. _lastAttackTime = System.currentTimeMillis();
  331. }
  332. return super.onAttack(npc, attacker, damage, isPet, skill);
  333. }
  334.  
  335. @Override
  336. public String onKill(Npc npc, Player killer, boolean isPet)
  337. {
  338. cancelQuestTimer("baium_despawn", npc, null);
  339. npc.broadcastPacket(new PlaySound(1, "BS01_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
  340.  
  341. // spawn the "Teleportation Cubic" for 15 minutes (to allow players to exit the lair)
  342. addSpawn(29055, 115203, 16620, 10078, 0, false, 900000, false);
  343.  
  344. long respawnTime = (long) Config.SPAWN_INTERVAL_BAIUM + Rnd.get(-Config.RANDOM_SPAWN_TIME_BAIUM, Config.RANDOM_SPAWN_TIME_BAIUM);
  345. respawnTime *= 3600000;
  346.  
  347. GrandBossManager.getInstance().setBossStatus(LIVE_BAIUM, DEAD);
  348. startQuestTimer("baium_unlock", respawnTime, null, null, false);
  349.  
  350. StatsSet info = GrandBossManager.getInstance().getStatsSet(LIVE_BAIUM);
  351. info.set("respawn_time", System.currentTimeMillis() + respawnTime);
  352. GrandBossManager.getInstance().setStatsSet(LIVE_BAIUM, info);
  353.  
  354. // Unspawn angels.
  355. for (Npc minion : _minions)
  356. {
  357. minion.getSpawn().setRespawnState(false);
  358. minion.deleteMe();
  359. }
  360. _minions.clear();
  361.  
  362. // Clean Baium AI
  363. cancelQuestTimer("skill_range", npc, null);
  364.  
  365. // Clean angels AI
  366. cancelQuestTimer("angels_aggro_reconsider", null, null);
  367.  
  368. return super.onKill(npc, killer, isPet);
  369. }
  370.  
  371. /**
  372. * This method allows to select a random target, and is used both for Baium and angels.
  373. * @param npc to check.
  374. * @return the random target.
  375. */
  376. private Character getRandomTarget(Npc npc)
  377. {
  378. int npcId = npc.getNpcId();
  379. List<Character> result = new ArrayList<>();
  380.  
  381. for (Character obj : npc.getKnownType(Character.class))
  382. {
  383. if (obj instanceof Player)
  384. {
  385. if (obj.isDead() || !(GeoEngine.getInstance().canSeeTarget(npc, obj)))
  386. continue;
  387.  
  388. if (((Player) obj).isGM() && ((Player) obj).getAppearance().getInvisible())
  389. continue;
  390.  
  391. if (npcId == ARCHANGEL && ((Player) obj).getActiveWeaponInstance() == null)
  392. continue;
  393.  
  394. result.add(obj);
  395. }
  396. // Case of Archangels, they can hit Baium.
  397. else if (obj instanceof GrandBoss && npcId == ARCHANGEL)
  398. result.add(obj);
  399. }
  400.  
  401. // If there's no players available, Baium and Angels are hitting each other.
  402. if (result.isEmpty())
  403. {
  404. if (npcId == LIVE_BAIUM) // Case of Baium. Angels should never be without target.
  405. {
  406. for (Npc minion : _minions)
  407. result.add(minion);
  408. }
  409. }
  410.  
  411. return (result.isEmpty()) ? null : Rnd.get(result);
  412. }
  413.  
  414. /**
  415. * The personal casting AI for Baium.
  416. * @param npc baium, basically...
  417. */
  418. private void callSkillAI(Npc npc)
  419. {
  420. if (npc.isInvul() || npc.isCastingNow())
  421. return;
  422.  
  423. // Pickup a target if no or dead victim. If Baium was hitting an angel, 50% luck he reconsiders his target. 10% luck he decides to reconsiders his target.
  424. if (_actualVictim == null || _actualVictim.isDead() || !(npc.getKnownType(Player.class).contains(_actualVictim)) || (_actualVictim instanceof Monster && Rnd.get(10) < 5) || Rnd.get(10) == 0)
  425. _actualVictim = getRandomTarget(npc);
  426.  
  427. // If result is null, return directly.
  428. if (_actualVictim == null)
  429. return;
  430.  
  431. final L2Skill skill = SkillTable.getInstance().getInfo(getRandomSkill(npc), 1);
  432.  
  433. // Adapt the skill range, because Baium is fat.
  434. if (Util.checkIfInRange((int) (skill.getCastRange() + npc.getCollisionRadius()), npc, _actualVictim, true))
  435. {
  436. npc.getAI().setIntention(CtrlIntention.IDLE);
  437. npc.setTarget(skill.getId() == 4135 ? npc : _actualVictim);
  438. npc.doCast(skill);
  439. }
  440. else
  441. npc.getAI().setIntention(CtrlIntention.FOLLOW, _actualVictim, null);
  442. }
  443.  
  444. /**
  445. * Pick a random skill through that list.<br>
  446. * If Baium feels surrounded, he will use AoE skills. Same behavior if he is near 2+ angels.<br>
  447. * @param npc baium
  448. * @return a usable skillId
  449. */
  450. private static int getRandomSkill(Npc npc)
  451. {
  452. // Baium's selfheal. It happens exceptionaly.
  453. if (npc.getCurrentHp() / npc.getMaxHp() < 0.1)
  454. {
  455. if (Rnd.get(10000) == 777) // His lucky day.
  456. return 4135;
  457. }
  458.  
  459. int skill = 4127; // Default attack if nothing is possible.
  460. final int chance = Rnd.get(100); // Remember, it's 0 to 99, not 1 to 100.
  461.  
  462. // If Baium feels surrounded or see 2+ angels, he unleashes his wrath upon heads :).
  463. if (getPlayersCountInRadius(600, npc, false) >= 20 || npc.getKnownTypeInRadius(Monster.class, 600).size() >= 2)
  464. {
  465. if (chance < 25)
  466. skill = 4130;
  467. else if (chance >= 25 && chance < 50)
  468. skill = 4131;
  469. else if (chance >= 50 && chance < 75)
  470. skill = 4128;
  471. else if (chance >= 75 && chance < 100)
  472. skill = 4129;
  473. }
  474. else
  475. {
  476. if (npc.getCurrentHp() / npc.getMaxHp() > 0.75)
  477. {
  478. if (chance < 10)
  479. skill = 4128;
  480. else if (chance >= 10 && chance < 20)
  481. skill = 4129;
  482. }
  483. else if (npc.getCurrentHp() / npc.getMaxHp() > 0.5)
  484. {
  485. if (chance < 10)
  486. skill = 4131;
  487. else if (chance >= 10 && chance < 20)
  488. skill = 4128;
  489. else if (chance >= 20 && chance < 30)
  490. skill = 4129;
  491. }
  492. else if (npc.getCurrentHp() / npc.getMaxHp() > 0.25)
  493. {
  494. if (chance < 10)
  495. skill = 4130;
  496. else if (chance >= 10 && chance < 20)
  497. skill = 4131;
  498. else if (chance >= 20 && chance < 30)
  499. skill = 4128;
  500. else if (chance >= 30 && chance < 40)
  501. skill = 4129;
  502. }
  503. else
  504. {
  505. if (chance < 10)
  506. skill = 4130;
  507. else if (chance >= 10 && chance < 20)
  508. skill = 4131;
  509. else if (chance >= 20 && chance < 30)
  510. skill = 4128;
  511. else if (chance >= 30 && chance < 40)
  512. skill = 4129;
  513. }
  514. }
  515. return skill;
  516. }
  517. }
Advertisement
Add Comment
Please, Sign In to add comment