Abnormal improvements.

This commit is contained in:
MobiusDev
2018-11-01 16:51:03 +00:00
parent bd7da50452
commit d35a9d46ec
90 changed files with 929 additions and 1632 deletions

View File

@@ -16,6 +16,8 @@
*/ */
package handlers.effecthandlers; package handlers.effecthandlers;
import java.util.Collections;
import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.StatsSet;
@@ -38,6 +40,19 @@ public final class CallSkillOnActionTime extends AbstractEffect
setTicks(params.getInt("ticks")); setTicks(params.getInt("ticks"));
} }
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
effected.getEffectList().stopEffects(Collections.singleton(_skill.getSkill().getAbnormalType()));
effected.getEffectList().addBlockedAbnormalTypes(Collections.singleton(_skill.getSkill().getAbnormalType()));
}
@Override
public void onExit(L2Character effector, L2Character effected, Skill skill)
{
effected.getEffectList().removeBlockedAbnormalTypes(Collections.singleton(_skill.getSkill().getAbnormalType()));
}
@Override @Override
public boolean onActionTime(L2Character effector, L2Character effected, Skill skill) public boolean onActionTime(L2Character effector, L2Character effected, Skill skill)
{ {

View File

@@ -136,6 +136,5 @@ public final class Disarmor extends AbstractEffect
} }
} }
} }
super.onExit(effector, effected, skill);
} }
} }

View File

@@ -84,6 +84,5 @@ public final class DoubleCast extends AbstractEffect
return null; return null;
}); });
} }
super.onExit(effector, effected, skill);
} }
} }

View File

@@ -65,15 +65,15 @@ public final class CharEffectList
{ {
private static final Logger LOGGER = Logger.getLogger(CharEffectList.class.getName()); private static final Logger LOGGER = Logger.getLogger(CharEffectList.class.getName());
/** Queue containing all effects from buffs for this effect list. */ /** Queue containing all effects from buffs for this effect list. */
private volatile Queue<BuffInfo> _actives; private volatile Queue<BuffInfo> _actives = new ConcurrentLinkedQueue<>();
/** List containing all passives for this effect list. They bypass most of the actions and they are not included in most operations. */ /** List containing all passives for this effect list. They bypass most of the actions and they are not included in most operations. */
private volatile Set<BuffInfo> _passives; private volatile Set<BuffInfo> _passives = ConcurrentHashMap.newKeySet();
/** List containing all options for this effect list. They bypass most of the actions and they are not included in most operations. */ /** List containing all options for this effect list. They bypass most of the actions and they are not included in most operations. */
private volatile Set<BuffInfo> _options; private volatile Set<BuffInfo> _options = ConcurrentHashMap.newKeySet();
/** Map containing the all stacked effect in progress for each {@code AbnormalType}. */ /** Map containing the all stacked effect in progress for each {@code AbnormalType}. */
private volatile Set<AbnormalType> _stackedEffects = EnumSet.noneOf(AbnormalType.class); private volatile Set<AbnormalType> _stackedEffects = EnumSet.noneOf(AbnormalType.class);
/** Set containing all {@code AbnormalType}s that shouldn't be added to this creature effect list. */ /** Set containing all {@code AbnormalType}s that shouldn't be added to this creature effect list. */
private volatile Set<AbnormalType> _blockedAbnormalTypes = null; private volatile Set<AbnormalType> _blockedAbnormalTypes = EnumSet.noneOf(AbnormalType.class);
/** Set containing all abnormal visual effects this creature currently displays. */ /** Set containing all abnormal visual effects this creature currently displays. */
private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects = EnumSet.noneOf(AbnormalVisualEffect.class); private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects = EnumSet.noneOf(AbnormalVisualEffect.class);
/** Short buff skill ID. */ /** Short buff skill ID. */
@@ -110,7 +110,7 @@ public final class CharEffectList
*/ */
public Set<BuffInfo> getPassives() public Set<BuffInfo> getPassives()
{ {
return _passives != null ? Collections.unmodifiableSet(_passives) : Collections.emptySet(); return Collections.unmodifiableSet(_passives);
} }
/** /**
@@ -119,7 +119,7 @@ public final class CharEffectList
*/ */
public Set<BuffInfo> getOptions() public Set<BuffInfo> getOptions()
{ {
return _options != null ? Collections.unmodifiableSet(_options) : Collections.emptySet(); return Collections.unmodifiableSet(_options);
} }
/** /**
@@ -128,7 +128,7 @@ public final class CharEffectList
*/ */
public Collection<BuffInfo> getEffects() public Collection<BuffInfo> getEffects()
{ {
return _actives != null ? Collections.unmodifiableCollection(_actives) : Collections.emptyList(); return Collections.unmodifiableCollection(_actives);
} }
/** /**
@@ -137,7 +137,7 @@ public final class CharEffectList
*/ */
public List<BuffInfo> getBuffs() public List<BuffInfo> getBuffs()
{ {
return _actives != null ? _actives.stream().filter(b -> !b.getSkill().getBuffType().isBuff()).collect(Collectors.toList()) : Collections.emptyList(); return _actives.stream().filter(b -> !b.getSkill().getBuffType().isBuff()).collect(Collectors.toList());
} }
/** /**
@@ -146,7 +146,7 @@ public final class CharEffectList
*/ */
public List<BuffInfo> getDebuffs() public List<BuffInfo> getDebuffs()
{ {
return _actives != null ? _actives.stream().filter(b -> b.getSkill().isDebuff()).collect(Collectors.toList()) : Collections.emptyList(); return _actives.stream().filter(b -> b.getSkill().isDebuff()).collect(Collectors.toList());
} }
/** /**
@@ -156,7 +156,7 @@ public final class CharEffectList
*/ */
public boolean isAffectedBySkill(int skillId) public boolean isAffectedBySkill(int skillId)
{ {
return ((_actives != null) && _actives.stream().anyMatch(i -> i.getSkill().getId() == skillId)) || ((_passives != null) && _passives.stream().anyMatch(i -> i.getSkill().getId() == skillId)); return (_actives.stream().anyMatch(i -> i.getSkill().getId() == skillId)) || (_passives.stream().anyMatch(i -> i.getSkill().getId() == skillId));
} }
/** /**
@@ -166,7 +166,7 @@ public final class CharEffectList
*/ */
public BuffInfo getBuffInfoBySkillId(int skillId) public BuffInfo getBuffInfoBySkillId(int skillId)
{ {
return Stream.concat(_actives != null ? _actives.stream() : Stream.empty(), _passives != null ? _passives.stream() : Stream.empty()).filter(b -> b.getSkill().getId() == skillId).findFirst().orElse(null); return Stream.concat(_actives.stream(), _passives.stream()).filter(b -> b.getSkill().getId() == skillId).findFirst().orElse(null);
} }
/** /**
@@ -216,18 +216,6 @@ public final class CharEffectList
*/ */
public void addBlockedAbnormalTypes(Set<AbnormalType> blockedAbnormalTypes) public void addBlockedAbnormalTypes(Set<AbnormalType> blockedAbnormalTypes)
{ {
// Initialize
if (_blockedAbnormalTypes == null)
{
synchronized (this)
{
if (_blockedAbnormalTypes == null)
{
_blockedAbnormalTypes = EnumSet.copyOf(blockedAbnormalTypes);
}
}
}
_blockedAbnormalTypes.addAll(blockedAbnormalTypes); _blockedAbnormalTypes.addAll(blockedAbnormalTypes);
} }
@@ -238,7 +226,7 @@ public final class CharEffectList
*/ */
public boolean removeBlockedAbnormalTypes(Set<AbnormalType> blockedBuffSlots) public boolean removeBlockedAbnormalTypes(Set<AbnormalType> blockedBuffSlots)
{ {
return (_blockedAbnormalTypes != null) && _blockedAbnormalTypes.removeAll(blockedBuffSlots); return _blockedAbnormalTypes.removeAll(blockedBuffSlots);
} }
/** /**
@@ -247,7 +235,7 @@ public final class CharEffectList
*/ */
public Set<AbnormalType> getBlockedAbnormalTypes() public Set<AbnormalType> getBlockedAbnormalTypes()
{ {
return _blockedAbnormalTypes != null ? Collections.unmodifiableSet(_blockedAbnormalTypes) : Collections.emptySet(); return Collections.unmodifiableSet(_blockedAbnormalTypes);
} }
/** /**
@@ -277,7 +265,7 @@ public final class CharEffectList
*/ */
public int getBuffCount() public int getBuffCount()
{ {
return _actives != null ? (_buffCount.get() - _hiddenBuffs.get()) : 0; return !_actives.isEmpty() ? (_buffCount.get() - _hiddenBuffs.get()) : 0;
} }
/** /**
@@ -374,7 +362,7 @@ public final class CharEffectList
*/ */
public void stopAllPassives(boolean update, boolean broadcast) public void stopAllPassives(boolean update, boolean broadcast)
{ {
if (_passives != null) if (!_passives.isEmpty())
{ {
_passives.forEach(this::remove); _passives.forEach(this::remove);
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -392,7 +380,7 @@ public final class CharEffectList
*/ */
public void stopAllOptions(boolean update, boolean broadcast) public void stopAllOptions(boolean update, boolean broadcast)
{ {
if (_options != null) if (!_options.isEmpty())
{ {
_options.forEach(this::remove); _options.forEach(this::remove);
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -490,7 +478,7 @@ public final class CharEffectList
*/ */
public void stopEffects(Predicate<BuffInfo> filter, boolean update, boolean broadcast) public void stopEffects(Predicate<BuffInfo> filter, boolean update, boolean broadcast)
{ {
if (_actives != null) if (!_actives.isEmpty())
{ {
_actives.stream().filter(filter).forEach(this::remove); _actives.stream().filter(filter).forEach(this::remove);
@@ -678,6 +666,10 @@ public final class CharEffectList
{ {
// Remove active effect. // Remove active effect.
removeActive(info, removed); removeActive(info, removed);
if (_owner.isNpc()) // Fix for all NPC debuff animations removed.
{
updateEffectList(broadcast);
}
} }
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -693,7 +685,7 @@ public final class CharEffectList
*/ */
private synchronized void removeActive(BuffInfo info, boolean removed) private synchronized void removeActive(BuffInfo info, boolean removed)
{ {
if (_actives != null) if (!_actives.isEmpty())
{ {
// Removes the buff from the given effect list. // Removes the buff from the given effect list.
_actives.remove(info); _actives.remove(info);
@@ -716,7 +708,7 @@ public final class CharEffectList
private void removePassive(BuffInfo info, boolean removed) private void removePassive(BuffInfo info, boolean removed)
{ {
if (_passives != null) if (!_passives.isEmpty())
{ {
_passives.remove(info); _passives.remove(info);
info.stopAllEffects(removed); info.stopAllEffects(removed);
@@ -725,7 +717,7 @@ public final class CharEffectList
private void removeOption(BuffInfo info, boolean removed) private void removeOption(BuffInfo info, boolean removed)
{ {
if (_options != null) if (!_options.isEmpty())
{ {
_options.remove(info); _options.remove(info);
info.stopAllEffects(removed); info.stopAllEffects(removed);
@@ -821,12 +813,6 @@ public final class CharEffectList
} }
} }
// Initialize
if (_actives == null)
{
_actives = new ConcurrentLinkedQueue<>();
}
// Manage effect stacking. // Manage effect stacking.
if (hasAbnormalType(skill.getAbnormalType())) if (hasAbnormalType(skill.getAbnormalType()))
{ {
@@ -857,7 +843,7 @@ public final class CharEffectList
} }
else else
{ {
// Remove effect that gets overriden. // Remove effect that gets overridden.
remove(existingInfo); remove(existingInfo);
} }
} }
@@ -865,7 +851,7 @@ public final class CharEffectList
{ {
info.setInUse(false); info.setInUse(false);
} }
else // The effect we try to add should be overriden. else // The effect we try to add should be overridden.
{ {
return; return;
} }
@@ -918,18 +904,6 @@ public final class CharEffectList
return; return;
} }
// Initialize
if (_passives == null)
{
synchronized (this)
{
if (_passives == null)
{
_passives = ConcurrentHashMap.newKeySet();
}
}
}
// Remove previous passives of this id. // Remove previous passives of this id.
_passives.stream().filter(Objects::nonNull).filter(b -> b.getSkill().getId() == skill.getId()).forEach(b -> _passives.stream().filter(Objects::nonNull).filter(b -> b.getSkill().getId() == skill.getId()).forEach(b ->
{ {
@@ -947,18 +921,6 @@ public final class CharEffectList
{ {
if (info.getOption() != null) if (info.getOption() != null)
{ {
// Initialize
if (_options == null)
{
synchronized (this)
{
if (_options == null)
{
_options = ConcurrentHashMap.newKeySet();
}
}
}
// Remove previous options of this id. // Remove previous options of this id.
_options.stream().filter(Objects::nonNull).filter(b -> b.getOption().getId() == info.getOption().getId()).forEach(b -> _options.stream().filter(Objects::nonNull).filter(b -> b.getOption().getId() == info.getOption().getId()).forEach(b ->
{ {
@@ -988,7 +950,7 @@ public final class CharEffectList
final Optional<PartySpelled> ps = ((party != null) || _owner.isSummon()) ? Optional.of(new PartySpelled(_owner)) : Optional.empty(); final Optional<PartySpelled> ps = ((party != null) || _owner.isSummon()) ? Optional.of(new PartySpelled(_owner)) : Optional.empty();
final Optional<ExOlympiadSpelledInfo> os = (player.isInOlympiadMode() && player.isOlympiadStart()) ? Optional.of(new ExOlympiadSpelledInfo(player)) : Optional.empty(); final Optional<ExOlympiadSpelledInfo> os = (player.isInOlympiadMode() && player.isOlympiadStart()) ? Optional.of(new ExOlympiadSpelledInfo(player)) : Optional.empty();
if (_actives != null) if (!_actives.isEmpty())
{ {
//@formatter:off //@formatter:off
_actives.stream() _actives.stream()
@@ -1109,8 +1071,6 @@ public final class CharEffectList
final Set<BuffInfo> unhideBuffs = new HashSet<>(); final Set<BuffInfo> unhideBuffs = new HashSet<>();
// Recalculate new flags // Recalculate new flags
if (_actives != null)
{
for (BuffInfo info : _actives) for (BuffInfo info : _actives)
{ {
if (info != null) if (info != null)
@@ -1144,7 +1104,14 @@ public final class CharEffectList
// Add AbnormalVisualEffect flag. // Add AbnormalVisualEffect flag.
if (skill.hasAbnormalVisualEffects()) if (skill.hasAbnormalVisualEffects())
{ {
abnormalVisualEffectFlags.addAll(skill.getAbnormalVisualEffects()); for (AbnormalVisualEffect ave : skill.getAbnormalVisualEffects())
{
abnormalVisualEffectFlags.add(ave);
_abnormalVisualEffects.add(ave);
}
if (broadcast)
{
_owner.updateAbnormalVisualEffects();
} }
} }
} }
@@ -1167,7 +1134,7 @@ public final class CharEffectList
if (broadcast) if (broadcast)
{ {
// Check if there is change in AbnormalVisualEffect // Check if there is change in AbnormalVisualEffect
if ((abnormalVisualEffectFlags.size() != _abnormalVisualEffects.size()) || !abnormalVisualEffectFlags.containsAll(_abnormalVisualEffects)) if (!abnormalVisualEffectFlags.containsAll(_abnormalVisualEffects))
{ {
_abnormalVisualEffects = abnormalVisualEffectFlags; _abnormalVisualEffects = abnormalVisualEffectFlags;
_owner.updateAbnormalVisualEffects(); _owner.updateAbnormalVisualEffects();

View File

@@ -77,7 +77,6 @@ public class DoppelgangerInstance extends L2Npc
info.setAbnormalTime(summonerInfo.getAbnormalTime()); info.setAbnormalTime(summonerInfo.getAbnormalTime());
getEffectList().add(info); getEffectList().add(info);
} }
} }
} }
} }

View File

@@ -786,7 +786,7 @@ public class CharStat
final CharEffectList effectList = _activeChar.getEffectList(); final CharEffectList effectList = _activeChar.getEffectList();
final Stream<BuffInfo> passives = effectList.getPassives().stream().filter(BuffInfo::isInUse).filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar)); final Stream<BuffInfo> passives = effectList.getPassives().stream().filter(BuffInfo::isInUse).filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar));
final Stream<BuffInfo> options = effectList.getOptions().stream().filter(BuffInfo::isInUse); final Stream<BuffInfo> options = effectList.getOptions().stream().filter(BuffInfo::isInUse);
final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives != null ? passives : Stream.empty(), options != null ? options : Stream.empty())); final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives, options));
// Call pump to each effect // Call pump to each effect
//@formatter:off //@formatter:off

View File

@@ -389,10 +389,10 @@ public final class BuffInfo
for (AbstractEffect effect : _effects) for (AbstractEffect effect : _effects)
{ {
// Instant effects shouldn't call onExit(..). // Instant effects shouldn't call onExit(..).
if (!effect.isInstant()) // if (!effect.isInstant())
{ // {
effect.onExit(_effector, _effected, _skill); effect.onExit(_effector, _effected, _skill);
} // }
} }
// Set the proper system message. // Set the proper system message.

View File

@@ -21,13 +21,11 @@ import java.util.List;
import com.l2jmobius.commons.network.PacketWriter; import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.skills.BuffInfo; import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.OutgoingPackets; import com.l2jmobius.gameserver.network.OutgoingPackets;
public class AbnormalStatusUpdate implements IClientOutgoingPacket public class AbnormalStatusUpdate implements IClientOutgoingPacket
{ {
private final List<BuffInfo> _effects = new ArrayList<>(); private final List<BuffInfo> _effects = new ArrayList<>();
private final List<Skill> _effects2 = new ArrayList<>();
public void addSkill(BuffInfo info) public void addSkill(BuffInfo info)
{ {
@@ -37,20 +35,12 @@ public class AbnormalStatusUpdate implements IClientOutgoingPacket
} }
} }
public void addSkill(Skill skill)
{
if (!skill.isHealingPotionSkill())
{
_effects2.add(skill);
}
}
@Override @Override
public boolean write(PacketWriter packet) public boolean write(PacketWriter packet)
{ {
OutgoingPackets.ABNORMAL_STATUS_UPDATE.writeId(packet); OutgoingPackets.ABNORMAL_STATUS_UPDATE.writeId(packet);
packet.writeH(_effects.size() + _effects2.size()); packet.writeH(_effects.size());
for (BuffInfo info : _effects) for (BuffInfo info : _effects)
{ {
if ((info != null) && info.isInUse()) if ((info != null) && info.isInUse())
@@ -62,17 +52,6 @@ public class AbnormalStatusUpdate implements IClientOutgoingPacket
writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime()); writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
} }
} }
for (Skill skill : _effects2)
{
if (skill != null)
{
packet.writeD(skill.getDisplayId());
packet.writeH(skill.getDisplayLevel());
// packet.writeH(0x00); // Sub level
packet.writeD(skill.getAbnormalType().getClientId());
packet.writeH(-1);
}
}
return true; return true;
} }
} }

View File

@@ -16,7 +16,6 @@
*/ */
package com.l2jmobius.gameserver.network.serverpackets; package com.l2jmobius.gameserver.network.serverpackets;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -24,40 +23,12 @@ import java.util.stream.Collectors;
import com.l2jmobius.commons.network.PacketWriter; import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.skills.BuffInfo; import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.OutgoingPackets; import com.l2jmobius.gameserver.network.OutgoingPackets;
public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
{ {
private final L2Character _character; private final L2Character _character;
private List<Effect> _effects = new ArrayList<>(); private final List<BuffInfo> _effects;
private static class Effect
{
protected int _skillId;
protected int _level;
protected int _abnormalType;
protected int _duration;
protected int _caster;
public Effect(BuffInfo info)
{
final Skill skill = info.getSkill();
final L2Character caster = info.getEffector();
int casterId = 0;
if (caster != null)
{
casterId = caster.getObjectId();
}
_skillId = skill.getDisplayId();
_level = skill.getDisplayLevel();
// _subLevel = skill.getSubLevel();
_abnormalType = skill.getAbnormalType().getClientId();
_duration = skill.isAura() ? -1 : info.getTime();
_caster = casterId;
}
}
public ExAbnormalStatusUpdateFromTarget(L2Character character) public ExAbnormalStatusUpdateFromTarget(L2Character character)
{ {
@@ -68,7 +39,6 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
.filter(Objects::nonNull) .filter(Objects::nonNull)
.filter(BuffInfo::isInUse) .filter(BuffInfo::isInUse)
.filter(b -> !b.getSkill().isToggle()) .filter(b -> !b.getSkill().isToggle())
.map(Effect::new)
.collect(Collectors.toList()); .collect(Collectors.toList());
//@formatter:on //@formatter:on
} }
@@ -81,13 +51,15 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
packet.writeD(_character.getObjectId()); packet.writeD(_character.getObjectId());
packet.writeH(_effects.size()); packet.writeH(_effects.size());
for (Effect info : _effects) for (BuffInfo info : _effects)
{ {
packet.writeD(info._skillId); packet.writeD(info.getSkill().getDisplayId());
packet.writeH(info._level); packet.writeH(info.getSkill().getDisplayLevel());
packet.writeH(info._abnormalType); // packet.writeH(info.getSkill().getSubLevel());
packet.writeH(info._duration); packet.writeH(info.getSkill().getAbnormalType().getClientId());
packet.writeD(info._caster); // writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
packet.writeH(info.getSkill().isAura() ? -1 : info.getTime());
packet.writeD(info.getEffectorObjectId());
} }
return true; return true;
} }

View File

@@ -16,6 +16,8 @@
*/ */
package handlers.effecthandlers; package handlers.effecthandlers;
import java.util.Collections;
import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.StatsSet;
@@ -38,6 +40,19 @@ public final class CallSkillOnActionTime extends AbstractEffect
setTicks(params.getInt("ticks")); setTicks(params.getInt("ticks"));
} }
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
effected.getEffectList().stopEffects(Collections.singleton(_skill.getSkill().getAbnormalType()));
effected.getEffectList().addBlockedAbnormalTypes(Collections.singleton(_skill.getSkill().getAbnormalType()));
}
@Override
public void onExit(L2Character effector, L2Character effected, Skill skill)
{
effected.getEffectList().removeBlockedAbnormalTypes(Collections.singleton(_skill.getSkill().getAbnormalType()));
}
@Override @Override
public boolean onActionTime(L2Character effector, L2Character effected, Skill skill) public boolean onActionTime(L2Character effector, L2Character effected, Skill skill)
{ {

View File

@@ -136,6 +136,5 @@ public final class Disarmor extends AbstractEffect
} }
} }
} }
super.onExit(effector, effected, skill);
} }
} }

View File

@@ -84,6 +84,5 @@ public final class DoubleCast extends AbstractEffect
return null; return null;
}); });
} }
super.onExit(effector, effected, skill);
} }
} }

View File

