Duel.java 25 KB

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