Duel.java 25 KB

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