@@ -65,15 +65,15 @@ public final class CharEffectList
{ {
private static final Logger LOGGER = Logger.getLogger(CharEffectList.class.getName()); private static final Logger LOGGER = Logger.getLogger(CharEffectList.class.getName());
/** Queue containing all effects from buffs for this effect list. */ /** Queue containing all effects from buffs for this effect list. */
private volatile Queue<BuffInfo> _actives; private volatile Queue<BuffInfo> _actives = new ConcurrentLinkedQueue<>();
/** List containing all passives for this effect list. They bypass most of the actions and they are not included in most operations. */ /** List containing all passives for this effect list. They bypass most of the actions and they are not included in most operations. */
private volatile Set<BuffInfo> _passives; private volatile Set<BuffInfo> _passives = ConcurrentHashMap.newKeySet();
/** List containing all options for this effect list. They bypass most of the actions and they are not included in most operations. */ /** List containing all options for this effect list. They bypass most of the actions and they are not included in most operations. */
private volatile Set<BuffInfo> _options; private volatile Set<BuffInfo> _options = ConcurrentHashMap.newKeySet();
/** Map containing the all stacked effect in progress for each {@code AbnormalType}. */ /** Map containing the all stacked effect in progress for each {@code AbnormalType}. */
private volatile Set<AbnormalType> _stackedEffects = EnumSet.noneOf(AbnormalType.class); private volatile Set<AbnormalType> _stackedEffects = EnumSet.noneOf(AbnormalType.class);
/** Set containing all {@code AbnormalType}s that shouldn't be added to this creature effect list. */ /** Set containing all {@code AbnormalType}s that shouldn't be added to this creature effect list. */
private volatile Set<AbnormalType> _blockedAbnormalTypes = null; private volatile Set<AbnormalType> _blockedAbnormalTypes = EnumSet.noneOf(AbnormalType.class);
/** Set containing all abnormal visual effects this creature currently displays. */ /** Set containing all abnormal visual effects this creature currently displays. */
private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects = EnumSet.noneOf(AbnormalVisualEffect.class); private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects = EnumSet.noneOf(AbnormalVisualEffect.class);
/** Short buff skill ID. */ /** Short buff skill ID. */
@@ -110,7 +110,7 @@ public final class CharEffectList
*/ */
public Set<BuffInfo> getPassives() public Set<BuffInfo> getPassives()
{ {
return _passives != null ? Collections.unmodifiableSet(_passives) : Collections.emptySet(); return Collections.unmodifiableSet(_passives);
} }
/** /**
@@ -119,7 +119,7 @@ public final class CharEffectList
*/ */
public Set<BuffInfo> getOptions() public Set<BuffInfo> getOptions()
{ {
return _options != null ? Collections.unmodifiableSet(_options) : Collections.emptySet(); return Collections.unmodifiableSet(_options);
} }
/** /**
@@ -128,7 +128,7 @@ public final class CharEffectList
*/ */
public Collection<BuffInfo> getEffects() public Collection<BuffInfo> getEffects()
{ {
return _actives != null ? Collections.unmodifiableCollection(_actives) : Collections.emptyList(); return Collections.unmodifiableCollection(_actives);
} }
/** /**
@@ -137,7 +137,7 @@ public final class CharEffectList
*/ */
public List<BuffInfo> getBuffs() public List<BuffInfo> getBuffs()
{ {
return _actives != null ? _actives.stream().filter(b -> !b.getSkill().getBuffType().isBuff()).collect(Collectors.toList()) : Collections.emptyList(); return _actives.stream().filter(b -> !b.getSkill().getBuffType().isBuff()).collect(Collectors.toList());
} }
/** /**
@@ -146,7 +146,7 @@ public final class CharEffectList
*/ */
public List<BuffInfo> getDebuffs() public List<BuffInfo> getDebuffs()
{ {
return _actives != null ? _actives.stream().filter(b -> b.getSkill().isDebuff()).collect(Collectors.toList()) : Collections.emptyList(); return _actives.stream().filter(b -> b.getSkill().isDebuff()).collect(Collectors.toList());
} }
/** /**
@@ -156,7 +156,7 @@ public final class CharEffectList
*/ */
public boolean isAffectedBySkill(int skillId) public boolean isAffectedBySkill(int skillId)
{ {
return ((_actives != null) && _actives.stream().anyMatch(i -> i.getSkill().getId() == skillId)) || ((_passives != null) && _passives.stream().anyMatch(i -> i.getSkill().getId() == skillId)); return (_actives.stream().anyMatch(i -> i.getSkill().getId() == skillId)) || (_passives.stream().anyMatch(i -> i.getSkill().getId() == skillId));
} }
/** /**
@@ -166,7 +166,7 @@ public final class CharEffectList
*/ */
public BuffInfo getBuffInfoBySkillId(int skillId) public BuffInfo getBuffInfoBySkillId(int skillId)
{ {
return Stream.concat(_actives != null ? _actives.stream() : Stream.empty(), _passives != null ? _passives.stream() : Stream.empty()).filter(b -> b.getSkill().getId() == skillId).findFirst().orElse(null); return Stream.concat(_actives.stream(), _passives.stream()).filter(b -> b.getSkill().getId() == skillId).findFirst().orElse(null);
} }
/** /**
@@ -216,18 +216,6 @@ public final class CharEffectList
*/ */
public void addBlockedAbnormalTypes(Set<AbnormalType> blockedAbnormalTypes) public void addBlockedAbnormalTypes(Set<AbnormalType> blockedAbnormalTypes)
{ {
// Initialize
if (_blockedAbnormalTypes == null)
{
synchronized (this)
{
if (_blockedAbnormalTypes == null)
{
_blockedAbnormalTypes = EnumSet.copyOf(blockedAbnormalTypes);
}
}
}
_blockedAbnormalTypes.addAll(blockedAbnormalTypes); _blockedAbnormalTypes.addAll(blockedAbnormalTypes);
} }
@@ -238,7 +226,7 @@ public final class CharEffectList
*/ */
public boolean removeBlockedAbnormalTypes(Set<AbnormalType> blockedBuffSlots) public boolean removeBlockedAbnormalTypes(Set<AbnormalType> blockedBuffSlots)
{ {
return (_blockedAbnormalTypes != null) && _blockedAbnormalTypes.removeAll(blockedBuffSlots); return _blockedAbnormalTypes.removeAll(blockedBuffSlots);
} }
/** /**
@@ -247,7 +235,7 @@ public final class CharEffectList
*/ */
public Set<AbnormalType> getBlockedAbnormalTypes() public Set<AbnormalType> getBlockedAbnormalTypes()
{ {
return _blockedAbnormalTypes != null ? Collections.unmodifiableSet(_blockedAbnormalTypes) : Collections.emptySet(); return Collections.unmodifiableSet(_blockedAbnormalTypes);
} }
/** /**
@@ -277,7 +265,7 @@ public final class CharEffectList
*/ */
public int getBuffCount() public int getBuffCount()
{ {
return _actives != null ? (_buffCount.get() - _hiddenBuffs.get()) : 0; return !_actives.isEmpty() ? (_buffCount.get() - _hiddenBuffs.get()) : 0;
} }
/** /**
@@ -374,7 +362,7 @@ public final class CharEffectList
*/ */
public void stopAllPassives(boolean update, boolean broadcast) public void stopAllPassives(boolean update, boolean broadcast)
{ {
if (_passives != null) if (!_passives.isEmpty())
{ {
_passives.forEach(this::remove); _passives.forEach(this::remove);
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -392,7 +380,7 @@ public final class CharEffectList
*/ */
public void stopAllOptions(boolean update, boolean broadcast) public void stopAllOptions(boolean update, boolean broadcast)
{ {
if (_options != null) if (!_options.isEmpty())
{ {
_options.forEach(this::remove); _options.forEach(this::remove);
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -490,7 +478,7 @@ public final class CharEffectList
*/ */
public void stopEffects(Predicate<BuffInfo> filter, boolean update, boolean broadcast) public void stopEffects(Predicate<BuffInfo> filter, boolean update, boolean broadcast)
{ {
if (_actives != null) if (!_actives.isEmpty())
{ {
_actives.stream().filter(filter).forEach(this::remove); _actives.stream().filter(filter).forEach(this::remove);
@@ -678,6 +666,10 @@ public final class CharEffectList
{ {
// Remove active effect. // Remove active effect.
removeActive(info, removed); removeActive(info, removed);
if (_owner.isNpc()) // Fix for all NPC debuff animations removed.
{
updateEffectList(broadcast);
}
} }
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -693,7 +685,7 @@ public final class CharEffectList
*/ */
private synchronized void removeActive(BuffInfo info, boolean removed) private synchronized void removeActive(BuffInfo info, boolean removed)
{ {
if (_actives != null) if (!_actives.isEmpty())
{ {
// Removes the buff from the given effect list. // Removes the buff from the given effect list.
_actives.remove(info); _actives.remove(info);
@@ -716,7 +708,7 @@ public final class CharEffectList
private void removePassive(BuffInfo info, boolean removed) private void removePassive(BuffInfo info, boolean removed)
{ {
if (_passives != null) if (!_passives.isEmpty())
{ {
_passives.remove(info); _passives.remove(info);
info.stopAllEffects(removed); info.stopAllEffects(removed);
@@ -725,7 +717,7 @@ public final class CharEffectList
private void removeOption(BuffInfo info, boolean removed) private void removeOption(BuffInfo info, boolean removed)
{ {
if (_options != null) if (!_options.isEmpty())
{ {
_options.remove(info); _options.remove(info);
info.stopAllEffects(removed); info.stopAllEffects(removed);
@@ -821,12 +813,6 @@ public final class CharEffectList
} }
} }
// Initialize
if (_actives == null)
{
_actives = new ConcurrentLinkedQueue<>();
}
// Manage effect stacking. // Manage effect stacking.
if (hasAbnormalType(skill.getAbnormalType())) if (hasAbnormalType(skill.getAbnormalType()))
{ {
@@ -857,7 +843,7 @@ public final class CharEffectList
} }
else else
{ {
// Remove effect that gets overriden. // Remove effect that gets overridden.
remove(existingInfo); remove(existingInfo);
} }
} }
@@ -865,7 +851,7 @@ public final class CharEffectList
{ {
info.setInUse(false); info.setInUse(false);
} }
else // The effect we try to add should be overriden. else // The effect we try to add should be overridden.
{ {
return; return;
} }
@@ -918,18 +904,6 @@ public final class CharEffectList
return; return;
} }
// Initialize
if (_passives == null)
{
synchronized (this)
{
if (_passives == null)
{
_passives = ConcurrentHashMap.newKeySet();
}
}
}
// Remove previous passives of this id. // Remove previous passives of this id.
_passives.stream().filter(Objects::nonNull).filter(b -> b.getSkill().getId() == skill.getId()).forEach(b -> _passives.stream().filter(Objects::nonNull).filter(b -> b.getSkill().getId() == skill.getId()).forEach(b ->
{ {
@@ -947,18 +921,6 @@ public final class CharEffectList
{ {
if (info.getOption() != null) if (info.getOption() != null)
{ {
// Initialize
if (_options == null)
{
synchronized (this)
{
if (_options == null)
{
_options = ConcurrentHashMap.newKeySet();
}
}
}
// Remove previous options of this id. // Remove previous options of this id.
_options.stream().filter(Objects::nonNull).filter(b -> b.getOption().getId() == info.getOption().getId()).forEach(b -> _options.stream().filter(Objects::nonNull).filter(b -> b.getOption().getId() == info.getOption().getId()).forEach(b ->
{ {
@@ -988,7 +950,7 @@ public final class CharEffectList
final Optional<PartySpelled> ps = ((party != null) || _owner.isSummon()) ? Optional.of(new PartySpelled(_owner)) : Optional.empty(); final Optional<PartySpelled> ps = ((party != null) || _owner.isSummon()) ? Optional.of(new PartySpelled(_owner)) : Optional.empty();
final Optional<ExOlympiadSpelledInfo> os = (player.isInOlympiadMode() && player.isOlympiadStart()) ? Optional.of(new ExOlympiadSpelledInfo(player)) : Optional.empty(); final Optional<ExOlympiadSpelledInfo> os = (player.isInOlympiadMode() && player.isOlympiadStart()) ? Optional.of(new ExOlympiadSpelledInfo(player)) : Optional.empty();
if (_actives != null) if (!_actives.isEmpty())
{ {
//@formatter:off //@formatter:off
_actives.stream() _actives.stream()
@@ -1109,8 +1071,6 @@ public final class CharEffectList
final Set<BuffInfo> unhideBuffs = new HashSet<>(); final Set<BuffInfo> unhideBuffs = new HashSet<>();
// Recalculate new flags // Recalculate new flags
if (_actives != null)
{
for (BuffInfo info : _actives) for (BuffInfo info : _actives)
{ {
if (info != null) if (info != null)
@@ -1144,7 +1104,14 @@ public final class CharEffectList
// Add AbnormalVisualEffect flag. // Add AbnormalVisualEffect flag.
if (skill.hasAbnormalVisualEffects()) if (skill.hasAbnormalVisualEffects())
{ {
abnormalVisualEffectFlags.addAll(skill.getAbnormalVisualEffects()); for (AbnormalVisualEffect ave : skill.getAbnormalVisualEffects())
{
abnormalVisualEffectFlags.add(ave);
_abnormalVisualEffects.add(ave);
}
if (broadcast)
{
_owner.updateAbnormalVisualEffects();
} }
} }
} }
@@ -1167,7 +1134,7 @@ public final class CharEffectList
if (broadcast) if (broadcast)
{ {
// Check if there is change in AbnormalVisualEffect // Check if there is change in AbnormalVisualEffect
if ((abnormalVisualEffectFlags.size() != _abnormalVisualEffects.size()) || !abnormalVisualEffectFlags.containsAll(_abnormalVisualEffects)) if (!abnormalVisualEffectFlags.containsAll(_abnormalVisualEffects))
{ {
_abnormalVisualEffects = abnormalVisualEffectFlags; _abnormalVisualEffects = abnormalVisualEffectFlags;
_owner.updateAbnormalVisualEffects(); _owner.updateAbnormalVisualEffects();

View File

@@ -77,7 +77,6 @@ public class DoppelgangerInstance extends L2Npc
info.setAbnormalTime(summonerInfo.getAbnormalTime()); info.setAbnormalTime(summonerInfo.getAbnormalTime());
getEffectList().add(info); getEffectList().add(info);
} }
} }
} }
} }

View File

@@ -786,7 +786,7 @@ public class CharStat
final CharEffectList effectList = _activeChar.getEffectList(); final CharEffectList effectList = _activeChar.getEffectList();
final Stream<BuffInfo> passives = effectList.getPassives().stream().filter(BuffInfo::isInUse).filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar)); final Stream<BuffInfo> passives = effectList.getPassives().stream().filter(BuffInfo::isInUse).filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar));
final Stream<BuffInfo> options = effectList.getOptions().stream().filter(BuffInfo::isInUse); final Stream<BuffInfo> options = effectList.getOptions().stream().filter(BuffInfo::isInUse);
final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives != null ? passives : Stream.empty(), options != null ? options : Stream.empty())); final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives, options));
// Call pump to each effect // Call pump to each effect
//@formatter:off //@formatter:off

View File

@@ -389,10 +389,10 @@ public final class BuffInfo
for (AbstractEffect effect : _effects) for (AbstractEffect effect : _effects)
{ {
// Instant effects shouldn't call onExit(..). // Instant effects shouldn't call onExit(..).
if (!effect.isInstant()) // if (!effect.isInstant())
{ // {
effect.onExit(_effector, _effected, _skill); effect.onExit(_effector, _effected, _skill);
} // }
} }
// Set the proper system message. // Set the proper system message.

View File

@@ -21,13 +21,11 @@ import java.util.List;
import com.l2jmobius.commons.network.PacketWriter; import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.skills.BuffInfo; import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.OutgoingPackets; import com.l2jmobius.gameserver.network.OutgoingPackets;
public class AbnormalStatusUpdate implements IClientOutgoingPacket public class AbnormalStatusUpdate implements IClientOutgoingPacket
{ {
private final List<BuffInfo> _effects = new ArrayList<>(); private final List<BuffInfo> _effects = new ArrayList<>();
private final List<Skill> _effects2 = new ArrayList<>();
public void addSkill(BuffInfo info) public void addSkill(BuffInfo info)
{ {
@@ -37,20 +35,12 @@ public class AbnormalStatusUpdate implements IClientOutgoingPacket
} }
} }
public void addSkill(Skill skill)
{
if (!skill.isHealingPotionSkill())
{
_effects2.add(skill);
}
}
@Override @Override
public boolean write(PacketWriter packet) public boolean write(PacketWriter packet)
{ {
OutgoingPackets.ABNORMAL_STATUS_UPDATE.writeId(packet); OutgoingPackets.ABNORMAL_STATUS_UPDATE.writeId(packet);
packet.writeH(_effects.size() + _effects2.size()); packet.writeH(_effects.size());
for (BuffInfo info : _effects) for (BuffInfo info : _effects)
{ {
if ((info != null) && info.isInUse()) if ((info != null) && info.isInUse())
@@ -62,17 +52,6 @@ public class AbnormalStatusUpdate implements IClientOutgoingPacket
writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime()); writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
} }
} }
for (Skill skill : _effects2)
{
if (skill != null)
{
packet.writeD(skill.getDisplayId());
packet.writeH(skill.getDisplayLevel());
packet.writeH(0x00); // Sub level
packet.writeD(skill.getAbnormalType().getClientId());
packet.writeH(-1);
}
}
return true; return true;
} }
} }

View File

@@ -16,7 +16,6 @@
*/ */
package com.l2jmobius.gameserver.network.serverpackets; package com.l2jmobius.gameserver.network.serverpackets;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -24,41 +23,12 @@ import java.util.stream.Collectors;
import com.l2jmobius.commons.network.PacketWriter; import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.skills.BuffInfo; import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.OutgoingPackets; import com.l2jmobius.gameserver.network.OutgoingPackets;
public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
{ {
private final L2Character _character; private final L2Character _character;
private List<Effect> _effects = new ArrayList<>(); private final List<BuffInfo> _effects;
private static class Effect
{
protected int _skillId;
protected int _level;
protected int _subLevel;
protected int _abnormalType;
protected int _duration;
protected int _caster;
public Effect(BuffInfo info)
{
final Skill skill = info.getSkill();
final L2Character caster = info.getEffector();
int casterId = 0;
if (caster != null)
{
casterId = caster.getObjectId();
}
_skillId = skill.getDisplayId();
_level = skill.getDisplayLevel();
_subLevel = skill.getSubLevel();
_abnormalType = skill.getAbnormalType().getClientId();
_duration = skill.isAura() ? -1 : info.getTime();
_caster = casterId;
}
}
public ExAbnormalStatusUpdateFromTarget(L2Character character) public ExAbnormalStatusUpdateFromTarget(L2Character character)
{ {
@@ -69,7 +39,6 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
.filter(Objects::nonNull) .filter(Objects::nonNull)
.filter(BuffInfo::isInUse) .filter(BuffInfo::isInUse)
.filter(b -> !b.getSkill().isToggle()) .filter(b -> !b.getSkill().isToggle())
.map(Effect::new)
.collect(Collectors.toList()); .collect(Collectors.toList());
//@formatter:on //@formatter:on
} }
@@ -82,14 +51,14 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
packet.writeD(_character.getObjectId()); packet.writeD(_character.getObjectId());
packet.writeH(_effects.size()); packet.writeH(_effects.size());
for (Effect info : _effects) for (BuffInfo info : _effects)
{ {
packet.writeD(info._skillId); packet.writeD(info.getSkill().getDisplayId());
packet.writeH(info._level); packet.writeH(info.getSkill().getDisplayLevel());
packet.writeH(info._subLevel); packet.writeH(info.getSkill().getSubLevel());
packet.writeH(info._abnormalType); packet.writeH(info.getSkill().getAbnormalType().getClientId());
writeOptionalD(packet, info._duration); writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
packet.writeD(info._caster); packet.writeD(info.getEffectorObjectId());
} }
return true; return true;
} }

View File

@@ -16,6 +16,8 @@
*/ */
package handlers.effecthandlers; package handlers.effecthandlers;
import java.util.Collections;
import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.StatsSet;
@@ -38,6 +40,19 @@ public final class CallSkillOnActionTime extends AbstractEffect
setTicks(params.getInt("ticks")); setTicks(params.getInt("ticks"));
} }
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
effected.getEffectList().stopEffects(Collections.singleton(_skill.getSkill().getAbnormalType()));
effected.getEffectList().addBlockedAbnormalTypes(Collections.singleton(_skill.getSkill().getAbnormalType()));
}
@Override
public void onExit(L2Character effector, L2Character effected, Skill skill)
{
effected.getEffectList().removeBlockedAbnormalTypes(Collections.singleton(_skill.getSkill().getAbnormalType()));
}
@Override @Override
public boolean onActionTime(L2Character effector, L2Character effected, Skill skill) public boolean onActionTime(L2Character effector, L2Character effected, Skill skill)
{ {

View File

@@ -136,6 +136,5 @@ public final class Disarmor extends AbstractEffect
} }
} }
} }
super.onExit(effector, effected, skill);
} }
} }

View File

@@ -84,6 +84,5 @@ public final class DoubleCast extends AbstractEffect
return null; return null;
}); });
} }
super.onExit(effector, effected, skill);
} }
} }

View File

