AltarsOfSacrifice.java 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /*
  2. * Copyright (C) 2004-2015 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.group_template;
  20. import java.util.logging.Level;
  21. import ai.npc.AbstractNpcAI;
  22. import com.l2jserver.gameserver.GeoData;
  23. import com.l2jserver.gameserver.model.L2Spawn;
  24. import com.l2jserver.gameserver.model.Location;
  25. import com.l2jserver.gameserver.model.actor.L2Npc;
  26. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  27. import com.l2jserver.gameserver.model.interfaces.ILocational;
  28. import com.l2jserver.util.Rnd;
  29. /**
  30. * @author HorridoJoho, janiko, FinalDestination, lion
  31. */
  32. public final class AltarsOfSacrifice extends AbstractNpcAI
  33. {
  34. private final class Altar
  35. {
  36. private final ILocational _middlePoint;
  37. private final int[] _bossNpcIds;
  38. private L2Npc _spawnedBoss;
  39. protected Altar(final ILocational middlePoint, final int... bossNpcIds)
  40. {
  41. _middlePoint = middlePoint;
  42. _bossNpcIds = bossNpcIds;
  43. _spawnedBoss = null;
  44. }
  45. protected void spawnBoss() throws Exception
  46. {
  47. if (!hasBosses() || (_spawnedBoss != null))
  48. {
  49. throw new IllegalStateException();
  50. }
  51. final L2Spawn spawn = new L2Spawn(_bossNpcIds[Rnd.get(_bossNpcIds.length)]);
  52. spawn.setAmount(1);
  53. spawn.setHeading(Rnd.get(65536));
  54. int radius = Rnd.get(BOSS_MIN_SPAWN_RADIUS, BOSS_MAX_SPAWN_RADIUS);
  55. double angleRadians = Rnd.get() * 2 * Math.PI;
  56. int spawnX = (int) (radius * Math.cos(angleRadians)) + _middlePoint.getX();
  57. int spawnY = (int) (radius * Math.sin(angleRadians)) + _middlePoint.getY();
  58. spawn.setXYZ(spawnX, spawnY, GeoData.getInstance().getHeight(spawnX, spawnY, _middlePoint.getZ()));
  59. spawn.stopRespawn();
  60. _spawnedBoss = spawn.spawnOne(false);
  61. }
  62. protected void despawnBoss()
  63. {
  64. if (_spawnedBoss != null)
  65. {
  66. _spawnedBoss.deleteMe();
  67. _spawnedBoss = null;
  68. }
  69. }
  70. protected void unload()
  71. {
  72. despawnBoss();
  73. }
  74. protected boolean hasBosses()
  75. {
  76. return _bossNpcIds.length > 0;
  77. }
  78. protected boolean isBossFighting()
  79. {
  80. return (_spawnedBoss != null) && _spawnedBoss.isInCombat();
  81. }
  82. }
  83. private static final String EVT_SPAWN_BOSS_PRE = "spawnboss";
  84. private static final String EVT_DESPAWN_BOSS_PRE = "despawnboss";
  85. private static final int BOSS_MIN_SPAWN_RADIUS = 250;
  86. private static final int BOSS_MAX_SPAWN_RADIUS = 500;
  87. // every 240 minutes/4 hours, altars change
  88. private static final long ALTAR_STATE_CHANGE_DELAY = 240 * 60 * 1000;
  89. // disabling formatter here to make this easily readable
  90. // @formatter:off
  91. private final Altar[] _altars = new Altar[]
  92. {
  93. // TalkingIsland
  94. new Altar
  95. (
  96. new Location(-92481, 244812, -3505)
  97. ),
  98. // Elven
  99. new Altar
  100. (
  101. new Location(40241, 53974, -3262)
  102. ),
  103. // DarkElven
  104. new Altar
  105. (
  106. new Location(1851, 21697, -3305),
  107. 25750
  108. ),
  109. // Dwarven
  110. new Altar
  111. (
  112. new Location(130133, -180968, -3271),
  113. 25800, 25782
  114. ),
  115. // Orc
  116. new Altar
  117. (
  118. new Location(-45329, -118327, -166),
  119. 25779
  120. ),
  121. // Kamael
  122. new Altar
  123. (
  124. new Location(-104031, 45059, -1417)
  125. ),
  126. // Oren
  127. new Altar
  128. (
  129. new Location(80188, 47037, -3109),
  130. 25767, 25770
  131. ),
  132. // Gludin
  133. new Altar
  134. (
  135. new Location(-86620, 151536, -3018),
  136. 25735, 25738, 25741
  137. ),
  138. // Gludio
  139. new Altar
  140. (
  141. new Location(-14152, 120674, -2935),
  142. 25744, 25747
  143. ),
  144. // Dion
  145. new Altar
  146. (
  147. new Location(16715, 148320, -3210),
  148. 25753, 25754, 25757
  149. ),
  150. // Heine
  151. new Altar
  152. (
  153. new Location(120123, 219164, -3319),
  154. 25773, 25776
  155. ),
  156. // Giran
  157. new Altar
  158. (
  159. new Location(80712, 142538, -3487),
  160. 25760, 25763, 25766
  161. ),
  162. // Aden
  163. new Altar
  164. (
  165. new Location(152720, 24714, -2083),
  166. 25793, 25794, 25797
  167. ),
  168. // Rune
  169. new Altar
  170. (
  171. new Location(28010, -49175, -1278)
  172. ),
  173. // Goddard
  174. new Altar
  175. (
  176. new Location(152274, -57706, -3383),
  177. 25787, 25790
  178. ),
  179. // Schutgart
  180. new Altar
  181. (
  182. new Location(82066, -139418, -2220),
  183. 25784
  184. ),
  185. // Primeval
  186. new Altar
  187. (
  188. new Location(10998, -24068, -3603)
  189. ),
  190. // Dragon Valley
  191. new Altar
  192. (
  193. new Location(69592, 118694, -3417)
  194. )
  195. };
  196. // @formatter:on
  197. public static void main(String[] args)
  198. {
  199. new AltarsOfSacrifice();
  200. }
  201. private AltarsOfSacrifice()
  202. {
  203. super("AltarsOfSacrifice", "ai/group_template");
  204. for (int i = 0; i < _altars.length; ++i)
  205. {
  206. if (_altars[i].hasBosses())
  207. {
  208. startQuestTimer(makeSpawnBossEvt(i), ALTAR_STATE_CHANGE_DELAY, null, null);
  209. }
  210. }
  211. }
  212. private String makeSpawnBossEvt(int altarIndex)
  213. {
  214. return EVT_SPAWN_BOSS_PRE + altarIndex;
  215. }
  216. private String makeDespawnBossEvt(int altarIndex)
  217. {
  218. return EVT_DESPAWN_BOSS_PRE + altarIndex;
  219. }
  220. private boolean isSpawnBossEvt(String event)
  221. {
  222. return event.startsWith(EVT_SPAWN_BOSS_PRE);
  223. }
  224. private boolean isDespawnBossEvt(String event)
  225. {
  226. return event.startsWith(EVT_DESPAWN_BOSS_PRE);
  227. }
  228. private int getSpawnBossIndex(String event)
  229. {
  230. return Integer.parseInt(event.substring(EVT_SPAWN_BOSS_PRE.length()));
  231. }
  232. private int getDespawnBossIndex(String event)
  233. {
  234. return Integer.parseInt(event.substring(EVT_DESPAWN_BOSS_PRE.length()));
  235. }
  236. @Override
  237. public boolean unload(boolean removeFromList)
  238. {
  239. _log.info(getClass().getSimpleName() + ": Unloading altars due to script unloading.");
  240. for (final Altar altar : _altars)
  241. {
  242. altar.unload();
  243. }
  244. return super.unload(removeFromList);
  245. }
  246. @Override
  247. public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
  248. {
  249. if (isSpawnBossEvt(event))
  250. {
  251. final int altarIndex = getSpawnBossIndex(event);
  252. final Altar altar = _altars[altarIndex];
  253. try
  254. {
  255. altar.spawnBoss();
  256. startQuestTimer(makeDespawnBossEvt(altarIndex), ALTAR_STATE_CHANGE_DELAY, null, null);
  257. }
  258. catch (Exception e)
  259. {
  260. _log.log(Level.WARNING, getClass().getSimpleName() + ": Failed to spawn altar boss.", e);
  261. // let's try again to spawn it in 5 seconds
  262. startQuestTimer(event, 5000, null, null);
  263. }
  264. }
  265. else if (isDespawnBossEvt(event))
  266. {
  267. final int altarIndex = getDespawnBossIndex(event);
  268. final Altar altar = _altars[altarIndex];
  269. if (altar.isBossFighting())
  270. {
  271. // periodically check if the altar boss is fighting, only despawn when not fighting anymore
  272. startQuestTimer(event, 5000, null, null);
  273. }
  274. else
  275. {
  276. altar.despawnBoss();
  277. startQuestTimer(makeSpawnBossEvt(altarIndex), ALTAR_STATE_CHANGE_DELAY, null, null);
  278. }
  279. }
  280. return null;
  281. }
  282. }