소스 검색

Added loot distribution features to party options.

In a party, adena is distributed evenly to all party members in the
range of the looter. This patch introduces three new config options
which can enable the same for all stackable items and/or all non
stackable items and/or specific item ids. The new options can be found
inside character.properties. You can read their description in the
properties file to have a more detailed description:
PartyEvenlyDistributeAllStackableItems
PartyEvenlyDistributeAllOtherItems
PartyEvenlyDistributeItems
HorridoJoho 2 년 전
부모
커밋
5e1fc76a17

+ 10 - 1
src/main/java/com/l2jserver/gameserver/config/CharacterConfiguration.java

@@ -1,5 +1,5 @@
 /*
- * Copyright © 2004-2021 L2J Server
+ * Copyright © 2004-2022 L2J Server
  *
  * This file is part of L2J Server.
  *
@@ -516,6 +516,15 @@ public interface CharacterConfiguration extends Reloadable {
 	
 	@Key("PartyRange2")
 	Integer getPartyRange2();
+
+	@Key("PartyEvenlyDistributeAllStackableItems")
+	Boolean getPartyEvenlyDistributeAllStackableItems();
+
+	@Key("PartyEvenlyDistributeAllOtherItems")
+	Boolean getPartyEvenlyDistributeAllOtherItems();
+	
+	@Key("PartyEvenlyDistributeItems")
+	List<Integer> getPartyEvenlyDistributeItems();
 	
 	@Key("LeavePartyLeader")
 	Boolean leavePartyLeader();

+ 43 - 28
src/main/java/com/l2jserver/gameserver/model/L2Party.java

@@ -1,5 +1,5 @@
 /*
- * Copyright © 2004-2021 L2J Server
+ * Copyright © 2004-2022 L2J Server
  * 
  * This file is part of L2J Server.
  * 
@@ -24,16 +24,13 @@ import static com.l2jserver.gameserver.config.Configuration.rates;
 
 import java.time.Duration;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.Future;
-import java.util.concurrent.atomic.AtomicLong;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -51,9 +48,8 @@ import com.l2jserver.gameserver.model.actor.instance.L2ServitorInstance;
 import com.l2jserver.gameserver.model.entity.DimensionalRift;
 import com.l2jserver.gameserver.model.holders.ItemHolder;
 import com.l2jserver.gameserver.model.itemcontainer.Inventory;
+import com.l2jserver.gameserver.model.items.L2Item;
 import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
-import com.l2jserver.gameserver.model.skills.AbnormalType;
-import com.l2jserver.gameserver.model.skills.BuffInfo;
 import com.l2jserver.gameserver.model.zone.ZoneId;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.serverpackets.ExAskModifyPartyLooting;
@@ -508,14 +504,26 @@ public class L2Party extends AbstractPlayerGroup {
 		return null;
 	}
 	
+	private boolean isItemToEvenlyDistribute(int itemId) {
+		L2Item item = ItemTable.getInstance().getTemplate(itemId);
+		if (item != null) {
+			if ((character().getPartyEvenlyDistributeAllStackableItems() && item.isStackable()) ||
+				(character().getPartyEvenlyDistributeAllOtherItems() && !item.isStackable())) {
+				return true;
+			}
+		}
+
+		return character().getPartyEvenlyDistributeItems().contains(itemId);
+	}
+	
 	/**
 	 * distribute item(s) to party members
 	 * @param player
 	 * @param item
 	 */
 	public void distributeItem(L2PcInstance player, L2ItemInstance item) {
-		if (item.getId() == Inventory.ADENA_ID) {
-			distributeAdena(player, item.getCount(), player);
+		if (isItemToEvenlyDistribute(item.getId())) {
+			distributeItemEvenly(player, item.getId(), item.getCount(), player);
 			ItemTable.getInstance().destroyItem("Party", item, player, null);
 			return;
 		}
@@ -549,8 +557,8 @@ public class L2Party extends AbstractPlayerGroup {
 	 * @param target the NPC target
 	 */
 	public void distributeItem(L2PcInstance player, int itemId, long itemCount, boolean spoil, L2Attackable target) {
-		if (itemId == Inventory.ADENA_ID) {
-			distributeAdena(player, itemCount, target);
+		if (isItemToEvenlyDistribute(itemId)) {
+			distributeItemEvenly(player, itemId, itemCount, target);
 			return;
 		}
 		
@@ -587,42 +595,49 @@ public class L2Party extends AbstractPlayerGroup {
 	}
 	
 	/**
-	 * Distribute adena to party members. <BR>
-	 * Check the number of party members that must be rewarded <BR>
-	 * (The party member must be in range to receive its reward)<BR>
+	 * Distribute an item evenly to party members in range.<BR>
+	 * Check the number of party members that must be rewarded<BR>
 	 * @param player owner (picker)
-	 * @param adena the amount of adena to split
+	 * @param itemId the id of the item to split
+	 * @param itemAmount the amount of the item to split
 	 * @param target the target who drop / pick the adena
 	 */
-	public void distributeAdena(L2PcInstance player, long adena, L2Character target) {
-		final Map<L2PcInstance, AtomicLong> toReward = new HashMap<>(9);
+	public void distributeItemEvenly(L2PcInstance player, int itemId, long itemAmount, L2Character target) {
+		var toReward = new HashMap<L2PcInstance, Long>(9);
 		
-		for (final L2PcInstance member : getMembers()) {
+		for (var member : getMembers()) {
 			if (Util.checkIfInRange(character().getPartyRange2(), target, member, true)) {
-				toReward.put(member, new AtomicLong());
+				toReward.put(member, 0L);
 			}
 		}
+
 		if (!toReward.isEmpty()) {
-			long leftOver = adena % toReward.size();
-			final long count = adena / toReward.size();
+			long leftOver = itemAmount % toReward.size();
+			final long count = itemAmount / toReward.size();
 			
 			if (count > 0) {
-				for (AtomicLong member : toReward.values()) {
-					member.addAndGet(count);
+				for (var member : toReward.keySet()) {
+					toReward.put(member, count);
 				}
 			}
 			
 			if (leftOver > 0) {
-				List<L2PcInstance> keys = new ArrayList<>(toReward.keySet());
+				var keys = new ArrayList<L2PcInstance>(toReward.keySet());
 				
 				while (leftOver-- > 0) {
-					Collections.shuffle(keys);
-					toReward.get(keys.get(0)).incrementAndGet();
+					int rndIndex = Rnd.get(0, toReward.size() - 1);
+					var rndMember = keys.get(rndIndex);
+					toReward.compute(rndMember, (m, n) -> n + 1);
 				}
 			}
-			for (Entry<L2PcInstance, AtomicLong> member : toReward.entrySet()) {
-				if (member.getValue().get() > 0) {
-					member.getKey().addAdena("Party", member.getValue().get(), player, true);
+
+			for (var member : toReward.entrySet()) {
+				if (member.getValue() > 0) {
+					if (itemId == Inventory.ADENA_ID) {
+						member.getKey().addAdena("Party", member.getValue(), player, true);
+					} else {
+						member.getKey().addItem("Party", itemId, member.getValue(), target, true);
+					}
 				}
 			}
 		}

+ 23 - 1
src/main/resources/config/character.properties

@@ -604,11 +604,33 @@ ClanMembersForWar = 15
 # Default: 1600
 PartyRange = 1600
 
-# 1. Used for Adena distribution in party
+# 1. Used for items which are evenly distributed in party
 # 2. Used to handle random and by turn party loot
 # Default: 1400
 PartyRange2 = 1400
 
+# Specifies whether stackable items will be split up to be evenly distributed to
+# all party members in range of the looter. Item amounts which can not be evenly
+# split up are distributed randomly to party members in range of the looter.
+# Default: False
+PartyEvenlyDistributeAllStackableItems=False
+
+# Specifies whether non stackable items will be split up to be evenly
+# distributed to all party members in range of the looter. That means if you
+# have a highrate server and get multiple fulldrops of the same item, it is
+# evenly distributed to all party members in range of the looter. Item amounts
+# which can not be evenly split up are distributed randomly to party members in
+# range of the looter.
+# Default: False
+PartyEvenlyDistributeAllOtherItems=False
+
+# List of items which get split up to be evenly distributed to party members. By
+# default, only adena is split. Item ids are seperated by comma. Item amounts
+# which can not be evenly split up are distributed randomly to party members in
+# range of the looter.
+# Default: 57
+PartyEvenlyDistributeItems=57
+
 # If true, when party leader leaves party, next member in party will be the leader.
 # If false the party be will dispersed.
 # Default: False