@@ -65,15 +65,15 @@ public final class CharEffectList
{ {
private static final Logger LOGGER = Logger.getLogger(CharEffectList.class.getName()); private static final Logger LOGGER = Logger.getLogger(CharEffectList.class.getName());
/** Queue containing all effects from buffs for this effect list. */ /** Queue containing all effects from buffs for this effect list. */
private volatile Queue<BuffInfo> _actives; private volatile Queue<BuffInfo> _actives = new ConcurrentLinkedQueue<>();
/** List containing all passives for this effect list. They bypass most of the actions and they are not included in most operations. */ /** List containing all passives for this effect list. They bypass most of the actions and they are not included in most operations. */
private volatile Set<BuffInfo> _passives; private volatile Set<BuffInfo> _passives = ConcurrentHashMap.newKeySet();
/** List containing all options for this effect list. They bypass most of the actions and they are not included in most operations. */ /** List containing all options for this effect list. They bypass most of the actions and they are not included in most operations. */
private volatile Set<BuffInfo> _options; private volatile Set<BuffInfo> _options = ConcurrentHashMap.newKeySet();
/** Map containing the all stacked effect in progress for each {@code AbnormalType}. */ /** Map containing the all stacked effect in progress for each {@code AbnormalType}. */
private volatile Set<AbnormalType> _stackedEffects = EnumSet.noneOf(AbnormalType.class); private volatile Set<AbnormalType> _stackedEffects = EnumSet.noneOf(AbnormalType.class);
/** Set containing all {@code AbnormalType}s that shouldn't be added to this creature effect list. */ /** Set containing all {@code AbnormalType}s that shouldn't be added to this creature effect list. */
private volatile Set<AbnormalType> _blockedAbnormalTypes = null; private volatile Set<AbnormalType> _blockedAbnormalTypes = EnumSet.noneOf(AbnormalType.class);
/** Set containing all abnormal visual effects this creature currently displays. */ /** Set containing all abnormal visual effects this creature currently displays. */
private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects = EnumSet.noneOf(AbnormalVisualEffect.class); private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects = EnumSet.noneOf(AbnormalVisualEffect.class);
/** Short buff skill ID. */ /** Short buff skill ID. */
@@ -110,7 +110,7 @@ public final class CharEffectList
*/ */
public Set<BuffInfo> getPassives() public Set<BuffInfo> getPassives()
{ {
return _passives != null ? Collections.unmodifiableSet(_passives) : Collections.emptySet(); return Collections.unmodifiableSet(_passives);
} }
/** /**
@@ -119,7 +119,7 @@ public final class CharEffectList
*/ */
public Set<BuffInfo> getOptions() public Set<BuffInfo> getOptions()
{ {
return _options != null ? Collections.unmodifiableSet(_options) : Collections.emptySet(); return Collections.unmodifiableSet(_options);
} }
/** /**
@@ -128,7 +128,7 @@ public final class CharEffectList
*/ */
public Collection<BuffInfo> getEffects() public Collection<BuffInfo> getEffects()
{ {
return _actives != null ? Collections.unmodifiableCollection(_actives) : Collections.emptyList(); return Collections.unmodifiableCollection(_actives);
} }
/** /**
@@ -137,7 +137,7 @@ public final class CharEffectList
*/ */
public List<BuffInfo> getBuffs() public List<BuffInfo> getBuffs()
{ {
return _actives != null ? _actives.stream().filter(b -> !b.getSkill().getBuffType().isBuff()).collect(Collectors.toList()) : Collections.emptyList(); return _actives.stream().filter(b -> !b.getSkill().getBuffType().isBuff()).collect(Collectors.toList());
} }
/** /**
@@ -146,7 +146,7 @@ public final class CharEffectList
*/ */
public List<BuffInfo> getDebuffs() public List<BuffInfo> getDebuffs()
{ {
return _actives != null ? _actives.stream().filter(b -> b.getSkill().isDebuff()).collect(Collectors.toList()) : Collections.emptyList(); return _actives.stream().filter(b -> b.getSkill().isDebuff()).collect(Collectors.toList());
} }
/** /**
@@ -156,7 +156,7 @@ public final class CharEffectList
*/ */
public boolean isAffectedBySkill(int skillId) public boolean isAffectedBySkill(int skillId)
{ {
return ((_actives != null) && _actives.stream().anyMatch(i -> i.getSkill().getId() == skillId)) || ((_passives != null) && _passives.stream().anyMatch(i -> i.getSkill().getId() == skillId)); return (_actives.stream().anyMatch(i -> i.getSkill().getId() == skillId)) || (_passives.stream().anyMatch(i -> i.getSkill().getId() == skillId));
} }
/** /**
@@ -166,7 +166,7 @@ public final class CharEffectList
*/ */
public BuffInfo getBuffInfoBySkillId(int skillId) public BuffInfo getBuffInfoBySkillId(int skillId)
{ {
return Stream.concat(_actives != null ? _actives.stream() : Stream.empty(), _passives != null ? _passives.stream() : Stream.empty()).filter(b -> b.getSkill().getId() == skillId).findFirst().orElse(null); return Stream.concat(_actives.stream(), _passives.stream()).filter(b -> b.getSkill().getId() == skillId).findFirst().orElse(null);
} }
/** /**
@@ -216,18 +216,6 @@ public final class CharEffectList
*/ */
public void addBlockedAbnormalTypes(Set<AbnormalType> blockedAbnormalTypes) public void addBlockedAbnormalTypes(Set<AbnormalType> blockedAbnormalTypes)
{ {
// Initialize
if (_blockedAbnormalTypes == null)
{
synchronized (this)
{
if (_blockedAbnormalTypes == null)
{
_blockedAbnormalTypes = EnumSet.copyOf(blockedAbnormalTypes);
}
}
}
_blockedAbnormalTypes.addAll(blockedAbnormalTypes); _blockedAbnormalTypes.addAll(blockedAbnormalTypes);
} }
@@ -238,7 +226,7 @@ public final class CharEffectList
*/ */
public boolean removeBlockedAbnormalTypes(Set<AbnormalType> blockedBuffSlots) public boolean removeBlockedAbnormalTypes(Set<AbnormalType> blockedBuffSlots)
{ {
return (_blockedAbnormalTypes != null) && _blockedAbnormalTypes.removeAll(blockedBuffSlots); return _blockedAbnormalTypes.removeAll(blockedBuffSlots);
} }
/** /**
@@ -247,7 +235,7 @@ public final class CharEffectList
*/ */
public Set<AbnormalType> getBlockedAbnormalTypes() public Set<AbnormalType> getBlockedAbnormalTypes()
{ {
return _blockedAbnormalTypes != null ? Collections.unmodifiableSet(_blockedAbnormalTypes) : Collections.emptySet(); return Collections.unmodifiableSet(_blockedAbnormalTypes);
} }
/** /**
@@ -277,7 +265,7 @@ public final class CharEffectList
*/ */
public int getBuffCount() public int getBuffCount()
{ {
return _actives != null ? (_buffCount.get() - _hiddenBuffs.get()) : 0; return !_actives.isEmpty() ? (_buffCount.get() - _hiddenBuffs.get()) : 0;
} }
/** /**
@@ -374,7 +362,7 @@ public final class CharEffectList
*/ */
public void stopAllPassives(boolean update, boolean broadcast) public void stopAllPassives(boolean update, boolean broadcast)
{ {
if (_passives != null) if (!_passives.isEmpty())
{ {
_passives.forEach(this::remove); _passives.forEach(this::remove);
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -392,7 +380,7 @@ public final class CharEffectList
*/ */
public void stopAllOptions(boolean update, boolean broadcast) public void stopAllOptions(boolean update, boolean broadcast)
{ {
if (_options != null) if (!_options.isEmpty())
{ {
_options.forEach(this::remove); _options.forEach(this::remove);
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -490,7 +478,7 @@ public final class CharEffectList
*/ */
public void stopEffects(Predicate<BuffInfo> filter, boolean update, boolean broadcast) public void stopEffects(Predicate<BuffInfo> filter, boolean update, boolean broadcast)
{ {
if (_actives != null) if (!_actives.isEmpty())
{ {
_actives.stream().filter(filter).forEach(this::remove); _actives.stream().filter(filter).forEach(this::remove);
@@ -678,6 +666,10 @@ public final class CharEffectList
{ {
// Remove active effect. // Remove active effect.
removeActive(info, removed); removeActive(info, removed);
if (_owner.isNpc()) // Fix for all NPC debuff animations removed.
{
updateEffectList(broadcast);
}
} }
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -693,7 +685,7 @@ public final class CharEffectList
*/ */
private synchronized void removeActive(BuffInfo info, boolean removed) private synchronized void removeActive(BuffInfo info, boolean removed)
{ {
if (_actives != null) if (!_actives.isEmpty())
{ {
// Removes the buff from the given effect list. // Removes the buff from the given effect list.
_actives.remove(info); _actives.remove(info);
@@ -716,7 +708,7 @@ public final class CharEffectList
private void removePassive(BuffInfo info, boolean removed) private void removePassive(BuffInfo info, boolean removed)
{ {
if (_passives != null) if (!_passives.isEmpty())
{ {
_passives.remove(info); _passives.remove(info);
info.stopAllEffects(removed); info.stopAllEffects(removed);
@@ -725,7 +717,7 @@ public final class CharEffectList
private void removeOption(BuffInfo info, boolean removed) private void removeOption(BuffInfo info, boolean removed)
{ {
if (_options != null) if (!_options.isEmpty())
{ {
_options.remove(info); _options.remove(info);
info.stopAllEffects(removed); info.stopAllEffects(removed);
@@ -821,12 +813,6 @@ public final class CharEffectList
} }
} }
// Initialize
if (_actives == null)
{
_actives = new ConcurrentLinkedQueue<>();
}
// Manage effect stacking. // Manage effect stacking.
if (hasAbnormalType(skill.getAbnormalType())) if (hasAbnormalType(skill.getAbnormalType()))
{ {
@@ -857,7 +843,7 @@ public final class CharEffectList
} }
else else
{ {
// Remove effect that gets overriden. // Remove effect that gets overridden.
remove(existingInfo); remove(existingInfo);
} }
} }
@@ -865,7 +851,7 @@ public final class CharEffectList
{ {
info.setInUse(false); info.setInUse(false);
} }
else // The effect we try to add should be overriden. else // The effect we try to add should be overridden.
{ {
return; return;
} }
@@ -918,18 +904,6 @@ public final class CharEffectList
return; return;
} }
// Initialize
if (_passives == null)
{
synchronized (this)
{
if (_passives == null)
{
_passives = ConcurrentHashMap.newKeySet();
}
}
}
// Remove previous passives of this id. // Remove previous passives of this id.
_passives.stream().filter(Objects::nonNull).filter(b -> b.getSkill().getId() == skill.getId()).forEach(b -> _passives.stream().filter(Objects::nonNull).filter(b -> b.getSkill().getId() == skill.getId()).forEach(b ->
{ {
@@ -947,18 +921,6 @@ public final class CharEffectList
{ {
if (info.getOption() != null) if (info.getOption() != null)
{ {
// Initialize
if (_options == null)
{
synchronized (this)
{
if (_options == null)
{
_options = ConcurrentHashMap.newKeySet();
}
}
}
// Remove previous options of this id. // Remove previous options of this id.
_options.stream().filter(Objects::nonNull).filter(b -> b.getOption().getId() == info.getOption().getId()).forEach(b -> _options.stream().filter(Objects::nonNull).filter(b -> b.getOption().getId() == info.getOption().getId()).forEach(b ->
{ {
@@ -988,7 +950,7 @@ public final class CharEffectList
final Optional<PartySpelled> ps = ((party != null) || _owner.isSummon()) ? Optional.of(new PartySpelled(_owner)) : Optional.empty(); final Optional<PartySpelled> ps = ((party != null) || _owner.isSummon()) ? Optional.of(new PartySpelled(_owner)) : Optional.empty();
final Optional<ExOlympiadSpelledInfo> os = (player.isInOlympiadMode() && player.isOlympiadStart()) ? Optional.of(new ExOlympiadSpelledInfo(player)) : Optional.empty(); final Optional<ExOlympiadSpelledInfo> os = (player.isInOlympiadMode() && player.isOlympiadStart()) ? Optional.of(new ExOlympiadSpelledInfo(player)) : Optional.empty();
if (_actives != null) if (!_actives.isEmpty())
{ {
//@formatter:off //@formatter:off
_actives.stream() _actives.stream()
@@ -1109,8 +1071,6 @@ public final class CharEffectList
final Set<BuffInfo> unhideBuffs = new HashSet<>(); final Set<BuffInfo> unhideBuffs = new HashSet<>();
// Recalculate new flags // Recalculate new flags
if (_actives != null)
{
for (BuffInfo info : _actives) for (BuffInfo info : _actives)
{ {
if (info != null) if (info != null)
@@ -1144,7 +1104,14 @@ public final class CharEffectList
// Add AbnormalVisualEffect flag. // Add AbnormalVisualEffect flag.
if (skill.hasAbnormalVisualEffects()) if (skill.hasAbnormalVisualEffects())
{ {
abnormalVisualEffectFlags.addAll(skill.getAbnormalVisualEffects()); for (AbnormalVisualEffect ave : skill.getAbnormalVisualEffects())
{
abnormalVisualEffectFlags.add(ave);
_abnormalVisualEffects.add(ave);
}
if (broadcast)
{
_owner.updateAbnormalVisualEffects();
} }
} }
} }
@@ -1167,7 +1134,7 @@ public final class CharEffectList
if (broadcast) if (broadcast)
{ {
// Check if there is change in AbnormalVisualEffect // Check if there is change in AbnormalVisualEffect
if ((abnormalVisualEffectFlags.size() != _abnormalVisualEffects.size()) || !abnormalVisualEffectFlags.containsAll(_abnormalVisualEffects)) if (!abnormalVisualEffectFlags.containsAll(_abnormalVisualEffects))
{ {
_abnormalVisualEffects = abnormalVisualEffectFlags; _abnormalVisualEffects = abnormalVisualEffectFlags;
_owner.updateAbnormalVisualEffects(); _owner.updateAbnormalVisualEffects();

View File

@@ -77,7 +77,6 @@ public class DoppelgangerInstance extends L2Npc
info.setAbnormalTime(summonerInfo.getAbnormalTime()); info.setAbnormalTime(summonerInfo.getAbnormalTime());
getEffectList().add(info); getEffectList().add(info);
} }
} }
} }
} }

View File

@@ -786,7 +786,7 @@ public class CharStat
final CharEffectList effectList = _activeChar.getEffectList(); final CharEffectList effectList = _activeChar.getEffectList();
final Stream<BuffInfo> passives = effectList.getPassives().stream().filter(BuffInfo::isInUse).filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar)); final Stream<BuffInfo> passives = effectList.getPassives().stream().filter(BuffInfo::isInUse).filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar));
final Stream<BuffInfo> options = effectList.getOptions().stream().filter(BuffInfo::isInUse); final Stream<BuffInfo> options = effectList.getOptions().stream().filter(BuffInfo::isInUse);
final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives != null ? passives : Stream.empty(), options != null ? options : Stream.empty())); final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives, options));
// Call pump to each effect // Call pump to each effect
//@formatter:off //@formatter:off

View File

@@ -389,10 +389,10 @@ public final class BuffInfo
for (AbstractEffect effect : _effects) for (AbstractEffect effect : _effects)
{ {
// Instant effects shouldn't call onExit(..). // Instant effects shouldn't call onExit(..).
if (!effect.isInstant()) // if (!effect.isInstant())
{ // {
effect.onExit(_effector, _effected, _skill); effect.onExit(_effector, _effected, _skill);
} // }
} }
// Set the proper system message. // Set the proper system message.

View File

@@ -21,13 +21,11 @@ import java.util.List;
import com.l2jmobius.commons.network.PacketWriter; import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.skills.BuffInfo; import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.OutgoingPackets; import com.l2jmobius.gameserver.network.OutgoingPackets;
public class AbnormalStatusUpdate implements IClientOutgoingPacket public class AbnormalStatusUpdate implements IClientOutgoingPacket
{ {
private final List<BuffInfo> _effects = new ArrayList<>(); private final List<BuffInfo> _effects = new ArrayList<>();
private final List<Skill> _effects2 = new ArrayList<>();
public void addSkill(BuffInfo info) public void addSkill(BuffInfo info)
{ {
@@ -37,20 +35,12 @@ public class AbnormalStatusUpdate implements IClientOutgoingPacket
} }
} }
public void addSkill(Skill skill)
{
if (!skill.isHealingPotionSkill())
{
_effects2.add(skill);
}
}
@Override @Override
public boolean write(PacketWriter packet) public boolean write(PacketWriter packet)
{ {
OutgoingPackets.ABNORMAL_STATUS_UPDATE.writeId(packet); OutgoingPackets.ABNORMAL_STATUS_UPDATE.writeId(packet);
packet.writeH(_effects.size() + _effects2.size()); packet.writeH(_effects.size());
for (BuffInfo info : _effects) for (BuffInfo info : _effects)
{ {
if ((info != null) && info.isInUse()) if ((info != null) && info.isInUse())
@@ -62,17 +52,6 @@ public class AbnormalStatusUpdate implements IClientOutgoingPacket
writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime()); writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
} }
} }
for (Skill skill : _effects2)
{
if (skill != null)
{
packet.writeD(skill.getDisplayId());
packet.writeH(skill.getDisplayLevel());
packet.writeH(0x00); // Sub level
packet.writeD(skill.getAbnormalType().getClientId());
packet.writeH(-1);
}
}
return true; return true;
} }
} }

View File

@@ -16,7 +16,6 @@
*/ */
package com.l2jmobius.gameserver.network.serverpackets; package com.l2jmobius.gameserver.network.serverpackets;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -24,41 +23,12 @@ import java.util.stream.Collectors;
import com.l2jmobius.commons.network.PacketWriter; import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.skills.BuffInfo; import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.OutgoingPackets; import com.l2jmobius.gameserver.network.OutgoingPackets;
public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
{ {
private final L2Character _character; private final L2Character _character;
private List<Effect> _effects = new ArrayList<>(); private final List<BuffInfo> _effects;
private static class Effect
{
protected int _skillId;
protected int _level;
protected int _subLevel;
protected int _abnormalType;
protected int _duration;
protected int _caster;
public Effect(BuffInfo info)
{
final Skill skill = info.getSkill();
final L2Character caster = info.getEffector();
int casterId = 0;
if (caster != null)
{
casterId = caster.getObjectId();
}
_skillId = skill.getDisplayId();
_level = skill.getDisplayLevel();
_subLevel = skill.getSubLevel();
_abnormalType = skill.getAbnormalType().getClientId();
_duration = skill.isAura() ? -1 : info.getTime();
_caster = casterId;
}
}
public ExAbnormalStatusUpdateFromTarget(L2Character character) public ExAbnormalStatusUpdateFromTarget(L2Character character)
{ {
@@ -69,7 +39,6 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
.filter(Objects::nonNull) .filter(Objects::nonNull)
.filter(BuffInfo::isInUse) .filter(BuffInfo::isInUse)
.filter(b -> !b.getSkill().isToggle()) .filter(b -> !b.getSkill().isToggle())
.map(Effect::new)
.collect(Collectors.toList()); .collect(Collectors.toList());
//@formatter:on //@formatter:on
} }
@@ -82,14 +51,14 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
packet.writeD(_character.getObjectId()); packet.writeD(_character.getObjectId());
packet.writeH(_effects.size()); packet.writeH(_effects.size());
for (Effect info : _effects) for (BuffInfo info : _effects)
{ {
packet.writeD(info._skillId); packet.writeD(info.getSkill().getDisplayId());
packet.writeH(info._level); packet.writeH(info.getSkill().getDisplayLevel());
packet.writeH(info._subLevel); packet.writeH(info.getSkill().getSubLevel());
packet.writeH(info._abnormalType); packet.writeH(info.getSkill().getAbnormalType().getClientId());
writeOptionalD(packet, info._duration); writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
packet.writeD(info._caster); packet.writeD(info.getEffectorObjectId());
} }
return true; return true;
} }

View File

@@ -16,6 +16,8 @@
*/ */
package handlers.effecthandlers; package handlers.effecthandlers;
import java.util.Collections;
import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.StatsSet;
@@ -38,6 +40,19 @@ public final class CallSkillOnActionTime extends AbstractEffect
setTicks(params.getInt("ticks")); setTicks(params.getInt("ticks"));
} }
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
effected.getEffectList().stopEffects(Collections.singleton(_skill.getSkill().getAbnormalType()));
effected.getEffectList().addBlockedAbnormalTypes(Collections.singleton(_skill.getSkill().getAbnormalType()));
}
@Override
public void onExit(L2Character effector, L2Character effected, Skill skill)
{
effected.getEffectList().removeBlockedAbnormalTypes(Collections.singleton(_skill.getSkill().getAbnormalType()));
}
@Override @Override
public boolean onActionTime(L2Character effector, L2Character effected, Skill skill) public boolean onActionTime(L2Character effector, L2Character effected, Skill skill)
{ {

View File

@@ -136,6 +136,5 @@ public final class Disarmor extends AbstractEffect
} }
} }
} }
super.onExit(effector, effected, skill);
} }
} }

View File

@@ -84,6 +84,5 @@ public final class DoubleCast extends AbstractEffect
return null; return null;
}); });
} }
super.onExit(effector, effected, skill);
} }
} }

View File

@@ -65,15 +65,15 @@ public final class CharEffectList
{ {
private static final Logger LOGGER = Logger.getLogger(CharEffectList.class.getName()); private static final Logger LOGGER = Logger.getLogger(CharEffectList.class.getName());
/** Queue containing all effects from buffs for this effect list. */ /** Queue containing all effects from buffs for this effect list. */
private volatile Queue<BuffInfo> _actives; private volatile Queue<BuffInfo> _actives = new ConcurrentLinkedQueue<>();
/** List containing all passives for this effect list. They bypass most of the actions and they are not included in most operations. */ /** List containing all passives for this effect list. They bypass most of the actions and they are not included in most operations. */
private volatile Set<BuffInfo> _passives; private volatile Set<BuffInfo> _passives = ConcurrentHashMap.newKeySet();
/** List containing all options for this effect list. They bypass most of the actions and they are not included in most operations. */ /** List containing all options for this effect list. They bypass most of the actions and they are not included in most operations. */
private volatile Set<BuffInfo> _options; private volatile Set<BuffInfo> _options = ConcurrentHashMap.newKeySet();
/** Map containing the all stacked effect in progress for each {@code AbnormalType}. */ /** Map containing the all stacked effect in progress for each {@code AbnormalType}. */
private volatile Set<AbnormalType> _stackedEffects = EnumSet.noneOf(AbnormalType.class); private volatile Set<AbnormalType> _stackedEffects = EnumSet.noneOf(AbnormalType.class);
/** Set containing all {@code AbnormalType}s that shouldn't be added to this creature effect list. */ /** Set containing all {@code AbnormalType}s that shouldn't be added to this creature effect list. */
private volatile Set<AbnormalType> _blockedAbnormalTypes = null; private volatile Set<AbnormalType> _blockedAbnormalTypes = EnumSet.noneOf(AbnormalType.class);
/** Set containing all abnormal visual effects this creature currently displays. */ /** Set containing all abnormal visual effects this creature currently displays. */
private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects = EnumSet.noneOf(AbnormalVisualEffect.class); private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects = EnumSet.noneOf(AbnormalVisualEffect.class);
/** Short buff skill ID. */ /** Short buff skill ID. */
@@ -110,7 +110,7 @@ public final class CharEffectList
*/ */
public Set<BuffInfo> getPassives() public Set<BuffInfo> getPassives()
{ {
return _passives != null ? Collections.unmodifiableSet(_passives) : Collections.emptySet(); return Collections.unmodifiableSet(_passives);
} }
/** /**
@@ -119,7 +119,7 @@ public final class CharEffectList
*/ */
public Set<BuffInfo> getOptions() public Set<BuffInfo> getOptions()
{ {
return _options != null ? Collections.unmodifiableSet(_options) : Collections.emptySet(); return Collections.unmodifiableSet(_options);
} }
/** /**
@@ -128,7 +128,7 @@ public final class CharEffectList
*/ */
public Collection<BuffInfo> getEffects() public Collection<BuffInfo> getEffects()
{ {
return _actives != null ? Collections.unmodifiableCollection(_actives) : Collections.emptyList(); return Collections.unmodifiableCollection(_actives);
} }
/** /**
@@ -137,7 +137,7 @@ public final class CharEffectList
*/ */
public List<BuffInfo> getBuffs() public List<BuffInfo> getBuffs()
{ {
return _actives != null ? _actives.stream().filter(b -> !b.getSkill().getBuffType().isBuff()).collect(Collectors.toList()) : Collections.emptyList(); return _actives.stream().filter(b -> !b.getSkill().getBuffType().isBuff()).collect(Collectors.toList());
} }
/** /**
@@ -146,7 +146,7 @@ public final class CharEffectList
*/ */
public List<BuffInfo> getDebuffs() public List<BuffInfo> getDebuffs()
{ {
return _actives != null ? _actives.stream().filter(b -> b.getSkill().isDebuff()).collect(Collectors.toList()) : Collections.emptyList(); return _actives.stream().filter(b -> b.getSkill().isDebuff()).collect(Collectors.toList());
} }
/** /**
@@ -156,7 +156,7 @@ public final class CharEffectList
*/ */
public boolean isAffectedBySkill(int skillId) public boolean isAffectedBySkill(int skillId)
{ {
return ((_actives != null) && _actives.stream().anyMatch(i -> i.getSkill().getId() == skillId)) || ((_passives != null) && _passives.stream().anyMatch(i -> i.getSkill().getId() == skillId)); return (_actives.stream().anyMatch(i -> i.getSkill().getId() == skillId)) || (_passives.stream().anyMatch(i -> i.getSkill().getId() == skillId));
} }
/** /**
@@ -166,7 +166,7 @@ public final class CharEffectList
*/ */
public BuffInfo getBuffInfoBySkillId(int skillId) public BuffInfo getBuffInfoBySkillId(int skillId)
{ {
return Stream.concat(_actives != null ? _actives.stream() : Stream.empty(), _passives != null ? _passives.stream() : Stream.empty()).filter(b -> b.getSkill().getId() == skillId).findFirst().orElse(null); return Stream.concat(_actives.stream(), _passives.stream()).filter(b -> b.getSkill().getId() == skillId).findFirst().orElse(null);
} }
/** /**
@@ -216,18 +216,6 @@ public final class CharEffectList
*/ */
public void addBlockedAbnormalTypes(Set<AbnormalType> blockedAbnormalTypes) public void addBlockedAbnormalTypes(Set<AbnormalType> blockedAbnormalTypes)
{ {
// Initialize
if (_blockedAbnormalTypes == null)
{
synchronized (this)
{
if (_blockedAbnormalTypes == null)
{
_blockedAbnormalTypes = EnumSet.copyOf(blockedAbnormalTypes);
}
}
}
_blockedAbnormalTypes.addAll(blockedAbnormalTypes); _blockedAbnormalTypes.addAll(blockedAbnormalTypes);
} }
@@ -238,7 +226,7 @@ public final class CharEffectList
*/ */
public boolean removeBlockedAbnormalTypes(Set<AbnormalType> blockedBuffSlots) public boolean removeBlockedAbnormalTypes(Set<AbnormalType> blockedBuffSlots)
{ {
return (_blockedAbnormalTypes != null) && _blockedAbnormalTypes.removeAll(blockedBuffSlots); return _blockedAbnormalTypes.removeAll(blockedBuffSlots);
} }
/** /**
@@ -247,7 +235,7 @@ public final class CharEffectList
*/ */
public Set<AbnormalType> getBlockedAbnormalTypes() public Set<AbnormalType> getBlockedAbnormalTypes()
{ {
return _blockedAbnormalTypes != null ? Collections.unmodifiableSet(_blockedAbnormalTypes) : Collections.emptySet(); return Collections.unmodifiableSet(_blockedAbnormalTypes);
} }
/** /**
@@ -277,7 +265,7 @@ public final class CharEffectList
*/ */
public int getBuffCount() public int getBuffCount()
{ {
return _actives != null ? (_buffCount.get() - _hiddenBuffs.get()) : 0; return !_actives.isEmpty() ? (_buffCount.get() - _hiddenBuffs.get()) : 0;
} }
/** /**
@@ -374,7 +362,7 @@ public final class CharEffectList
*/ */
public void stopAllPassives(boolean update, boolean broadcast) public void stopAllPassives(boolean update, boolean broadcast)
{ {
if (_passives != null) if (!_passives.isEmpty())
{ {
_passives.forEach(this::remove); _passives.forEach(this::remove);
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -392,7 +380,7 @@ public final class CharEffectList
*/ */
public void stopAllOptions(boolean update, boolean broadcast) public void stopAllOptions(boolean update, boolean broadcast)
{ {
if (_options != null) if (!_options.isEmpty())
{ {
_options.forEach(this::remove); _options.forEach(this::remove);
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -490,7 +478,7 @@ public final class CharEffectList
*/ */
public void stopEffects(Predicate<BuffInfo> filter, boolean update, boolean broadcast) public void stopEffects(Predicate<BuffInfo> filter, boolean update, boolean broadcast)
{ {
if (_actives != null) if (!_actives.isEmpty())
{ {
_actives.stream().filter(filter).forEach(this::remove); _actives.stream().filter(filter).forEach(this::remove);
@@ -678,6 +666,10 @@ public final class CharEffectList
{ {
// Remove active effect. // Remove active effect.
removeActive(info, removed); removeActive(info, removed);
if (_owner.isNpc()) // Fix for all NPC debuff animations removed.
{
updateEffectList(broadcast);
}
} }
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -693,7 +685,7 @@ public final class CharEffectList
*/ */
private synchronized void removeActive(BuffInfo info, boolean removed) private synchronized void removeActive(BuffInfo info, boolean removed)
{ {
if (_actives != null) if (!_actives.isEmpty())
{ {
// Removes the buff from the given effect list. // Removes the buff from the given effect list.
_actives.remove(info); _actives.remove(info);
@@ -716,7 +708,7 @@ public final class CharEffectList
private void removePassive(BuffInfo info, boolean removed) private void removePassive(BuffInfo info, boolean removed)
{ {
if (_passives != null) if (!_passives.isEmpty())
{ {
_passives.remove(info); _passives.remove(info);
info.stopAllEffects(removed); info.stopAllEffects(removed);
@@ -725,7 +717,7 @@ public final class CharEffectList
private void removeOption(BuffInfo info, boolean removed) private void removeOption(BuffInfo info, boolean removed)
{ {
if (_options != null) if (!_options.isEmpty())
{ {
_options.remove(info); _options.remove(info);
info.stopAllEffects(removed); info.stopAllEffects(removed);
@@ -821,12 +813,6 @@ public final class CharEffectList
} }
} }
// Initialize
if (_actives == null)
{
_actives = new ConcurrentLinkedQueue<>();
}
// Manage effect stacking. // Manage effect stacking.
if (hasAbnormalType(skill.getAbnormalType())) if (hasAbnormalType(skill.getAbnormalType()))
{ {
@@ -857,7 +843,7 @@ public final class CharEffectList
} }
else else
{ {
// Remove effect that gets overriden. // Remove effect that gets overridden.
remove(existingInfo); remove(existingInfo);
} }
} }
@@ -865,7 +851,7 @@ public final class CharEffectList
{ {
info.setInUse(false); info.setInUse(false);
} }
else // The effect we try to add should be overriden. else // The effect we try to add should be overridden.
{ {
return; return;
} }
@@ -918,18 +904,6 @@ public final class CharEffectList
return; return;
} }
// Initialize
if (_passives == null)
{
synchronized (this)
{
if (_passives == null)
{
_passives = ConcurrentHashMap.newKeySet();
}
}
}
// Remove previous passives of this id. // Remove previous passives of this id.
_passives.stream().filter(Objects::nonNull).filter(b -> b.getSkill().getId() == skill.getId()).forEach(b -> _passives.stream().filter(Objects::nonNull).filter(b -> b.getSkill().getId() == skill.getId()).forEach(b ->
{ {
@@ -947,18 +921,6 @@ public final class CharEffectList
{ {
if (info.getOption() != null) if (info.getOption() != null)
{ {
// Initialize
if (_options == null)
{
synchronized (this)
{
if (_options == null)
{
_options = ConcurrentHashMap.newKeySet();
}
}
}
// Remove previous options of this id. // Remove previous options of this id.
_options.stream().filter(Objects::nonNull).filter(b -> b.getOption().getId() == info.getOption().getId()).forEach(b -> _options.stream().filter(Objects::nonNull).filter(b -> b.getOption().getId() == info.getOption().getId()).forEach(b ->
{ {
@@ -988,7 +950,7 @@ public final class CharEffectList
final Optional<PartySpelled> ps = ((party != null) || _owner.isSummon()) ? Optional.of(new PartySpelled(_owner)) : Optional.empty(); final Optional<PartySpelled> ps = ((party != null) || _owner.isSummon()) ? Optional.of(new PartySpelled(_owner)) : Optional.empty();
final Optional<ExOlympiadSpelledInfo> os = (player.isInOlympiadMode() && player.isOlympiadStart()) ? Optional.of(new ExOlympiadSpelledInfo(player)) : Optional.empty(); final Optional<ExOlympiadSpelledInfo> os = (player.isInOlympiadMode() && player.isOlympiadStart()) ? Optional.of(new ExOlympiadSpelledInfo(player)) : Optional.empty();
if (_actives != null) if (!_actives.isEmpty())
{ {
//@formatter:off //@formatter:off
_actives.stream() _actives.stream()
@@ -1109,8 +1071,6 @@ public final class CharEffectList
final Set<BuffInfo> unhideBuffs = new HashSet<>(); final Set<BuffInfo> unhideBuffs = new HashSet<>();
// Recalculate new flags // Recalculate new flags
if (_actives != null)
{
for (BuffInfo info : _actives) for (BuffInfo info : _actives)
{ {
if (info != null) if (info != null)
@@ -1144,7 +1104,14 @@ public final class CharEffectList
// Add AbnormalVisualEffect flag. // Add AbnormalVisualEffect flag.
if (skill.hasAbnormalVisualEffects()) if (skill.hasAbnormalVisualEffects())
{ {
abnormalVisualEffectFlags.addAll(skill.getAbnormalVisualEffects()); for (AbnormalVisualEffect ave : skill.getAbnormalVisualEffects())
{
abnormalVisualEffectFlags.add(ave);
_abnormalVisualEffects.add(ave);
}
if (broadcast)
{
_owner.updateAbnormalVisualEffects();
} }
} }
} }
@@ -1167,7 +1134,7 @@ public final class CharEffectList
if (broadcast) if (broadcast)
{ {
// Check if there is change in AbnormalVisualEffect // Check if there is change in AbnormalVisualEffect
if ((abnormalVisualEffectFlags.size() != _abnormalVisualEffects.size()) || !abnormalVisualEffectFlags.containsAll(_abnormalVisualEffects)) if (!abnormalVisualEffectFlags.containsAll(_abnormalVisualEffects))
{ {
_abnormalVisualEffects = abnormalVisualEffectFlags; _abnormalVisualEffects = abnormalVisualEffectFlags;
_owner.updateAbnormalVisualEffects(); _owner.updateAbnormalVisualEffects();

View File

@@ -77,7 +77,6 @@ public class DoppelgangerInstance extends L2Npc
info.setAbnormalTime(summonerInfo.getAbnormalTime()); info.setAbnormalTime(summonerInfo.getAbnormalTime());
getEffectList().add(info); getEffectList().add(info);
} }
} }
} }
} }

View File

@@ -786,7 +786,7 @@ public class CharStat
final CharEffectList effectList = _activeChar.getEffectList(); final CharEffectList effectList = _activeChar.getEffectList();
final Stream<BuffInfo> passives = effectList.getPassives().stream().filter(BuffInfo::isInUse).filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar)); final Stream<BuffInfo> passives = effectList.getPassives().stream().filter(BuffInfo::isInUse).filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar));
final Stream<BuffInfo> options = effectList.getOptions().stream().filter(BuffInfo::isInUse); final Stream<BuffInfo> options = effectList.getOptions().stream().filter(BuffInfo::isInUse);
final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives != null ? passives : Stream.empty(), options != null ? options : Stream.empty())); final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives, options));
// Call pump to each effect // Call pump to each effect
//@formatter:off //@formatter:off

View File

@@ -389,10 +389,10 @@ public final class BuffInfo
for (AbstractEffect effect : _effects) for (AbstractEffect effect : _effects)
{ {
// Instant effects shouldn't call onExit(..). // Instant effects shouldn't call onExit(..).
if (!effect.isInstant()) // if (!effect.isInstant())
{ // {
effect.onExit(_effector, _effected, _skill); effect.onExit(_effector, _effected, _skill);
} // }
} }
// Set the proper system message. // Set the proper system message.

View File

@@ -21,13 +21,11 @@ import java.util.List;
import com.l2jmobius.commons.network.PacketWriter; import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.skills.BuffInfo; import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.OutgoingPackets; import com.l2jmobius.gameserver.network.OutgoingPackets;
public class AbnormalStatusUpdate implements IClientOutgoingPacket public class AbnormalStatusUpdate implements IClientOutgoingPacket
{ {
private final List<BuffInfo> _effects = new ArrayList<>(); private final List<BuffInfo> _effects = new ArrayList<>();
private final List<Skill> _effects2 = new ArrayList<>();
public void addSkill(BuffInfo info) public void addSkill(BuffInfo info)
{ {
@@ -37,20 +35,12 @@ public class AbnormalStatusUpdate implements IClientOutgoingPacket
} }
} }
public void addSkill(Skill skill)
{
if (!skill.isHealingPotionSkill())
{
_effects2.add(skill);
}
}
@Override @Override
public boolean write(PacketWriter packet) public boolean write(PacketWriter packet)
{ {
OutgoingPackets.ABNORMAL_STATUS_UPDATE.writeId(packet); OutgoingPackets.ABNORMAL_STATUS_UPDATE.writeId(packet);
packet.writeH(_effects.size() + _effects2.size()); packet.writeH(_effects.size());
for (BuffInfo info : _effects) for (BuffInfo info : _effects)
{ {
if ((info != null) && info.isInUse()) if ((info != null) && info.isInUse())
@@ -62,17 +52,6 @@ public class AbnormalStatusUpdate implements IClientOutgoingPacket
writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime()); writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
} }
} }
for (Skill skill : _effects2)
{
if (skill != null)
{
packet.writeD(skill.getDisplayId());
packet.writeH(skill.getDisplayLevel());
packet.writeH(0x00); // Sub level
packet.writeD(skill.getAbnormalType().getClientId());
packet.writeH(-1);
}
}
return true; return true;
} }
} }

View File

@@ -16,7 +16,6 @@
*/ */
package com.l2jmobius.gameserver.network.serverpackets; package com.l2jmobius.gameserver.network.serverpackets;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -24,41 +23,12 @@ import java.util.stream.Collectors;
import com.l2jmobius.commons.network.PacketWriter; import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.skills.BuffInfo; import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.OutgoingPackets; import com.l2jmobius.gameserver.network.OutgoingPackets;
public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
{ {
private final L2Character _character; private final L2Character _character;
private List<Effect> _effects = new ArrayList<>(); private final List<BuffInfo> _effects;
private static class Effect
{
protected int _skillId;
protected int _level;
protected int _subLevel;
protected int _abnormalType;
protected int _duration;
protected int _caster;
public Effect(BuffInfo info)
{
final Skill skill = info.getSkill();
final L2Character caster = info.getEffector();
int casterId = 0;
if (caster != null)
{
casterId = caster.getObjectId();
}
_skillId = skill.getDisplayId();
_level = skill.getDisplayLevel();
_subLevel = skill.getSubLevel();
_abnormalType = skill.getAbnormalType().getClientId();
_duration = skill.isAura() ? -1 : info.getTime();
_caster = casterId;
}
}
public ExAbnormalStatusUpdateFromTarget(L2Character character) public ExAbnormalStatusUpdateFromTarget(L2Character character)
{ {
@@ -69,7 +39,6 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
.filter(Objects::nonNull) .filter(Objects::nonNull)
.filter(BuffInfo::isInUse) .filter(BuffInfo::isInUse)
.filter(b -> !b.getSkill().isToggle()) .filter(b -> !b.getSkill().isToggle())
.map(Effect::new)
.collect(Collectors.toList()); .collect(Collectors.toList());
//@formatter:on //@formatter:on
} }
@@ -82,14 +51,14 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
packet.writeD(_character.getObjectId()); packet.writeD(_character.getObjectId());
packet.writeH(_effects.size()); packet.writeH(_effects.size());
for (Effect info : _effects) for (BuffInfo info : _effects)
{ {
packet.writeD(info._skillId); packet.writeD(info.getSkill().getDisplayId());
packet.writeH(info._level); packet.writeH(info.getSkill().getDisplayLevel());
packet.writeH(info._subLevel); packet.writeH(info.getSkill().getSubLevel());
packet.writeH(info._abnormalType); packet.writeH(info.getSkill().getAbnormalType().getClientId());
writeOptionalD(packet, info._duration); writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
packet.writeD(info._caster); packet.writeD(info.getEffectorObjectId());
} }
return true; return true;
} }

View File

@@ -16,6 +16,8 @@
*/ */
package handlers.effecthandlers; package handlers.effecthandlers;
import java.util.Collections;
import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.StatsSet;
@@ -38,6 +40,19 @@ public final class CallSkillOnActionTime extends AbstractEffect
setTicks(params.getInt("ticks")); setTicks(params.getInt("ticks"));
} }
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
effected.getEffectList().stopEffects(Collections.singleton(_skill.getSkill().getAbnormalType()));
effected.getEffectList().addBlockedAbnormalTypes(Collections.singleton(_skill.getSkill().getAbnormalType()));
}
@Override
public void onExit(L2Character effector, L2Character effected, Skill skill)
{
effected.getEffectList().removeBlockedAbnormalTypes(Collections.singleton(_skill.getSkill().getAbnormalType()));
}
@Override @Override
public boolean onActionTime(L2Character effector, L2Character effected, Skill skill) public boolean onActionTime(L2Character effector, L2Character effected, Skill skill)
{ {

View File

@@ -136,6 +136,5 @@ public final class Disarmor extends AbstractEffect
} }
} }
} }
super.onExit(effector, effected, skill);
} }
} }

View File

@@ -84,6 +84,5 @@ public final class DoubleCast extends AbstractEffect
return null; return null;
}); });
} }
super.onExit(effector, effected, skill);
} }
} }

