Duel.java 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065
  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.entity;
  16. import java.util.Calendar;
  17. import java.util.logging.Level;
  18. import java.util.logging.Logger;
  19. import javolution.util.FastList;
  20. import com.l2jserver.gameserver.ThreadPoolManager;
  21. import com.l2jserver.gameserver.ai.CtrlIntention;
  22. import com.l2jserver.gameserver.instancemanager.DuelManager;
  23. import com.l2jserver.gameserver.model.actor.L2Character;
  24. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  25. import com.l2jserver.gameserver.model.effects.L2Effect;
  26. import com.l2jserver.gameserver.network.SystemMessageId;
  27. import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
  28. import com.l2jserver.gameserver.network.serverpackets.ExDuelEnd;
  29. import com.l2jserver.gameserver.network.serverpackets.ExDuelReady;
  30. import com.l2jserver.gameserver.network.serverpackets.ExDuelStart;
  31. import com.l2jserver.gameserver.network.serverpackets.ExDuelUpdateUserInfo;
  32. import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
  33. import com.l2jserver.gameserver.network.serverpackets.PlaySound;
  34. import com.l2jserver.gameserver.network.serverpackets.SocialAction;
  35. import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
  36. public class Duel
  37. {
  38. protected static final Logger _log = Logger.getLogger(Duel.class.getName());
  39. public static final int DUELSTATE_NODUEL = 0;
  40. public static final int DUELSTATE_DUELLING = 1;
  41. public static final int DUELSTATE_DEAD = 2;
  42. public static final int DUELSTATE_WINNER = 3;
  43. public static final int DUELSTATE_INTERRUPTED = 4;
  44. private final int _duelId;
  45. private L2PcInstance _playerA;
  46. private L2PcInstance _playerB;
  47. private final boolean _partyDuel;
  48. private final Calendar _duelEndTime;
  49. private int _surrenderRequest = 0;
  50. private int _countdown = 4;
  51. private boolean _finished = false;
  52. private FastList<PlayerCondition> _playerConditions;
  53. public static enum DuelResultEnum
  54. {
  55. Continue,
  56. Team1Win,
  57. Team2Win,
  58. Team1Surrender,
  59. Team2Surrender,
  60. Canceled,
  61. Timeout
  62. }
  63. public Duel(L2PcInstance playerA, L2PcInstance playerB, int partyDuel, int duelId)
  64. {
  65. _duelId = duelId;
  66. _playerA = playerA;
  67. _playerB = playerB;
  68. _partyDuel = partyDuel == 1 ? true : false;
  69. _duelEndTime = Calendar.getInstance();
  70. if (_partyDuel)
  71. {
  72. _duelEndTime.add(Calendar.SECOND, 300);
  73. }
  74. else
  75. {
  76. _duelEndTime.add(Calendar.SECOND, 120);
  77. }
  78. _playerConditions = new FastList<>();
  79. setFinished(false);
  80. if (_partyDuel)
  81. {
  82. // increase countdown so that start task can teleport players
  83. _countdown++;
  84. // inform players that they will be portet shortly
  85. SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.IN_A_MOMENT_YOU_WILL_BE_TRANSPORTED_TO_THE_SITE_WHERE_THE_DUEL_WILL_TAKE_PLACE);
  86. broadcastToTeam1(sm);
  87. broadcastToTeam2(sm);
  88. }
  89. // Schedule duel start
  90. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartDuelTask(this), 3000);
  91. }
  92. public static class PlayerCondition
  93. {
  94. private L2PcInstance _player;
  95. private double _hp;
  96. private double _mp;
  97. private double _cp;
  98. private boolean _paDuel;
  99. private int _x, _y, _z;
  100. private FastList<L2Effect> _debuffs;
  101. public PlayerCondition(L2PcInstance player, boolean partyDuel)
  102. {
  103. if (player == null)
  104. {
  105. return;
  106. }
  107. _player = player;
  108. _hp = _player.getCurrentHp();
  109. _mp = _player.getCurrentMp();
  110. _cp = _player.getCurrentCp();
  111. _paDuel = partyDuel;
  112. if (_paDuel)
  113. {
  114. _x = _player.getX();
  115. _y = _player.getY();
  116. _z = _player.getZ();
  117. }
  118. }
  119. public void restoreCondition()
  120. {
  121. if (_player == null)
  122. {
  123. return;
  124. }
  125. _player.setCurrentHp(_hp);
  126. _player.setCurrentMp(_mp);
  127. _player.setCurrentCp(_cp);
  128. if (_paDuel)
  129. {
  130. teleportBack();
  131. }
  132. if (_debuffs != null) // Debuff removal
  133. {
  134. for (L2Effect temp : _debuffs)
  135. {
  136. if (temp != null)
  137. {
  138. temp.exit();
  139. }
  140. }
  141. }
  142. }
  143. public void registerDebuff(L2Effect debuff)
  144. {
  145. if (_debuffs == null)
  146. {
  147. _debuffs = new FastList<>();
  148. }
  149. _debuffs.add(debuff);
  150. }
  151. public void teleportBack()
  152. {
  153. if (_paDuel)
  154. {
  155. _player.teleToLocation(_x, _y, _z);
  156. }
  157. }
  158. public L2PcInstance getPlayer()
  159. {
  160. return _player;
  161. }
  162. }
  163. public class ScheduleDuelTask implements Runnable
  164. {
  165. private final Duel _duel;
  166. public ScheduleDuelTask(Duel duel)
  167. {
  168. _duel = duel;
  169. }
  170. @Override
  171. public void run()
  172. {
  173. try
  174. {
  175. DuelResultEnum status = _duel.checkEndDuelCondition();
  176. if (status == DuelResultEnum.Canceled)
  177. {
  178. // do not schedule duel end if it was interrupted
  179. setFinished(true);
  180. _duel.endDuel(status);
  181. }
  182. else if (status != DuelResultEnum.Continue)
  183. {
  184. setFinished(true);
  185. playKneelAnimation();
  186. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleEndDuelTask(_duel, status), 5000);
  187. }
  188. else
  189. {
  190. ThreadPoolManager.getInstance().scheduleGeneral(this, 1000);
  191. }
  192. }
  193. catch (Exception e)
  194. {
  195. _log.log(Level.SEVERE, "", e);
  196. }
  197. }
  198. }
  199. public static class ScheduleStartDuelTask implements Runnable
  200. {
  201. private final Duel _duel;
  202. public ScheduleStartDuelTask(Duel duel)
  203. {
  204. _duel = duel;
  205. }
  206. @Override
  207. public void run()
  208. {
  209. try
  210. {
  211. // start/continue countdown
  212. int count = _duel.countdown();
  213. if (count == 4)
  214. {
  215. // players need to be teleportet first
  216. // TODO: stadia manager needs a function to return an unused stadium for duels
  217. // currently only teleports to the same stadium
  218. _duel.teleportPlayers(-83760, -238825, -3331);
  219. // give players 20 seconds to complete teleport and get ready (its ought to be 30 on offical..)
  220. ThreadPoolManager.getInstance().scheduleGeneral(this, 20000);
  221. }
  222. else if (count > 0) // duel not started yet - continue countdown
  223. {
  224. ThreadPoolManager.getInstance().scheduleGeneral(this, 1000);
  225. }
  226. else
  227. {
  228. _duel.startDuel();
  229. }
  230. }
  231. catch (Exception e)
  232. {
  233. _log.log(Level.SEVERE, "", e);
  234. }
  235. }
  236. }
  237. public static class ScheduleEndDuelTask implements Runnable
  238. {
  239. private final Duel _duel;
  240. private final DuelResultEnum _result;
  241. public ScheduleEndDuelTask(Duel duel, DuelResultEnum result)
  242. {
  243. _duel = duel;
  244. _result = result;
  245. }
  246. @Override
  247. public void run()
  248. {
  249. try
  250. {
  251. _duel.endDuel(_result);
  252. }
  253. catch (Exception e)
  254. {
  255. _log.log(Level.SEVERE, "", e);
  256. }
  257. }
  258. }
  259. /**
  260. * Stops all players from attacking. Used for duel timeout / interrupt.
  261. */
  262. private void stopFighting()
  263. {
  264. ActionFailed af = ActionFailed.STATIC_PACKET;
  265. if (_partyDuel)
  266. {
  267. for (L2PcInstance temp : _playerA.getParty().getMembers())
  268. {
  269. temp.abortCast();
  270. temp.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
  271. temp.setTarget(null);
  272. temp.sendPacket(af);
  273. }
  274. for (L2PcInstance temp : _playerB.getParty().getMembers())
  275. {
  276. temp.abortCast();
  277. temp.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
  278. temp.setTarget(null);
  279. temp.sendPacket(af);
  280. }
  281. }
  282. else
  283. {
  284. _playerA.abortCast();
  285. _playerB.abortCast();
  286. _playerA.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
  287. _playerA.setTarget(null);
  288. _playerB.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
  289. _playerB.setTarget(null);
  290. _playerA.sendPacket(af);
  291. _playerB.sendPacket(af);
  292. }
  293. }
  294. /**
  295. * Check if a player engaged in pvp combat (only for 1on1 duels)
  296. * @param sendMessage
  297. * @return returns true if a duelist is engaged in Pvp combat
  298. */
  299. public boolean isDuelistInPvp(boolean sendMessage)
  300. {
  301. if (_partyDuel)
  302. {
  303. // Party duels take place in arenas - should be no other players there
  304. return false;
  305. }
  306. else if ((_playerA.getPvpFlag() != 0) || (_playerB.getPvpFlag() != 0))
  307. {
  308. if (sendMessage)
  309. {
  310. String engagedInPvP = "The duel was canceled because a duelist engaged in PvP combat.";
  311. _playerA.sendMessage(engagedInPvP);
  312. _playerB.sendMessage(engagedInPvP);
  313. }
  314. return true;
  315. }
  316. return false;
  317. }
  318. /**
  319. * Starts the duel
  320. */
  321. public void startDuel()
  322. {
  323. // Save player Conditions
  324. savePlayerConditions();
  325. if ((_playerA == null) || (_playerB == null) || _playerA.isInDuel() || _playerB.isInDuel())
  326. {
  327. // clean up
  328. _playerConditions.clear();
  329. _playerConditions = null;
  330. DuelManager.getInstance().removeDuel(this);
  331. return;
  332. }
  333. if (_partyDuel)
  334. {
  335. // set isInDuel() state
  336. // cancel all active trades, just in case? xD
  337. for (L2PcInstance temp : _playerA.getParty().getMembers())
  338. {
  339. temp.cancelActiveTrade();
  340. temp.setIsInDuel(_duelId);
  341. temp.setTeam(1);
  342. temp.broadcastUserInfo();
  343. broadcastToTeam2(new ExDuelUpdateUserInfo(temp));
  344. }
  345. for (L2PcInstance temp : _playerB.getParty().getMembers())
  346. {
  347. temp.cancelActiveTrade();
  348. temp.setIsInDuel(_duelId);
  349. temp.setTeam(2);
  350. temp.broadcastUserInfo();
  351. broadcastToTeam1(new ExDuelUpdateUserInfo(temp));
  352. }
  353. // Send duel Start packets
  354. ExDuelReady ready = new ExDuelReady(1);
  355. ExDuelStart start = new ExDuelStart(1);
  356. broadcastToTeam1(ready);
  357. broadcastToTeam2(ready);
  358. broadcastToTeam1(start);
  359. broadcastToTeam2(start);
  360. }
  361. else
  362. {
  363. // set isInDuel() state
  364. _playerA.setIsInDuel(_duelId);
  365. _playerA.setTeam(1);
  366. _playerB.setIsInDuel(_duelId);
  367. _playerB.setTeam(2);
  368. // Send duel Start packets
  369. ExDuelReady ready = new ExDuelReady(0);
  370. ExDuelStart start = new ExDuelStart(0);
  371. broadcastToTeam1(ready);
  372. broadcastToTeam2(ready);
  373. broadcastToTeam1(start);
  374. broadcastToTeam2(start);
  375. broadcastToTeam1(new ExDuelUpdateUserInfo(_playerB));
  376. broadcastToTeam2(new ExDuelUpdateUserInfo(_playerA));
  377. _playerA.broadcastUserInfo();
  378. _playerB.broadcastUserInfo();
  379. }
  380. // play sound
  381. PlaySound ps = new PlaySound(1, "B04_S01", 0, 0, 0, 0, 0);
  382. broadcastToTeam1(ps);
  383. broadcastToTeam2(ps);
  384. // start duelling task
  385. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleDuelTask(this), 1000);
  386. }
  387. /**
  388. * Save the current player condition: hp, mp, cp, location
  389. */
  390. public void savePlayerConditions()
  391. {
  392. if (_partyDuel)
  393. {
  394. for (L2PcInstance temp : _playerA.getParty().getMembers())
  395. {
  396. _playerConditions.add(new PlayerCondition(temp, _partyDuel));
  397. }
  398. for (L2PcInstance temp : _playerB.getParty().getMembers())
  399. {
  400. _playerConditions.add(new PlayerCondition(temp, _partyDuel));
  401. }
  402. }
  403. else
  404. {
  405. _playerConditions.add(new PlayerCondition(_playerA, _partyDuel));
  406. _playerConditions.add(new PlayerCondition(_playerB, _partyDuel));
  407. }
  408. }
  409. /**
  410. * Restore player conditions
  411. * @param abnormalDuelEnd true if the duel was the duel canceled
  412. */
  413. public void restorePlayerConditions(boolean abnormalDuelEnd)
  414. {
  415. // update isInDuel() state for all players
  416. if (_partyDuel)
  417. {
  418. for (L2PcInstance temp : _playerA.getParty().getMembers())
  419. {
  420. temp.setIsInDuel(0);
  421. temp.setTeam(0);
  422. temp.broadcastUserInfo();
  423. }
  424. for (L2PcInstance temp : _playerB.getParty().getMembers())
  425. {
  426. temp.setIsInDuel(0);
  427. temp.setTeam(0);
  428. temp.broadcastUserInfo();
  429. }
  430. }
  431. else
  432. {
  433. _playerA.setIsInDuel(0);
  434. _playerA.setTeam(0);
  435. _playerA.broadcastUserInfo();
  436. _playerB.setIsInDuel(0);
  437. _playerB.setTeam(0);
  438. _playerB.broadcastUserInfo();
  439. }
  440. // if it is an abnormal DuelEnd do not restore hp, mp, cp
  441. if (abnormalDuelEnd)
  442. {
  443. return;
  444. }
  445. // restore player conditions
  446. for (FastList.Node<PlayerCondition> e = _playerConditions.head(), end = _playerConditions.tail(); (e = e.getNext()) != end;)
  447. {
  448. e.getValue().restoreCondition();
  449. }
  450. }
  451. /**
  452. * Get the duel id
  453. * @return id
  454. */
  455. public int getId()
  456. {
  457. return _duelId;
  458. }
  459. /**
  460. * Returns the remaining time
  461. * @return remaining time
  462. */
  463. public int getRemainingTime()
  464. {
  465. return (int) (_duelEndTime.getTimeInMillis() - Calendar.getInstance().getTimeInMillis());
  466. }
  467. /**
  468. * Get the player that requested the duel
  469. * @return duel requester
  470. */
  471. public L2PcInstance getPlayerA()
  472. {
  473. return _playerA;
  474. }
  475. /**
  476. * Get the player that was challenged
  477. * @return challenged player
  478. */
  479. public L2PcInstance getPlayerB()
  480. {
  481. return _playerB;
  482. }
  483. /**
  484. * Returns whether this is a party duel or not
  485. * @return is party duel
  486. */
  487. public boolean isPartyDuel()
  488. {
  489. return _partyDuel;
  490. }
  491. public void setFinished(boolean mode)
  492. {
  493. _finished = mode;
  494. }
  495. public boolean getFinished()
  496. {
  497. return _finished;
  498. }
  499. /**
  500. * teleport all players to the given coordinates
  501. * @param x
  502. * @param y
  503. * @param z
  504. */
  505. public void teleportPlayers(int x, int y, int z)
  506. {
  507. // TODO: adjust the values if needed... or implement something better (especially using more then 1 arena)
  508. if (!_partyDuel)
  509. {
  510. return;
  511. }
  512. int offset = 0;
  513. for (L2PcInstance temp : _playerA.getParty().getMembers())
  514. {
  515. temp.teleToLocation((x + offset) - 180, y - 150, z);
  516. offset += 40;
  517. }
  518. offset = 0;
  519. for (L2PcInstance temp : _playerB.getParty().getMembers())
  520. {
  521. temp.teleToLocation((x + offset) - 180, y + 150, z);
  522. offset += 40;
  523. }
  524. }
  525. /**
  526. * Broadcast a packet to the challenger team
  527. * @param packet
  528. */
  529. public void broadcastToTeam1(L2GameServerPacket packet)
  530. {
  531. if (_playerA == null)
  532. {
  533. return;
  534. }
  535. if (_partyDuel && (_playerA.getParty() != null))
  536. {
  537. for (L2PcInstance temp : _playerA.getParty().getMembers())
  538. {
  539. temp.sendPacket(packet);
  540. }
  541. }
  542. else
  543. {
  544. _playerA.sendPacket(packet);
  545. }
  546. }
  547. /**
  548. * Broadcast a packet to the challenged team
  549. * @param packet
  550. */
  551. public void broadcastToTeam2(L2GameServerPacket packet)
  552. {
  553. if (_playerB == null)
  554. {
  555. return;
  556. }
  557. if (_partyDuel && (_playerB.getParty() != null))
  558. {
  559. for (L2PcInstance temp : _playerB.getParty().getMembers())
  560. {
  561. temp.sendPacket(packet);
  562. }
  563. }
  564. else
  565. {
  566. _playerB.sendPacket(packet);
  567. }
  568. }
  569. /**
  570. * Get the duel winner
  571. * @return winner
  572. */
  573. public L2PcInstance getWinner()
  574. {
  575. if (!getFinished() || (_playerA == null) || (_playerB == null))
  576. {
  577. return null;
  578. }
  579. if (_playerA.getDuelState() == DUELSTATE_WINNER)
  580. {
  581. return _playerA;
  582. }
  583. if (_playerB.getDuelState() == DUELSTATE_WINNER)
  584. {
  585. return _playerB;
  586. }
  587. return null;
  588. }
  589. /**
  590. * Get the duel looser
  591. * @return looser
  592. */
  593. public L2PcInstance getLooser()
  594. {
  595. if (!getFinished() || (_playerA == null) || (_playerB == null))
  596. {
  597. return null;
  598. }
  599. if (_playerA.getDuelState() == DUELSTATE_WINNER)
  600. {
  601. return _playerB;
  602. }
  603. else if (_playerB.getDuelState() == DUELSTATE_WINNER)
  604. {
  605. return _playerA;
  606. }
  607. return null;
  608. }
  609. /**
  610. * Playback the bow animation for all loosers
  611. */
  612. public void playKneelAnimation()
  613. {
  614. L2PcInstance looser = getLooser();
  615. if (looser == null)
  616. {
  617. return;
  618. }
  619. if (_partyDuel && (looser.getParty() != null))
  620. {
  621. for (L2PcInstance temp : looser.getParty().getMembers())
  622. {
  623. temp.broadcastPacket(new SocialAction(temp.getObjectId(), 7));
  624. }
  625. }
  626. else
  627. {
  628. looser.broadcastPacket(new SocialAction(looser.getObjectId(), 7));
  629. }
  630. }
  631. /**
  632. * Do the countdown and send message to players if necessary
  633. * @return current count
  634. */
  635. public int countdown()
  636. {
  637. _countdown--;
  638. if (_countdown > 3)
  639. {
  640. return _countdown;
  641. }
  642. // Broadcast countdown to duelists
  643. SystemMessage sm = null;
  644. if (_countdown > 0)
  645. {
  646. sm = SystemMessage.getSystemMessage(SystemMessageId.THE_DUEL_WILL_BEGIN_IN_S1_SECONDS);
  647. sm.addNumber(_countdown);
  648. }
  649. else
  650. {
  651. sm = SystemMessage.getSystemMessage(SystemMessageId.LET_THE_DUEL_BEGIN);
  652. }
  653. broadcastToTeam1(sm);
  654. broadcastToTeam2(sm);
  655. return _countdown;
  656. }
  657. /**
  658. * The duel has reached a state in which it can no longer continue
  659. * @param result the duel result.
  660. */
  661. public void endDuel(DuelResultEnum result)
  662. {
  663. if ((_playerA == null) || (_playerB == null))
  664. {
  665. // clean up
  666. _playerConditions.clear();
  667. _playerConditions = null;
  668. DuelManager.getInstance().removeDuel(this);
  669. return;
  670. }
  671. // inform players of the result
  672. SystemMessage sm = null;
  673. switch (result)
  674. {
  675. case Team1Win:
  676. case Team2Surrender:
  677. restorePlayerConditions(false);
  678. // send SystemMessage
  679. if (_partyDuel)
  680. {
  681. sm = SystemMessage.getSystemMessage(SystemMessageId.C1_PARTY_HAS_WON_THE_DUEL);
  682. }
  683. else
  684. {
  685. sm = SystemMessage.getSystemMessage(SystemMessageId.C1_HAS_WON_THE_DUEL);
  686. }
  687. sm.addString(_playerA.getName());
  688. broadcastToTeam1(sm);
  689. broadcastToTeam2(sm);
  690. break;
  691. case Team1Surrender:
  692. case Team2Win:
  693. restorePlayerConditions(false);
  694. // send SystemMessage
  695. if (_partyDuel)
  696. {
  697. sm = SystemMessage.getSystemMessage(SystemMessageId.C1_PARTY_HAS_WON_THE_DUEL);
  698. }
  699. else
  700. {
  701. sm = SystemMessage.getSystemMessage(SystemMessageId.C1_HAS_WON_THE_DUEL);
  702. }
  703. sm.addString(_playerB.getName());
  704. broadcastToTeam1(sm);
  705. broadcastToTeam2(sm);
  706. break;
  707. case Canceled:
  708. stopFighting();
  709. // dont restore hp, mp, cp
  710. restorePlayerConditions(true);
  711. // TODO: is there no other message for a canceled duel?
  712. // send SystemMessage
  713. sm = SystemMessage.getSystemMessage(SystemMessageId.THE_DUEL_HAS_ENDED_IN_A_TIE);
  714. broadcastToTeam1(sm);
  715. broadcastToTeam2(sm);
  716. break;
  717. case Timeout:
  718. stopFighting();
  719. // hp,mp,cp seem to be restored in a timeout too...
  720. restorePlayerConditions(false);
  721. // send SystemMessage
  722. sm = SystemMessage.getSystemMessage(SystemMessageId.THE_DUEL_HAS_ENDED_IN_A_TIE);
  723. broadcastToTeam1(sm);
  724. broadcastToTeam2(sm);
  725. break;
  726. }
  727. // Send end duel packet
  728. ExDuelEnd duelEnd = null;
  729. if (_partyDuel)
  730. {
  731. duelEnd = new ExDuelEnd(1);
  732. }
  733. else
  734. {
  735. duelEnd = new ExDuelEnd(0);
  736. }
  737. broadcastToTeam1(duelEnd);
  738. broadcastToTeam2(duelEnd);
  739. // clean up
  740. _playerConditions.clear();
  741. _playerConditions = null;
  742. DuelManager.getInstance().removeDuel(this);
  743. }
  744. /**
  745. * Did a situation occur in which the duel has to be ended?
  746. * @return DuelResultEnum duel status
  747. */
  748. public DuelResultEnum checkEndDuelCondition()
  749. {
  750. // one of the players might leave during duel
  751. if ((_playerA == null) || (_playerB == null))
  752. {
  753. return DuelResultEnum.Canceled;
  754. }
  755. // got a duel surrender request?
  756. if (_surrenderRequest != 0)
  757. {
  758. if (_surrenderRequest == 1)
  759. {
  760. return DuelResultEnum.Team1Surrender;
  761. }
  762. return DuelResultEnum.Team2Surrender;
  763. }
  764. // duel timed out
  765. else if (getRemainingTime() <= 0)
  766. {
  767. return DuelResultEnum.Timeout;
  768. }
  769. // Has a player been declared winner yet?
  770. else if (_playerA.getDuelState() == DUELSTATE_WINNER)
  771. {
  772. // If there is a Winner already there should be no more fighting going on
  773. stopFighting();
  774. return DuelResultEnum.Team1Win;
  775. }
  776. else if (_playerB.getDuelState() == DUELSTATE_WINNER)
  777. {
  778. // If there is a Winner already there should be no more fighting going on
  779. stopFighting();
  780. return DuelResultEnum.Team2Win;
  781. }
  782. // More end duel conditions for 1on1 duels
  783. else if (!_partyDuel)
  784. {
  785. // Duel was interrupted e.g.: player was attacked by mobs / other players
  786. if ((_playerA.getDuelState() == DUELSTATE_INTERRUPTED) || (_playerB.getDuelState() == DUELSTATE_INTERRUPTED))
  787. {
  788. return DuelResultEnum.Canceled;
  789. }
  790. // Are the players too far apart?
  791. if (!_playerA.isInsideRadius(_playerB, 1600, false, false))
  792. {
  793. return DuelResultEnum.Canceled;
  794. }
  795. // Did one of the players engage in PvP combat?
  796. if (isDuelistInPvp(true))
  797. {
  798. return DuelResultEnum.Canceled;
  799. }
  800. // is one of the players in a Siege, Peace or PvP zone?
  801. if (_playerA.isInsideZone(L2Character.ZONE_PEACE) || _playerB.isInsideZone(L2Character.ZONE_PEACE) || _playerA.isInsideZone(L2Character.ZONE_SIEGE) || _playerB.isInsideZone(L2Character.ZONE_SIEGE) || _playerA.isInsideZone(L2Character.ZONE_PVP) || _playerB.isInsideZone(L2Character.ZONE_PVP))
  802. {
  803. return DuelResultEnum.Canceled;
  804. }
  805. }
  806. return DuelResultEnum.Continue;
  807. }
  808. /**
  809. * Register a surrender request
  810. * @param player the player that surrenders.
  811. */
  812. public void doSurrender(L2PcInstance player)
  813. {
  814. // already recived a surrender request
  815. if (_surrenderRequest != 0)
  816. {
  817. return;
  818. }
  819. // stop the fight
  820. stopFighting();
  821. // TODO: Can every party member cancel a party duel? or only the party leaders?
  822. if (_partyDuel)
  823. {
  824. if (_playerA.getParty().getMembers().contains(player))
  825. {
  826. _surrenderRequest = 1;
  827. for (L2PcInstance temp : _playerA.getParty().getMembers())
  828. {
  829. temp.setDuelState(DUELSTATE_DEAD);
  830. }
  831. for (L2PcInstance temp : _playerB.getParty().getMembers())
  832. {
  833. temp.setDuelState(DUELSTATE_WINNER);
  834. }
  835. }
  836. else if (_playerB.getParty().getMembers().contains(player))
  837. {
  838. _surrenderRequest = 2;
  839. for (L2PcInstance temp : _playerB.getParty().getMembers())
  840. {
  841. temp.setDuelState(DUELSTATE_DEAD);
  842. }
  843. for (L2PcInstance temp : _playerA.getParty().getMembers())
  844. {
  845. temp.setDuelState(DUELSTATE_WINNER);
  846. }
  847. }
  848. }
  849. else
  850. {
  851. if (player == _playerA)
  852. {
  853. _surrenderRequest = 1;
  854. _playerA.setDuelState(DUELSTATE_DEAD);
  855. _playerB.setDuelState(DUELSTATE_WINNER);
  856. }
  857. else if (player == _playerB)
  858. {
  859. _surrenderRequest = 2;
  860. _playerB.setDuelState(DUELSTATE_DEAD);
  861. _playerA.setDuelState(DUELSTATE_WINNER);
  862. }
  863. }
  864. }
  865. /**
  866. * This function is called whenever a player was defeated in a duel
  867. * @param player the player defeated.
  868. */
  869. public void onPlayerDefeat(L2PcInstance player)
  870. {
  871. // Set player as defeated
  872. player.setDuelState(DUELSTATE_DEAD);
  873. if (_partyDuel)
  874. {
  875. boolean teamdefeated = true;
  876. for (L2PcInstance temp : player.getParty().getMembers())
  877. {
  878. if (temp.getDuelState() == DUELSTATE_DUELLING)
  879. {
  880. teamdefeated = false;
  881. break;
  882. }
  883. }
  884. if (teamdefeated)
  885. {
  886. L2PcInstance winner = _playerA;
  887. if (_playerA.getParty().getMembers().contains(player))
  888. {
  889. winner = _playerB;
  890. }
  891. for (L2PcInstance temp : winner.getParty().getMembers())
  892. {
  893. temp.setDuelState(DUELSTATE_WINNER);
  894. }
  895. }
  896. }
  897. else
  898. {
  899. if ((player != _playerA) && (player != _playerB))
  900. {
  901. _log.warning("Error in onPlayerDefeat(): player is not part of this 1vs1 duel");
  902. }
  903. if (_playerA == player)
  904. {
  905. _playerB.setDuelState(DUELSTATE_WINNER);
  906. }
  907. else
  908. {
  909. _playerA.setDuelState(DUELSTATE_WINNER);
  910. }
  911. }
  912. }
  913. /**
  914. * This function is called whenever a player leaves a party
  915. * @param player the player quitting.
  916. */
  917. public void onRemoveFromParty(L2PcInstance player)
  918. {
  919. // if it isnt a party duel ignore this
  920. if (!_partyDuel)
  921. {
  922. return;
  923. }
  924. // this player is leaving his party during party duel
  925. // if hes either playerA or playerB cancel the duel and port the players back
  926. if ((player == _playerA) || (player == _playerB))
  927. {
  928. for (FastList.Node<PlayerCondition> e = _playerConditions.head(), end = _playerConditions.tail(); (e = e.getNext()) != end;)
  929. {
  930. e.getValue().teleportBack();
  931. e.getValue().getPlayer().setIsInDuel(0);
  932. }
  933. _playerA = null;
  934. _playerB = null;
  935. }
  936. else
  937. // teleport the player back & delete his PlayerCondition record
  938. {
  939. for (FastList.Node<PlayerCondition> e = _playerConditions.head(), end = _playerConditions.tail(); (e = e.getNext()) != end;)
  940. {
  941. if (e.getValue().getPlayer() == player)
  942. {
  943. e.getValue().teleportBack();
  944. _playerConditions.remove(e.getValue());
  945. break;
  946. }
  947. }
  948. player.setIsInDuel(0);
  949. }
  950. }
  951. public void onBuff(L2PcInstance player, L2Effect debuff)
  952. {
  953. for (FastList.Node<PlayerCondition> e = _playerConditions.head(), end = _playerConditions.tail(); (e = e.getNext()) != end;)
  954. {
  955. if (e.getValue().getPlayer() == player)
  956. {
  957. e.getValue().registerDebuff(debuff);
  958. return;
  959. }
  960. }
  961. }
  962. }