Advertisement
Guest User

L2Party.java

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