View File

@@ -65,15 +65,15 @@ public final class CharEffectList
{ {
private static final Logger LOGGER = Logger.getLogger(CharEffectList.class.getName()); private static final Logger LOGGER = Logger.getLogger(CharEffectList.class.getName());
/** Queue containing all effects from buffs for this effect list. */ /** Queue containing all effects from buffs for this effect list. */
private volatile Queue<BuffInfo> _actives; private volatile Queue<BuffInfo> _actives = new ConcurrentLinkedQueue<>();
/** List containing all passives for this effect list. They bypass most of the actions and they are not included in most operations. */ /** List containing all passives for this effect list. They bypass most of the actions and they are not included in most operations. */
private volatile Set<BuffInfo> _passives; private volatile Set<BuffInfo> _passives = ConcurrentHashMap.newKeySet();
/** List containing all options for this effect list. They bypass most of the actions and they are not included in most operations. */ /** List containing all options for this effect list. They bypass most of the actions and they are not included in most operations. */
private volatile Set<BuffInfo> _options; private volatile Set<BuffInfo> _options = ConcurrentHashMap.newKeySet();
/** Map containing the all stacked effect in progress for each {@code AbnormalType}. */ /** Map containing the all stacked effect in progress for each {@code AbnormalType}. */
private volatile Set<AbnormalType> _stackedEffects = EnumSet.noneOf(AbnormalType.class); private volatile Set<AbnormalType> _stackedEffects = EnumSet.noneOf(AbnormalType.class);
/** Set containing all {@code AbnormalType}s that shouldn't be added to this creature effect list. */ /** Set containing all {@code AbnormalType}s that shouldn't be added to this creature effect list. */
private volatile Set<AbnormalType> _blockedAbnormalTypes = null; private volatile Set<AbnormalType> _blockedAbnormalTypes = EnumSet.noneOf(AbnormalType.class);
/** Set containing all abnormal visual effects this creature currently displays. */ /** Set containing all abnormal visual effects this creature currently displays. */
private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects = EnumSet.noneOf(AbnormalVisualEffect.class); private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects = EnumSet.noneOf(AbnormalVisualEffect.class);
/** Short buff skill ID. */ /** Short buff skill ID. */
@@ -110,7 +110,7 @@ public final class CharEffectList
*/ */
public Set<BuffInfo> getPassives() public Set<BuffInfo> getPassives()
{ {
return _passives != null ? Collections.unmodifiableSet(_passives) : Collections.emptySet(); return Collections.unmodifiableSet(_passives);
} }
/** /**
@@ -119,7 +119,7 @@ public final class CharEffectList
*/ */
public Set<BuffInfo> getOptions() public Set<BuffInfo> getOptions()
{ {
return _options != null ? Collections.unmodifiableSet(_options) : Collections.emptySet(); return Collections.unmodifiableSet(_options);
} }
/** /**
@@ -128,7 +128,7 @@ public final class CharEffectList
*/ */
public Collection<BuffInfo> getEffects() public Collection<BuffInfo> getEffects()
{ {
return _actives != null ? Collections.unmodifiableCollection(_actives) : Collections.emptyList(); return Collections.unmodifiableCollection(_actives);
} }
/** /**
@@ -137,7 +137,7 @@ public final class CharEffectList
*/ */
public List<BuffInfo> getBuffs() public List<BuffInfo> getBuffs()
{ {
return _actives != null ? _actives.stream().filter(b -> !b.getSkill().getBuffType().isBuff()).collect(Collectors.toList()) : Collections.emptyList(); return _actives.stream().filter(b -> !b.getSkill().getBuffType().isBuff()).collect(Collectors.toList());
} }
/** /**
@@ -146,7 +146,7 @@ public final class CharEffectList
*/ */
public List<BuffInfo> getDebuffs() public List<BuffInfo> getDebuffs()
{ {
return _actives != null ? _actives.stream().filter(b -> b.getSkill().isDebuff()).collect(Collectors.toList()) : Collections.emptyList(); return _actives.stream().filter(b -> b.getSkill().isDebuff()).collect(Collectors.toList());
} }
/** /**
@@ -156,7 +156,7 @@ public final class CharEffectList
*/ */
public boolean isAffectedBySkill(int skillId) public boolean isAffectedBySkill(int skillId)
{ {
return ((_actives != null) && _actives.stream().anyMatch(i -> i.getSkill().getId() == skillId)) || ((_passives != null) && _passives.stream().anyMatch(i -> i.getSkill().getId() == skillId)); return (_actives.stream().anyMatch(i -> i.getSkill().getId() == skillId)) || (_passives.stream().anyMatch(i -> i.getSkill().getId() == skillId));
} }
/** /**
@@ -166,7 +166,7 @@ public final class CharEffectList
*/ */
public BuffInfo getBuffInfoBySkillId(int skillId) public BuffInfo getBuffInfoBySkillId(int skillId)
{ {
return Stream.concat(_actives != null ? _actives.stream() : Stream.empty(), _passives != null ? _passives.stream() : Stream.empty()).filter(b -> b.getSkill().getId() == skillId).findFirst().orElse(null); return Stream.concat(_actives.stream(), _passives.stream()).filter(b -> b.getSkill().getId() == skillId).findFirst().orElse(null);
} }
/** /**
@@ -216,18 +216,6 @@ public final class CharEffectList
*/ */
public void addBlockedAbnormalTypes(Set<AbnormalType> blockedAbnormalTypes) public void addBlockedAbnormalTypes(Set<AbnormalType> blockedAbnormalTypes)
{ {
// Initialize
if (_blockedAbnormalTypes == null)
{
synchronized (this)
{
if (_blockedAbnormalTypes == null)
{
_blockedAbnormalTypes = EnumSet.copyOf(blockedAbnormalTypes);
}
}
}
_blockedAbnormalTypes.addAll(blockedAbnormalTypes); _blockedAbnormalTypes.addAll(blockedAbnormalTypes);
} }
@@ -238,7 +226,7 @@ public final class CharEffectList
*/ */
public boolean removeBlockedAbnormalTypes(Set<AbnormalType> blockedBuffSlots) public boolean removeBlockedAbnormalTypes(Set<AbnormalType> blockedBuffSlots)
{ {
return (_blockedAbnormalTypes != null) && _blockedAbnormalTypes.removeAll(blockedBuffSlots); return _blockedAbnormalTypes.removeAll(blockedBuffSlots);
} }
/** /**
@@ -247,7 +235,7 @@ public final class CharEffectList
*/ */
public Set<AbnormalType> getBlockedAbnormalTypes() public Set<AbnormalType> getBlockedAbnormalTypes()
{ {
return _blockedAbnormalTypes != null ? Collections.unmodifiableSet(_blockedAbnormalTypes) : Collections.emptySet(); return Collections.unmodifiableSet(_blockedAbnormalTypes);
} }
/** /**
@@ -277,7 +265,7 @@ public final class CharEffectList
*/ */
public int getBuffCount() public int getBuffCount()
{ {
return _actives != null ? (_buffCount.get() - _hiddenBuffs.get()) : 0; return !_actives.isEmpty() ? (_buffCount.get() - _hiddenBuffs.get()) : 0;
} }
/** /**
@@ -374,7 +362,7 @@ public final class CharEffectList
*/ */
public void stopAllPassives(boolean update, boolean broadcast) public void stopAllPassives(boolean update, boolean broadcast)
{ {
if (_passives != null) if (!_passives.isEmpty())
{ {
_passives.forEach(this::remove); _passives.forEach(this::remove);
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -392,7 +380,7 @@ public final class CharEffectList
*/ */
public void stopAllOptions(boolean update, boolean broadcast) public void stopAllOptions(boolean update, boolean broadcast)
{ {
if (_options != null) if (!_options.isEmpty())
{ {
_options.forEach(this::remove); _options.forEach(this::remove);
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -490,7 +478,7 @@ public final class CharEffectList
*/ */
public void stopEffects(Predicate<BuffInfo> filter, boolean update, boolean broadcast) public void stopEffects(Predicate<BuffInfo> filter, boolean update, boolean broadcast)
{ {
if (_actives != null) if (!_actives.isEmpty())
{ {
_actives.stream().filter(filter).forEach(this::remove); _actives.stream().filter(filter).forEach(this::remove);
@@ -678,6 +666,10 @@ public final class CharEffectList
{ {
// Remove active effect. // Remove active effect.
removeActive(info, removed); removeActive(info, removed);
if (_owner.isNpc()) // Fix for all NPC debuff animations removed.
{
updateEffectList(broadcast);
}
} }
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -693,7 +685,7 @@ public final class CharEffectList
*/ */
private synchronized void removeActive(BuffInfo info, boolean removed) private synchronized void removeActive(BuffInfo info, boolean removed)
{ {
if (_actives != null) if (!_actives.isEmpty())
{ {
// Removes the buff from the given effect list. // Removes the buff from the given effect list.
_actives.remove(info); _actives.remove(info);
@@ -716,7 +708,7 @@ public final class CharEffectList
private void removePassive(BuffInfo info, boolean removed) private void removePassive(BuffInfo info, boolean removed)
{ {
if (_passives != null) if (!_passives.isEmpty())
{ {
_passives.remove(info); _passives.remove(info);
info.stopAllEffects(removed); info.stopAllEffects(removed);
@@ -725,7 +717,7 @@ public final class CharEffectList
private void removeOption(BuffInfo info, boolean removed) private void removeOption(BuffInfo info, boolean removed)
{ {
if (_options != null) if (!_options.isEmpty())
{ {
_options.remove(info); _options.remove(info);
info.stopAllEffects(removed); info.stopAllEffects(removed);
@@ -821,12 +813,6 @@ public final class CharEffectList
} }
} }
// Initialize
if (_actives == null)
{
_actives = new ConcurrentLinkedQueue<>();
}
// Manage effect stacking. // Manage effect stacking.
if (hasAbnormalType(skill.getAbnormalType())) if (hasAbnormalType(skill.getAbnormalType()))
{ {
@@ -857,7 +843,7 @@ public final class CharEffectList
} }
else else
{ {
// Remove effect that gets overriden. // Remove effect that gets overridden.
remove(existingInfo); remove(existingInfo);
} }
} }
@@ -865,7 +851,7 @@ public final class CharEffectList
{ {
info.setInUse(false); info.setInUse(false);
} }
else // The effect we try to add should be overriden. else // The effect we try to add should be overridden.
{ {
return; return;
} }
@@ -918,18 +904,6 @@ public final class CharEffectList
return; return;
} }
// Initialize
if (_passives == null)
{
synchronized (this)
{
if (_passives == null)
{
_passives = ConcurrentHashMap.newKeySet();
}
}
}
// Remove previous passives of this id. // Remove previous passives of this id.
_passives.stream().filter(Objects::nonNull).filter(b -> b.getSkill().getId() == skill.getId()).forEach(b -> _passives.stream().filter(Objects::nonNull).filter(b -> b.getSkill().getId() == skill.getId()).forEach(b ->
{ {
@@ -947,18 +921,6 @@ public final class CharEffectList
{ {
if (info.getOption() != null) if (info.getOption() != null)
{ {
// Initialize
if (_options == null)
{
synchronized (this)
{
if (_options == null)
{
_options = ConcurrentHashMap.newKeySet();
}
}
}
// Remove previous options of this id. // Remove previous options of this id.
_options.stream().filter(Objects::nonNull).filter(b -> b.getOption().getId() == info.getOption().getId()).forEach(b -> _options.stream().filter(Objects::nonNull).filter(b -> b.getOption().getId() == info.getOption().getId()).forEach(b ->
{ {
@@ -988,7 +950,7 @@ public final class CharEffectList
final Optional<PartySpelled> ps = ((party != null) || _owner.isSummon()) ? Optional.of(new PartySpelled(_owner)) : Optional.empty(); final Optional<PartySpelled> ps = ((party != null) || _owner.isSummon()) ? Optional.of(new PartySpelled(_owner)) : Optional.empty();
final Optional<ExOlympiadSpelledInfo> os = (player.isInOlympiadMode() && player.isOlympiadStart()) ? Optional.of(new ExOlympiadSpelledInfo(player)) : Optional.empty(); final Optional<ExOlympiadSpelledInfo> os = (player.isInOlympiadMode() && player.isOlympiadStart()) ? Optional.of(new ExOlympiadSpelledInfo(player)) : Optional.empty();
if (_actives != null) if (!_actives.isEmpty())
{ {
//@formatter:off //@formatter:off
_actives.stream() _actives.stream()
@@ -1109,8 +1071,6 @@ public final class CharEffectList
final Set<BuffInfo> unhideBuffs = new HashSet<>(); final Set<BuffInfo> unhideBuffs = new HashSet<>();
// Recalculate new flags // Recalculate new flags
if (_actives != null)
{
for (BuffInfo info : _actives) for (BuffInfo info : _actives)
{ {
if (info != null) if (info != null)
@@ -1144,7 +1104,14 @@ public final class CharEffectList
// Add AbnormalVisualEffect flag. // Add AbnormalVisualEffect flag.
if (skill.hasAbnormalVisualEffects()) if (skill.hasAbnormalVisualEffects())
{ {
abnormalVisualEffectFlags.addAll(skill.getAbnormalVisualEffects()); for (AbnormalVisualEffect ave : skill.getAbnormalVisualEffects())
{
abnormalVisualEffectFlags.add(ave);
_abnormalVisualEffects.add(ave);
}
if (broadcast)
{
_owner.updateAbnormalVisualEffects();
} }
} }
} }
@@ -1167,7 +1134,7 @@ public final class CharEffectList
if (broadcast) if (broadcast)
{ {
// Check if there is change in AbnormalVisualEffect // Check if there is change in AbnormalVisualEffect
if ((abnormalVisualEffectFlags.size() != _abnormalVisualEffects.size()) || !abnormalVisualEffectFlags.containsAll(_abnormalVisualEffects)) if (!abnormalVisualEffectFlags.containsAll(_abnormalVisualEffects))
{ {
_abnormalVisualEffects = abnormalVisualEffectFlags; _abnormalVisualEffects = abnormalVisualEffectFlags;
_owner.updateAbnormalVisualEffects(); _owner.updateAbnormalVisualEffects();

View File

@@ -77,7 +77,6 @@ public class DoppelgangerInstance extends L2Npc
info.setAbnormalTime(summonerInfo.getAbnormalTime()); info.setAbnormalTime(summonerInfo.getAbnormalTime());
getEffectList().add(info); getEffectList().add(info);
} }
} }
} }
} }

View File

@@ -786,7 +786,7 @@ public class CharStat
final CharEffectList effectList = _activeChar.getEffectList(); final CharEffectList effectList = _activeChar.getEffectList();
final Stream<BuffInfo> passives = effectList.getPassives().stream().filter(BuffInfo::isInUse).filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar)); final Stream<BuffInfo> passives = effectList.getPassives().stream().filter(BuffInfo::isInUse).filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar));
final Stream<BuffInfo> options = effectList.getOptions().stream().filter(BuffInfo::isInUse); final Stream<BuffInfo> options = effectList.getOptions().stream().filter(BuffInfo::isInUse);
final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives != null ? passives : Stream.empty(), options != null ? options : Stream.empty())); final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives, options));
// Call pump to each effect // Call pump to each effect
//@formatter:off //@formatter:off

View File

@@ -389,10 +389,10 @@ public final class BuffInfo
for (AbstractEffect effect : _effects) for (AbstractEffect effect : _effects)
{ {
// Instant effects shouldn't call onExit(..). // Instant effects shouldn't call onExit(..).
if (!effect.isInstant()) // if (!effect.isInstant())
{ // {
effect.onExit(_effector, _effected, _skill); effect.onExit(_effector, _effected, _skill);
} // }
} }
// Set the proper system message. // Set the proper system message.

View File

@@ -21,13 +21,11 @@ import java.util.List;
import com.l2jmobius.commons.network.PacketWriter; import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.skills.BuffInfo; import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.OutgoingPackets; import com.l2jmobius.gameserver.network.OutgoingPackets;
public class AbnormalStatusUpdate implements IClientOutgoingPacket public class AbnormalStatusUpdate implements IClientOutgoingPacket
{ {
private final List<BuffInfo> _effects = new ArrayList<>(); private final List<BuffInfo> _effects = new ArrayList<>();
private final List<Skill> _effects2 = new ArrayList<>();
public void addSkill(BuffInfo info) public void addSkill(BuffInfo info)
{ {
@@ -37,20 +35,12 @@ public class AbnormalStatusUpdate implements IClientOutgoingPacket
} }
} }
public void addSkill(Skill skill)
{
if (!skill.isHealingPotionSkill())
{
_effects2.add(skill);
}
}
@Override @Override
public boolean write(PacketWriter packet) public boolean write(PacketWriter packet)
{ {
OutgoingPackets.ABNORMAL_STATUS_UPDATE.writeId(packet); OutgoingPackets.ABNORMAL_STATUS_UPDATE.writeId(packet);
packet.writeH(_effects.size() + _effects2.size()); packet.writeH(_effects.size());
for (BuffInfo info : _effects) for (BuffInfo info : _effects)
{ {
if ((info != null) && info.isInUse()) if ((info != null) && info.isInUse())
@@ -62,17 +52,6 @@ public class AbnormalStatusUpdate implements IClientOutgoingPacket
writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime()); writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
} }
} }
for (Skill skill : _effects2)
{
if (skill != null)
{
packet.writeD(skill.getDisplayId());
packet.writeH(skill.getDisplayLevel());
packet.writeH(0x00); // Sub level
packet.writeD(skill.getAbnormalType().getClientId());
packet.writeH(-1);
}
}
return true; return true;
} }
} }

View File

@@ -16,7 +16,6 @@
*/ */
package com.l2jmobius.gameserver.network.serverpackets; package com.l2jmobius.gameserver.network.serverpackets;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -24,41 +23,12 @@ import java.util.stream.Collectors;
import com.l2jmobius.commons.network.PacketWriter; import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.skills.BuffInfo; import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.OutgoingPackets; import com.l2jmobius.gameserver.network.OutgoingPackets;
public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
{ {
private final L2Character _character; private final L2Character _character;
private List<Effect> _effects = new ArrayList<>(); private final List<BuffInfo> _effects;
private static class Effect
{
protected int _skillId;
protected int _level;
protected int _subLevel;
protected int _abnormalType;
protected int _duration;
protected int _caster;
public Effect(BuffInfo info)
{
final Skill skill = info.getSkill();
final L2Character caster = info.getEffector();
int casterId = 0;
if (caster != null)
{
casterId = caster.getObjectId();
}
_skillId = skill.getDisplayId();
_level = skill.getDisplayLevel();
_subLevel = skill.getSubLevel();
_abnormalType = skill.getAbnormalType().getClientId();
_duration = skill.isAura() ? -1 : info.getTime();
_caster = casterId;
}
}
public ExAbnormalStatusUpdateFromTarget(L2Character character) public ExAbnormalStatusUpdateFromTarget(L2Character character)
{ {
@@ -69,7 +39,6 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
.filter(Objects::nonNull) .filter(Objects::nonNull)
.filter(BuffInfo::isInUse) .filter(BuffInfo::isInUse)
.filter(b -> !b.getSkill().isToggle()) .filter(b -> !b.getSkill().isToggle())
.map(Effect::new)
.collect(Collectors.toList()); .collect(Collectors.toList());
//@formatter:on //@formatter:on
} }
@@ -82,14 +51,14 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
packet.writeD(_character.getObjectId()); packet.writeD(_character.getObjectId());
packet.writeH(_effects.size()); packet.writeH(_effects.size());
for (Effect info : _effects) for (BuffInfo info : _effects)
{ {
packet.writeD(info._skillId); packet.writeD(info.getSkill().getDisplayId());
packet.writeH(info._level); packet.writeH(info.getSkill().getDisplayLevel());
packet.writeH(info._subLevel); packet.writeH(info.getSkill().getSubLevel());
packet.writeH(info._abnormalType); packet.writeH(info.getSkill().getAbnormalType().getClientId());
writeOptionalD(packet, info._duration); writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
packet.writeD(info._caster); packet.writeD(info.getEffectorObjectId());
} }
return true; return true;
} }

View File

@@ -16,6 +16,8 @@
*/ */
package handlers.effecthandlers; package handlers.effecthandlers;
import java.util.Collections;
import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.StatsSet;
@@ -38,6 +40,19 @@ public final class CallSkillOnActionTime extends AbstractEffect
setTicks(params.getInt("ticks")); setTicks(params.getInt("ticks"));
} }
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
effected.getEffectList().stopEffects(Collections.singleton(_skill.getSkill().getAbnormalType()));
effected.getEffectList().addBlockedAbnormalTypes(Collections.singleton(_skill.getSkill().getAbnormalType()));
}
@Override
public void onExit(L2Character effector, L2Character effected, Skill skill)
{
effected.getEffectList().removeBlockedAbnormalTypes(Collections.singleton(_skill.getSkill().getAbnormalType()));
}
@Override @Override
public boolean onActionTime(L2Character effector, L2Character effected, Skill skill) public boolean onActionTime(L2Character effector, L2Character effected, Skill skill)
{ {

View File

@@ -136,6 +136,5 @@ public final class Disarmor extends AbstractEffect
} }
} }
} }
super.onExit(effector, effected, skill);
} }
} }

View File

@@ -84,6 +84,5 @@ public final class DoubleCast extends AbstractEffect
return null; return null;
}); });
} }
super.onExit(effector, effected, skill);
} }
} }

