AirShipController.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. /*
  2. * This program is free software: you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation, either version 3 of the License, or (at your option) any later
  5. * version.
  6. *
  7. * This program is distributed in the hope that it will be useful, but WITHOUT
  8. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  10. * details.
  11. *
  12. * You should have received a copy of the GNU General Public License along with
  13. * this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. package vehicles;
  16. import java.util.concurrent.Future;
  17. import java.util.logging.Level;
  18. import java.util.logging.Logger;
  19. import com.l2jserver.gameserver.ThreadPoolManager;
  20. import com.l2jserver.gameserver.instancemanager.AirShipManager;
  21. import com.l2jserver.gameserver.instancemanager.ZoneManager;
  22. import com.l2jserver.gameserver.model.L2Clan;
  23. import com.l2jserver.gameserver.model.Location;
  24. import com.l2jserver.gameserver.model.VehiclePathPoint;
  25. import com.l2jserver.gameserver.model.actor.L2Character;
  26. import com.l2jserver.gameserver.model.actor.L2Npc;
  27. import com.l2jserver.gameserver.model.actor.instance.L2AirShipInstance;
  28. import com.l2jserver.gameserver.model.actor.instance.L2ControllableAirShipInstance;
  29. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  30. import com.l2jserver.gameserver.model.quest.Quest;
  31. import com.l2jserver.gameserver.model.zone.L2ZoneType;
  32. import com.l2jserver.gameserver.model.zone.type.L2ScriptZone;
  33. import com.l2jserver.gameserver.network.SystemMessageId;
  34. import com.l2jserver.gameserver.network.clientpackets.Say2;
  35. import com.l2jserver.gameserver.network.serverpackets.NpcSay;
  36. import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
  37. public abstract class AirShipController extends Quest
  38. {
  39. public static final Logger _log = Logger.getLogger(AirShipController.class.getName());
  40. protected int _dockZone = 0;
  41. protected int _shipSpawnX = 0;
  42. protected int _shipSpawnY = 0;
  43. protected int _shipSpawnZ = 0;
  44. protected int _shipHeading = 0;
  45. protected Location _oustLoc = null;
  46. protected int _locationId = 0;
  47. protected VehiclePathPoint[] _arrivalPath = null;
  48. protected VehiclePathPoint[] _departPath = null;
  49. protected VehiclePathPoint[][] _teleportsTable = null;
  50. protected int[] _fuelTable = null;
  51. protected int _movieId = 0;
  52. protected boolean _isBusy = false;
  53. protected L2ControllableAirShipInstance _dockedShip = null;
  54. private final Runnable _decayTask = new DecayTask();
  55. private final Runnable _departTask = new DepartTask();
  56. private Future<?> _departSchedule = null;
  57. private NpcSay _arrivalMessage = null;
  58. private static final int DEPART_INTERVAL = 300000; // 5 min
  59. private static final int LICENSE = 13559;
  60. private static final int STARSTONE = 13277;
  61. private static final int SUMMON_COST = 5;
  62. private static final SystemMessage SM_ALREADY_EXISTS = SystemMessage.getSystemMessage(SystemMessageId.THE_AIRSHIP_IS_ALREADY_EXISTS);
  63. private static final SystemMessage SM_ALREADY_SUMMONED = SystemMessage.getSystemMessage(SystemMessageId.ANOTHER_AIRSHIP_ALREADY_SUMMONED);
  64. private static final SystemMessage SM_NEED_LICENSE = SystemMessage.getSystemMessage(SystemMessageId.THE_AIRSHIP_NEED_LICENSE_TO_SUMMON);
  65. private static final SystemMessage SM_NEED_CLANLVL5 = SystemMessage.getSystemMessage(SystemMessageId.THE_AIRSHIP_NEED_CLANLVL_5_TO_SUMMON);
  66. private static final SystemMessage SM_NO_PRIVS = SystemMessage.getSystemMessage(SystemMessageId.THE_AIRSHIP_NO_PRIVILEGES);
  67. private static final SystemMessage SM_ALREADY_USED = SystemMessage.getSystemMessage(SystemMessageId.THE_AIRSHIP_ALREADY_USED);
  68. private static final SystemMessage SM_LICENSE_ALREADY_ACQUIRED = SystemMessage.getSystemMessage(SystemMessageId.THE_AIRSHIP_SUMMON_LICENSE_ALREADY_ACQUIRED);
  69. private static final SystemMessage SM_LICENSE_ENTERED = SystemMessage.getSystemMessage(SystemMessageId.THE_AIRSHIP_SUMMON_LICENSE_ENTERED);
  70. private static final SystemMessage SM_NEED_MORE = SystemMessage.getSystemMessage(SystemMessageId.THE_AIRSHIP_NEED_MORE_S1).addItemName(STARSTONE);
  71. @Override
  72. public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
  73. {
  74. if ("summon".equalsIgnoreCase(event))
  75. {
  76. if (_dockedShip != null)
  77. {
  78. if (_dockedShip.isOwner(player))
  79. player.sendPacket(SM_ALREADY_EXISTS);
  80. return null;
  81. }
  82. if (_isBusy)
  83. {
  84. player.sendPacket(SM_ALREADY_SUMMONED);
  85. return null;
  86. }
  87. if ((player.getClanPrivileges() & L2Clan.CP_CL_SUMMON_AIRSHIP) != L2Clan.CP_CL_SUMMON_AIRSHIP)
  88. {
  89. player.sendPacket(SM_NO_PRIVS);
  90. return null;
  91. }
  92. int ownerId = player.getClanId();
  93. if (!AirShipManager.getInstance().hasAirShipLicense(ownerId))
  94. {
  95. player.sendPacket(SM_NEED_LICENSE);
  96. return null;
  97. }
  98. if (AirShipManager.getInstance().hasAirShip(ownerId))
  99. {
  100. player.sendPacket(SM_ALREADY_USED);
  101. return null;
  102. }
  103. if (!player.destroyItemByItemId("AirShipSummon", STARSTONE, SUMMON_COST, npc, true))
  104. {
  105. player.sendPacket(SM_NEED_MORE);
  106. return null;
  107. }
  108. _isBusy = true;
  109. final L2AirShipInstance ship = AirShipManager.getInstance().getNewAirShip(_shipSpawnX, _shipSpawnY, _shipSpawnZ, _shipHeading, ownerId);
  110. if (ship != null)
  111. {
  112. if (_arrivalPath != null)
  113. ship.executePath(_arrivalPath);
  114. if (_arrivalMessage == null)
  115. _arrivalMessage = new NpcSay(npc.getObjectId(), Say2.SHOUT, npc.getNpcId(), 1800219); // The airship has been summoned. It will automatically depart in 5 minutes.
  116. npc.broadcastPacket(_arrivalMessage);
  117. }
  118. else
  119. _isBusy = false;
  120. return null;
  121. }
  122. else if ("board".equalsIgnoreCase(event))
  123. {
  124. if (player.isTransformed())
  125. {
  126. player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_TRANSFORMED);
  127. return null;
  128. }
  129. else if (player.isParalyzed())
  130. {
  131. player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_PETRIFIED);
  132. return null;
  133. }
  134. else if (player.isDead() || player.isFakeDeath())
  135. {
  136. player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_DEAD);
  137. return null;
  138. }
  139. else if (player.isFishing())
  140. {
  141. player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_FISHING);
  142. return null;
  143. }
  144. else if (player.isInCombat())
  145. {
  146. player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_IN_BATTLE);
  147. return null;
  148. }
  149. else if (player.isInDuel())
  150. {
  151. player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_IN_A_DUEL);
  152. return null;
  153. }
  154. else if (player.isSitting())
  155. {
  156. player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_SITTING);
  157. return null;
  158. }
  159. else if (player.isCastingNow())
  160. {
  161. player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_CASTING);
  162. return null;
  163. }
  164. else if (player.isCursedWeaponEquipped())
  165. {
  166. player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_A_CURSED_WEAPON_IS_EQUIPPED);
  167. return null;
  168. }
  169. else if (player.isCombatFlagEquipped())
  170. {
  171. player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_HOLDING_A_FLAG);
  172. return null;
  173. }
  174. else if (player.getPet() != null || player.isMounted())
  175. {
  176. player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_A_PET_OR_A_SERVITOR_IS_SUMMONED);
  177. return null;
  178. }
  179. else if (player.isFlyingMounted())
  180. {
  181. player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_NOT_MEET_REQUEIREMENTS);
  182. return null;
  183. }
  184. if (_dockedShip != null)
  185. _dockedShip.addPassenger(player);
  186. return null;
  187. }
  188. else if ("register".equalsIgnoreCase(event))
  189. {
  190. if (player.getClan() == null || player.getClan().getLevel() < 5)
  191. {
  192. player.sendPacket(SM_NEED_CLANLVL5);
  193. return null;
  194. }
  195. if (!player.isClanLeader())
  196. {
  197. player.sendPacket(SM_NO_PRIVS);
  198. return null;
  199. }
  200. final int ownerId = player.getClanId();
  201. if (AirShipManager.getInstance().hasAirShipLicense(ownerId))
  202. {
  203. player.sendPacket(SM_LICENSE_ALREADY_ACQUIRED);
  204. return null;
  205. }
  206. if (!player.destroyItemByItemId("AirShipLicense", LICENSE, 1, npc, true))
  207. {
  208. player.sendPacket(SM_NEED_MORE);
  209. return null;
  210. }
  211. AirShipManager.getInstance().registerLicense(ownerId);
  212. player.sendPacket(SM_LICENSE_ENTERED);
  213. return null;
  214. }
  215. else
  216. return event;
  217. }
  218. @Override
  219. public String onFirstTalk(L2Npc npc, L2PcInstance player)
  220. {
  221. if (player.getQuestState(getName()) == null)
  222. newQuestState(player);
  223. return npc.getNpcId() + ".htm";
  224. }
  225. @Override
  226. public String onEnterZone(L2Character character, L2ZoneType zone)
  227. {
  228. if (character instanceof L2ControllableAirShipInstance)
  229. {
  230. if (_dockedShip == null)
  231. {
  232. _dockedShip = (L2ControllableAirShipInstance) character;
  233. _dockedShip.setInDock(_dockZone);
  234. _dockedShip.setOustLoc(_oustLoc);
  235. // Ship is not empty - display movie to passengers and dock
  236. if (!_dockedShip.isEmpty())
  237. {
  238. if (_movieId != 0)
  239. {
  240. for (L2PcInstance passenger : _dockedShip.getPassengers())
  241. {
  242. if (passenger != null)
  243. passenger.showQuestMovie(_movieId);
  244. }
  245. }
  246. ThreadPoolManager.getInstance().scheduleGeneral(_decayTask, 1000);
  247. }
  248. else
  249. _departSchedule = ThreadPoolManager.getInstance().scheduleGeneral(_departTask, DEPART_INTERVAL);
  250. }
  251. }
  252. return null;
  253. }
  254. @Override
  255. public String onExitZone(L2Character character, L2ZoneType zone)
  256. {
  257. if (character instanceof L2ControllableAirShipInstance)
  258. {
  259. if (character.equals(_dockedShip))
  260. {
  261. if (_departSchedule != null)
  262. {
  263. _departSchedule.cancel(false);
  264. _departSchedule = null;
  265. }
  266. _dockedShip.setInDock(0);
  267. _dockedShip = null;
  268. _isBusy = false;
  269. }
  270. }
  271. return null;
  272. }
  273. protected void validityCheck()
  274. {
  275. L2ScriptZone zone = ZoneManager.getInstance().getZoneById(_dockZone, L2ScriptZone.class);
  276. if (zone == null)
  277. {
  278. _log.log(Level.WARNING, getName()+": Invalid zone "+_dockZone+", controller disabled");
  279. _isBusy = true;
  280. return;
  281. }
  282. VehiclePathPoint p;
  283. if (_arrivalPath != null)
  284. {
  285. if (_arrivalPath.length == 0)
  286. {
  287. _log.log(Level.WARNING, getName()+": Zero arrival path length.");
  288. _arrivalPath = null;
  289. }
  290. else
  291. {
  292. p = _arrivalPath[_arrivalPath.length - 1];
  293. if (!zone.isInsideZone(p.x, p.y, p.z))
  294. {
  295. _log.log(Level.WARNING, getName()+": Arrival path finish point ("+p.x+","+p.y+","+p.z+") not in zone "+_dockZone);
  296. _arrivalPath = null;
  297. }
  298. }
  299. }
  300. if (_arrivalPath == null)
  301. {
  302. if (!ZoneManager.getInstance().getZoneById(_dockZone, L2ScriptZone.class).isInsideZone(_shipSpawnX, _shipSpawnY, _shipSpawnZ))
  303. {
  304. _log.log(Level.WARNING, getName()+": Arrival path is null and spawn point not in zone "+_dockZone+", controller disabled");
  305. _isBusy = true;
  306. return;
  307. }
  308. }
  309. if (_departPath != null)
  310. {
  311. if (_departPath.length == 0)
  312. {
  313. _log.log(Level.WARNING, getName()+": Zero depart path length.");
  314. _departPath = null;
  315. }
  316. else
  317. {
  318. p = _departPath[_departPath.length - 1];
  319. if (zone.isInsideZone(p.x, p.y, p.z))
  320. {
  321. _log.log(Level.WARNING, getName()+": Departure path finish point ("+p.x+","+p.y+","+p.z+") in zone "+_dockZone);
  322. _departPath = null;
  323. }
  324. }
  325. }
  326. if (_teleportsTable != null)
  327. {
  328. if (_fuelTable == null)
  329. _log.log(Level.WARNING, getName()+": Fuel consumption not defined.");
  330. else
  331. {
  332. if (_teleportsTable.length != _fuelTable.length)
  333. _log.log(Level.WARNING, getName()+": Fuel consumption not match teleport list.");
  334. else
  335. AirShipManager.getInstance().registerAirShipTeleportList(_dockZone, _locationId, _teleportsTable, _fuelTable);
  336. }
  337. }
  338. }
  339. private final class DecayTask implements Runnable
  340. {
  341. public void run()
  342. {
  343. if (_dockedShip != null)
  344. _dockedShip.deleteMe();
  345. }
  346. }
  347. private final class DepartTask implements Runnable
  348. {
  349. public void run()
  350. {
  351. if (_dockedShip != null
  352. && _dockedShip.isInDock()
  353. && !_dockedShip.isMoving())
  354. {
  355. if (_departPath != null)
  356. _dockedShip.executePath(_departPath);
  357. else
  358. _dockedShip.deleteMe();
  359. }
  360. }
  361. }
  362. public AirShipController(int questId, String name, String descr)
  363. {
  364. super(questId, name, descr);
  365. }
  366. }