Duel.java 25 KB

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