AirShipController.java 13 KB

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