View File

@@ -65,15 +65,15 @@ public final class CharEffectList
{ {
private static final Logger LOGGER = Logger.getLogger(CharEffectList.class.getName()); private static final Logger LOGGER = Logger.getLogger(CharEffectList.class.getName());
/** Queue containing all effects from buffs for this effect list. */ /** Queue containing all effects from buffs for this effect list. */
private volatile Queue<BuffInfo> _actives; private volatile Queue<BuffInfo> _actives = new ConcurrentLinkedQueue<>();
/** List containing all passives for this effect list. They bypass most of the actions and they are not included in most operations. */ /** List containing all passives for this effect list. They bypass most of the actions and they are not included in most operations. */
private volatile Set<BuffInfo> _passives; private volatile Set<BuffInfo> _passives = ConcurrentHashMap.newKeySet();
/** List containing all options for this effect list. They bypass most of the actions and they are not included in most operations. */ /** List containing all options for this effect list. They bypass most of the actions and they are not included in most operations. */
private volatile Set<BuffInfo> _options; private volatile Set<BuffInfo> _options = ConcurrentHashMap.newKeySet();
/** Map containing the all stacked effect in progress for each {@code AbnormalType}. */ /** Map containing the all stacked effect in progress for each {@code AbnormalType}. */
private volatile Set<AbnormalType> _stackedEffects = EnumSet.noneOf(AbnormalType.class); private volatile Set<AbnormalType> _stackedEffects = EnumSet.noneOf(AbnormalType.class);
/** Set containing all {@code AbnormalType}s that shouldn't be added to this creature effect list. */ /** Set containing all {@code AbnormalType}s that shouldn't be added to this creature effect list. */
private volatile Set<AbnormalType> _blockedAbnormalTypes = null; private volatile Set<AbnormalType> _blockedAbnormalTypes = EnumSet.noneOf(AbnormalType.class);
/** Set containing all abnormal visual effects this creature currently displays. */ /** Set containing all abnormal visual effects this creature currently displays. */
private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects = EnumSet.noneOf(AbnormalVisualEffect.class); private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects = EnumSet.noneOf(AbnormalVisualEffect.class);
/** Short buff skill ID. */ /** Short buff skill ID. */
@@ -110,7 +110,7 @@ public final class CharEffectList
*/ */
public Set<BuffInfo> getPassives() public Set<BuffInfo> getPassives()
{ {
return _passives != null ? Collections.unmodifiableSet(_passives) : Collections.emptySet(); return Collections.unmodifiableSet(_passives);
} }
/** /**
@@ -119,7 +119,7 @@ public final class CharEffectList
*/ */
public Set<BuffInfo> getOptions() public Set<BuffInfo> getOptions()
{ {
return _options != null ? Collections.unmodifiableSet(_options) : Collections.emptySet(); return Collections.unmodifiableSet(_options);
} }
/** /**
@@ -128,7 +128,7 @@ public final class CharEffectList
*/ */
public Collection<BuffInfo> getEffects() public Collection<BuffInfo> getEffects()
{ {
return _actives != null ? Collections.unmodifiableCollection(_actives) : Collections.emptyList(); return Collections.unmodifiableCollection(_actives);
} }
/** /**
@@ -137,7 +137,7 @@ public final class CharEffectList
*/ */
public List<BuffInfo> getBuffs() public List<BuffInfo> getBuffs()
{ {
return _actives != null ? _actives.stream().filter(b -> !b.getSkill().getBuffType().isBuff()).collect(Collectors.toList()) : Collections.emptyList(); return _actives.stream().filter(b -> !b.getSkill().getBuffType().isBuff()).collect(Collectors.toList());
} }
/** /**
@@ -146,7 +146,7 @@ public final class CharEffectList
*/ */
public List<BuffInfo> getDebuffs() public List<BuffInfo> getDebuffs()
{ {
return _actives != null ? _actives.stream().filter(b -> b.getSkill().isDebuff()).collect(Collectors.toList()) : Collections.emptyList(); return _actives.stream().filter(b -> b.getSkill().isDebuff()).collect(Collectors.toList());
} }
/** /**
@@ -156,7 +156,7 @@ public final class CharEffectList
*/ */
public boolean isAffectedBySkill(int skillId) public boolean isAffectedBySkill(int skillId)
{ {
return ((_actives != null) && _actives.stream().anyMatch(i -> i.getSkill().getId() == skillId)) || ((_passives != null) && _passives.stream().anyMatch(i -> i.getSkill().getId() == skillId)); return (_actives.stream().anyMatch(i -> i.getSkill().getId() == skillId)) || (_passives.stream().anyMatch(i -> i.getSkill().getId() == skillId));
} }
/** /**
@@ -166,7 +166,7 @@ public final class CharEffectList
*/ */
public BuffInfo getBuffInfoBySkillId(int skillId) public BuffInfo getBuffInfoBySkillId(int skillId)
{ {
return Stream.concat(_actives != null ? _actives.stream() : Stream.empty(), _passives != null ? _passives.stream() : Stream.empty()).filter(b -> b.getSkill().getId() == skillId).findFirst().orElse(null); return Stream.concat(_actives.stream(), _passives.stream()).filter(b -> b.getSkill().getId() == skillId).findFirst().orElse(null);
} }
/** /**
@@ -216,18 +216,6 @@ public final class CharEffectList
*/ */
public void addBlockedAbnormalTypes(Set<AbnormalType> blockedAbnormalTypes) public void addBlockedAbnormalTypes(Set<AbnormalType> blockedAbnormalTypes)
{ {
// Initialize
if (_blockedAbnormalTypes == null)
{
synchronized (this)
{
if (_blockedAbnormalTypes == null)
{
_blockedAbnormalTypes = EnumSet.copyOf(blockedAbnormalTypes);
}
}
}
_blockedAbnormalTypes.addAll(blockedAbnormalTypes); _blockedAbnormalTypes.addAll(blockedAbnormalTypes);
} }
@@ -238,7 +226,7 @@ public final class CharEffectList
*/ */
public boolean removeBlockedAbnormalTypes(Set<AbnormalType> blockedBuffSlots) public boolean removeBlockedAbnormalTypes(Set<AbnormalType> blockedBuffSlots)
{ {
return (_blockedAbnormalTypes != null) && _blockedAbnormalTypes.removeAll(blockedBuffSlots); return _blockedAbnormalTypes.removeAll(blockedBuffSlots);
} }
/** /**
@@ -247,7 +235,7 @@ public final class CharEffectList
*/ */
public Set<AbnormalType> getBlockedAbnormalTypes() public Set<AbnormalType> getBlockedAbnormalTypes()
{ {
return _blockedAbnormalTypes != null ? Collections.unmodifiableSet(_blockedAbnormalTypes) : Collections.emptySet(); return Collections.unmodifiableSet(_blockedAbnormalTypes);
} }
/** /**
@@ -277,7 +265,7 @@ public final class CharEffectList
*/ */
public int getBuffCount() public int getBuffCount()
{ {
return _actives != null ? (_buffCount.get() - _hiddenBuffs.get()) : 0; return !_actives.isEmpty() ? (_buffCount.get() - _hiddenBuffs.get()) : 0;
} }
/** /**
@@ -374,7 +362,7 @@ public final class CharEffectList
*/ */
public void stopAllPassives(boolean update, boolean broadcast) public void stopAllPassives(boolean update, boolean broadcast)
{ {
if (_passives != null) if (!_passives.isEmpty())
{ {
_passives.forEach(this::remove); _passives.forEach(this::remove);
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -392,7 +380,7 @@ public final class CharEffectList
*/ */
public void stopAllOptions(boolean update, boolean broadcast) public void stopAllOptions(boolean update, boolean broadcast)
{ {
if (_options != null) if (!_options.isEmpty())
{ {
_options.forEach(this::remove); _options.forEach(this::remove);
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -490,7 +478,7 @@ public final class CharEffectList
*/ */
public void stopEffects(Predicate<BuffInfo> filter, boolean update, boolean broadcast) public void stopEffects(Predicate<BuffInfo> filter, boolean update, boolean broadcast)
{ {
if (_actives != null) if (!_actives.isEmpty())
{ {
_actives.stream().filter(filter).forEach(this::remove); _actives.stream().filter(filter).forEach(this::remove);
@@ -678,6 +666,10 @@ public final class CharEffectList
{ {
// Remove active effect. // Remove active effect.
removeActive(info, removed); removeActive(info, removed);
if (_owner.isNpc()) // Fix for all NPC debuff animations removed.
{
updateEffectList(broadcast);
}
} }
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -693,7 +685,7 @@ public final class CharEffectList
*/ */
private synchronized void removeActive(BuffInfo info, boolean removed) private synchronized void removeActive(BuffInfo info, boolean removed)
{ {
if (_actives != null) if (!_actives.isEmpty())
{ {
// Removes the buff from the given effect list. // Removes the buff from the given effect list.
_actives.remove(info); _actives.remove(info);
@@ -716,7 +708,7 @@ public final class CharEffectList
private void removePassive(BuffInfo info, boolean removed) private void removePassive(BuffInfo info, boolean removed)
{ {
if (_passives != null) if (!_passives.isEmpty())
{ {
_passives.remove(info); _passives.remove(info);
info.stopAllEffects(removed); info.stopAllEffects(removed);
@@ -725,7 +717,7 @@ public final class CharEffectList
private void removeOption(BuffInfo info, boolean removed) private void removeOption(BuffInfo info, boolean removed)
{ {
if (_options != null) if (!_options.isEmpty())
{ {
_options.remove(info); _options.remove(info);
info.stopAllEffects(removed); info.stopAllEffects(removed);
@@ -821,12 +813,6 @@ public final class CharEffectList
} }
} }
// Initialize
if (_actives == null)
{
_actives = new ConcurrentLinkedQueue<>();
}
// Manage effect stacking. // Manage effect stacking.
if (hasAbnormalType(skill.getAbnormalType())) if (hasAbnormalType(skill.getAbnormalType()))
{ {
@@ -857,7 +843,7 @@ public final class CharEffectList
} }
else else
{ {
// Remove effect that gets overriden. // Remove effect that gets overridden.
remove(existingInfo); remove(existingInfo);
} }
} }
@@ -865,7 +851,7 @@ public final class CharEffectList
{ {
info.setInUse(false); info.setInUse(false);
} }
else // The effect we try to add should be overriden. else // The effect we try to add should be overridden.
{ {
return; return;
} }
@@ -918,18 +904,6 @@ public final class CharEffectList
return; return;
} }
// Initialize
if (_passives == null)
{
synchronized (this)
{
if (_passives == null)
{
_passives = ConcurrentHashMap.newKeySet();
}
}
}
// Remove previous passives of this id. // Remove previous passives of this id.
_passives.stream().filter(Objects::nonNull).filter(b -> b.getSkill().getId() == skill.getId()).forEach(b -> _passives.stream().filter(Objects::nonNull).filter(b -> b.getSkill().getId() == skill.getId()).forEach(b ->
{ {
@@ -947,18 +921,6 @@ public final class CharEffectList
{ {
if (info.getOption() != null) if (info.getOption() != null)
{ {
// Initialize
if (_options == null)
{
synchronized (this)
{
if (_options == null)
{
_options = ConcurrentHashMap.newKeySet();
}
}
}
// Remove previous options of this id. // Remove previous options of this id.
_options.stream().filter(Objects::nonNull).filter(b -> b.getOption().getId() == info.getOption().getId()).forEach(b -> _options.stream().filter(Objects::nonNull).filter(b -> b.getOption().getId() == info.getOption().getId()).forEach(b ->
{ {
@@ -988,7 +950,7 @@ public final class CharEffectList
final Optional<PartySpelled> ps = ((party != null) || _owner.isSummon()) ? Optional.of(new PartySpelled(_owner)) : Optional.empty(); final Optional<PartySpelled> ps = ((party != null) || _owner.isSummon()) ? Optional.of(new PartySpelled(_owner)) : Optional.empty();
final Optional<ExOlympiadSpelledInfo> os = (player.isInOlympiadMode() && player.isOlympiadStart()) ? Optional.of(new ExOlympiadSpelledInfo(player)) : Optional.empty(); final Optional<ExOlympiadSpelledInfo> os = (player.isInOlympiadMode() && player.isOlympiadStart()) ? Optional.of(new ExOlympiadSpelledInfo(player)) : Optional.empty();
if (_actives != null) if (!_actives.isEmpty())
{ {
//@formatter:off //@formatter:off
_actives.stream() _actives.stream()
@@ -1109,8 +1071,6 @@ public final class CharEffectList
final Set<BuffInfo> unhideBuffs = new HashSet<>(); final Set<BuffInfo> unhideBuffs = new HashSet<>();
// Recalculate new flags // Recalculate new flags
if (_actives != null)
{
for (BuffInfo info : _actives) for (BuffInfo info : _actives)
{ {
if (info != null) if (info != null)
@@ -1144,7 +1104,14 @@ public final class CharEffectList
// Add AbnormalVisualEffect flag. // Add AbnormalVisualEffect flag.
if (skill.hasAbnormalVisualEffects()) if (skill.hasAbnormalVisualEffects())
{ {
abnormalVisualEffectFlags.addAll(skill.getAbnormalVisualEffects()); for (AbnormalVisualEffect ave : skill.getAbnormalVisualEffects())
{
abnormalVisualEffectFlags.add(ave);
_abnormalVisualEffects.add(ave);
}
if (broadcast)
{
_owner.updateAbnormalVisualEffects();
} }
} }
} }
@@ -1167,7 +1134,7 @@ public final class CharEffectList
if (broadcast) if (broadcast)
{ {
// Check if there is change in AbnormalVisualEffect // Check if there is change in AbnormalVisualEffect
if ((abnormalVisualEffectFlags.size() != _abnormalVisualEffects.size()) || !abnormalVisualEffectFlags.containsAll(_abnormalVisualEffects)) if (!abnormalVisualEffectFlags.containsAll(_abnormalVisualEffects))
{ {
_abnormalVisualEffects = abnormalVisualEffectFlags; _abnormalVisualEffects = abnormalVisualEffectFlags;
_owner.updateAbnormalVisualEffects(); _owner.updateAbnormalVisualEffects();

View File

@@ -77,7 +77,6 @@ public class DoppelgangerInstance extends L2Npc
info.setAbnormalTime(summonerInfo.getAbnormalTime()); info.setAbnormalTime(summonerInfo.getAbnormalTime());
getEffectList().add(info); getEffectList().add(info);
} }
} }
} }
} }

View File

@@ -786,7 +786,7 @@ public class CharStat
final CharEffectList effectList = _activeChar.getEffectList(); final CharEffectList effectList = _activeChar.getEffectList();
final Stream<BuffInfo> passives = effectList.getPassives().stream().filter(BuffInfo::isInUse).filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar)); final Stream<BuffInfo> passives = effectList.getPassives().stream().filter(BuffInfo::isInUse).filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar));
final Stream<BuffInfo> options = effectList.getOptions().stream().filter(BuffInfo::isInUse); final Stream<BuffInfo> options = effectList.getOptions().stream().filter(BuffInfo::isInUse);
final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives != null ? passives : Stream.empty(), options != null ? options : Stream.empty())); final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives, options));
// Call pump to each effect // Call pump to each effect
//@formatter:off //@formatter:off

View File

@@ -389,10 +389,10 @@ public final class BuffInfo
for (AbstractEffect effect : _effects) for (AbstractEffect effect : _effects)
{ {
// Instant effects shouldn't call onExit(..). // Instant effects shouldn't call onExit(..).
if (!effect.isInstant()) // if (!effect.isInstant())
{ // {
effect.onExit(_effector, _effected, _skill); effect.onExit(_effector, _effected, _skill);
} // }
} }
// Set the proper system message. // Set the proper system message.

View File

@@ -21,13 +21,11 @@ import java.util.List;
import com.l2jmobius.commons.network.PacketWriter; import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.skills.BuffInfo; import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.OutgoingPackets; import com.l2jmobius.gameserver.network.OutgoingPackets;
public class AbnormalStatusUpdate implements IClientOutgoingPacket public class AbnormalStatusUpdate implements IClientOutgoingPacket
{ {
private final List<BuffInfo> _effects = new ArrayList<>(); private final List<BuffInfo> _effects = new ArrayList<>();
private final List<Skill> _effects2 = new ArrayList<>();
public void addSkill(BuffInfo info) public void addSkill(BuffInfo info)
{ {
@@ -37,20 +35,12 @@ public class AbnormalStatusUpdate implements IClientOutgoingPacket
} }
} }
public void addSkill(Skill skill)
{
if (!skill.isHealingPotionSkill())
{
_effects2.add(skill);
}
}
@Override @Override
public boolean write(PacketWriter packet) public boolean write(PacketWriter packet)
{ {
OutgoingPackets.ABNORMAL_STATUS_UPDATE.writeId(packet); OutgoingPackets.ABNORMAL_STATUS_UPDATE.writeId(packet);
packet.writeH(_effects.size() + _effects2.size()); packet.writeH(_effects.size());
for (BuffInfo info : _effects) for (BuffInfo info : _effects)
{ {
if ((info != null) && info.isInUse()) if ((info != null) && info.isInUse())
@@ -62,17 +52,6 @@ public class AbnormalStatusUpdate implements IClientOutgoingPacket
writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime()); writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
} }
} }
for (Skill skill : _effects2)
{
if (skill != null)
{
packet.writeD(skill.getDisplayId());
packet.writeH(skill.getDisplayLevel());
packet.writeH(0x00); // Sub level
packet.writeD(skill.getAbnormalType().getClientId());
packet.writeH(-1);
}
}
return true; return true;
} }
} }

View File

@@ -16,7 +16,6 @@
*/ */
package com.l2jmobius.gameserver.network.serverpackets; package com.l2jmobius.gameserver.network.serverpackets;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -24,41 +23,12 @@ import java.util.stream.Collectors;
import com.l2jmobius.commons.network.PacketWriter; import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.skills.BuffInfo; import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.OutgoingPackets; import com.l2jmobius.gameserver.network.OutgoingPackets;
public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
{ {
private final L2Character _character; private final L2Character _character;
private List<Effect> _effects = new ArrayList<>(); private final List<BuffInfo> _effects;
private static class Effect
{
protected int _skillId;
protected int _level;
protected int _subLevel;
protected int _abnormalType;
protected int _duration;
protected int _caster;
public Effect(BuffInfo info)
{
final Skill skill = info.getSkill();
final L2Character caster = info.getEffector();
int casterId = 0;
if (caster != null)
{
casterId = caster.getObjectId();
}
_skillId = skill.getDisplayId();
_level = skill.getDisplayLevel();
_subLevel = skill.getSubLevel();
_abnormalType = skill.getAbnormalType().getClientId();
_duration = skill.isAura() ? -1 : info.getTime();
_caster = casterId;
}
}
public ExAbnormalStatusUpdateFromTarget(L2Character character) public ExAbnormalStatusUpdateFromTarget(L2Character character)
{ {
@@ -69,7 +39,6 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
.filter(Objects::nonNull) .filter(Objects::nonNull)
.filter(BuffInfo::isInUse) .filter(BuffInfo::isInUse)
.filter(b -> !b.getSkill().isToggle()) .filter(b -> !b.getSkill().isToggle())
.map(Effect::new)
.collect(Collectors.toList()); .collect(Collectors.toList());
//@formatter:on //@formatter:on
} }
@@ -82,14 +51,14 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
packet.writeD(_character.getObjectId()); packet.writeD(_character.getObjectId());
packet.writeH(_effects.size()); packet.writeH(_effects.size());
for (Effect info : _effects) for (BuffInfo info : _effects)
{ {
packet.writeD(info._skillId); packet.writeD(info.getSkill().getDisplayId());
packet.writeH(info._level); packet.writeH(info.getSkill().getDisplayLevel());
packet.writeH(info._subLevel); packet.writeH(info.getSkill().getSubLevel());
packet.writeH(info._abnormalType); packet.writeH(info.getSkill().getAbnormalType().getClientId());
writeOptionalD(packet, info._duration); writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
packet.writeD(info._caster); packet.writeD(info.getEffectorObjectId());
} }
return true; return true;
} }

View File

@@ -16,6 +16,8 @@
*/ */
package handlers.effecthandlers; package handlers.effecthandlers;
import java.util.Collections;
import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.StatsSet;
@@ -38,6 +40,19 @@ public final class CallSkillOnActionTime extends AbstractEffect
setTicks(params.getInt("ticks")); setTicks(params.getInt("ticks"));
} }
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
effected.getEffectList().stopEffects(Collections.singleton(_skill.getSkill().getAbnormalType()));
effected.getEffectList().addBlockedAbnormalTypes(Collections.singleton(_skill.getSkill().getAbnormalType()));
}
@Override
public void onExit(L2Character effector, L2Character effected, Skill skill)
{
effected.getEffectList().removeBlockedAbnormalTypes(Collections.singleton(_skill.getSkill().getAbnormalType()));
}
@Override @Override
public boolean onActionTime(L2Character effector, L2Character effected, Skill skill) public boolean onActionTime(L2Character effector, L2Character effected, Skill skill)
{ {

View File

@@ -136,6 +136,5 @@ public final class Disarmor extends AbstractEffect
} }
} }
} }
super.onExit(effector, effected, skill);
} }
} }

View File

@@ -84,6 +84,5 @@ public final class DoubleCast extends AbstractEffect
return null; return null;
}); });
} }
super.onExit(effector, effected, skill);
} }
} }

View File

