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()) {