Advertisement
TheMustaine

package org.l2jmobius.gameserver.model;

May 10th, 2022
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 24.74 KB | None | 0 0
  1. * This file is part of the L2J Mobius project.
  2. *
  3. * This program is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 3 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. * General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. package org.l2jmobius.gameserver.model;
  17.  
  18. import java.util.ArrayList;
  19. import java.util.List;
  20. import java.util.NoSuchElementException;
  21. import java.util.concurrent.Future;
  22.  
  23. import org.l2jmobius.Config;
  24. import org.l2jmobius.commons.threads.ThreadPool;
  25. import org.l2jmobius.commons.util.Rnd;
  26. import org.l2jmobius.gameserver.data.ItemTable;
  27. import org.l2jmobius.gameserver.instancemanager.DuelManager;
  28. import org.l2jmobius.gameserver.model.actor.Attackable;
  29. import org.l2jmobius.gameserver.model.actor.Creature;
  30. import org.l2jmobius.gameserver.model.actor.Playable;
  31. import org.l2jmobius.gameserver.model.actor.Player;
  32. import org.l2jmobius.gameserver.model.actor.instance.Pet;
  33. import org.l2jmobius.gameserver.model.actor.instance.Servitor;
  34. import org.l2jmobius.gameserver.model.holders.ItemHolder;
  35. import org.l2jmobius.gameserver.model.item.instance.Item;
  36. import org.l2jmobius.gameserver.model.partymatching.PartyMatchRoom;
  37. import org.l2jmobius.gameserver.model.partymatching.PartyMatchRoomList;
  38. import org.l2jmobius.gameserver.model.sevensigns.SevenSignsFestival;
  39. import org.l2jmobius.gameserver.model.skill.Stat;
  40. import org.l2jmobius.gameserver.network.SystemMessageId;
  41. import org.l2jmobius.gameserver.network.serverpackets.CreatureSay;
  42. import org.l2jmobius.gameserver.network.serverpackets.ExCloseMPCC;
  43. import org.l2jmobius.gameserver.network.serverpackets.ExOpenMPCC;
  44. import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
  45. import org.l2jmobius.gameserver.network.serverpackets.PartyMemberPosition;
  46. import org.l2jmobius.gameserver.network.serverpackets.PartySmallWindowAdd;
  47. import org.l2jmobius.gameserver.network.serverpackets.PartySmallWindowAll;
  48. import org.l2jmobius.gameserver.network.serverpackets.PartySmallWindowDelete;
  49. import org.l2jmobius.gameserver.network.serverpackets.PartySmallWindowDeleteAll;
  50. import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
  51. import org.l2jmobius.gameserver.taskmanager.GameTimeTaskManager;
  52. import org.l2jmobius.gameserver.util.Util;
  53.  
  54. /**
  55. * @author nuocnam
  56. * @version $Revision: 1.6.2.2.2.6 $ $Date: 2005/04/11 19:12:16 $
  57. */
  58. public class Party
  59. {
  60. private static final double[] BONUS_EXP_SP =
  61. {
  62. 1,
  63. 1.30,
  64. 1.39,
  65. 1.50,
  66. 1.54,
  67. 1.58,
  68. 1.63,
  69. 1.67,
  70. 1.71
  71. };
  72.  
  73. private static final int PARTY_POSITION_BROADCAST = 10000;
  74.  
  75. public static final int ITEM_LOOTER = 0;
  76. public static final int ITEM_RANDOM = 1;
  77. public static final int ITEM_RANDOM_SPOIL = 2;
  78. public static final int ITEM_ORDER = 3;
  79. public static final int ITEM_ORDER_SPOIL = 4;
  80.  
  81. private final List<Player> _members;
  82. private boolean _pendingInvitation = false;
  83. private long _pendingInviteTimeout;
  84. private int _partyLvl = 0;
  85. private int _itemDistribution = 0;
  86. private int _itemLastLoot = 0;
  87.  
  88. private CommandChannel _commandChannel = null;
  89. private DimensionalRift _dr;
  90.  
  91. private Future<?> _positionBroadcastTask = null;
  92. protected PartyMemberPosition _positionPacket;
  93.  
  94. /**
  95. * constructor ensures party has always one member - leader
  96. * @param leader
  97. * @param itemDistribution
  98. */
  99. public Party(Player leader, int itemDistribution)
  100. {
  101. _members = new ArrayList<>();
  102. _itemDistribution = itemDistribution;
  103. _members.add(leader);
  104. _partyLvl = leader.getLevel();
  105. }
  106.  
  107. /**
  108. * returns number of party members
  109. * @return
  110. */
  111. public int getMemberCount()
  112. {
  113. return _members.size();
  114. }
  115.  
  116. /**
  117. * Check if another player can start invitation process
  118. * @return boolean if party waits for invitation respond
  119. */
  120. public boolean getPendingInvitation()
  121. {
  122. return _pendingInvitation;
  123. }
  124.  
  125. /**
  126. * set invitation process flag and store time for expiration happens when: player join party or player decline to join
  127. * @param value
  128. */
  129. public void setPendingInvitation(boolean value)
  130. {
  131. _pendingInvitation = value;
  132. _pendingInviteTimeout = GameTimeTaskManager.getGameTicks() + (Player.REQUEST_TIMEOUT * GameTimeTaskManager.TICKS_PER_SECOND);
  133. }
  134.  
  135. /**
  136. * Check if player invitation is expired
  137. * @return boolean if time is expired
  138. * @see org.l2jmobius.gameserver.model.actor.Player#isRequestExpired()
  139. */
  140. public boolean isInvitationRequestExpired()
  141. {
  142. return (_pendingInviteTimeout <= GameTimeTaskManager.getGameTicks());
  143. }
  144.  
  145. /**
  146. * returns all party members
  147. * @return
  148. */
  149. public List<Player> getPartyMembers()
  150. {
  151. return _members;
  152. }
  153.  
  154. /**
  155. * get random member from party
  156. * @param itemId
  157. * @param target
  158. * @return
  159. */
  160. private Player getCheckedRandomMember(int itemId, Creature target)
  161. {
  162. final List<Player> availableMembers = new ArrayList<>();
  163. for (Player member : _members)
  164. {
  165. if (member.getInventory().validateCapacityByItemId(itemId) && Util.checkIfInRange(Config.ALT_PARTY_RANGE, target, member, true))
  166. {
  167. availableMembers.add(member);
  168. }
  169. }
  170.  
  171. if (!availableMembers.isEmpty())
  172. {
  173. return availableMembers.get(Rnd.get(availableMembers.size()));
  174. }
  175. return null;
  176. }
  177.  
  178. /**
  179. * get next item looter
  180. * @param itemId
  181. * @param target
  182. * @return
  183. */
  184. private Player getCheckedNextLooter(int itemId, Creature target)
  185. {
  186. for (@SuppressWarnings("unused")
  187. Player member : _members)
  188. {
  189. if (++_itemLastLoot >= _members.size())
  190. {
  191. _itemLastLoot = 0;
  192. }
  193.  
  194. Player player;
  195. try
  196. {
  197. player = _members.get(_itemLastLoot);
  198. if (player.getInventory().validateCapacityByItemId(itemId) && Util.checkIfInRange(Config.ALT_PARTY_RANGE, target, player, true))
  199. {
  200. return player;
  201. }
  202. }
  203. catch (Exception e)
  204. {
  205. // continue, take another member if this just logged off
  206. }
  207. }
  208.  
  209. return null;
  210. }
  211.  
  212. /**
  213. * get next item looter
  214. * @param player
  215. * @param itemId
  216. * @param spoil
  217. * @param target
  218. * @return
  219. */
  220. private Player getActualLooter(Player player, int itemId, boolean spoil, Creature target)
  221. {
  222. Player looter = player;
  223.  
  224. switch (_itemDistribution)
  225. {
  226. case ITEM_RANDOM:
  227. {
  228. if (!spoil)
  229. {
  230. looter = getCheckedRandomMember(itemId, target);
  231. }
  232. break;
  233. }
  234. case ITEM_RANDOM_SPOIL:
  235. {
  236. looter = getCheckedRandomMember(itemId, target);
  237. break;
  238. }
  239. case ITEM_ORDER:
  240. {
  241. if (!spoil)
  242. {
  243. looter = getCheckedNextLooter(itemId, target);
  244. }
  245. break;
  246. }
  247. case ITEM_ORDER_SPOIL:
  248. {
  249. looter = getCheckedNextLooter(itemId, target);
  250. break;
  251. }
  252. }
  253.  
  254. if (looter == null)
  255. {
  256. looter = player;
  257. }
  258.  
  259. return looter;
  260. }
  261.  
  262. /**
  263. * true if player is party leader
  264. * @param player
  265. * @return
  266. */
  267. public boolean isLeader(Player player)
  268. {
  269. return getLeader().equals(player);
  270. }
  271.  
  272. /**
  273. * Returns the Object ID for the party leader to be used as a unique identifier of this party
  274. * @return int
  275. */
  276. public int getPartyLeaderOID()
  277. {
  278. return getLeader().getObjectId();
  279. }
  280.  
  281. /**
  282. * Broadcasts packet to every party member
  283. * @param msg
  284. */
  285. public void broadcastToPartyMembers(IClientOutgoingPacket msg)
  286. {
  287. for (Player member : _members)
  288. {
  289. if (member != null)
  290. {
  291. member.sendPacket(msg);
  292. }
  293. }
  294. }
  295.  
  296. public void broadcastToPartyMembersNewLeader()
  297. {
  298. for (Player member : _members)
  299. {
  300. if (member != null)
  301. {
  302. member.sendPacket(new PartySmallWindowDeleteAll());
  303. member.sendPacket(new PartySmallWindowAll(member, this));
  304. member.broadcastUserInfo();
  305. }
  306. }
  307. }
  308.  
  309. public void broadcastCSToPartyMembers(CreatureSay msg, Player broadcaster)
  310. {
  311. for (Player member : _members)
  312. {
  313. if ((member == null) || (broadcaster == null))
  314. {
  315. continue;
  316. }
  317.  
  318. final boolean blocked = member.getBlockList().isInBlockList(broadcaster);
  319. if (!blocked)
  320. {
  321. member.sendPacket(msg);
  322. }
  323. }
  324. }
  325.  
  326. /**
  327. * Send a Server->Client packet to all other Player of the Party.
  328. * @param player
  329. * @param msg
  330. */
  331. public void broadcastToPartyMembers(Player player, IClientOutgoingPacket msg)
  332. {
  333. for (Player member : _members)
  334. {
  335. if ((member != null) && !member.equals(player))
  336. {
  337. member.sendPacket(msg);
  338. }
  339. }
  340. }
  341.  
  342. /**
  343. * adds new member to party
  344. * @param player
  345. */
  346. public synchronized void addPartyMember(Player player)
  347. {
  348. if (_members.contains(player))
  349. {
  350. return;
  351. }
  352.  
  353. // sends new member party window for all members
  354. player.sendPacket(new PartySmallWindowAll(player, this));
  355. SystemMessage msg = new SystemMessage(SystemMessageId.YOU_HAVE_JOINED_S1_S_PARTY);
  356. msg.addString(getLeader().getName());
  357. player.sendPacket(msg);
  358.  
  359. msg = new SystemMessage(SystemMessageId.S1_HAS_JOINED_THE_PARTY);
  360. msg.addString(player.getName());
  361. broadcastToPartyMembers(msg);
  362. broadcastToPartyMembers(new PartySmallWindowAdd(player, this));
  363. for (Player member : _members)
  364. {
  365. player.sendPacket(new PartySmallWindowAdd(member, this));
  366. }
  367.  
  368. // add player to party, adjust party level
  369. _members.add(player);
  370. if (player.getLevel() > _partyLvl)
  371. {
  372. _partyLvl = player.getLevel();
  373. }
  374.  
  375. for (Player member : _members)
  376. {
  377. player.sendPacket(new PartySmallWindowAdd(member, this));
  378. }
  379.  
  380. // update partySpelled
  381. for (Player member : _members)
  382. {
  383. if (member != null)
  384. {
  385. member.updateEffectIcons(true); // update party icons only
  386. member.broadcastUserInfo();
  387. }
  388. }
  389.  
  390. if (isInDimensionalRift())
  391. {
  392. _dr.partyMemberInvited();
  393. }
  394.  
  395. // open the CCInformationwindow
  396. if (isInCommandChannel())
  397. {
  398. player.sendPacket(new ExOpenMPCC());
  399. }
  400.  
  401. // activate position task
  402. if (_positionBroadcastTask == null)
  403. {
  404. _positionBroadcastTask = ThreadPool.scheduleAtFixedRate(new PositionBroadcast(), PARTY_POSITION_BROADCAST / 2, PARTY_POSITION_BROADCAST);
  405. }
  406. }
  407.  
  408. /**
  409. * Remove player from party Overloaded method that takes player's name as parameter
  410. * @param name
  411. */
  412. public void removePartyMember(String name)
  413. {
  414. final Player player = getPlayerByName(name);
  415. if (player != null)
  416. {
  417. removePartyMember(player);
  418. }
  419. }
  420.  
  421. /**
  422. * Remove player from party
  423. * @param player
  424. */
  425. public void removePartyMember(Player player)
  426. {
  427. removePartyMember(player, true);
  428. }
  429.  
  430. public synchronized void removePartyMember(Player player, boolean sendMessage)
  431. {
  432. if (_members.contains(player))
  433. {
  434. final boolean isLeader = isLeader(player);
  435. _members.remove(player);
  436. recalculatePartyLevel();
  437.  
  438. if (player.isFestivalParticipant())
  439. {
  440. SevenSignsFestival.getInstance().updateParticipants(player, this);
  441. }
  442.  
  443. if (player.isInDuel())
  444. {
  445. DuelManager.getInstance().onRemoveFromParty(player);
  446. }
  447.  
  448. if (sendMessage)
  449. {
  450. player.sendPacket(SystemMessageId.YOU_HAVE_WITHDRAWN_FROM_THE_PARTY);
  451. final SystemMessage msg = new SystemMessage(SystemMessageId.S1_HAS_LEFT_THE_PARTY);
  452. msg.addString(player.getName());
  453. broadcastToPartyMembers(msg);
  454. }
  455.  
  456. player.sendPacket(new PartySmallWindowDeleteAll());
  457. player.setParty(null);
  458.  
  459. broadcastToPartyMembers(new PartySmallWindowDelete(player));
  460. if (isInDimensionalRift())
  461. {
  462. _dr.partyMemberExited(player);
  463. }
  464.  
  465. // Close the CCInfoWindow
  466. if (isInCommandChannel())
  467. {
  468. player.sendPacket(new ExCloseMPCC());
  469. }
  470.  
  471. if (isLeader && (_members.size() > 1))
  472. {
  473. final SystemMessage msg = new SystemMessage(SystemMessageId.S1_HAS_BECOME_THE_PARTY_LEADER);
  474. msg.addString(getLeader().getName());
  475. broadcastToPartyMembers(msg);
  476. broadcastToPartyMembersNewLeader();
  477. }
  478.  
  479. if (_members.size() == 1)
  480. {
  481. if (isInCommandChannel())
  482. {
  483. // delete the whole command channel when the party who opened the channel is disbanded
  484. if (_commandChannel.getChannelLeader().equals(getLeader()))
  485. {
  486. _commandChannel.disbandChannel();
  487. }
  488. else
  489. {
  490. _commandChannel.removeParty(this);
  491. }
  492. }
  493.  
  494. final Player leader = getLeader();
  495. if (leader != null)
  496. {
  497. leader.setParty(null);
  498. if (leader.isInDuel())
  499. {
  500. DuelManager.getInstance().onRemoveFromParty(leader);
  501. }
  502. }
  503.  
  504. if (_positionBroadcastTask != null)
  505. {
  506. _positionBroadcastTask.cancel(false);
  507. _positionBroadcastTask = null;
  508. }
  509. _members.clear();
  510. }
  511. }
  512. }
  513.  
  514. /**
  515. * Change party leader (used for string arguments)
  516. * @param name
  517. */
  518.  
  519. public void changePartyLeader(String name)
  520. {
  521. final Player player = getPlayerByName(name);
  522. if ((player != null) && !player.isInDuel())
  523. {
  524. if (_members.contains(player))
  525. {
  526. if (isLeader(player))
  527. {
  528. player.sendPacket(SystemMessageId.SLOW_DOWN_YOU_ARE_ALREADY_THE_PARTY_LEADER);
  529. }
  530. else
  531. {
  532. // Swap party members
  533. Player temp;
  534. final int p1 = _members.indexOf(player);
  535. temp = getLeader();
  536. _members.set(0, _members.get(p1));
  537. _members.set(p1, temp);
  538. SystemMessage msg = new SystemMessage(SystemMessageId.S1_HAS_BECOME_THE_PARTY_LEADER);
  539. msg.addString(getLeader().getName());
  540. broadcastToPartyMembers(msg);
  541. broadcastToPartyMembersNewLeader();
  542.  
  543. if (isInCommandChannel() && temp.equals(_commandChannel.getChannelLeader()))
  544. {
  545. _commandChannel.setChannelLeader(getLeader());
  546. msg = new SystemMessage(SystemMessageId.COMMAND_CHANNEL_AUTHORITY_HAS_BEEN_TRANSFERRED_TO_S1);
  547. msg.addString(_commandChannel.getChannelLeader().getName());
  548. _commandChannel.broadcastToChannelMembers(msg);
  549. }
  550.  
  551. if (player.isInPartyMatchRoom())
  552. {
  553. final PartyMatchRoom room = PartyMatchRoomList.getInstance().getPlayerRoom(player);
  554. room.changeLeader(player);
  555. }
  556. }
  557. }
  558. else
  559. {
  560. player.sendPacket(SystemMessageId.YOU_MAY_ONLY_TRANSFER_PARTY_LEADERSHIP_TO_ANOTHER_MEMBER_OF_THE_PARTY);
  561. }
  562. }
  563. }
  564.  
  565. /**
  566. * finds a player in the party by name
  567. * @param name
  568. * @return
  569. */
  570. private Player getPlayerByName(String name)
  571. {
  572. for (Player member : _members)
  573. {
  574. if (member.getName().equalsIgnoreCase(name))
  575. {
  576. return member;
  577. }
  578. }
  579. return null;
  580. }
  581.  
  582. /**
  583. * distribute item(s) to party members
  584. * @param player
  585. * @param item
  586. */
  587. public void distributeItem(Player player, Item item)
  588. {
  589. if (item.getItemId() == 57)
  590. {
  591. distributeAdena(player, item.getCount(), player);
  592. ItemTable.getInstance().destroyItem("Party", item, player, null);
  593. return;
  594. }
  595.  
  596. final Player target = getActualLooter(player, item.getItemId(), false, player);
  597. target.addItem("Party", item, player, true);
  598.  
  599. // Send messages to other party members about reward
  600. if (item.getCount() > 1)
  601. {
  602. final SystemMessage msg = new SystemMessage(SystemMessageId.S1_HAS_OBTAINED_S3_S2);
  603. msg.addString(target.getName());
  604. msg.addItemName(item.getItemId());
  605. msg.addNumber(item.getCount());
  606. broadcastToPartyMembers(target, msg);
  607. }
  608. else
  609. {
  610. final SystemMessage msg = new SystemMessage(SystemMessageId.S1_HAS_OBTAINED_S2);
  611. msg.addString(target.getName());
  612. msg.addItemName(item.getItemId());
  613. broadcastToPartyMembers(target, msg);
  614. }
  615. }
  616.  
  617. /**
  618. * distribute item(s) to party members
  619. * @param player
  620. * @param item
  621. * @param spoil
  622. * @param target
  623. */
  624. public void distributeItem(Player player, ItemHolder item, boolean spoil, Attackable target)
  625. {
  626. if (item == null)
  627. {
  628. return;
  629. }
  630.  
  631. if (item.getId() == 57)
  632. {
  633. distributeAdena(player, item.getCount(), target);
  634. return;
  635. }
  636.  
  637. final Player looter = getActualLooter(player, item.getId(), spoil, target);
  638. looter.addItem(spoil ? "Sweep" : "Party", item.getId(), item.getCount(), player, true);
  639.  
  640. // Send messages to other aprty members about reward
  641. if (item.getCount() > 1)
  642. {
  643. final SystemMessage msg = spoil ? new SystemMessage(SystemMessageId.S1_HAS_OBTAINED_S3_S2_BY_USING_SWEEPER) : new SystemMessage(SystemMessageId.S1_HAS_OBTAINED_S3_S2);
  644. msg.addString(looter.getName());
  645. msg.addItemName(item.getId());
  646. msg.addNumber(item.getCount());
  647. broadcastToPartyMembers(looter, msg);
  648. }
  649. else
  650. {
  651. final SystemMessage msg = spoil ? new SystemMessage(SystemMessageId.S1_HAS_OBTAINED_S2_BY_USING_SWEEPER) : new SystemMessage(SystemMessageId.S1_HAS_OBTAINED_S2);
  652. msg.addString(looter.getName());
  653. msg.addItemName(item.getId());
  654. broadcastToPartyMembers(looter, msg);
  655. }
  656. }
  657.  
  658. /**
  659. * distribute adena to party members
  660. * @param player
  661. * @param adena
  662. * @param target
  663. */
  664. public void distributeAdena(Player player, int adena, Creature target)
  665. {
  666. // Get all the party members
  667. final List<Player> membersList = _members;
  668.  
  669. // Check the number of party members that must be rewarded (The party member must be in range to receive its reward)
  670. final List<Player> rewarded = new ArrayList<>();
  671. for (Player member : membersList)
  672. {
  673. if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, target, member, true))
  674. {
  675. continue;
  676. }
  677. rewarded.add(member);
  678. }
  679.  
  680. // Avoid null exceptions, if any
  681. if (rewarded.isEmpty())
  682. {
  683. return;
  684. }
  685.  
  686. // Now we can actually distribute the adena reward (Total adena split by the number of party members that are in range and must be rewarded)
  687. final int count = adena / rewarded.size();
  688. for (Player member : rewarded)
  689. {
  690. member.addAdena("Party", count, player, true);
  691. }
  692. }
  693.  
  694. /**
  695. * Distribute Experience and SP rewards to Player Party members in the known area of the last attacker.<br>
  696. * <br>
  697. * <b><u>Actions</u>:</b><br>
  698. * <li>Get the Player owner of the Summon (if necessary)</li>
  699. * <li>Calculate the Experience and SP reward distribution rate</li>
  700. * <li>Add Experience and SP to the Player</li><br>
  701. * <font color=#FF0000><b><u>Caution</u>: This method DOESN'T GIVE rewards to Pet</b></font><br>
  702. * Exception are Pets that leech from the owner's XP; they get the exp indirectly, via the owner's exp gain
  703. * @param xpRewardValue The Experience reward to distribute
  704. * @param spRewardValue The SP reward to distribute
  705. * @param rewardedMembers The list of Player to reward
  706. * @param topLvl
  707. */
  708. public void distributeXpAndSp(long xpRewardValue, int spRewardValue, List<Playable> rewardedMembers, int topLvl)
  709. {
  710. Servitor summon = null;
  711. final List<Playable> validMembers = getValidMembers(rewardedMembers, topLvl);
  712. float penalty;
  713. double sqLevel;
  714. double preCalculation;
  715. int xpReward = (int) (xpRewardValue * getExpBonus(validMembers.size()));
  716. int spReward = (int) (spRewardValue * getSpBonus(validMembers.size()));
  717. double sqLevelSum = 0;
  718. for (Playable character : validMembers)
  719. {
  720. sqLevelSum += character.getLevel() * character.getLevel();
  721. }
  722.  
  723. // Go through the Players and Pets (not Summons) that must be rewarded
  724. synchronized (rewardedMembers)
  725. {
  726. for (Creature member : rewardedMembers)
  727. {
  728. if (member.isDead())
  729. {
  730. continue;
  731. }
  732.  
  733. penalty = 0;
  734.  
  735. // The Summon penalty
  736. if (member.getPet() instanceof Servitor)
  737. {
  738. summon = (Servitor) member.getPet();
  739. penalty = summon.getExpPenalty();
  740. }
  741.  
  742. // Pets that leech xp from the owner (like babypets) do not get rewarded directly
  743. if (member instanceof Pet)
  744. {
  745. if (((Pet) member).getPetData().getOwnerExpTaken() > 0)
  746. {
  747. continue;
  748. }
  749. // TODO: This is a temporary fix while correct pet xp in party is figured out
  750. penalty = (float) 0.85;
  751. }
  752.  
  753. // Calculate and add the EXP and SP reward to the member
  754. if (validMembers.contains(member))
  755. {
  756. sqLevel = member.getLevel() * member.getLevel();
  757. preCalculation = (sqLevel / sqLevelSum) * (1 - penalty);
  758.  
  759. // Add the XP/SP points to the requested party member
  760. if (!member.isDead())
  761. {
  762. member.addExpAndSp(Math.round(member.calcStat(Stat.EXPSP_RATE, xpReward * preCalculation, null, null)), (int) member.calcStat(Stat.EXPSP_RATE, spReward * preCalculation, null, null));
  763. }
  764. }
  765. else
  766. {
  767. member.addExpAndSp(0, 0);
  768. }
  769. }
  770. }
  771. }
  772.  
  773. /**
  774. * Calculates and gives final XP and SP rewards to the party member.<br>
  775. * This method takes in consideration number of members, members' levels, rewarder's level and bonus modifier for the actual party.
  776. * @param member is the Creature to be rewarded
  777. * @param xpReward is the total amount of XP to be "splited" and given to the member
  778. * @param spReward is the total amount of SP to be "splited" and given to the member
  779. * @param penalty is the penalty that must be applied to the XP rewards of the requested member
  780. */
  781.  
  782. /**
  783. * refresh party level
  784. */
  785. public void recalculatePartyLevel()
  786. {
  787. int newLevel = 0;
  788. for (Player member : _members)
  789. {
  790. if (member == null)
  791. {
  792. _members.remove(member);
  793. continue;
  794. }
  795.  
  796. if (member.getLevel() > newLevel)
  797. {
  798. newLevel = member.getLevel();
  799. }
  800. }
  801.  
  802. _partyLvl = newLevel;
  803. }
  804.  
  805. private List<Playable> getValidMembers(List<Playable> members, int topLvl)
  806. {
  807. final List<Playable> validMembers = new ArrayList<>();
  808.  
  809. // Fixed LevelDiff cutoff point
  810. if (Config.PARTY_XP_CUTOFF_METHOD.equalsIgnoreCase("level"))
  811. {
  812. for (Playable member : members)
  813. {
  814. if ((topLvl - member.getLevel()) <= Config.PARTY_XP_CUTOFF_LEVEL)
  815. {
  816. validMembers.add(member);
  817. }
  818. }
  819. }
  820. // Fixed MinPercentage cutoff point
  821. else if (Config.PARTY_XP_CUTOFF_METHOD.equalsIgnoreCase("percentage"))
  822. {
  823. int sqLevelSum = 0;
  824. for (Playable member : members)
  825. {
  826. sqLevelSum += member.getLevel() * member.getLevel();
  827. }
  828.  
  829. for (Playable member : members)
  830. {
  831. final int sqLevel = member.getLevel() * member.getLevel();
  832. if ((sqLevel * 100) >= (sqLevelSum * Config.PARTY_XP_CUTOFF_PERCENT))
  833. {
  834. validMembers.add(member);
  835. }
  836. }
  837. }
  838. // Automatic cutoff method
  839. else if (Config.PARTY_XP_CUTOFF_METHOD.equalsIgnoreCase("auto"))
  840. {
  841. int sqLevelSum = 0;
  842. for (Playable member : members)
  843. {
  844. sqLevelSum += member.getLevel() * member.getLevel();
  845. }
  846.  
  847. int i = members.size() - 1;
  848. if (i < 1)
  849. {
  850. return members;
  851. }
  852.  
  853. if (i >= BONUS_EXP_SP.length)
  854. {
  855. i = BONUS_EXP_SP.length - 1;
  856. }
  857.  
  858. for (Playable member : members)
  859. {
  860. final int sqLevel = member.getLevel() * member.getLevel();
  861. if (sqLevel >= (sqLevelSum * (1 - (1 / ((1 + BONUS_EXP_SP[i]) - BONUS_EXP_SP[i - 1])))))
  862. {
  863. validMembers.add(member);
  864. }
  865. }
  866. }
  867. return validMembers;
  868. }
  869.  
  870. private double getBaseExpSpBonus(int membersCount)
  871. {
  872. int i = membersCount - 1;
  873. if (i < 1)
  874. {
  875. return 1;
  876. }
  877.  
  878. if (i >= BONUS_EXP_SP.length)
  879. {
  880. i = BONUS_EXP_SP.length - 1;
  881. }
  882.  
  883. return BONUS_EXP_SP[i];
  884. }
  885.  
  886. private double getExpBonus(int membersCount)
  887. {
  888. if (membersCount < 2)
  889. {
  890. // not is a valid party
  891. return getBaseExpSpBonus(membersCount);
  892. }
  893. return getBaseExpSpBonus(membersCount) * Config.RATE_PARTY_XP;
  894. }
  895.  
  896. private double getSpBonus(int membersCount)
  897. {
  898. if (membersCount < 2)
  899. {
  900. // not is a valid party
  901. return getBaseExpSpBonus(membersCount);
  902. }
  903. return getBaseExpSpBonus(membersCount) * Config.RATE_PARTY_SP;
  904. }
  905.  
  906. public int getLevel()
  907. {
  908. return _partyLvl;
  909. }
  910.  
  911. public int getLootDistribution()
  912. {
  913. return _itemDistribution;
  914. }
  915.  
  916. public boolean isInCommandChannel()
  917. {
  918. return _commandChannel != null;
  919. }
  920.  
  921. public CommandChannel getCommandChannel()
  922. {
  923. return _commandChannel;
  924. }
  925.  
  926. public void setCommandChannel(CommandChannel channel)
  927. {
  928. _commandChannel = channel;
  929. }
  930.  
  931. public boolean isInDimensionalRift()
  932. {
  933. return _dr != null;
  934. }
  935.  
  936. public void setDimensionalRift(DimensionalRift dr)
  937. {
  938. _dr = dr;
  939. }
  940.  
  941. public DimensionalRift getDimensionalRift()
  942. {
  943. return _dr;
  944. }
  945.  
  946. public Player getLeader()
  947. {
  948. try
  949. {
  950. return _members.get(0);
  951. }
  952. catch (NoSuchElementException e)
  953. {
  954. return null;
  955. }
  956. }
  957.  
  958. protected class PositionBroadcast implements Runnable
  959. {
  960. @Override
  961. public void run()
  962. {
  963. if (_positionPacket == null)
  964. {
  965. _positionPacket = new PartyMemberPosition(Party.this);
  966. }
  967. else
  968. {
  969. _positionPacket.reuse(Party.this);
  970. }
  971.  
  972. broadcastToPartyMembers(_positionPacket);
  973. }
  974. }
  975. }
  976.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement