Calculate total party damage for rewards.
Contributed by Trance.
This commit is contained in:
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -325,6 +327,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -346,17 +360,22 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
||||||
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
{
|
{
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -382,8 +401,61 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> 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<PartyContainer> 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<PlayerInstance> 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
|
// Calculate raidboss points
|
||||||
if (_isRaid && !_isRaidMinion)
|
if (_isRaid && !_isRaidMinion)
|
||||||
{
|
{
|
||||||
@@ -439,11 +511,17 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
|
||||||
doEventDrop(lastAttacker);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -318,6 +320,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -339,17 +353,22 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
||||||
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
{
|
{
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -375,8 +394,61 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> 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<PartyContainer> 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<PlayerInstance> 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
|
// Calculate raidboss points
|
||||||
if (_isRaid && !_isRaidMinion)
|
if (_isRaid && !_isRaidMinion)
|
||||||
{
|
{
|
||||||
@@ -432,11 +504,17 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
|
||||||
doEventDrop(lastAttacker);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -318,6 +320,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -339,17 +353,22 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
||||||
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
{
|
{
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -375,8 +394,61 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> 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<PartyContainer> 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<PlayerInstance> 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
|
// Calculate raidboss points
|
||||||
if (_isRaid && !_isRaidMinion)
|
if (_isRaid && !_isRaidMinion)
|
||||||
{
|
{
|
||||||
@@ -432,11 +504,17 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
|
||||||
doEventDrop(lastAttacker);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -318,6 +320,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -339,17 +353,22 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
||||||
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
{
|
{
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -375,8 +394,61 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> 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<PartyContainer> 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<PlayerInstance> 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
|
// Calculate raidboss points
|
||||||
if (_isRaid && !_isRaidMinion)
|
if (_isRaid && !_isRaidMinion)
|
||||||
{
|
{
|
||||||
@@ -432,11 +504,17 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
|
||||||
doEventDrop(lastAttacker);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -317,6 +319,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -338,17 +352,22 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
||||||
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
{
|
{
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -374,8 +393,61 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> 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<PartyContainer> 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<PlayerInstance> 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
|
// Calculate raidboss points
|
||||||
if (_isRaid && !_isRaidMinion)
|
if (_isRaid && !_isRaidMinion)
|
||||||
{
|
{
|
||||||
@@ -431,11 +503,17 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
|
||||||
doEventDrop(lastAttacker);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -317,6 +319,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -338,17 +352,22 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
||||||
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
{
|
{
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -374,8 +393,61 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> 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<PartyContainer> 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<PlayerInstance> 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
|
// Calculate raidboss points
|
||||||
if (_isRaid && !_isRaidMinion)
|
if (_isRaid && !_isRaidMinion)
|
||||||
{
|
{
|
||||||
@@ -431,11 +503,17 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
|
||||||
doEventDrop(lastAttacker);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -317,6 +319,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -338,17 +352,22 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
||||||
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
{
|
{
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -374,8 +393,61 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> 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<PartyContainer> 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<PlayerInstance> 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
|
// Calculate raidboss points
|
||||||
if (_isRaid && !_isRaidMinion)
|
if (_isRaid && !_isRaidMinion)
|
||||||
{
|
{
|
||||||
@@ -431,11 +503,17 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
|
||||||
doEventDrop(lastAttacker);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -317,6 +319,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -338,17 +352,22 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
||||||
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
{
|
{
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -374,8 +393,61 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> 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<PartyContainer> 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<PlayerInstance> 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
|
// Calculate raidboss points
|
||||||
if (_isRaid && !_isRaidMinion)
|
if (_isRaid && !_isRaidMinion)
|
||||||
{
|
{
|
||||||
@@ -431,11 +503,17 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
|
||||||
doEventDrop(lastAttacker);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -317,6 +319,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -338,17 +352,22 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
||||||
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
{
|
{
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -374,8 +393,61 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> 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<PartyContainer> 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<PlayerInstance> 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
|
// Calculate raidboss points
|
||||||
if (_isRaid && !_isRaidMinion)
|
if (_isRaid && !_isRaidMinion)
|
||||||
{
|
{
|
||||||
@@ -431,11 +503,17 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
|
||||||
doEventDrop(lastAttacker);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -317,6 +319,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -338,17 +352,22 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
||||||
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
{
|
{
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -374,8 +393,61 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> 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<PartyContainer> 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<PlayerInstance> 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
|
// Calculate raidboss points
|
||||||
if (_isRaid && !_isRaidMinion)
|
if (_isRaid && !_isRaidMinion)
|
||||||
{
|
{
|
||||||
@@ -431,11 +503,17 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
|
||||||
doEventDrop(lastAttacker);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
@@ -18,9 +18,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -342,6 +344,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -367,6 +381,7 @@ public class Attackable extends Npc
|
|||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
@@ -378,8 +393,11 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -405,13 +423,73 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> damagingParties = new ArrayList<>();
|
||||||
|
for (AggroInfo info : _aggroList.values())
|
||||||
|
{
|
||||||
|
final Creature attacker = info.getAttacker();
|
||||||
|
if (attacker == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manage Base, Quests and Sweep drops of the Attackable
|
long totalMemberDamage = 0;
|
||||||
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
final Party party = attacker.getParty();
|
||||||
|
if (party == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
Optional<PartyContainer> 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<PlayerInstance> 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;
|
||||||
|
|
||||||
|
// 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);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
@@ -18,9 +18,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -342,6 +344,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -367,6 +381,7 @@ public class Attackable extends Npc
|
|||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
@@ -378,8 +393,11 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -405,13 +423,73 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> damagingParties = new ArrayList<>();
|
||||||
|
for (AggroInfo info : _aggroList.values())
|
||||||
|
{
|
||||||
|
final Creature attacker = info.getAttacker();
|
||||||
|
if (attacker == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manage Base, Quests and Sweep drops of the Attackable
|
long totalMemberDamage = 0;
|
||||||
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
final Party party = attacker.getParty();
|
||||||
|
if (party == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
Optional<PartyContainer> 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<PlayerInstance> 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;
|
||||||
|
|
||||||
|
// 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);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -318,6 +320,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -339,17 +353,22 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
||||||
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
{
|
{
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -375,8 +394,61 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> 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<PartyContainer> 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<PlayerInstance> 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
|
// Calculate raidboss points
|
||||||
if (_isRaid && !_isRaidMinion)
|
if (_isRaid && !_isRaidMinion)
|
||||||
{
|
{
|
||||||
@@ -432,11 +504,17 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
|
||||||
doEventDrop(lastAttacker);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -318,6 +320,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -339,17 +353,22 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
||||||
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
{
|
{
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -375,8 +394,61 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> 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<PartyContainer> 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<PlayerInstance> 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
|
// Calculate raidboss points
|
||||||
if (_isRaid && !_isRaidMinion)
|
if (_isRaid && !_isRaidMinion)
|
||||||
{
|
{
|
||||||
@@ -432,11 +504,17 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
|
||||||
doEventDrop(lastAttacker);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -318,6 +320,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -339,17 +353,22 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
||||||
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
{
|
{
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -375,8 +394,61 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> 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<PartyContainer> 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<PlayerInstance> 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
|
// Calculate raidboss points
|
||||||
if (_isRaid && !_isRaidMinion)
|
if (_isRaid && !_isRaidMinion)
|
||||||
{
|
{
|
||||||
@@ -432,11 +504,17 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
|
||||||
doEventDrop(lastAttacker);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -320,6 +322,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -341,17 +355,22 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
||||||
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
{
|
{
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -377,8 +396,61 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> 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<PartyContainer> 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<PlayerInstance> 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
|
// Calculate raidboss points
|
||||||
if (_isRaid && !_isRaidMinion)
|
if (_isRaid && !_isRaidMinion)
|
||||||
{
|
{
|
||||||
@@ -434,11 +506,17 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
|
||||||
doEventDrop(lastAttacker);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -320,6 +322,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -341,17 +355,22 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
||||||
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
{
|
{
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -377,8 +396,61 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> 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<PartyContainer> 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<PlayerInstance> 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
|
// Calculate raidboss points
|
||||||
if (_isRaid && !_isRaidMinion)
|
if (_isRaid && !_isRaidMinion)
|
||||||
{
|
{
|
||||||
@@ -434,11 +506,17 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
|
||||||
doEventDrop(lastAttacker);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -320,6 +322,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -341,17 +355,22 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
||||||
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
{
|
{
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -377,8 +396,61 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> 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<PartyContainer> 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<PlayerInstance> 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
|
// Calculate raidboss points
|
||||||
if (_isRaid && !_isRaidMinion)
|
if (_isRaid && !_isRaidMinion)
|
||||||
{
|
{
|
||||||
@@ -434,11 +506,17 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
|
||||||
doEventDrop(lastAttacker);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -322,6 +324,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -343,17 +357,22 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
||||||
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
{
|
{
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -379,8 +398,61 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> 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<PartyContainer> 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<PlayerInstance> 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
|
// Calculate raidboss points
|
||||||
if (_isRaid && !_isRaidMinion)
|
if (_isRaid && !_isRaidMinion)
|
||||||
{
|
{
|
||||||
@@ -436,11 +508,17 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
|
||||||
doEventDrop(lastAttacker);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -321,6 +323,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -342,17 +356,22 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
||||||
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
{
|
{
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -378,8 +397,61 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> 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<PartyContainer> 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<PlayerInstance> 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
|
// Calculate raidboss points
|
||||||
if (_isRaid && !_isRaidMinion)
|
if (_isRaid && !_isRaidMinion)
|
||||||
{
|
{
|
||||||
@@ -435,11 +507,17 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
|
||||||
doEventDrop(lastAttacker);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
@@ -19,9 +19,11 @@ package org.l2jmobius.gameserver.model.actor;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -321,6 +323,18 @@ public class Attackable extends Npc
|
|||||||
return true;
|
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.<br>
|
* Distribute Exp and SP rewards to PlayerInstance (including Summon owner) that hit the Attackable and to their Party members.<br>
|
||||||
* Actions:<br>
|
* Actions:<br>
|
||||||
@@ -342,17 +356,22 @@ public class Attackable extends Npc
|
|||||||
|
|
||||||
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
// NOTE: Concurrent-safe map is used because while iterating to verify all conditions sometimes an entry must be removed.
|
||||||
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
final Map<PlayerInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
PlayerInstance maxDealer = null;
|
PlayerInstance maxDealer = null;
|
||||||
long maxDamage = 0;
|
long maxDamage = 0;
|
||||||
long totalDamage = 0;
|
long totalDamage = 0;
|
||||||
|
|
||||||
// While Iterating over This Map Removing Object is Not Allowed
|
// While Iterating over This Map Removing Object is Not Allowed
|
||||||
// Go through the _aggroList of the Attackable
|
// Go through the _aggroList of the Attackable
|
||||||
for (AggroInfo info : _aggroList.values())
|
for (AggroInfo info : _aggroList.values())
|
||||||
{
|
{
|
||||||
// Get the Creature corresponding to this attacker
|
// Get the Creature corresponding to this attacker
|
||||||
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
final PlayerInstance attacker = info.getAttacker().getActingPlayer();
|
||||||
if (attacker != null)
|
if (attacker == null)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get damages done by this attacker
|
// Get damages done by this attacker
|
||||||
final long damage = info.getDamage();
|
final long damage = info.getDamage();
|
||||||
|
|
||||||
@@ -378,8 +397,61 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<PartyContainer> 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<PartyContainer> 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<PlayerInstance> 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
|
// Calculate raidboss points
|
||||||
if (_isRaid && !_isRaidMinion)
|
if (_isRaid && !_isRaidMinion)
|
||||||
{
|
{
|
||||||
@@ -435,11 +507,17 @@ public class Attackable extends Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
doItemDrop((maxDealer != null) && maxDealer.isOnline() ? maxDealer : lastAttacker);
|
||||||
|
|
||||||
// Manage drop of Special Events created by GM for a defined period
|
|
||||||
doEventDrop(lastAttacker);
|
doEventDrop(lastAttacker);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getMustRewardExpSP())
|
if (!getMustRewardExpSP())
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user