diff --git a/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index b668a436c0..0169abee36 100644
--- a/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -325,6 +327,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -346,44 +360,102 @@ public class Attackable extends Npc
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
final Map rewards = new ConcurrentHashMap<>();
+
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
{
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
+
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
// Calculate raidboss points
if (_isRaid && !_isRaidMinion)
{
@@ -439,11 +511,17 @@ public class Attackable extends Npc
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
-
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{
diff --git a/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index e39ed646e7..d52223304a 100644
--- a/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -318,6 +320,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -339,44 +353,102 @@ public class Attackable extends Npc
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
final Map rewards = new ConcurrentHashMap<>();
+
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
{
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
+
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
// Calculate raidboss points
if (_isRaid && !_isRaidMinion)
{
@@ -432,11 +504,17 @@ public class Attackable extends Npc
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
-
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{
diff --git a/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index e39ed646e7..d52223304a 100644
--- a/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -318,6 +320,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -339,44 +353,102 @@ public class Attackable extends Npc
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
final Map rewards = new ConcurrentHashMap<>();
+
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
{
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
+
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
// Calculate raidboss points
if (_isRaid && !_isRaidMinion)
{
@@ -432,11 +504,17 @@ public class Attackable extends Npc
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
-
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{
diff --git a/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index e39ed646e7..d52223304a 100644
--- a/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -318,6 +320,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -339,44 +353,102 @@ public class Attackable extends Npc
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
final Map rewards = new ConcurrentHashMap<>();
+
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
{
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
+
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
// Calculate raidboss points
if (_isRaid && !_isRaidMinion)
{
@@ -432,11 +504,17 @@ public class Attackable extends Npc
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
-
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{
diff --git a/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index 43fe92a776..02a5f9e090 100644
--- a/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -317,6 +319,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -338,44 +352,102 @@ public class Attackable extends Npc
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
final Map rewards = new ConcurrentHashMap<>();
+
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
{
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
+
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
// Calculate raidboss points
if (_isRaid && !_isRaidMinion)
{
@@ -431,11 +503,17 @@ public class Attackable extends Npc
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
-
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{
diff --git a/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index 43fe92a776..02a5f9e090 100644
--- a/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -317,6 +319,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -338,44 +352,102 @@ public class Attackable extends Npc
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
final Map rewards = new ConcurrentHashMap<>();
+
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
{
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
+
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
// Calculate raidboss points
if (_isRaid && !_isRaidMinion)
{
@@ -431,11 +503,17 @@ public class Attackable extends Npc
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
-
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{
diff --git a/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index 43fe92a776..02a5f9e090 100644
--- a/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -317,6 +319,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -338,44 +352,102 @@ public class Attackable extends Npc
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
final Map rewards = new ConcurrentHashMap<>();
+
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
{
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
+
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
// Calculate raidboss points
if (_isRaid && !_isRaidMinion)
{
@@ -431,11 +503,17 @@ public class Attackable extends Npc
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
-
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{
diff --git a/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index 121b62df28..2214c9bd1e 100644
--- a/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -317,6 +319,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -338,44 +352,102 @@ public class Attackable extends Npc
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
final Map rewards = new ConcurrentHashMap<>();
+
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
{
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
+
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
// Calculate raidboss points
if (_isRaid && !_isRaidMinion)
{
@@ -431,11 +503,17 @@ public class Attackable extends Npc
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
-
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{
diff --git a/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index 121b62df28..2214c9bd1e 100644
--- a/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -317,6 +319,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -338,44 +352,102 @@ public class Attackable extends Npc
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
final Map rewards = new ConcurrentHashMap<>();
+
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
{
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
+
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
// Calculate raidboss points
if (_isRaid && !_isRaidMinion)
{
@@ -431,11 +503,17 @@ public class Attackable extends Npc
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
-
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index 121b62df28..2214c9bd1e 100644
--- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -317,6 +319,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -338,44 +352,102 @@ public class Attackable extends Npc
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
final Map rewards = new ConcurrentHashMap<>();
+
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
{
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
+
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
// Calculate raidboss points
if (_isRaid && !_isRaidMinion)
{
@@ -431,11 +503,17 @@ public class Attackable extends Npc
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
-
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{
diff --git a/L2J_Mobius_CT_2.4_Epilogue/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_CT_2.4_Epilogue/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index cef0cc5e11..ff6261dea1 100644
--- a/L2J_Mobius_CT_2.4_Epilogue/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_CT_2.4_Epilogue/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -18,9 +18,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -342,6 +344,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -367,6 +381,7 @@ public class Attackable extends Npc
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
@@ -378,40 +393,103 @@ public class Attackable extends Npc
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
+ // Manage Base, Quests and Sweep drops of the Attackable
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{
diff --git a/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index cef0cc5e11..ff6261dea1 100644
--- a/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -18,9 +18,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -342,6 +344,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -367,6 +381,7 @@ public class Attackable extends Npc
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
@@ -378,40 +393,103 @@ public class Attackable extends Npc
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
+ // Manage Base, Quests and Sweep drops of the Attackable
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index 9be8bcd5c7..dd182a0c09 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -318,6 +320,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -339,44 +353,102 @@ public class Attackable extends Npc
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
final Map rewards = new ConcurrentHashMap<>();
+
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
{
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
+
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
// Calculate raidboss points
if (_isRaid && !_isRaidMinion)
{
@@ -432,11 +504,17 @@ public class Attackable extends Npc
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
-
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index 9be8bcd5c7..dd182a0c09 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -318,6 +320,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -339,44 +353,102 @@ public class Attackable extends Npc
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
final Map rewards = new ConcurrentHashMap<>();
+
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
{
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
+
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
// Calculate raidboss points
if (_isRaid && !_isRaidMinion)
{
@@ -432,11 +504,17 @@ public class Attackable extends Npc
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
-
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index 9be8bcd5c7..dd182a0c09 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -318,6 +320,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -339,44 +353,102 @@ public class Attackable extends Npc
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
final Map rewards = new ConcurrentHashMap<>();
+
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
{
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
+
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
// Calculate raidboss points
if (_isRaid && !_isRaidMinion)
{
@@ -432,11 +504,17 @@ public class Attackable extends Npc
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
-
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index 8481c90869..ac15805d30 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -320,6 +322,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -341,44 +355,102 @@ public class Attackable extends Npc
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
final Map rewards = new ConcurrentHashMap<>();
+
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
{
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
+
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
// Calculate raidboss points
if (_isRaid && !_isRaidMinion)
{
@@ -434,11 +506,17 @@ public class Attackable extends Npc
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
-
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index 8481c90869..ac15805d30 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -320,6 +322,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -341,44 +355,102 @@ public class Attackable extends Npc
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
final Map rewards = new ConcurrentHashMap<>();
+
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
{
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
+
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
// Calculate raidboss points
if (_isRaid && !_isRaidMinion)
{
@@ -434,11 +506,17 @@ public class Attackable extends Npc
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
-
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index 8481c90869..ac15805d30 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -320,6 +322,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -341,44 +355,102 @@ public class Attackable extends Npc
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
final Map rewards = new ConcurrentHashMap<>();
+
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
{
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
+
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
// Calculate raidboss points
if (_isRaid && !_isRaidMinion)
{
@@ -434,11 +506,17 @@ public class Attackable extends Npc
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
-
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{
diff --git a/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index 338b327fde..d9e17218f3 100644
--- a/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -322,6 +324,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -343,44 +357,102 @@ public class Attackable extends Npc
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
final Map rewards = new ConcurrentHashMap<>();
+
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
{
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
+
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
// Calculate raidboss points
if (_isRaid && !_isRaidMinion)
{
@@ -436,11 +508,17 @@ public class Attackable extends Npc
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
-
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index 71c770e663..2604da8df0 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -321,6 +323,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -342,44 +356,102 @@ public class Attackable extends Npc
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
final Map rewards = new ConcurrentHashMap<>();
+
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
{
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
+
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
// Calculate raidboss points
if (_isRaid && !_isRaidMinion)
{
@@ -435,11 +507,17 @@ public class Attackable extends Npc
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
-
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index 71c770e663..2604da8df0 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
@@ -321,6 +323,18 @@ public class Attackable extends Npc
return true;
}
+ static class PartyContainer
+ {
+ Party party;
+ long damage = 0L;
+
+ public PartyContainer(Party party, long damage)
+ {
+ this.party = party;
+ this.damage = damage;
+ }
+ }
+
/**
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.
* Actions:
@@ -342,44 +356,102 @@ public class Attackable extends Npc
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
final Map rewards = new ConcurrentHashMap<>();
+
PlayerInstance maxDealer = null;
long maxDamage = 0;
long totalDamage = 0;
+
// While Iterating over This Map Removing Object is Not Allowed
// Go through the _aggroList of the Attackable
for (AggroInfo info : _aggroList.values())
{
// Get the Creature corresponding to this attacker
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
- if (attacker != null)
+ if (attacker == null)
{
- // Get damages done by this attacker
- final long damage = info.getDamage();
-
- // Prevent unwanted behavior
- if (damage > 1)
+ continue;
+ }
+
+ // Get damages done by this attacker
+ final long damage = info.getDamage();
+
+ // Prevent unwanted behavior
+ if (damage > 1)
+ {
+ // Check if damage dealer isn't too far from this (killed monster)
+ if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
{
- // Check if damage dealer isn't too far from this (killed monster)
- if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, this, attacker, true))
- {
- continue;
- }
-
- totalDamage += damage;
-
- // Calculate real damages (Summoners should get own damage plus summon's damage)
- final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
- reward.addDamage(damage);
-
- if (reward.getDamage() > maxDamage)
- {
- maxDealer = attacker;
- maxDamage = reward.getDamage();
- }
+ continue;
+ }
+
+ totalDamage += damage;
+
+ // Calculate real damages (Summoners should get own damage plus summon's damage)
+ final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
+ reward.addDamage(damage);
+
+ if (reward.getDamage() > maxDamage)
+ {
+ maxDealer = attacker;
+ maxDamage = reward.getDamage();
}
}
}
+ final List damagingParties = new ArrayList<>();
+ for (AggroInfo info : _aggroList.values())
+ {
+ final Creature attacker = info.getAttacker();
+ if (attacker == null)
+ {
+ continue;
+ }
+
+ long totalMemberDamage = 0;
+ final Party party = attacker.getParty();
+ if (party == null)
+ {
+ continue;
+ }
+
+ Optional partyContainerStream = Optional.empty();
+ for (int i = 0, damagingPartiesSize = damagingParties.size(); i < damagingPartiesSize; i++)
+ {
+ final PartyContainer p = damagingParties.get(i);
+ if (p.party == party)
+ {
+ partyContainerStream = Optional.of(p);
+ break;
+ }
+ }
+
+ final PartyContainer container = partyContainerStream.orElse(new PartyContainer(party, 0L));
+ final List members = party.getMembers();
+ for (PlayerInstance e : members)
+ {
+ final AggroInfo memberAggro = _aggroList.get(e);
+ if (memberAggro == null)
+ {
+ continue;
+ }
+
+ if (memberAggro.getDamage() > 1)
+ {
+ totalMemberDamage += memberAggro.getDamage();
+ }
+ }
+ container.damage = totalMemberDamage;
+
+ if (partyContainerStream.isEmpty())
+ {
+ damagingParties.add(container);
+ }
+ }
+
+ final PartyContainer mostDamageParty;
+ damagingParties.sort(Comparator.comparingLong(c -> c.damage));
+ mostDamageParty = damagingParties.size() > 0 ? damagingParties.get(0) : null;
+
// Calculate raidboss points
if (_isRaid && !_isRaidMinion)
{
@@ -435,11 +507,17 @@ public class Attackable extends Npc
}
}
- // Manage Base, Quests and Sweep drops of the Attackable
- doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
-
- // Manage drop of Special Events created by GM for a defined period
- doEventDrop(lastAttacker);
+ if ((mostDamageParty != null) && (mostDamageParty.damage > maxDamage))
+ {
+ PlayerInstance leader = mostDamageParty.party.getLeader();
+ doItemDrop(leader);
+ doEventDrop(leader);
+ }
+ else
+ {
+ doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
+ doEventDrop(lastAttacker);
+ }
if (!getMustRewardExpSP())
{