OlympiadGameTask.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  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 com.l2jserver.gameserver.model.olympiad;
  16. import java.util.logging.Level;
  17. import java.util.logging.Logger;
  18. import com.l2jserver.Config;
  19. import com.l2jserver.gameserver.ThreadPoolManager;
  20. import com.l2jserver.gameserver.model.zone.type.L2OlympiadStadiumZone;
  21. import com.l2jserver.gameserver.network.SystemMessageId;
  22. import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
  23. /**
  24. * @author DS
  25. */
  26. public final class OlympiadGameTask implements Runnable
  27. {
  28. protected static final Logger _log = Logger.getLogger(OlympiadGameTask.class.getName());
  29. protected static final long BATTLE_PERIOD = Config.ALT_OLY_BATTLE; // 6 mins
  30. public static final int[] TELEPORT_TO_ARENA =
  31. {
  32. 120,
  33. 60,
  34. 30,
  35. 15,
  36. 10,
  37. 5,
  38. 4,
  39. 3,
  40. 2,
  41. 1,
  42. 0
  43. };
  44. public static final int[] BATTLE_START_TIME_FIRST =
  45. {
  46. 60,
  47. 50,
  48. 40,
  49. 30,
  50. 20,
  51. 10,
  52. 0
  53. };
  54. public static final int[] BATTLE_START_TIME_SECOND =
  55. {
  56. 10,
  57. 5,
  58. 4,
  59. 3,
  60. 2,
  61. 1,
  62. 0
  63. };
  64. public static final int[] TELEPORT_TO_TOWN =
  65. {
  66. 40,
  67. 30,
  68. 20,
  69. 10,
  70. 5,
  71. 4,
  72. 3,
  73. 2,
  74. 1,
  75. 0
  76. };
  77. private final L2OlympiadStadiumZone _zone;
  78. private AbstractOlympiadGame _game;
  79. private GameState _state = GameState.IDLE;
  80. private boolean _needAnnounce = false;
  81. private int _countDown = 0;
  82. private static enum GameState
  83. {
  84. BEGIN,
  85. TELEPORT_TO_ARENA,
  86. GAME_STARTED,
  87. BATTLE_COUNTDOWN_FIRST,
  88. BATTLE_COUNTDOWN_SECOND,
  89. BATTLE_STARTED,
  90. BATTLE_IN_PROGRESS,
  91. GAME_STOPPED,
  92. TELEPORT_TO_TOWN,
  93. CLEANUP,
  94. IDLE
  95. }
  96. public OlympiadGameTask(L2OlympiadStadiumZone zone)
  97. {
  98. _zone = zone;
  99. zone.registerTask(this);
  100. }
  101. public final boolean isRunning()
  102. {
  103. return _state != GameState.IDLE;
  104. }
  105. public final boolean isGameStarted()
  106. {
  107. return (_state.ordinal() >= GameState.GAME_STARTED.ordinal()) && (_state.ordinal() <= GameState.CLEANUP.ordinal());
  108. }
  109. public final boolean isBattleStarted()
  110. {
  111. return _state == GameState.BATTLE_IN_PROGRESS;
  112. }
  113. public final boolean isBattleFinished()
  114. {
  115. return _state == GameState.TELEPORT_TO_TOWN;
  116. }
  117. public final boolean needAnnounce()
  118. {
  119. if (_needAnnounce)
  120. {
  121. _needAnnounce = false;
  122. return true;
  123. }
  124. return false;
  125. }
  126. public final L2OlympiadStadiumZone getZone()
  127. {
  128. return _zone;
  129. }
  130. public final AbstractOlympiadGame getGame()
  131. {
  132. return _game;
  133. }
  134. public final void attachGame(AbstractOlympiadGame game)
  135. {
  136. if ((game != null) && (_state != GameState.IDLE))
  137. {
  138. _log.log(Level.WARNING, "Attempt to overwrite non-finished game in state " + _state);
  139. return;
  140. }
  141. _game = game;
  142. _state = GameState.BEGIN;
  143. _needAnnounce = false;
  144. ThreadPoolManager.getInstance().executeTask(this);
  145. }
  146. @Override
  147. public final void run()
  148. {
  149. try
  150. {
  151. int delay = 1; // schedule next call after 1s
  152. switch (_state)
  153. {
  154. // Game created
  155. case BEGIN:
  156. {
  157. _state = GameState.TELEPORT_TO_ARENA;
  158. _countDown = Config.ALT_OLY_WAIT_TIME;
  159. break;
  160. }
  161. // Teleport to arena countdown
  162. case TELEPORT_TO_ARENA:
  163. {
  164. if (_countDown > 0)
  165. {
  166. SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_WILL_ENTER_THE_OLYMPIAD_STADIUM_IN_S1_SECOND_S);
  167. sm.addNumber(_countDown);
  168. _game.broadcastPacket(sm);
  169. }
  170. delay = getDelay(TELEPORT_TO_ARENA);
  171. if (_countDown <= 0)
  172. {
  173. _state = GameState.GAME_STARTED;
  174. }
  175. break;
  176. }
  177. // Game start, port players to arena
  178. case GAME_STARTED:
  179. {
  180. if (!startGame())
  181. {
  182. _state = GameState.GAME_STOPPED;
  183. break;
  184. }
  185. _state = GameState.BATTLE_COUNTDOWN_FIRST;
  186. _countDown = BATTLE_START_TIME_FIRST[0];
  187. delay = 5;
  188. break;
  189. }
  190. // Battle start countdown, first part (60-10)
  191. case BATTLE_COUNTDOWN_FIRST:
  192. {
  193. if (_countDown > 0)
  194. {
  195. SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.THE_GAME_WILL_START_IN_S1_SECOND_S);
  196. sm.addNumber(_countDown);
  197. _zone.broadcastPacket(sm);
  198. }
  199. delay = getDelay(BATTLE_START_TIME_FIRST);
  200. if (_countDown <= 0)
  201. {
  202. openDoors();
  203. _state = GameState.BATTLE_COUNTDOWN_SECOND;
  204. _countDown = BATTLE_START_TIME_SECOND[0];
  205. delay = getDelay(BATTLE_START_TIME_SECOND);
  206. }
  207. break;
  208. }
  209. // Battle start countdown, second part (10-0)
  210. case BATTLE_COUNTDOWN_SECOND:
  211. {
  212. if (_countDown > 0)
  213. {
  214. SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.THE_GAME_WILL_START_IN_S1_SECOND_S);
  215. sm.addNumber(_countDown);
  216. _zone.broadcastPacket(sm);
  217. }
  218. delay = getDelay(BATTLE_START_TIME_SECOND);
  219. if (_countDown <= 0)
  220. {
  221. _state = GameState.BATTLE_STARTED;
  222. }
  223. break;
  224. }
  225. // Beginning of the battle
  226. case BATTLE_STARTED:
  227. {
  228. _countDown = 0;
  229. _state = GameState.BATTLE_IN_PROGRESS; // set state first, used in zone update
  230. if (!startBattle())
  231. {
  232. _state = GameState.GAME_STOPPED;
  233. }
  234. break;
  235. }
  236. // Checks during battle
  237. case BATTLE_IN_PROGRESS:
  238. {
  239. _countDown += 1000;
  240. if (checkBattle() || (_countDown > Config.ALT_OLY_BATTLE))
  241. {
  242. _state = GameState.GAME_STOPPED;
  243. }
  244. break;
  245. }
  246. // End of the battle
  247. case GAME_STOPPED:
  248. {
  249. _state = GameState.TELEPORT_TO_TOWN;
  250. _countDown = TELEPORT_TO_TOWN[0];
  251. stopGame();
  252. delay = getDelay(TELEPORT_TO_TOWN);
  253. break;
  254. }
  255. // Teleport to town countdown
  256. case TELEPORT_TO_TOWN:
  257. {
  258. if (_countDown > 0)
  259. {
  260. SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_WILL_BE_MOVED_TO_TOWN_IN_S1_SECONDS);
  261. sm.addNumber(_countDown);
  262. _game.broadcastPacket(sm);
  263. }
  264. delay = getDelay(TELEPORT_TO_TOWN);
  265. if (_countDown <= 0)
  266. {
  267. _state = GameState.CLEANUP;
  268. }
  269. break;
  270. }
  271. // Removals
  272. case CLEANUP:
  273. {
  274. cleanupGame();
  275. _state = GameState.IDLE;
  276. _game = null;
  277. return;
  278. }
  279. }
  280. ThreadPoolManager.getInstance().scheduleGeneral(this, delay * 1000);
  281. }
  282. catch (Exception e)
  283. {
  284. switch (_state)
  285. {
  286. case GAME_STOPPED:
  287. case TELEPORT_TO_TOWN:
  288. case CLEANUP:
  289. case IDLE:
  290. {
  291. _log.log(Level.WARNING, "Unable to return players back in town, exception: " + e.getMessage());
  292. _state = GameState.IDLE;
  293. _game = null;
  294. return;
  295. }
  296. }
  297. _log.log(Level.WARNING, "Exception in " + _state + ", trying to port players back: " + e.getMessage(), e);
  298. _state = GameState.GAME_STOPPED;
  299. ThreadPoolManager.getInstance().scheduleGeneral(this, 1000);
  300. }
  301. }
  302. private final int getDelay(int[] times)
  303. {
  304. int time;
  305. for (int i = 0; i < (times.length - 1); i++)
  306. {
  307. time = times[i];
  308. if (time >= _countDown)
  309. {
  310. continue;
  311. }
  312. final int delay = _countDown - time;
  313. _countDown = time;
  314. return delay;
  315. }
  316. // should not happens
  317. _countDown = -1;
  318. return 1;
  319. }
  320. /**
  321. * Second stage: check for defaulted, port players to arena, announce game.
  322. * @return true if no participants defaulted.
  323. */
  324. private final boolean startGame()
  325. {
  326. try
  327. {
  328. // Checking for opponents and teleporting to arena
  329. if (_game.checkDefaulted())
  330. {
  331. return false;
  332. }
  333. _zone.closeDoors();
  334. if (_game.needBuffers())
  335. {
  336. _zone.spawnBuffers();
  337. }
  338. if (!_game.portPlayersToArena(_zone.getSpawns()))
  339. {
  340. return false;
  341. }
  342. _game.removals();
  343. _needAnnounce = true;
  344. OlympiadGameManager.getInstance().startBattle(); // inform manager
  345. return true;
  346. }
  347. catch (Exception e)
  348. {
  349. _log.log(Level.WARNING, e.getMessage(), e);
  350. }
  351. return false;
  352. }
  353. /**
  354. * Third stage: open doors.
  355. */
  356. private final void openDoors()
  357. {
  358. try
  359. {
  360. _game.resetDamage();
  361. _zone.openDoors();
  362. }
  363. catch (Exception e)
  364. {
  365. _log.log(Level.WARNING, e.getMessage(), e);
  366. }
  367. }
  368. /**
  369. * Fourth stage: last checks, remove buffers, start competition itself.
  370. * @return true if all participants online and ready on the stadium.
  371. */
  372. private final boolean startBattle()
  373. {
  374. try
  375. {
  376. if (_game.needBuffers())
  377. {
  378. _zone.deleteBuffers();
  379. }
  380. if (_game.checkBattleStatus() && _game.makeCompetitionStart())
  381. {
  382. // game successfully started
  383. _game.broadcastOlympiadInfo(_zone);
  384. _zone.broadcastPacket(SystemMessage.getSystemMessage(SystemMessageId.STARTS_THE_GAME));
  385. _zone.updateZoneStatusForCharactersInside();
  386. return true;
  387. }
  388. }
  389. catch (Exception e)
  390. {
  391. _log.log(Level.WARNING, e.getMessage(), e);
  392. }
  393. return false;
  394. }
  395. /**
  396. * Fifth stage: battle is running, returns true if winner found.
  397. * @return
  398. */
  399. private final boolean checkBattle()
  400. {
  401. try
  402. {
  403. return _game.haveWinner();
  404. }
  405. catch (Exception e)
  406. {
  407. _log.log(Level.WARNING, e.getMessage(), e);
  408. }
  409. return true;
  410. }
  411. /**
  412. * Sixth stage: winner's validations
  413. */
  414. private final void stopGame()
  415. {
  416. try
  417. {
  418. _game.validateWinner(_zone);
  419. }
  420. catch (Exception e)
  421. {
  422. _log.log(Level.WARNING, e.getMessage(), e);
  423. }
  424. try
  425. {
  426. _zone.updateZoneStatusForCharactersInside();
  427. }
  428. catch (Exception e)
  429. {
  430. _log.log(Level.WARNING, e.getMessage(), e);
  431. }
  432. try
  433. {
  434. _game.cleanEffects();
  435. }
  436. catch (Exception e)
  437. {
  438. _log.log(Level.WARNING, e.getMessage(), e);
  439. }
  440. }
  441. /**
  442. * Seventh stage: game cleanup (port players back, closing doors, etc)
  443. */
  444. private final void cleanupGame()
  445. {
  446. try
  447. {
  448. _game.playersStatusBack();
  449. }
  450. catch (Exception e)
  451. {
  452. _log.log(Level.WARNING, e.getMessage(), e);
  453. }
  454. try
  455. {
  456. _game.portPlayersBack();
  457. }
  458. catch (Exception e)
  459. {
  460. _log.log(Level.WARNING, e.getMessage(), e);
  461. }
  462. try
  463. {
  464. _game.clearPlayers();
  465. }
  466. catch (Exception e)
  467. {
  468. _log.log(Level.WARNING, e.getMessage(), e);
  469. }
  470. try
  471. {
  472. _zone.closeDoors();
  473. }
  474. catch (Exception e)
  475. {
  476. _log.log(Level.WARNING, e.getMessage(), e);
  477. }
  478. }
  479. }