Duel.java 25 KB

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