@@ -65,15 +65,15 @@ public final class CharEffectList
{ {
private static final Logger LOGGER = Logger.getLogger(CharEffectList.class.getName()); private static final Logger LOGGER = Logger.getLogger(CharEffectList.class.getName());
/** Queue containing all effects from buffs for this effect list. */ /** Queue containing all effects from buffs for this effect list. */
private volatile Queue<BuffInfo> _actives; private volatile Queue<BuffInfo> _actives = new ConcurrentLinkedQueue<>();
/** List containing all passives for this effect list. They bypass most of the actions and they are not included in most operations. */ /** List containing all passives for this effect list. They bypass most of the actions and they are not included in most operations. */
private volatile Set<BuffInfo> _passives; private volatile Set<BuffInfo> _passives = ConcurrentHashMap.newKeySet();
/** List containing all options for this effect list. They bypass most of the actions and they are not included in most operations. */ /** List containing all options for this effect list. They bypass most of the actions and they are not included in most operations. */
private volatile Set<BuffInfo> _options; private volatile Set<BuffInfo> _options = ConcurrentHashMap.newKeySet();
/** Map containing the all stacked effect in progress for each {@code AbnormalType}. */ /** Map containing the all stacked effect in progress for each {@code AbnormalType}. */
private volatile Set<AbnormalType> _stackedEffects = EnumSet.noneOf(AbnormalType.class); private volatile Set<AbnormalType> _stackedEffects = EnumSet.noneOf(AbnormalType.class);
/** Set containing all {@code AbnormalType}s that shouldn't be added to this creature effect list. */ /** Set containing all {@code AbnormalType}s that shouldn't be added to this creature effect list. */
private volatile Set<AbnormalType> _blockedAbnormalTypes = null; private volatile Set<AbnormalType> _blockedAbnormalTypes = EnumSet.noneOf(AbnormalType.class);
/** Set containing all abnormal visual effects this creature currently displays. */ /** Set containing all abnormal visual effects this creature currently displays. */
private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects = EnumSet.noneOf(AbnormalVisualEffect.class); private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects = EnumSet.noneOf(AbnormalVisualEffect.class);
/** Short buff skill ID. */ /** Short buff skill ID. */
@@ -110,7 +110,7 @@ public final class CharEffectList
*/ */
public Set<BuffInfo> getPassives() public Set<BuffInfo> getPassives()
{ {
return _passives != null ? Collections.unmodifiableSet(_passives) : Collections.emptySet(); return Collections.unmodifiableSet(_passives);
} }
/** /**
@@ -119,7 +119,7 @@ public final class CharEffectList
*/ */
public Set<BuffInfo> getOptions() public Set<BuffInfo> getOptions()
{ {
return _options != null ? Collections.unmodifiableSet(_options) : Collections.emptySet(); return Collections.unmodifiableSet(_options);
} }
/** /**
@@ -128,7 +128,7 @@ public final class CharEffectList
*/ */
public Collection<BuffInfo> getEffects() public Collection<BuffInfo> getEffects()
{ {
return _actives != null ? Collections.unmodifiableCollection(_actives) : Collections.emptyList(); return Collections.unmodifiableCollection(_actives);
} }
/** /**
@@ -137,7 +137,7 @@ public final class CharEffectList
*/ */
public List<BuffInfo> getBuffs() public List<BuffInfo> getBuffs()
{ {
return _actives != null ? _actives.stream().filter(b -> !b.getSkill().getBuffType().isBuff()).collect(Collectors.toList()) : Collections.emptyList(); return _actives.stream().filter(b -> !b.getSkill().getBuffType().isBuff()).collect(Collectors.toList());
} }
/** /**
@@ -146,7 +146,7 @@ public final class CharEffectList
*/ */
public List<BuffInfo> getDebuffs() public List<BuffInfo> getDebuffs()
{ {
return _actives != null ? _actives.stream().filter(b -> b.getSkill().isDebuff()).collect(Collectors.toList()) : Collections.emptyList(); return _actives.stream().filter(b -> b.getSkill().isDebuff()).collect(Collectors.toList());
} }
/** /**
@@ -156,7 +156,7 @@ public final class CharEffectList
*/ */
public boolean isAffectedBySkill(int skillId) public boolean isAffectedBySkill(int skillId)
{ {
return ((_actives != null) && _actives.stream().anyMatch(i -> i.getSkill().getId() == skillId)) || ((_passives != null) && _passives.stream().anyMatch(i -> i.getSkill().getId() == skillId)); return (_actives.stream().anyMatch(i -> i.getSkill().getId() == skillId)) || (_passives.stream().anyMatch(i -> i.getSkill().getId() == skillId));
} }
/** /**
@@ -166,7 +166,7 @@ public final class CharEffectList
*/ */
public BuffInfo getBuffInfoBySkillId(int skillId) public BuffInfo getBuffInfoBySkillId(int skillId)
{ {
return Stream.concat(_actives != null ? _actives.stream() : Stream.empty(), _passives != null ? _passives.stream() : Stream.empty()).filter(b -> b.getSkill().getId() == skillId).findFirst().orElse(null); return Stream.concat(_actives.stream(), _passives.stream()).filter(b -> b.getSkill().getId() == skillId).findFirst().orElse(null);
} }
/** /**
@@ -216,18 +216,6 @@ public final class CharEffectList
*/ */
public void addBlockedAbnormalTypes(Set<AbnormalType> blockedAbnormalTypes) public void addBlockedAbnormalTypes(Set<AbnormalType> blockedAbnormalTypes)
{ {
// Initialize
if (_blockedAbnormalTypes == null)
{
synchronized (this)
{
if (_blockedAbnormalTypes == null)
{
_blockedAbnormalTypes = EnumSet.copyOf(blockedAbnormalTypes);
}
}
}
_blockedAbnormalTypes.addAll(blockedAbnormalTypes); _blockedAbnormalTypes.addAll(blockedAbnormalTypes);
} }
@@ -238,7 +226,7 @@ public final class CharEffectList
*/ */
public boolean removeBlockedAbnormalTypes(Set<AbnormalType> blockedBuffSlots) public boolean removeBlockedAbnormalTypes(Set<AbnormalType> blockedBuffSlots)
{ {
return (_blockedAbnormalTypes != null) && _blockedAbnormalTypes.removeAll(blockedBuffSlots); return _blockedAbnormalTypes.removeAll(blockedBuffSlots);
} }
/** /**
@@ -247,7 +235,7 @@ public final class CharEffectList
*/ */
public Set<AbnormalType> getBlockedAbnormalTypes() public Set<AbnormalType> getBlockedAbnormalTypes()
{ {
return _blockedAbnormalTypes != null ? Collections.unmodifiableSet(_blockedAbnormalTypes) : Collections.emptySet(); return Collections.unmodifiableSet(_blockedAbnormalTypes);
} }
/** /**
@@ -277,7 +265,7 @@ public final class CharEffectList
*/ */
public int getBuffCount() public int getBuffCount()
{ {
return _actives != null ? (_buffCount.get() - _hiddenBuffs.get()) : 0; return !_actives.isEmpty() ? (_buffCount.get() - _hiddenBuffs.get()) : 0;
} }
/** /**
@@ -374,7 +362,7 @@ public final class CharEffectList
*/ */
public void stopAllPassives(boolean update, boolean broadcast) public void stopAllPassives(boolean update, boolean broadcast)
{ {
if (_passives != null) if (!_passives.isEmpty())
{ {
_passives.forEach(this::remove); _passives.forEach(this::remove);
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -392,7 +380,7 @@ public final class CharEffectList
*/ */
public void stopAllOptions(boolean update, boolean broadcast) public void stopAllOptions(boolean update, boolean broadcast)
{ {
if (_options != null) if (!_options.isEmpty())
{ {
_options.forEach(this::remove); _options.forEach(this::remove);
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -490,7 +478,7 @@ public final class CharEffectList
*/ */
public void stopEffects(Predicate<BuffInfo> filter, boolean update, boolean broadcast) public void stopEffects(Predicate<BuffInfo> filter, boolean update, boolean broadcast)
{ {
if (_actives != null) if (!_actives.isEmpty())
{ {
_actives.stream().filter(filter).forEach(this::remove); _actives.stream().filter(filter).forEach(this::remove);
@@ -678,6 +666,10 @@ public final class CharEffectList
{ {
// Remove active effect. // Remove active effect.
removeActive(info, removed); removeActive(info, removed);
if (_owner.isNpc()) // Fix for all NPC debuff animations removed.
{
updateEffectList(broadcast);
}
} }
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -693,7 +685,7 @@ public final class CharEffectList
*/ */
private synchronized void removeActive(BuffInfo info, boolean removed) private synchronized void removeActive(BuffInfo info, boolean removed)
{ {
if (_actives != null) if (!_actives.isEmpty())
{ {
// Removes the buff from the given effect list. // Removes the buff from the given effect list.
_actives.remove(info); _actives.remove(info);
@@ -716,7 +708,7 @@ public final class CharEffectList
private void removePassive(BuffInfo info, boolean removed) private void removePassive(BuffInfo info, boolean removed)
{ {
if (_passives != null) if (!_passives.isEmpty())
{ {
_passives.remove(info); _passives.remove(info);
info.stopAllEffects(removed); info.stopAllEffects(removed);
@@ -725,7 +717,7 @@ public final class CharEffectList
private void removeOption(BuffInfo info, boolean removed) private void removeOption(BuffInfo info, boolean removed)
{ {
if (_options != null) if (!_options.isEmpty())
{ {
_options.remove(info); _options.remove(info);
info.stopAllEffects(removed); info.stopAllEffects(removed);
@@ -821,12 +813,6 @@ public final class CharEffectList
} }
} }
// Initialize
if (_actives == null)
{
_actives = new ConcurrentLinkedQueue<>();
}
// Manage effect stacking. // Manage effect stacking.
if (hasAbnormalType(skill.getAbnormalType())) if (hasAbnormalType(skill.getAbnormalType()))
{ {
@@ -857,7 +843,7 @@ public final class CharEffectList
} }
else else
{ {
// Remove effect that gets overriden. // Remove effect that gets overridden.
remove(existingInfo); remove(existingInfo);
} }
} }
@@ -865,7 +851,7 @@ public final class CharEffectList
{ {
info.setInUse(false); info.setInUse(false);
} }
else // The effect we try to add should be overriden. else // The effect we try to add should be overridden.
{ {
return; return;
} }
@@ -918,18 +904,6 @@ public final class CharEffectList
return; return;
} }
// Initialize
if (_passives == null)
{
synchronized (this)
{
if (_passives == null)
{
_passives = ConcurrentHashMap.newKeySet();
}
}
}
// Remove previous passives of this id. // Remove previous passives of this id.
_passives.stream().filter(Objects::nonNull).filter(b -> b.getSkill().getId() == skill.getId()).forEach(b -> _passives.stream().filter(Objects::nonNull).filter(b -> b.getSkill().getId() == skill.getId()).forEach(b ->
{ {
@@ -947,18 +921,6 @@ public final class CharEffectList
{ {
if (info.getOption() != null) if (info.getOption() != null)
{ {
// Initialize
if (_options == null)
{
synchronized (this)
{
if (_options == null)
{
_options = ConcurrentHashMap.newKeySet();
}
}
}
// Remove previous options of this id. // Remove previous options of this id.
_options.stream().filter(Objects::nonNull).filter(b -> b.getOption().getId() == info.getOption().getId()).forEach(b -> _options.stream().filter(Objects::nonNull).filter(b -> b.getOption().getId() == info.getOption().getId()).forEach(b ->
{ {
@@ -988,7 +950,7 @@ public final class CharEffectList
final Optional<PartySpelled> ps = ((party != null) || _owner.isSummon()) ? Optional.of(new PartySpelled(_owner)) : Optional.empty(); final Optional<PartySpelled> ps = ((party != null) || _owner.isSummon()) ? Optional.of(new PartySpelled(_owner)) : Optional.empty();
final Optional<ExOlympiadSpelledInfo> os = (player.isInOlympiadMode() && player.isOlympiadStart()) ? Optional.of(new ExOlympiadSpelledInfo(player)) : Optional.empty(); final Optional<ExOlympiadSpelledInfo> os = (player.isInOlympiadMode() && player.isOlympiadStart()) ? Optional.of(new ExOlympiadSpelledInfo(player)) : Optional.empty();
if (_actives != null) if (!_actives.isEmpty())
{ {
//@formatter:off //@formatter:off
_actives.stream() _actives.stream()
@@ -1109,8 +1071,6 @@ public final class CharEffectList
final Set<BuffInfo> unhideBuffs = new HashSet<>(); final Set<BuffInfo> unhideBuffs = new HashSet<>();
// Recalculate new flags // Recalculate new flags
if (_actives != null)
{
for (BuffInfo info : _actives) for (BuffInfo info : _actives)
{ {
if (info != null) if (info != null)
@@ -1144,7 +1104,14 @@ public final class CharEffectList
// Add AbnormalVisualEffect flag. // Add AbnormalVisualEffect flag.
if (skill.hasAbnormalVisualEffects()) if (skill.hasAbnormalVisualEffects())
{ {
abnormalVisualEffectFlags.addAll(skill.getAbnormalVisualEffects()); for (AbnormalVisualEffect ave : skill.getAbnormalVisualEffects())
{
abnormalVisualEffectFlags.add(ave);
_abnormalVisualEffects.add(ave);
}
if (broadcast)
{
_owner.updateAbnormalVisualEffects();
} }
} }
} }
@@ -1167,7 +1134,7 @@ public final class CharEffectList
if (broadcast) if (broadcast)
{ {
// Check if there is change in AbnormalVisualEffect // Check if there is change in AbnormalVisualEffect
if ((abnormalVisualEffectFlags.size() != _abnormalVisualEffects.size()) || !abnormalVisualEffectFlags.containsAll(_abnormalVisualEffects)) if (!abnormalVisualEffectFlags.containsAll(_abnormalVisualEffects))
{ {
_abnormalVisualEffects = abnormalVisualEffectFlags; _abnormalVisualEffects = abnormalVisualEffectFlags;
_owner.updateAbnormalVisualEffects(); _owner.updateAbnormalVisualEffects();

View File

@@ -77,7 +77,6 @@ public class DoppelgangerInstance extends L2Npc
info.setAbnormalTime(summonerInfo.getAbnormalTime()); info.setAbnormalTime(summonerInfo.getAbnormalTime());
getEffectList().add(info); getEffectList().add(info);
} }
} }
} }
} }

View File

@@ -776,7 +776,7 @@ public class CharStat
final CharEffectList effectList = _activeChar.getEffectList(); final CharEffectList effectList = _activeChar.getEffectList();
final Stream<BuffInfo> passives = effectList.getPassives().stream().filter(BuffInfo::isInUse).filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar)); final Stream<BuffInfo> passives = effectList.getPassives().stream().filter(BuffInfo::isInUse).filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar));
final Stream<BuffInfo> options = effectList.getOptions().stream().filter(BuffInfo::isInUse); final Stream<BuffInfo> options = effectList.getOptions().stream().filter(BuffInfo::isInUse);
final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives != null ? passives : Stream.empty(), options != null ? options : Stream.empty())); final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives, options));
// Call pump to each effect // Call pump to each effect
//@formatter:off //@formatter:off

View File

@@ -389,10 +389,10 @@ public final class BuffInfo
for (AbstractEffect effect : _effects) for (AbstractEffect effect : _effects)
{ {
// Instant effects shouldn't call onExit(..). // Instant effects shouldn't call onExit(..).
if (!effect.isInstant()) // if (!effect.isInstant())
{ // {
effect.onExit(_effector, _effected, _skill); effect.onExit(_effector, _effected, _skill);
} // }
} }
// Set the proper system message. // Set the proper system message.

View File

@@ -21,17 +21,11 @@ import java.util.List;
import com.l2jmobius.commons.network.PacketWriter; import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.skills.BuffInfo; import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.OutgoingPackets; import com.l2jmobius.gameserver.network.OutgoingPackets;
/**
* @author Mobius
* @version Classic 2.0
*/
public class AbnormalStatusUpdate implements IClientOutgoingPacket public class AbnormalStatusUpdate implements IClientOutgoingPacket
{ {
private final List<BuffInfo> _effects = new ArrayList<>(); private final List<BuffInfo> _effects = new ArrayList<>();
private final List<Skill> _effects2 = new ArrayList<>();
public void addSkill(BuffInfo info) public void addSkill(BuffInfo info)
{ {
@@ -41,38 +35,21 @@ public class AbnormalStatusUpdate implements IClientOutgoingPacket
} }
} }
public void addSkill(Skill skill)
{
if (!skill.isHealingPotionSkill())
{
_effects2.add(skill);
}
}
@Override @Override
public boolean write(PacketWriter packet) public boolean write(PacketWriter packet)
{ {
OutgoingPackets.ABNORMAL_STATUS_UPDATE.writeId(packet); OutgoingPackets.ABNORMAL_STATUS_UPDATE.writeId(packet);
packet.writeH(_effects.size() + _effects2.size()); packet.writeH(_effects.size());
for (BuffInfo info : _effects) for (BuffInfo info : _effects)
{ {
if ((info != null) && info.isInUse()) if ((info != null) && info.isInUse())
{ {
packet.writeD(info.getSkill().getDisplayId()); packet.writeD(info.getSkill().getDisplayId());
packet.writeH(info.getSkill().getDisplayLevel()); packet.writeH(info.getSkill().getDisplayLevel());
packet.writeD(0x00); // packet.writeH(info.getSkill().getSubLevel());
packet.writeH(info.getSkill().isAura() ? -1 : info.getTime()); packet.writeD(info.getSkill().getAbnormalType().getClientId());
} writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
}
for (Skill skill : _effects2)
{
if (skill != null)
{
packet.writeD(skill.getDisplayId());
packet.writeH(skill.getDisplayLevel());
packet.writeD(skill.getAbnormalType().getClientId());
packet.writeH(-1);
} }
} }
return true; return true;

View File

@@ -16,8 +16,8 @@
*/ */
package com.l2jmobius.gameserver.network.serverpackets; package com.l2jmobius.gameserver.network.serverpackets;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.l2jmobius.commons.network.PacketWriter; import com.l2jmobius.commons.network.PacketWriter;
@@ -25,35 +25,10 @@ import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.skills.BuffInfo; import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.network.OutgoingPackets; import com.l2jmobius.gameserver.network.OutgoingPackets;
/**
* @author proGenitor <br>
* Experimental packet compatible for L2Classic 2.0.
*/
public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
{ {
private final L2Character _character; private final L2Character _character;
private List<Effect> _effects = new ArrayList<>(); private final List<BuffInfo> _effects;
private static class Effect
{
protected int _skillId;
protected int _level;
protected int _subLevel;
protected int _abnormalType;
protected int _duration;
protected int _caster;
public Effect(BuffInfo info)
{
final L2Character caster = info.getEffector();
int casterId = 0;
if (caster != null)
{
casterId = caster.getObjectId();
}
_caster = casterId;
}
}
public ExAbnormalStatusUpdateFromTarget(L2Character character) public ExAbnormalStatusUpdateFromTarget(L2Character character)
{ {
@@ -61,7 +36,9 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
_character = character; _character = character;
_effects = character.getEffectList().getEffects() _effects = character.getEffectList().getEffects()
.stream() .stream()
.map(Effect::new) .filter(Objects::nonNull)
.filter(BuffInfo::isInUse)
.filter(b -> !b.getSkill().isToggle())
.collect(Collectors.toList()); .collect(Collectors.toList());
//@formatter:on //@formatter:on
} }
@@ -74,14 +51,14 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
packet.writeD(_character.getObjectId()); packet.writeD(_character.getObjectId());
packet.writeH(_effects.size()); packet.writeH(_effects.size());
for (Effect info : _effects) for (BuffInfo info : _effects)
{ {
packet.writeD(info._skillId); packet.writeD(info.getSkill().getDisplayId());
packet.writeH(info._level); packet.writeH(info.getSkill().getDisplayLevel());
packet.writeH(info._subLevel); // packet.writeH(info.getSkill().getSubLevel());
packet.writeH(info._abnormalType); packet.writeH(info.getSkill().getAbnormalType().getClientId());
writeOptionalD(packet, info._duration); writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
packet.writeD(info._caster); packet.writeD(info.getEffectorObjectId());
} }
return true; return true;
} }

View File

@@ -16,6 +16,8 @@
*/ */
package handlers.effecthandlers; package handlers.effecthandlers;
import java.util.Collections;
import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.StatsSet;
@@ -38,6 +40,19 @@ public final class CallSkillOnActionTime extends AbstractEffect
setTicks(params.getInt("ticks")); setTicks(params.getInt("ticks"));
} }
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
effected.getEffectList().stopEffects(Collections.singleton(_skill.getSkill().getAbnormalType()));
effected.getEffectList().addBlockedAbnormalTypes(Collections.singleton(_skill.getSkill().getAbnormalType()));
}
@Override
public void onExit(L2Character effector, L2Character effected, Skill skill)
{
effected.getEffectList().removeBlockedAbnormalTypes(Collections.singleton(_skill.getSkill().getAbnormalType()));
}
@Override @Override
public boolean onActionTime(L2Character effector, L2Character effected, Skill skill) public boolean onActionTime(L2Character effector, L2Character effected, Skill skill)
{ {

View File

@@ -136,6 +136,5 @@ public final class Disarmor extends AbstractEffect
} }
} }
} }
super.onExit(effector, effected, skill);
} }
} }

View File

@@ -84,6 +84,5 @@ public final class DoubleCast extends AbstractEffect
return null; return null;
}); });
} }
super.onExit(effector, effected, skill);
} }
} }

View File

@@ -65,15 +65,15 @@ public final class CharEffectList
{ {
private static final Logger LOGGER = Logger.getLogger(CharEffectList.class.getName()); private static final Logger LOGGER = Logger.getLogger(CharEffectList.class.getName());
/** Queue containing all effects from buffs for this effect list. */ /** Queue containing all effects from buffs for this effect list. */
private volatile Queue<BuffInfo> _actives; private volatile Queue<BuffInfo> _actives = new ConcurrentLinkedQueue<>();
/** List containing all passives for this effect list. They bypass most of the actions and they are not included in most operations. */ /** List containing all passives for this effect list. They bypass most of the actions and they are not included in most operations. */
private volatile Set<BuffInfo> _passives; private volatile Set<BuffInfo> _passives = ConcurrentHashMap.newKeySet();
/** List containing all options for this effect list. They bypass most of the actions and they are not included in most operations. */ /** List containing all options for this effect list. They bypass most of the actions and they are not included in most operations. */
private volatile Set<BuffInfo> _options; private volatile Set<BuffInfo> _options = ConcurrentHashMap.newKeySet();
/** Map containing the all stacked effect in progress for each {@code AbnormalType}. */ /** Map containing the all stacked effect in progress for each {@code AbnormalType}. */
private volatile Set<AbnormalType> _stackedEffects = EnumSet.noneOf(AbnormalType.class); private volatile Set<AbnormalType> _stackedEffects = EnumSet.noneOf(AbnormalType.class);
/** Set containing all {@code AbnormalType}s that shouldn't be added to this creature effect list. */ /** Set containing all {@code AbnormalType}s that shouldn't be added to this creature effect list. */
private volatile Set<AbnormalType> _blockedAbnormalTypes = null; private volatile Set<AbnormalType> _blockedAbnormalTypes = EnumSet.noneOf(AbnormalType.class);
/** Set containing all abnormal visual effects this creature currently displays. */ /** Set containing all abnormal visual effects this creature currently displays. */
private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects = EnumSet.noneOf(AbnormalVisualEffect.class); private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects = EnumSet.noneOf(AbnormalVisualEffect.class);
/** Short buff skill ID. */ /** Short buff skill ID. */
@@ -110,7 +110,7 @@ public final class CharEffectList
*/ */
public Set<BuffInfo> getPassives() public Set<BuffInfo> getPassives()
{ {
return _passives != null ? Collections.unmodifiableSet(_passives) : Collections.emptySet(); return Collections.unmodifiableSet(_passives);
} }
/** /**
@@ -119,7 +119,7 @@ public final class CharEffectList
*/ */
public Set<BuffInfo> getOptions() public Set<BuffInfo> getOptions()
{ {
return _options != null ? Collections.unmodifiableSet(_options) : Collections.emptySet(); return Collections.unmodifiableSet(_options);
} }
/** /**
@@ -128,7 +128,7 @@ public final class CharEffectList
*/ */
public Collection<BuffInfo> getEffects() public Collection<BuffInfo> getEffects()
{ {
return _actives != null ? Collections.unmodifiableCollection(_actives) : Collections.emptyList(); return Collections.unmodifiableCollection(_actives);
} }
/** /**
@@ -137,7 +137,7 @@ public final class CharEffectList
*/ */
public List<BuffInfo> getBuffs() public List<BuffInfo> getBuffs()
{ {
return _actives != null ? _actives.stream().filter(b -> !b.getSkill().getBuffType().isBuff()).collect(Collectors.toList()) : Collections.emptyList(); return _actives.stream().filter(b -> !b.getSkill().getBuffType().isBuff()).collect(Collectors.toList());
} }
/** /**
@@ -146,7 +146,7 @@ public final class CharEffectList
*/ */
public List<BuffInfo> getDebuffs() public List<BuffInfo> getDebuffs()
{ {
return _actives != null ? _actives.stream().filter(b -> b.getSkill().isDebuff()).collect(Collectors.toList()) : Collections.emptyList(); return _actives.stream().filter(b -> b.getSkill().isDebuff()).collect(Collectors.toList());
} }
/** /**
@@ -156,7 +156,7 @@ public final class CharEffectList
*/ */
public boolean isAffectedBySkill(int skillId) public boolean isAffectedBySkill(int skillId)
{ {
return ((_actives != null) && _actives.stream().anyMatch(i -> i.getSkill().getId() == skillId)) || ((_passives != null) && _passives.stream().anyMatch(i -> i.getSkill().getId() == skillId)); return (_actives.stream().anyMatch(i -> i.getSkill().getId() == skillId)) || (_passives.stream().anyMatch(i -> i.getSkill().getId() == skillId));
} }
/** /**
@@ -166,7 +166,7 @@ public final class CharEffectList
*/ */
public BuffInfo getBuffInfoBySkillId(int skillId) public BuffInfo getBuffInfoBySkillId(int skillId)
{ {
return Stream.concat(_actives != null ? _actives.stream() : Stream.empty(), _passives != null ? _passives.stream() : Stream.empty()).filter(b -> b.getSkill().getId() == skillId).findFirst().orElse(null); return Stream.concat(_actives.stream(), _passives.stream()).filter(b -> b.getSkill().getId() == skillId).findFirst().orElse(null);
} }
/** /**
@@ -216,18 +216,6 @@ public final class CharEffectList
*/ */
public void addBlockedAbnormalTypes(Set<AbnormalType> blockedAbnormalTypes) public void addBlockedAbnormalTypes(Set<AbnormalType> blockedAbnormalTypes)
{ {
// Initialize
if (_blockedAbnormalTypes == null)
{
synchronized (this)
{
if (_blockedAbnormalTypes == null)
{
_blockedAbnormalTypes = EnumSet.copyOf(blockedAbnormalTypes);
}
}
}
_blockedAbnormalTypes.addAll(blockedAbnormalTypes); _blockedAbnormalTypes.addAll(blockedAbnormalTypes);
} }
@@ -238,7 +226,7 @@ public final class CharEffectList
*/ */
public boolean removeBlockedAbnormalTypes(Set<AbnormalType> blockedBuffSlots) public boolean removeBlockedAbnormalTypes(Set<AbnormalType> blockedBuffSlots)
{ {
return (_blockedAbnormalTypes != null) && _blockedAbnormalTypes.removeAll(blockedBuffSlots); return _blockedAbnormalTypes.removeAll(blockedBuffSlots);
} }
/** /**
@@ -247,7 +235,7 @@ public final class CharEffectList
*/ */
public Set<AbnormalType> getBlockedAbnormalTypes() public Set<AbnormalType> getBlockedAbnormalTypes()
{ {
return _blockedAbnormalTypes != null ? Collections.unmodifiableSet(_blockedAbnormalTypes) : Collections.emptySet(); return Collections.unmodifiableSet(_blockedAbnormalTypes);
} }
/** /**
@@ -277,7 +265,7 @@ public final class CharEffectList
*/ */
public int getBuffCount() public int getBuffCount()
{ {
return _actives != null ? (_buffCount.get() - _hiddenBuffs.get()) : 0; return !_actives.isEmpty() ? (_buffCount.get() - _hiddenBuffs.get()) : 0;
} }
/** /**
@@ -374,7 +362,7 @@ public final class CharEffectList
*/ */
public void stopAllPassives(boolean update, boolean broadcast) public void stopAllPassives(boolean update, boolean broadcast)
{ {
if (_passives != null) if (!_passives.isEmpty())
{ {
_passives.forEach(this::remove); _passives.forEach(this::remove);
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -392,7 +380,7 @@ public final class CharEffectList
*/ */
public void stopAllOptions(boolean update, boolean broadcast) public void stopAllOptions(boolean update, boolean broadcast)
{ {
if (_options != null) if (!_options.isEmpty())
{ {
_options.forEach(this::remove); _options.forEach(this::remove);
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -490,7 +478,7 @@ public final class CharEffectList
*/ */
public void stopEffects(Predicate<BuffInfo> filter, boolean update, boolean broadcast) public void stopEffects(Predicate<BuffInfo> filter, boolean update, boolean broadcast)
{ {
if (_actives != null) if (!_actives.isEmpty())
{ {
_actives.stream().filter(filter).forEach(this::remove); _actives.stream().filter(filter).forEach(this::remove);
@@ -678,6 +666,10 @@ public final class CharEffectList
{ {
// Remove active effect. // Remove active effect.
removeActive(info, removed); removeActive(info, removed);
if (_owner.isNpc()) // Fix for all NPC debuff animations removed.
{
updateEffectList(broadcast);
}
} }
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -693,7 +685,7 @@ public final class CharEffectList
*/ */
private synchronized void removeActive(BuffInfo info, boolean removed) private synchronized void removeActive(BuffInfo info, boolean removed)
{ {
if (_actives != null) if (!_actives.isEmpty())
{ {
// Removes the buff from the given effect list. // Removes the buff from the given effect list.
_actives.remove(info); _actives.remove(info);
@@ -716,7 +708,7 @@ public final class CharEffectList
private void removePassive(BuffInfo info, boolean removed) private void removePassive(BuffInfo info, boolean removed)
{ {
if (_passives != null) if (!_passives.isEmpty())
{ {
_passives.remove(info); _passives.remove(info);
info.stopAllEffects(removed); info.stopAllEffects(removed);
@@ -725,7 +717,7 @@ public final class CharEffectList
private void removeOption(BuffInfo info, boolean removed) private void removeOption(BuffInfo info, boolean removed)
{ {
if (_options != null) if (!_options.isEmpty())
{ {
_options.remove(info); _options.remove(info);
info.stopAllEffects(removed); info.stopAllEffects(removed);
@@ -821,12 +813,6 @@ public final class CharEffectList
} }
} }
// Initialize
if (_actives == null)
{
_actives = new ConcurrentLinkedQueue<>();
}
// Manage effect stacking. // Manage effect stacking.
if (hasAbnormalType(skill.getAbnormalType())) if (hasAbnormalType(skill.getAbnormalType()))
{ {
@@ -857,7 +843,7 @@ public final class CharEffectList
} }
else else
{ {
// Remove effect that gets overriden. // Remove effect that gets overridden.
remove(existingInfo); remove(existingInfo);
} }
} }
@@ -865,7 +851,7 @@ public final class CharEffectList
{ {
info.setInUse(false); info.setInUse(false);
} }
else // The effect we try to add should be overriden. else // The effect we try to add should be overridden.
{ {
return; return;
} }
@@ -918,18 +904,6 @@ public final class CharEffectList
return; return;
} }
// Initialize
if (_passives == null)
{
synchronized (this)
{
if (_passives == null)
{
_passives = ConcurrentHashMap.newKeySet();
}
}
}
// Remove previous passives of this id. // Remove previous passives of this id.
_passives.stream().filter(Objects::nonNull).filter(b -> b.getSkill().getId() == skill.getId()).forEach(b -> _passives.stream().filter(Objects::nonNull).filter(b -> b.getSkill().getId() == skill.getId()).forEach(b ->
{ {
@@ -947,18 +921,6 @@ public final class CharEffectList
{ {
if (info.getOption() != null) if (info.getOption() != null)
{ {
// Initialize
if (_options == null)
{
synchronized (this)
{
if (_options == null)
{
_options = ConcurrentHashMap.newKeySet();
}
}
}
// Remove previous options of this id. // Remove previous options of this id.
_options.stream().filter(Objects::nonNull).filter(b -> b.getOption().getId() == info.getOption().getId()).forEach(b -> _options.stream().filter(Objects::nonNull).filter(b -> b.getOption().getId() == info.getOption().getId()).forEach(b ->
{ {
@@ -988,7 +950,7 @@ public final class CharEffectList
final Optional<PartySpelled> ps = ((party != null) || _owner.isSummon()) ? Optional.of(new PartySpelled(_owner)) : Optional.empty(); final Optional<PartySpelled> ps = ((party != null) || _owner.isSummon()) ? Optional.of(new PartySpelled(_owner)) : Optional.empty();
final Optional<ExOlympiadSpelledInfo> os = (player.isInOlympiadMode() && player.isOlympiadStart()) ? Optional.of(new ExOlympiadSpelledInfo(player)) : Optional.empty(); final Optional<ExOlympiadSpelledInfo> os = (player.isInOlympiadMode() && player.isOlympiadStart()) ? Optional.of(new ExOlympiadSpelledInfo(player)) : Optional.empty();
if (_actives != null) if (!_actives.isEmpty())
{ {
//@formatter:off //@formatter:off
_actives.stream() _actives.stream()
@@ -1109,8 +1071,6 @@ public final class CharEffectList
final Set<BuffInfo> unhideBuffs = new HashSet<>(); final Set<BuffInfo> unhideBuffs = new HashSet<>();
// Recalculate new flags // Recalculate new flags
if (_actives != null)
{
for (BuffInfo info : _actives) for (BuffInfo info : _actives)
{ {
if (info != null) if (info != null)
@@ -1144,7 +1104,14 @@ public final class CharEffectList
// Add AbnormalVisualEffect flag. // Add AbnormalVisualEffect flag.
if (skill.hasAbnormalVisualEffects()) if (skill.hasAbnormalVisualEffects())
{ {
abnormalVisualEffectFlags.addAll(skill.getAbnormalVisualEffects()); for (AbnormalVisualEffect ave : skill.getAbnormalVisualEffects())
{
abnormalVisualEffectFlags.add(ave);
_abnormalVisualEffects.add(ave);
}
if (broadcast)
{
_owner.updateAbnormalVisualEffects();
} }
} }
} }
@@ -1167,7 +1134,7 @@ public final class CharEffectList
if (broadcast) if (broadcast)
{ {
// Check if there is change in AbnormalVisualEffect // Check if there is change in AbnormalVisualEffect
if ((abnormalVisualEffectFlags.size() != _abnormalVisualEffects.size()) || !abnormalVisualEffectFlags.containsAll(_abnormalVisualEffects)) if (!abnormalVisualEffectFlags.containsAll(_abnormalVisualEffects))
{ {
_abnormalVisualEffects = abnormalVisualEffectFlags; _abnormalVisualEffects = abnormalVisualEffectFlags;
_owner.updateAbnormalVisualEffects(); _owner.updateAbnormalVisualEffects();

View File

@@ -77,7 +77,6 @@ public class DoppelgangerInstance extends L2Npc
info.setAbnormalTime(summonerInfo.getAbnormalTime()); info.setAbnormalTime(summonerInfo.getAbnormalTime());
getEffectList().add(info); getEffectList().add(info);
} }
} }
} }
} }

View File

@@ -776,7 +776,7 @@ public class CharStat
final CharEffectList effectList = _activeChar.getEffectList(); final CharEffectList effectList = _activeChar.getEffectList();
final Stream<BuffInfo> passives = effectList.getPassives().stream().filter(BuffInfo::isInUse).filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar)); final Stream<BuffInfo> passives = effectList.getPassives().stream().filter(BuffInfo::isInUse).filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar));
final Stream<BuffInfo> options = effectList.getOptions().stream().filter(BuffInfo::isInUse); final Stream<BuffInfo> options = effectList.getOptions().stream().filter(BuffInfo::isInUse);
final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives != null ? passives : Stream.empty(), options != null ? options : Stream.empty())); final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives, options));
// Call pump to each effect // Call pump to each effect
//@formatter:off //@formatter:off

View File

@@ -389,10 +389,10 @@ public final class BuffInfo
for (AbstractEffect effect : _effects) for (AbstractEffect effect : _effects)
{ {
// Instant effects shouldn't call onExit(..). // Instant effects shouldn't call onExit(..).
if (!effect.isInstant()) // if (!effect.isInstant())
{ // {
effect.onExit(_effector, _effected, _skill); effect.onExit(_effector, _effected, _skill);
} // }
} }
// Set the proper system message. // Set the proper system message.

View File

@@ -21,17 +21,11 @@ import java.util.List;
import com.l2jmobius.commons.network.PacketWriter; import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.skills.BuffInfo; import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.OutgoingPackets; import com.l2jmobius.gameserver.network.OutgoingPackets;
/**
* @author Mobius
* @version Classic 2.0
*/
public class AbnormalStatusUpdate implements IClientOutgoingPacket public class AbnormalStatusUpdate implements IClientOutgoingPacket
{ {
private final List<BuffInfo> _effects = new ArrayList<>(); private final List<BuffInfo> _effects = new ArrayList<>();
private final List<Skill> _effects2 = new ArrayList<>();
public void addSkill(BuffInfo info) public void addSkill(BuffInfo info)
{ {
@@ -41,38 +35,21 @@ public class AbnormalStatusUpdate implements IClientOutgoingPacket
} }
} }
public void addSkill(Skill skill)
{
if (!skill.isHealingPotionSkill())
{
_effects2.add(skill);
}
}
@Override @Override
public boolean write(PacketWriter packet) public boolean write(PacketWriter packet)
{ {
OutgoingPackets.ABNORMAL_STATUS_UPDATE.writeId(packet); OutgoingPackets.ABNORMAL_STATUS_UPDATE.writeId(packet);
packet.writeH(_effects.size() + _effects2.size()); packet.writeH(_effects.size());
for (BuffInfo info : _effects) for (BuffInfo info : _effects)
{ {
if ((info != null) && info.isInUse()) if ((info != null) && info.isInUse())
{ {
packet.writeD(info.getSkill().getDisplayId()); packet.writeD(info.getSkill().getDisplayId());
packet.writeH(info.getSkill().getDisplayLevel()); packet.writeH(info.getSkill().getDisplayLevel());
packet.writeD(0x00); // packet.writeH(info.getSkill().getSubLevel());
packet.writeH(info.getSkill().isAura() ? -1 : info.getTime()); packet.writeD(info.getSkill().getAbnormalType().getClientId());
} writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
}
for (Skill skill : _effects2)
{
if (skill != null)
{
packet.writeD(skill.getDisplayId());
packet.writeH(skill.getDisplayLevel());
packet.writeD(skill.getAbnormalType().getClientId());
packet.writeH(-1);
} }
} }
return true; return true;

View File

@@ -16,8 +16,8 @@
*/ */
package com.l2jmobius.gameserver.network.serverpackets; package com.l2jmobius.gameserver.network.serverpackets;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.l2jmobius.commons.network.PacketWriter; import com.l2jmobius.commons.network.PacketWriter;
@@ -25,35 +25,10 @@ import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.skills.BuffInfo; import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.network.OutgoingPackets; import com.l2jmobius.gameserver.network.OutgoingPackets;
/**
* @author proGenitor <br>
* Experimental packet compatible for L2Classic 2.0.
*/
public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
{ {
private final L2Character _character; private final L2Character _character;
private List<Effect> _effects = new ArrayList<>(); private final List<BuffInfo> _effects;
private static class Effect
{
protected int _skillId;
protected int _level;
protected int _subLevel;
protected int _abnormalType;
protected int _duration;
protected int _caster;
public Effect(BuffInfo info)
{
final L2Character caster = info.getEffector();
int casterId = 0;
if (caster != null)
{
casterId = caster.getObjectId();
}
_caster = casterId;
}
}
public ExAbnormalStatusUpdateFromTarget(L2Character character) public ExAbnormalStatusUpdateFromTarget(L2Character character)
{ {
@@ -61,7 +36,9 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
_character = character; _character = character;
_effects = character.getEffectList().getEffects() _effects = character.getEffectList().getEffects()
.stream() .stream()
.map(Effect::new) .filter(Objects::nonNull)
.filter(BuffInfo::isInUse)
.filter(b -> !b.getSkill().isToggle())
.collect(Collectors.toList()); .collect(Collectors.toList());
//@formatter:on //@formatter:on
} }
@@ -74,14 +51,14 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
packet.writeD(_character.getObjectId()); packet.writeD(_character.getObjectId());
packet.writeH(_effects.size()); packet.writeH(_effects.size());
for (Effect info : _effects) for (BuffInfo info : _effects)
{ {
packet.writeD(info._skillId); packet.writeD(info.getSkill().getDisplayId());
packet.writeH(info._level); packet.writeH(info.getSkill().getDisplayLevel());
packet.writeH(info._subLevel); // packet.writeH(info.getSkill().getSubLevel());
packet.writeH(info._abnormalType); packet.writeH(info.getSkill().getAbnormalType().getClientId());
writeOptionalD(packet, info._duration); writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
packet.writeD(info._caster); packet.writeD(info.getEffectorObjectId());
} }
return true; return true;
} }

View File

@@ -16,6 +16,8 @@
*/ */
package handlers.effecthandlers; package handlers.effecthandlers;
import java.util.Collections;
import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.StatsSet;
@@ -38,6 +40,19 @@ public final class CallSkillOnActionTime extends AbstractEffect
setTicks(params.getInt("ticks")); setTicks(params.getInt("ticks"));
} }
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
effected.getEffectList().stopEffects(Collections.singleton(_skill.getSkill().getAbnormalType()));
effected.getEffectList().addBlockedAbnormalTypes(Collections.singleton(_skill.getSkill().getAbnormalType()));
}
@Override
public void onExit(L2Character effector, L2Character effected, Skill skill)
{
effected.getEffectList().removeBlockedAbnormalTypes(Collections.singleton(_skill.getSkill().getAbnormalType()));
}
@Override @Override
public boolean onActionTime(L2Character effector, L2Character effected, Skill skill) public boolean onActionTime(L2Character effector, L2Character effected, Skill skill)
{ {

View File

@@ -136,6 +136,5 @@ public final class Disarmor extends AbstractEffect
} }
} }
} }
super.onExit(effector, effected, skill);
} }
} }

View File

@@ -84,6 +84,5 @@ public final class DoubleCast extends AbstractEffect
return null; return null;
}); });
} }
super.onExit(effector, effected, skill);
} }
} }

View File

@@ -65,15 +65,15 @@ public final class CharEffectList
{ {
private static final Logger LOGGER = Logger.getLogger(CharEffectList.class.getName()); private static final Logger LOGGER = Logger.getLogger(CharEffectList.class.getName());
/** Queue containing all effects from buffs for this effect list. */ /** Queue containing all effects from buffs for this effect list. */
private volatile Queue<BuffInfo> _actives; private volatile Queue<BuffInfo> _actives = new ConcurrentLinkedQueue<>();
/** List containing all passives for this effect list. They bypass most of the actions and they are not included in most operations. */ /** List containing all passives for this effect list. They bypass most of the actions and they are not included in most operations. */
private volatile Set<BuffInfo> _passives; private volatile Set<BuffInfo> _passives = ConcurrentHashMap.newKeySet();
/** List containing all options for this effect list. They bypass most of the actions and they are not included in most operations. */ /** List containing all options for this effect list. They bypass most of the actions and they are not included in most operations. */
private volatile Set<BuffInfo> _options; private volatile Set<BuffInfo> _options = ConcurrentHashMap.newKeySet();
/** Map containing the all stacked effect in progress for each {@code AbnormalType}. */ /** Map containing the all stacked effect in progress for each {@code AbnormalType}. */
private volatile Set<AbnormalType> _stackedEffects = EnumSet.noneOf(AbnormalType.class); private volatile Set<AbnormalType> _stackedEffects = EnumSet.noneOf(AbnormalType.class);
/** Set containing all {@code AbnormalType}s that shouldn't be added to this creature effect list. */ /** Set containing all {@code AbnormalType}s that shouldn't be added to this creature effect list. */
private volatile Set<AbnormalType> _blockedAbnormalTypes = null; private volatile Set<AbnormalType> _blockedAbnormalTypes = EnumSet.noneOf(AbnormalType.class);
/** Set containing all abnormal visual effects this creature currently displays. */ /** Set containing all abnormal visual effects this creature currently displays. */
private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects = EnumSet.noneOf(AbnormalVisualEffect.class); private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects = EnumSet.noneOf(AbnormalVisualEffect.class);
/** Short buff skill ID. */ /** Short buff skill ID. */
@@ -110,7 +110,7 @@ public final class CharEffectList
*/ */
public Set<BuffInfo> getPassives() public Set<BuffInfo> getPassives()
{ {
return _passives != null ? Collections.unmodifiableSet(_passives) : Collections.emptySet(); return Collections.unmodifiableSet(_passives);
} }
/** /**
@@ -119,7 +119,7 @@ public final class CharEffectList
*/ */
public Set<BuffInfo> getOptions() public Set<BuffInfo> getOptions()
{ {
return _options != null ? Collections.unmodifiableSet(_options) : Collections.emptySet(); return Collections.unmodifiableSet(_options);
} }
/** /**
@@ -128,7 +128,7 @@ public final class CharEffectList
*/ */
public Collection<BuffInfo> getEffects() public Collection<BuffInfo> getEffects()
{ {
return _actives != null ? Collections.unmodifiableCollection(_actives) : Collections.emptyList(); return Collections.unmodifiableCollection(_actives);
} }
/** /**
@@ -137,7 +137,7 @@ public final class CharEffectList
*/ */
public List<BuffInfo> getBuffs() public List<BuffInfo> getBuffs()
{ {
return _actives != null ? _actives.stream().filter(b -> !b.getSkill().getBuffType().isBuff()).collect(Collectors.toList()) : Collections.emptyList(); return _actives.stream().filter(b -> !b.getSkill().getBuffType().isBuff()).collect(Collectors.toList());
} }
/** /**
@@ -146,7 +146,7 @@ public final class CharEffectList
*/ */
public List<BuffInfo> getDebuffs() public List<BuffInfo> getDebuffs()
{ {
return _actives != null ? _actives.stream().filter(b -> b.getSkill().isDebuff()).collect(Collectors.toList()) : Collections.emptyList(); return _actives.stream().filter(b -> b.getSkill().isDebuff()).collect(Collectors.toList());
} }
/** /**
@@ -156,7 +156,7 @@ public final class CharEffectList
*/ */
public boolean isAffectedBySkill(int skillId) public boolean isAffectedBySkill(int skillId)
{ {
return ((_actives != null) && _actives.stream().anyMatch(i -> i.getSkill().getId() == skillId)) || ((_passives != null) && _passives.stream().anyMatch(i -> i.getSkill().getId() == skillId)); return (_actives.stream().anyMatch(i -> i.getSkill().getId() == skillId)) || (_passives.stream().anyMatch(i -> i.getSkill().getId() == skillId));
} }
/** /**
@@ -166,7 +166,7 @@ public final class CharEffectList
*/ */
public BuffInfo getBuffInfoBySkillId(int skillId) public BuffInfo getBuffInfoBySkillId(int skillId)
{ {
return Stream.concat(_actives != null ? _actives.stream() : Stream.empty(), _passives != null ? _passives.stream() : Stream.empty()).filter(b -> b.getSkill().getId() == skillId).findFirst().orElse(null); return Stream.concat(_actives.stream(), _passives.stream()).filter(b -> b.getSkill().getId() == skillId).findFirst().orElse(null);
} }
/** /**
@@ -216,18 +216,6 @@ public final class CharEffectList
*/ */
public void addBlockedAbnormalTypes(Set<AbnormalType> blockedAbnormalTypes) public void addBlockedAbnormalTypes(Set<AbnormalType> blockedAbnormalTypes)
{ {
// Initialize
if (_blockedAbnormalTypes == null)
{
synchronized (this)
{
if (_blockedAbnormalTypes == null)
{
_blockedAbnormalTypes = EnumSet.copyOf(blockedAbnormalTypes);
}
}
}
_blockedAbnormalTypes.addAll(blockedAbnormalTypes); _blockedAbnormalTypes.addAll(blockedAbnormalTypes);
} }
@@ -238,7 +226,7 @@ public final class CharEffectList
*/ */
public boolean removeBlockedAbnormalTypes(Set<AbnormalType> blockedBuffSlots) public boolean removeBlockedAbnormalTypes(Set<AbnormalType> blockedBuffSlots)
{ {
return (_blockedAbnormalTypes != null) && _blockedAbnormalTypes.removeAll(blockedBuffSlots); return _blockedAbnormalTypes.removeAll(blockedBuffSlots);
} }
/** /**
@@ -247,7 +235,7 @@ public final class CharEffectList
*/ */
public Set<AbnormalType> getBlockedAbnormalTypes() public Set<AbnormalType> getBlockedAbnormalTypes()
{ {
return _blockedAbnormalTypes != null ? Collections.unmodifiableSet(_blockedAbnormalTypes) : Collections.emptySet(); return Collections.unmodifiableSet(_blockedAbnormalTypes);
} }
/** /**
@@ -277,7 +265,7 @@ public final class CharEffectList
*/ */
public int getBuffCount() public int getBuffCount()
{ {
return _actives != null ? (_buffCount.get() - _hiddenBuffs.get()) : 0; return !_actives.isEmpty() ? (_buffCount.get() - _hiddenBuffs.get()) : 0;
} }
/** /**
@@ -374,7 +362,7 @@ public final class CharEffectList
*/ */
public void stopAllPassives(boolean update, boolean broadcast) public void stopAllPassives(boolean update, boolean broadcast)
{ {
if (_passives != null) if (!_passives.isEmpty())
{ {
_passives.forEach(this::remove); _passives.forEach(this::remove);
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -392,7 +380,7 @@ public final class CharEffectList
*/ */
public void stopAllOptions(boolean update, boolean broadcast) public void stopAllOptions(boolean update, boolean broadcast)
{ {
if (_options != null) if (!_options.isEmpty())
{ {
_options.forEach(this::remove); _options.forEach(this::remove);
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -490,7 +478,7 @@ public final class CharEffectList
*/ */
public void stopEffects(Predicate<BuffInfo> filter, boolean update, boolean broadcast) public void stopEffects(Predicate<BuffInfo> filter, boolean update, boolean broadcast)
{ {
if (_actives != null) if (!_actives.isEmpty())
{ {
_actives.stream().filter(filter).forEach(this::remove); _actives.stream().filter(filter).forEach(this::remove);
@@ -678,6 +666,10 @@ public final class CharEffectList
{ {
// Remove active effect. // Remove active effect.
removeActive(info, removed); removeActive(info, removed);
if (_owner.isNpc()) // Fix for all NPC debuff animations removed.
{
updateEffectList(broadcast);
}
} }
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -693,7 +685,7 @@ public final class CharEffectList
*/ */
private synchronized void removeActive(BuffInfo info, boolean removed) private synchronized void removeActive(BuffInfo info, boolean removed)
{ {
if (_actives != null) if (!_actives.isEmpty())
{ {
// Removes the buff from the given effect list. // Removes the buff from the given effect list.
_actives.remove(info); _actives.remove(info);
@@ -716,7 +708,7 @@ public final class CharEffectList
private void removePassive(BuffInfo info, boolean removed) private void removePassive(BuffInfo info, boolean removed)
{ {
if (_passives != null) if (!_passives.isEmpty())
{ {
_passives.remove(info); _passives.remove(info);
info.stopAllEffects(removed); info.stopAllEffects(removed);
@@ -725,7 +717,7 @@ public final class CharEffectList
private void removeOption(BuffInfo info, boolean removed) private void removeOption(BuffInfo info, boolean removed)
{ {
if (_options != null) if (!_options.isEmpty())
{ {
_options.remove(info); _options.remove(info);
info.stopAllEffects(removed); info.stopAllEffects(removed);
@@ -821,12 +813,6 @@ public final class CharEffectList
} }
} }
// Initialize
if (_actives == null)
{
_actives = new ConcurrentLinkedQueue<>();
}
// Manage effect stacking. // Manage effect stacking.
if (hasAbnormalType(skill.getAbnormalType())) if (hasAbnormalType(skill.getAbnormalType()))
{ {
@@ -857,7 +843,7 @@ public final class CharEffectList
} }
else else
{ {
// Remove effect that gets overriden. // Remove effect that gets overridden.
remove(existingInfo); remove(existingInfo);
} }
} }
@@ -865,7 +851,7 @@ public final class CharEffectList
{ {
info.setInUse(false); info.setInUse(false);
} }
else // The effect we try to add should be overriden. else // The effect we try to add should be overridden.
{ {
return; return;
} }
@@ -918,18 +904,6 @@ public final class CharEffectList
return; return;
} }
// Initialize
if (_passives == null)
{
synchronized (this)
{
if (_passives == null)
{
_passives = ConcurrentHashMap.newKeySet();
}
}
}
// Remove previous passives of this id. // Remove previous passives of this id.
_passives.stream().filter(Objects::nonNull).filter(b -> b.getSkill().getId() == skill.getId()).forEach(b -> _passives.stream().filter(Objects::nonNull).filter(b -> b.getSkill().getId() == skill.getId()).forEach(b ->
{ {
@@ -947,18 +921,6 @@ public final class CharEffectList
{ {
if (info.getOption() != null) if (info.getOption() != null)
{ {
// Initialize
if (_options == null)
{
synchronized (this)
{
if (_options == null)
{
_options = ConcurrentHashMap.newKeySet();
}
}
}
// Remove previous options of this id. // Remove previous options of this id.
_options.stream().filter(Objects::nonNull).filter(b -> b.getOption().getId() == info.getOption().getId()).forEach(b -> _options.stream().filter(Objects::nonNull).filter(b -> b.getOption().getId() == info.getOption().getId()).forEach(b ->
{ {
@@ -988,7 +950,7 @@ public final class CharEffectList
final Optional<PartySpelled> ps = ((party != null) || _owner.isSummon()) ? Optional.of(new PartySpelled(_owner)) : Optional.empty(); final Optional<PartySpelled> ps = ((party != null) || _owner.isSummon()) ? Optional.of(new PartySpelled(_owner)) : Optional.empty();
final Optional<ExOlympiadSpelledInfo> os = (player.isInOlympiadMode() && player.isOlympiadStart()) ? Optional.of(new ExOlympiadSpelledInfo(player)) : Optional.empty(); final Optional<ExOlympiadSpelledInfo> os = (player.isInOlympiadMode() && player.isOlympiadStart()) ? Optional.of(new ExOlympiadSpelledInfo(player)) : Optional.empty();
if (_actives != null) if (!_actives.isEmpty())
{ {
//@formatter:off //@formatter:off
_actives.stream() _actives.stream()
@@ -1109,8 +1071,6 @@ public final class CharEffectList
final Set<BuffInfo> unhideBuffs = new HashSet<>(); final Set<BuffInfo> unhideBuffs = new HashSet<>();
// Recalculate new flags // Recalculate new flags
if (_actives != null)
{
for (BuffInfo info : _actives) for (BuffInfo info : _actives)
{ {
if (info != null) if (info != null)
@@ -1144,7 +1104,14 @@ public final class CharEffectList
// Add AbnormalVisualEffect flag. // Add AbnormalVisualEffect flag.
if (skill.hasAbnormalVisualEffects()) if (skill.hasAbnormalVisualEffects())
{ {
abnormalVisualEffectFlags.addAll(skill.getAbnormalVisualEffects()); for (AbnormalVisualEffect ave : skill.getAbnormalVisualEffects())
{
abnormalVisualEffectFlags.add(ave);
_abnormalVisualEffects.add(ave);
}
if (broadcast)
{
_owner.updateAbnormalVisualEffects();
} }
} }
} }
@@ -1167,7 +1134,7 @@ public final class CharEffectList
if (broadcast) if (broadcast)
{ {
// Check if there is change in AbnormalVisualEffect // Check if there is change in AbnormalVisualEffect
if ((abnormalVisualEffectFlags.size() != _abnormalVisualEffects.size()) || !abnormalVisualEffectFlags.containsAll(_abnormalVisualEffects)) if (!abnormalVisualEffectFlags.containsAll(_abnormalVisualEffects))
{ {
_abnormalVisualEffects = abnormalVisualEffectFlags; _abnormalVisualEffects = abnormalVisualEffectFlags;
_owner.updateAbnormalVisualEffects(); _owner.updateAbnormalVisualEffects();

View File

@@ -77,7 +77,6 @@ public class DoppelgangerInstance extends L2Npc
info.setAbnormalTime(summonerInfo.getAbnormalTime()); info.setAbnormalTime(summonerInfo.getAbnormalTime());
getEffectList().add(info); getEffectList().add(info);
} }
} }
} }
} }

View File

@@ -776,7 +776,7 @@ public class CharStat
final CharEffectList effectList = _activeChar.getEffectList(); final CharEffectList effectList = _activeChar.getEffectList();
final Stream<BuffInfo> passives = effectList.getPassives().stream().filter(BuffInfo::isInUse).filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar)); final Stream<BuffInfo> passives = effectList.getPassives().stream().filter(BuffInfo::isInUse).filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar));
final Stream<BuffInfo> options = effectList.getOptions().stream().filter(BuffInfo::isInUse); final Stream<BuffInfo> options = effectList.getOptions().stream().filter(BuffInfo::isInUse);
final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives != null ? passives : Stream.empty(), options != null ? options : Stream.empty())); final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives, options));
// Call pump to each effect // Call pump to each effect
//@formatter:off //@formatter:off

View File

@@ -389,10 +389,10 @@ public final class BuffInfo
for (AbstractEffect effect : _effects) for (AbstractEffect effect : _effects)
{ {
// Instant effects shouldn't call onExit(..). // Instant effects shouldn't call onExit(..).
if (!effect.isInstant()) // if (!effect.isInstant())
{ // {
effect.onExit(_effector, _effected, _skill); effect.onExit(_effector, _effected, _skill);
} // }
} }
// Set the proper system message. // Set the proper system message.

View File

@@ -21,17 +21,11 @@ import java.util.List;
import com.l2jmobius.commons.network.PacketWriter; import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.skills.BuffInfo; import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.OutgoingPackets; import com.l2jmobius.gameserver.network.OutgoingPackets;
/**
* @author Mobius
* @version Classic 2.0
*/
public class AbnormalStatusUpdate implements IClientOutgoingPacket public class AbnormalStatusUpdate implements IClientOutgoingPacket
{ {
private final List<BuffInfo> _effects = new ArrayList<>(); private final List<BuffInfo> _effects = new ArrayList<>();
private final List<Skill> _effects2 = new ArrayList<>();
public void addSkill(BuffInfo info) public void addSkill(BuffInfo info)
{ {
@@ -41,38 +35,21 @@ public class AbnormalStatusUpdate implements IClientOutgoingPacket
} }
} }
public void addSkill(Skill skill)
{
if (!skill.isHealingPotionSkill())
{
_effects2.add(skill);
}
}
@Override @Override
public boolean write(PacketWriter packet) public boolean write(PacketWriter packet)
{ {
OutgoingPackets.ABNORMAL_STATUS_UPDATE.writeId(packet); OutgoingPackets.ABNORMAL_STATUS_UPDATE.writeId(packet);
packet.writeH(_effects.size() + _effects2.size()); packet.writeH(_effects.size());
for (BuffInfo info : _effects) for (BuffInfo info : _effects)
{ {
if ((info != null) && info.isInUse()) if ((info != null) && info.isInUse())
{ {
packet.writeD(info.getSkill().getDisplayId()); packet.writeD(info.getSkill().getDisplayId());
packet.writeH(info.getSkill().getDisplayLevel()); packet.writeH(info.getSkill().getDisplayLevel());
packet.writeD(0x00); // packet.writeH(info.getSkill().getSubLevel());
packet.writeH(info.getSkill().isAura() ? -1 : info.getTime()); packet.writeD(info.getSkill().getAbnormalType().getClientId());
} writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
}
for (Skill skill : _effects2)
{
if (skill != null)
{
packet.writeD(skill.getDisplayId());
packet.writeH(skill.getDisplayLevel());
packet.writeD(skill.getAbnormalType().getClientId());
packet.writeH(-1);
} }
} }
return true; return true;

View File

@@ -16,8 +16,8 @@
*/ */
package com.l2jmobius.gameserver.network.serverpackets; package com.l2jmobius.gameserver.network.serverpackets;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.l2jmobius.commons.network.PacketWriter; import com.l2jmobius.commons.network.PacketWriter;
@@ -25,35 +25,10 @@ import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.skills.BuffInfo; import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.network.OutgoingPackets; import com.l2jmobius.gameserver.network.OutgoingPackets;
/**
* @author proGenitor <br>
* Experimental packet compatible for L2Classic 2.0.
*/
public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
{ {
private final L2Character _character; private final L2Character _character;
private List<Effect> _effects = new ArrayList<>(); private final List<BuffInfo> _effects;
private static class Effect
{
protected int _skillId;
protected int _level;
protected int _subLevel;
protected int _abnormalType;
protected int _duration;
protected int _caster;
public Effect(BuffInfo info)
{
final L2Character caster = info.getEffector();
int casterId = 0;
if (caster != null)
{
casterId = caster.getObjectId();
}
_caster = casterId;
}
}
public ExAbnormalStatusUpdateFromTarget(L2Character character) public ExAbnormalStatusUpdateFromTarget(L2Character character)
{ {
@@ -61,7 +36,9 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
_character = character; _character = character;
_effects = character.getEffectList().getEffects() _effects = character.getEffectList().getEffects()
.stream() .stream()
.map(Effect::new) .filter(Objects::nonNull)
.filter(BuffInfo::isInUse)
.filter(b -> !b.getSkill().isToggle())
.collect(Collectors.toList()); .collect(Collectors.toList());
//@formatter:on //@formatter:on
} }
@@ -74,14 +51,14 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
packet.writeD(_character.getObjectId()); packet.writeD(_character.getObjectId());
packet.writeH(_effects.size()); packet.writeH(_effects.size());
for (Effect info : _effects) for (BuffInfo info : _effects)
{ {
packet.writeD(info._skillId); packet.writeD(info.getSkill().getDisplayId());
packet.writeH(info._level); packet.writeH(info.getSkill().getDisplayLevel());
packet.writeH(info._subLevel); // packet.writeH(info.getSkill().getSubLevel());
packet.writeH(info._abnormalType); packet.writeH(info.getSkill().getAbnormalType().getClientId());
writeOptionalD(packet, info._duration); writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
packet.writeD(info._caster); packet.writeD(info.getEffectorObjectId());
} }
return true; return true;
} }

View File

@@ -16,6 +16,8 @@
*/ */
package handlers.effecthandlers; package handlers.effecthandlers;
import java.util.Collections;
import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.StatsSet;
@@ -38,6 +40,19 @@ public final class CallSkillOnActionTime extends AbstractEffect
setTicks(params.getInt("ticks")); setTicks(params.getInt("ticks"));
} }
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
effected.getEffectList().stopEffects(Collections.singleton(_skill.getSkill().getAbnormalType()));
effected.getEffectList().addBlockedAbnormalTypes(Collections.singleton(_skill.getSkill().getAbnormalType()));
}
@Override
public void onExit(L2Character effector, L2Character effected, Skill skill)
{
effected.getEffectList().removeBlockedAbnormalTypes(Collections.singleton(_skill.getSkill().getAbnormalType()));
}
@Override @Override
public boolean onActionTime(L2Character effector, L2Character effected, Skill skill) public boolean onActionTime(L2Character effector, L2Character effected, Skill skill)
{ {

View File

@@ -136,6 +136,5 @@ public final class Disarmor extends AbstractEffect
} }
} }
} }
super.onExit(effector, effected, skill);
} }
} }

View File

@@ -84,6 +84,5 @@ public final class DoubleCast extends AbstractEffect
return null; return null;
}); });
} }
super.onExit(effector, effected, skill);
} }
} }

View File

@@ -65,15 +65,15 @@ public final class CharEffectList
{ {
private static final Logger LOGGER = Logger.getLogger(CharEffectList.class.getName()); private static final Logger LOGGER = Logger.getLogger(CharEffectList.class.getName());
/** Queue containing all effects from buffs for this effect list. */ /** Queue containing all effects from buffs for this effect list. */
private volatile Queue<BuffInfo> _actives; private volatile Queue<BuffInfo> _actives = new ConcurrentLinkedQueue<>();
/** List containing all passives for this effect list. They bypass most of the actions and they are not included in most operations. */ /** List containing all passives for this effect list. They bypass most of the actions and they are not included in most operations. */
private volatile Set<BuffInfo> _passives; private volatile Set<BuffInfo> _passives = ConcurrentHashMap.newKeySet();
/** List containing all options for this effect list. They bypass most of the actions and they are not included in most operations. */ /** List containing all options for this effect list. They bypass most of the actions and they are not included in most operations. */
private volatile Set<BuffInfo> _options; private volatile Set<BuffInfo> _options = ConcurrentHashMap.newKeySet();
/** Map containing the all stacked effect in progress for each {@code AbnormalType}. */ /** Map containing the all stacked effect in progress for each {@code AbnormalType}. */
private volatile Set<AbnormalType> _stackedEffects = EnumSet.noneOf(AbnormalType.class); private volatile Set<AbnormalType> _stackedEffects = EnumSet.noneOf(AbnormalType.class);
/** Set containing all {@code AbnormalType}s that shouldn't be added to this creature effect list. */ /** Set containing all {@code AbnormalType}s that shouldn't be added to this creature effect list. */
private volatile Set<AbnormalType> _blockedAbnormalTypes = null; private volatile Set<AbnormalType> _blockedAbnormalTypes = EnumSet.noneOf(AbnormalType.class);
/** Set containing all abnormal visual effects this creature currently displays. */ /** Set containing all abnormal visual effects this creature currently displays. */
private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects = EnumSet.noneOf(AbnormalVisualEffect.class); private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects = EnumSet.noneOf(AbnormalVisualEffect.class);
/** Short buff skill ID. */ /** Short buff skill ID. */
@@ -110,7 +110,7 @@ public final class CharEffectList
*/ */
public Set<BuffInfo> getPassives() public Set<BuffInfo> getPassives()
{ {
return _passives != null ? Collections.unmodifiableSet(_passives) : Collections.emptySet(); return Collections.unmodifiableSet(_passives);
} }
/** /**
@@ -119,7 +119,7 @@ public final class CharEffectList
*/ */
public Set<BuffInfo> getOptions() public Set<BuffInfo> getOptions()
{ {
return _options != null ? Collections.unmodifiableSet(_options) : Collections.emptySet(); return Collections.unmodifiableSet(_options);
} }
/** /**
@@ -128,7 +128,7 @@ public final class CharEffectList
*/ */
public Collection<BuffInfo> getEffects() public Collection<BuffInfo> getEffects()
{ {
return _actives != null ? Collections.unmodifiableCollection(_actives) : Collections.emptyList(); return Collections.unmodifiableCollection(_actives);
} }
/** /**
@@ -137,7 +137,7 @@ public final class CharEffectList
*/ */
public List<BuffInfo> getBuffs() public List<BuffInfo> getBuffs()
{ {
return _actives != null ? _actives.stream().filter(b -> !b.getSkill().getBuffType().isBuff()).collect(Collectors.toList()) : Collections.emptyList(); return _actives.stream().filter(b -> !b.getSkill().getBuffType().isBuff()).collect(Collectors.toList());
} }
/** /**
@@ -146,7 +146,7 @@ public final class CharEffectList
*/ */
public List<BuffInfo> getDebuffs() public List<BuffInfo> getDebuffs()
{ {
return _actives != null ? _actives.stream().filter(b -> b.getSkill().isDebuff()).collect(Collectors.toList()) : Collections.emptyList(); return _actives.stream().filter(b -> b.getSkill().isDebuff()).collect(Collectors.toList());
} }
/** /**
@@ -156,7 +156,7 @@ public final class CharEffectList
*/ */
public boolean isAffectedBySkill(int skillId) public boolean isAffectedBySkill(int skillId)
{ {
return ((_actives != null) && _actives.stream().anyMatch(i -> i.getSkill().getId() == skillId)) || ((_passives != null) && _passives.stream().anyMatch(i -> i.getSkill().getId() == skillId)); return (_actives.stream().anyMatch(i -> i.getSkill().getId() == skillId)) || (_passives.stream().anyMatch(i -> i.getSkill().getId() == skillId));
} }
/** /**
@@ -166,7 +166,7 @@ public final class CharEffectList
*/ */
public BuffInfo getBuffInfoBySkillId(int skillId) public BuffInfo getBuffInfoBySkillId(int skillId)
{ {
return Stream.concat(_actives != null ? _actives.stream() : Stream.empty(), _passives != null ? _passives.stream() : Stream.empty()).filter(b -> b.getSkill().getId() == skillId).findFirst().orElse(null); return Stream.concat(_actives.stream(), _passives.stream()).filter(b -> b.getSkill().getId() == skillId).findFirst().orElse(null);
} }
/** /**
@@ -216,18 +216,6 @@ public final class CharEffectList
*/ */
public void addBlockedAbnormalTypes(Set<AbnormalType> blockedAbnormalTypes) public void addBlockedAbnormalTypes(Set<AbnormalType> blockedAbnormalTypes)
{ {
// Initialize
if (_blockedAbnormalTypes == null)
{
synchronized (this)
{
if (_blockedAbnormalTypes == null)
{
_blockedAbnormalTypes = EnumSet.copyOf(blockedAbnormalTypes);
}
}
}
_blockedAbnormalTypes.addAll(blockedAbnormalTypes); _blockedAbnormalTypes.addAll(blockedAbnormalTypes);
} }
@@ -238,7 +226,7 @@ public final class CharEffectList
*/ */
public boolean removeBlockedAbnormalTypes(Set<AbnormalType> blockedBuffSlots) public boolean removeBlockedAbnormalTypes(Set<AbnormalType> blockedBuffSlots)
{ {
return (_blockedAbnormalTypes != null) && _blockedAbnormalTypes.removeAll(blockedBuffSlots); return _blockedAbnormalTypes.removeAll(blockedBuffSlots);
} }
/** /**
@@ -247,7 +235,7 @@ public final class CharEffectList
*/ */
public Set<AbnormalType> getBlockedAbnormalTypes() public Set<AbnormalType> getBlockedAbnormalTypes()
{ {
return _blockedAbnormalTypes != null ? Collections.unmodifiableSet(_blockedAbnormalTypes) : Collections.emptySet(); return Collections.unmodifiableSet(_blockedAbnormalTypes);
} }
/** /**
@@ -277,7 +265,7 @@ public final class CharEffectList
*/ */
public int getBuffCount() public int getBuffCount()
{ {
return _actives != null ? (_buffCount.get() - _hiddenBuffs.get()) : 0; return !_actives.isEmpty() ? (_buffCount.get() - _hiddenBuffs.get()) : 0;
} }
/** /**
@@ -374,7 +362,7 @@ public final class CharEffectList
*/ */
public void stopAllPassives(boolean update, boolean broadcast) public void stopAllPassives(boolean update, boolean broadcast)
{ {
if (_passives != null) if (!_passives.isEmpty())
{ {
_passives.forEach(this::remove); _passives.forEach(this::remove);
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -392,7 +380,7 @@ public final class CharEffectList
*/ */
public void stopAllOptions(boolean update, boolean broadcast) public void stopAllOptions(boolean update, boolean broadcast)
{ {
if (_options != null) if (!_options.isEmpty())
{ {
_options.forEach(this::remove); _options.forEach(this::remove);
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -490,7 +478,7 @@ public final class CharEffectList
*/ */
public void stopEffects(Predicate<BuffInfo> filter, boolean update, boolean broadcast) public void stopEffects(Predicate<BuffInfo> filter, boolean update, boolean broadcast)
{ {
if (_actives != null) if (!_actives.isEmpty())
{ {
_actives.stream().filter(filter).forEach(this::remove); _actives.stream().filter(filter).forEach(this::remove);
@@ -678,6 +666,10 @@ public final class CharEffectList
{ {
// Remove active effect. // Remove active effect.
removeActive(info, removed); removeActive(info, removed);
if (_owner.isNpc()) // Fix for all NPC debuff animations removed.
{
updateEffectList(broadcast);
}
} }
// Update stats, effect flags and icons. // Update stats, effect flags and icons.
@@ -693,7 +685,7 @@ public final class CharEffectList
*/ */
private synchronized void removeActive(BuffInfo info, boolean removed) private synchronized void removeActive(BuffInfo info, boolean removed)
{ {
if (_actives != null) if (!_actives.isEmpty())
{ {
// Removes the buff from the given effect list. // Removes the buff from the given effect list.
_actives.remove(info); _actives.remove(info);
@@ -716,7 +708,7 @@ public final class CharEffectList
private void removePassive(BuffInfo info, boolean removed) private void removePassive(BuffInfo info, boolean removed)
{ {
if (_passives != null) if (!_passives.isEmpty())
{ {
_passives.remove(info); _passives.remove(info);
info.stopAllEffects(removed); info.stopAllEffects(removed);
@@ -725,7 +717,7 @@ public final class CharEffectList
private void removeOption(BuffInfo info, boolean removed) private void removeOption(BuffInfo info, boolean removed)
{ {
if (_options != null) if (!_options.isEmpty())
{ {
_options.remove(info); _options.remove(info);
info.stopAllEffects(removed); info.stopAllEffects(removed);
@@ -821,12 +813,6 @@ public final class CharEffectList
} }
} }
// Initialize
if (_actives == null)
{
_actives = new ConcurrentLinkedQueue<>();
}
// Manage effect stacking. // Manage effect stacking.
if (hasAbnormalType(skill.getAbnormalType())) if (hasAbnormalType(skill.getAbnormalType()))
{ {
@@ -857,7 +843,7 @@ public final class CharEffectList
} }
else else
{ {
// Remove effect that gets overriden. // Remove effect that gets overridden.
remove(existingInfo); remove(existingInfo);
} }
} }
@@ -865,7 +851,7 @@ public final class CharEffectList
{ {
info.setInUse(false); info.setInUse(false);
} }
else // The effect we try to add should be overriden. else // The effect we try to add should be overridden.
{ {
return; return;
} }
@@ -918,18 +904,6 @@ public final class CharEffectList
return; return;
} }
// Initialize
if (_passives == null)
{
synchronized (this)
{
if (_passives == null)
{
_passives = ConcurrentHashMap.newKeySet();
}
}
}
// Remove previous passives of this id. // Remove previous passives of this id.
_passives.stream().filter(Objects::nonNull).filter(b -> b.getSkill().getId() == skill.getId()).forEach(b -> _passives.stream().filter(Objects::nonNull).filter(b -> b.getSkill().getId() == skill.getId()).forEach(b ->
{ {
@@ -947,18 +921,6 @@ public final class CharEffectList
{ {
if (info.getOption() != null) if (info.getOption() != null)
{ {
// Initialize
if (_options == null)
{
synchronized (this)
{
if (_options == null)
{
_options = ConcurrentHashMap.newKeySet();
}
}
}
// Remove previous options of this id. // Remove previous options of this id.
_options.stream().filter(Objects::nonNull).filter(b -> b.getOption().getId() == info.getOption().getId()).forEach(b -> _options.stream().filter(Objects::nonNull).filter(b -> b.getOption().getId() == info.getOption().getId()).forEach(b ->
{ {
@@ -988,7 +950,7 @@ public final class CharEffectList
final Optional<PartySpelled> ps = ((party != null) || _owner.isSummon()) ? Optional.of(new PartySpelled(_owner)) : Optional.empty(); final Optional<PartySpelled> ps = ((party != null) || _owner.isSummon()) ? Optional.of(new PartySpelled(_owner)) : Optional.empty();
final Optional<ExOlympiadSpelledInfo> os = (player.isInOlympiadMode() && player.isOlympiadStart()) ? Optional.of(new ExOlympiadSpelledInfo(player)) : Optional.empty(); final Optional<ExOlympiadSpelledInfo> os = (player.isInOlympiadMode() && player.isOlympiadStart()) ? Optional.of(new ExOlympiadSpelledInfo(player)) : Optional.empty();
if (_actives != null) if (!_actives.isEmpty())
{ {
//@formatter:off //@formatter:off
_actives.stream() _actives.stream()
@@ -1109,8 +1071,6 @@ public final class CharEffectList
final Set<BuffInfo> unhideBuffs = new HashSet<>(); final Set<BuffInfo> unhideBuffs = new HashSet<>();
// Recalculate new flags // Recalculate new flags
if (_actives != null)
{
for (BuffInfo info : _actives) for (BuffInfo info : _actives)
{ {
if (info != null) if (info != null)
@@ -1144,7 +1104,14 @@ public final class CharEffectList
// Add AbnormalVisualEffect flag. // Add AbnormalVisualEffect flag.
if (skill.hasAbnormalVisualEffects()) if (skill.hasAbnormalVisualEffects())
{ {
abnormalVisualEffectFlags.addAll(skill.getAbnormalVisualEffects()); for (AbnormalVisualEffect ave : skill.getAbnormalVisualEffects())
{
abnormalVisualEffectFlags.add(ave);
_abnormalVisualEffects.add(ave);
}
if (broadcast)
{
_owner.updateAbnormalVisualEffects();
} }
} }
} }
@@ -1167,7 +1134,7 @@ public final class CharEffectList
if (broadcast) if (broadcast)
{ {
// Check if there is change in AbnormalVisualEffect // Check if there is change in AbnormalVisualEffect
if ((abnormalVisualEffectFlags.size() != _abnormalVisualEffects.size()) || !abnormalVisualEffectFlags.containsAll(_abnormalVisualEffects)) if (!abnormalVisualEffectFlags.containsAll(_abnormalVisualEffects))
{ {
_abnormalVisualEffects = abnormalVisualEffectFlags; _abnormalVisualEffects = abnormalVisualEffectFlags;
_owner.updateAbnormalVisualEffects(); _owner.updateAbnormalVisualEffects();

View File

@@ -77,7 +77,6 @@ public class DoppelgangerInstance extends L2Npc
info.setAbnormalTime(summonerInfo.getAbnormalTime()); info.setAbnormalTime(summonerInfo.getAbnormalTime());
getEffectList().add(info); getEffectList().add(info);
} }
} }
} }
} }

View File

@@ -776,7 +776,7 @@ public class CharStat
final CharEffectList effectList = _activeChar.getEffectList(); final CharEffectList effectList = _activeChar.getEffectList();
final Stream<BuffInfo> passives = effectList.getPassives().stream().filter(BuffInfo::isInUse).filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar)); final Stream<BuffInfo> passives = effectList.getPassives().stream().filter(BuffInfo::isInUse).filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar));
final Stream<BuffInfo> options = effectList.getOptions().stream().filter(BuffInfo::isInUse); final Stream<BuffInfo> options = effectList.getOptions().stream().filter(BuffInfo::isInUse);
final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives != null ? passives : Stream.empty(), options != null ? options : Stream.empty())); final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives, options));
// Call pump to each effect // Call pump to each effect
//@formatter:off //@formatter:off

View File

@@ -389,10 +389,10 @@ public final class BuffInfo
for (AbstractEffect effect : _effects) for (AbstractEffect effect : _effects)
{ {
// Instant effects shouldn't call onExit(..). // Instant effects shouldn't call onExit(..).
if (!effect.isInstant()) // if (!effect.isInstant())
{ // {
effect.onExit(_effector, _effected, _skill); effect.onExit(_effector, _effected, _skill);
} // }
} }
// Set the proper system message. // Set the proper system message.

View File

@@ -21,17 +21,11 @@ import java.util.List;
import com.l2jmobius.commons.network.PacketWriter; import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.skills.BuffInfo; import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.OutgoingPackets; import com.l2jmobius.gameserver.network.OutgoingPackets;
/**
* @author Mobius
* @version Classic 2.0
*/
public class AbnormalStatusUpdate implements IClientOutgoingPacket public class AbnormalStatusUpdate implements IClientOutgoingPacket
{ {
private final List<BuffInfo> _effects = new ArrayList<>(); private final List<BuffInfo> _effects = new ArrayList<>();
private final List<Skill> _effects2 = new ArrayList<>();
public void addSkill(BuffInfo info) public void addSkill(BuffInfo info)
{ {
@@ -41,38 +35,21 @@ public class AbnormalStatusUpdate implements IClientOutgoingPacket
} }
} }
public void addSkill(Skill skill)
{
if (!skill.isHealingPotionSkill())
{
_effects2.add(skill);
}
}
@Override @Override
public boolean write(PacketWriter packet) public boolean write(PacketWriter packet)
{ {
OutgoingPackets.ABNORMAL_STATUS_UPDATE.writeId(packet); OutgoingPackets.ABNORMAL_STATUS_UPDATE.writeId(packet);
packet.writeH(_effects.size() + _effects2.size()); packet.writeH(_effects.size());
for (BuffInfo info : _effects) for (BuffInfo info : _effects)
{ {
if ((info != null) && info.isInUse()) if ((info != null) && info.isInUse())
{ {
packet.writeD(info.getSkill().getDisplayId()); packet.writeD(info.getSkill().getDisplayId());
packet.writeH(info.getSkill().getDisplayLevel()); packet.writeH(info.getSkill().getDisplayLevel());
packet.writeD(0x00); // packet.writeH(info.getSkill().getSubLevel());
packet.writeH(info.getSkill().isAura() ? -1 : info.getTime()); packet.writeD(info.getSkill().getAbnormalType().getClientId());
} writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
}
for (Skill skill : _effects2)
{
if (skill != null)
{
packet.writeD(skill.getDisplayId());
packet.writeH(skill.getDisplayLevel());
packet.writeD(skill.getAbnormalType().getClientId());
packet.writeH(-1);
} }
} }
return true; return true;

View File

@@ -16,8 +16,8 @@
*/ */
package com.l2jmobius.gameserver.network.serverpackets; package com.l2jmobius.gameserver.network.serverpackets;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.l2jmobius.commons.network.PacketWriter; import com.l2jmobius.commons.network.PacketWriter;
@@ -25,35 +25,10 @@ import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.skills.BuffInfo; import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.network.OutgoingPackets; import com.l2jmobius.gameserver.network.OutgoingPackets;
/**
* @author proGenitor <br>
* Experimental packet compatible for L2Classic 2.0.
*/
public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
{ {
private final L2Character _character; private final L2Character _character;
private List<Effect> _effects = new ArrayList<>(); private final List<BuffInfo> _effects;
private static class Effect
{
protected int _skillId;
protected int _level;
protected int _subLevel;
protected int _abnormalType;
protected int _duration;
protected int _caster;
public Effect(BuffInfo info)
{
final L2Character caster = info.getEffector();
int casterId = 0;
if (caster != null)
{
casterId = caster.getObjectId();
}
_caster = casterId;
}
}
public ExAbnormalStatusUpdateFromTarget(L2Character character) public ExAbnormalStatusUpdateFromTarget(L2Character character)
{ {
@@ -61,7 +36,9 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
_character = character; _character = character;
_effects = character.getEffectList().getEffects() _effects = character.getEffectList().getEffects()
.stream() .stream()
.map(Effect::new) .filter(Objects::nonNull)
.filter(BuffInfo::isInUse)
.filter(b -> !b.getSkill().isToggle())
.collect(Collectors.toList()); .collect(Collectors.toList());
//@formatter:on //@formatter:on
} }
@@ -74,14 +51,14 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
packet.writeD(_character.getObjectId()); packet.writeD(_character.getObjectId());
packet.writeH(_effects.size()); packet.writeH(_effects.size());
for (Effect info : _effects) for (BuffInfo info : _effects)
{ {
packet.writeD(info._skillId); packet.writeD(info.getSkill().getDisplayId());
packet.writeH(info._level); packet.writeH(info.getSkill().getDisplayLevel());
packet.writeH(info._subLevel); // packet.writeH(info.getSkill().getSubLevel());
packet.writeH(info._abnormalType); packet.writeH(info.getSkill().getAbnormalType().getClientId());
writeOptionalD(packet, info._duration); writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
packet.writeD(info._caster); packet.writeD(info.getEffectorObjectId());
} }
return true; return true;
} }