Effect list rework.

Contributed by Liamxroy.
This commit is contained in:
MobiusDev
2017-09-22 17:02:39 +00:00
parent d279eb7aa7
commit d571278f5f
448 changed files with 11336 additions and 7576 deletions

View File

@@ -53,7 +53,6 @@ import com.l2jmobius.gameserver.model.events.impl.character.npc.OnAttackableFact
import com.l2jmobius.gameserver.model.events.impl.character.npc.OnAttackableHate;
import com.l2jmobius.gameserver.model.events.returns.TerminateReturn;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.model.skills.SkillCaster;
import com.l2jmobius.gameserver.model.zone.ZoneId;
@@ -350,6 +349,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
_globalAggro--;
}
}
// Add all autoAttackable L2Character in L2Attackable Aggro Range to its _aggroList with 0 damage and 1 hate
// A L2Attackable isn't aggressive during 10s after its spawn because _globalAggro is set to -10
if (_globalAggro >= 0)
@@ -931,8 +931,13 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
// Skip if target is already affected by such skill.
if (skill.isContinuous())
{
final BuffInfo info = ((L2Character) target).getEffectList().getBuffInfoByAbnormalType(skill.getAbnormalType());
if ((info != null) && (info.getSkill().getAbnormalLvl() >= skill.getAbnormalLvl()))
if (((L2Character) target).getEffectList().hasAbnormalType(skill.getAbnormalType(), i -> (i.getSkill().getAbnormalLvl() >= skill.getAbnormalLvl())))
{
return false;
}
// There are cases where bad skills (negative effect points) are actually buffs and NPCs cast them on players, but they shouldn't.
if ((!skill.isDebuff() || !skill.isBad()) && target.isAutoAttackable(getActiveChar()))
{
return false;
}
@@ -943,12 +948,12 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
{
if (skill.isBad())
{
if (!((L2Character) target).getEffectList().hasBuffs() && !((L2Character) target).getEffectList().hasDances())
if (((L2Character) target).getEffectList().getBuffCount() == 0)
{
return false;
}
}
else if (!((L2Character) target).getEffectList().hasDebuffs())
else if (((L2Character) target).getEffectList().getDebuffCount() == 0)
{
return false;
}
@@ -1011,11 +1016,14 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
return null;
}
// There are cases where bad skills (negative effect points) are actually buffs and NPCs cast them on players, but they shouldn't.
final boolean isBad = skill.isContinuous() ? skill.isDebuff() : skill.isBad();
// Check current target first.
final int range = insideCastRange ? skill.getCastRange() + getActiveChar().getTemplate().getCollisionRadius() : 2000; // TODO need some forget range
Stream<L2Character> stream;
if (skill.isBad())
if (isBad)
{
//@formatter:off
stream = npc.getAggroList().values().stream()

View File

@@ -19,14 +19,11 @@ package com.l2jmobius.gameserver.model.actor;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_ACTIVE;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Queue;
import java.util.Set;
@@ -39,7 +36,6 @@ import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Predicate;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.l2jmobius.Config;
import com.l2jmobius.commons.util.EmptyQueue;
@@ -120,7 +116,6 @@ import com.l2jmobius.gameserver.model.items.type.WeaponType;
import com.l2jmobius.gameserver.model.options.OptionsSkillHolder;
import com.l2jmobius.gameserver.model.options.OptionsSkillType;
import com.l2jmobius.gameserver.model.skills.AbnormalType;
import com.l2jmobius.gameserver.model.skills.AbnormalVisualEffect;
import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.CommonSkill;
import com.l2jmobius.gameserver.model.skills.Skill;
@@ -246,9 +241,6 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
private SkillChannelized _channelized = null;
private volatile Set<AbnormalVisualEffect> _abnormalVisualEffects;
private volatile Set<AbnormalVisualEffect> _currentAbnormalVisualEffects;
private Optional<Transform> _transform = Optional.empty();
/** Movement data of this L2Character */
@@ -2523,95 +2515,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
*/
public final void setWalking()
{
if (isRunning())
{
setIsRunning(false);
}
}
/**
* Resets the abnormal visual effects recalculating all of them that are applied from skills and sending packet for updating them on client if a change is found.
*/
public void resetCurrentAbnormalVisualEffects()
{
final Collection<BuffInfo> passives = getEffectList().hasPassives() ? new ArrayList<>(getEffectList().getPassives()) : null;
//@formatter:off
final Set<AbnormalVisualEffect> abnormalVisualEffects = Stream.concat(getEffectList().getEffects().stream(), passives != null ? passives.stream() : Stream.empty())
.filter(Objects::nonNull)
.map(BuffInfo::getSkill)
.filter(Skill::hasAbnormalVisualEffects)
.flatMap(s -> s.getAbnormalVisualEffects().stream())
.collect(Collectors.toCollection(HashSet::new));
//@formatter:on
if (_abnormalVisualEffects != null)
{
abnormalVisualEffects.addAll(_abnormalVisualEffects);
}
if ((_currentAbnormalVisualEffects == null) || !_currentAbnormalVisualEffects.equals(abnormalVisualEffects))
{
_currentAbnormalVisualEffects = Collections.unmodifiableSet(abnormalVisualEffects);
updateAbnormalVisualEffects();
}
}
/**
* Gets the currently applied abnormal visual effects.
* @return the abnormal visual effects
*/
public Set<AbnormalVisualEffect> getCurrentAbnormalVisualEffects()
{
return _currentAbnormalVisualEffects != null ? _currentAbnormalVisualEffects : Collections.emptySet();
}
/**
* Checks if the creature has the abnormal visual effect.
* @param ave the abnormal visual effect
* @return {@code true} if the creature has the abnormal visual effect, {@code false} otherwise
*/
public boolean hasAbnormalVisualEffect(AbnormalVisualEffect ave)
{
return (_abnormalVisualEffects != null) && _abnormalVisualEffects.contains(ave);
}
/**
* Adds the abnormal visual and sends packet for updating them in client.
* @param aves the abnormal visual effects
*/
public final void startAbnormalVisualEffect(AbnormalVisualEffect... aves)
{
for (AbnormalVisualEffect ave : aves)
{
if (_abnormalVisualEffects == null)
{
synchronized (this)
{
if (_abnormalVisualEffects == null)
{
_abnormalVisualEffects = Collections.newSetFromMap(new ConcurrentHashMap<>());
}
}
}
_abnormalVisualEffects.add(ave);
}
resetCurrentAbnormalVisualEffects();
}
/**
* Removes the abnormal visual and sends packet for updating them in client.
* @param aves the abnormal visual effects
*/
public final void stopAbnormalVisualEffect(AbnormalVisualEffect... aves)
{
if (_abnormalVisualEffects != null)
{
for (AbnormalVisualEffect ave : aves)
{
_abnormalVisualEffects.remove(ave);
}
resetCurrentAbnormalVisualEffects();
}
setIsRunning(false);
}
/**
@@ -2672,11 +2576,6 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
_effectList.stopSkillEffects(true, skill.getId());
}
public final void stopEffects(AbnormalType abnormalType)
{
_effectList.stopSkillEffects(true, abnormalType);
}
public final void stopEffects(EffectFlag effectFlag)
{
_effectList.stopEffects(effectFlag);
@@ -2737,7 +2636,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
{
if (removeEffects)
{
stopEffects(AbnormalType.STUN);
getEffectList().stopEffects(AbnormalType.STUN);
}
if (!isPlayer())
@@ -2760,8 +2659,8 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
{
if (removeEffects)
{
getEffectList().stopSkillEffects(false, AbnormalType.TRANSFORM);
getEffectList().stopSkillEffects(false, AbnormalType.CHANGEBODY);
getEffectList().stopEffects(AbnormalType.TRANSFORM);
getEffectList().stopEffects(AbnormalType.CHANGEBODY);
}
if (isTransformed())
@@ -2776,7 +2675,13 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
updateAbnormalVisualEffects();
}
public abstract void updateAbnormalVisualEffects();
/**
* Updates the visual abnormal state of this character. <br>
*/
public void updateAbnormalVisualEffects()
{
// overridden
}
/**
* Update active skills in progress (In Use and Not In Use because stacked) icons on client.<br>

View File

@@ -196,7 +196,6 @@ public abstract class L2Playable extends L2Character
// Notify L2Character AI
getAI().notifyEvent(CtrlEvent.EVT_DEAD);
super.updateEffectIcons();
return true;
}

View File

@@ -796,7 +796,6 @@ public abstract class L2Summon extends L2Playable
{
party.broadcastToPartyMembers(getOwner(), new ExPartyPetWindowUpdate(this));
}
updateEffectIcons(true);
}
public void broadcastNpcInfo(int val)
@@ -841,8 +840,6 @@ public abstract class L2Summon extends L2Playable
if (activeChar == getOwner())
{
activeChar.sendPacket(new PetInfo(this, isDead() ? 0 : 1));
// The PetInfo packet wipes the PartySpelled (list of active spells' icons). Re-add them
updateEffectIcons(true);
if (isPet())
{
activeChar.sendPacket(new PetItemList(getInventory().getItems()));

View File

@@ -426,11 +426,6 @@ public abstract class L2Vehicle extends L2Character
return super.deleteMe();
}
@Override
public void updateAbnormalVisualEffects()
{
}
@Override
public L2ItemInstance getActiveWeaponInstance()
{

View File

@@ -69,7 +69,7 @@ public class DoppelgangerInstance extends L2Npc
if (_copySummonerEffects && (getSummoner() != null))
{
for (BuffInfo summonerInfo : getSummoner().getEffectList().getBuffs())
for (BuffInfo summonerInfo : getSummoner().getEffectList().getEffects())
{
if (summonerInfo.getAbnormalTime() > 0)
{

View File

@@ -327,11 +327,6 @@ public final class L2DoorInstance extends L2Character
return (isCastle || isFort);
}
@Override
public void updateAbnormalVisualEffects()
{
}
/**
* Return null.
*/

View File

@@ -8498,12 +8498,6 @@ public final class L2PcInstance extends L2Playable
updateAndBroadcastStatus(2);
}
public final void stopAllEffectsNotStayOnSubclassChange()
{
getEffectList().stopAllEffectsNotStayOnSubclassChange();
updateAndBroadcastStatus(2);
}
public final void stopCubics()
{
if (!_cubics.isEmpty())
@@ -8904,7 +8898,7 @@ public final class L2PcInstance extends L2Playable
setLastLocation();
// Remove Hide.
getEffectList().stopSkillEffects(true, AbnormalType.HIDE);
getEffectList().stopEffects(AbnormalType.HIDE);
setObserving(true);
sendPacket(new ObservationMode(loc));
@@ -8938,7 +8932,7 @@ public final class L2PcInstance extends L2Playable
}
// Remove Hide.
getEffectList().stopSkillEffects(true, AbnormalType.HIDE);
getEffectList().stopEffects(AbnormalType.HIDE);
if (!_cubics.isEmpty())
{
@@ -9795,7 +9789,7 @@ public final class L2PcInstance extends L2Playable
}
stopAllEffectsExceptThoseThatLastThroughDeath();
stopAllEffectsNotStayOnSubclassChange();
stopAllEffects();
stopCubics();
restoreRecipeBook(false);
@@ -10051,7 +10045,6 @@ public final class L2PcInstance extends L2Playable
public void doRevive()
{
super.doRevive();
updateEffectIcons();
sendPacket(new EtcStatusUpdate(this));
_revivePet = false;
_reviveRequested = 0;

View File

@@ -573,7 +573,6 @@ public class L2ServitorInstance extends L2Summon implements Runnable
}
sendPacket(new SetSummonRemainTime(getLifeTime(), _lifeTimeRemaining));
updateEffectIcons();
// Using same task to check if owner is in visible range
if (calculateDistance(getOwner(), true, false) > 2000)

View File

@@ -178,11 +178,6 @@ public final class L2StaticObjectInstance extends L2Character
return _meshIndex;
}
@Override
public void updateAbnormalVisualEffects()
{
}
@Override
public void sendInfo(L2PcInstance activeChar)
{

View File

@@ -361,12 +361,6 @@ public final class L2TrapInstance extends L2Npc
}
}
@Override
public void updateAbnormalVisualEffects()
{
}
public boolean hasLifeTime()
{
return _hasLifeTime;

View File

@@ -773,9 +773,9 @@ public class CharStat
// Collect all necessary effects
final CharEffectList effectList = _activeChar.getEffectList();
final Stream<BuffInfo> passives = effectList.hasPassives() ? effectList.getPassives().stream().filter(info -> info.getSkill().checkConditions(SkillConditionScope.PASSIVE, _activeChar, _activeChar)) : null;
final Stream<BuffInfo> options = effectList.hasOptions() ? effectList.getOptions().stream() : null;
final Stream<BuffInfo> effectsStream = Stream.concat(effectList.getEffects().stream(), Stream.concat(passives != null ? passives : Stream.empty(), options != null ? options : Stream.empty()));
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> effectsStream = Stream.concat(effectList.getEffects().stream().filter(BuffInfo::isInUse), Stream.concat(passives != null ? passives : Stream.empty(), options != null ? options : Stream.empty()));
// Call pump to each effect
//@formatter:off

View File

@@ -38,9 +38,6 @@ public class PetStat extends SummonStat
}
getActiveChar().updateAndBroadcastStatus(1);
// The PetInfo packet wipes the PartySpelled (list of active spells' icons). Re-add them
getActiveChar().updateEffectIcons(true);
return true;
}

View File

@@ -172,7 +172,7 @@ public class CharStatus
}
if (Formulas.calcRealTargetBreak())
{
getActiveChar().getEffectList().stopSkillEffects(true, AbnormalType.REAL_TARGET);
getActiveChar().getEffectList().stopEffects(AbnormalType.REAL_TARGET);
}
}

View File

@@ -119,7 +119,7 @@ public class PcStatus extends PlayableStatus
}
if (Formulas.calcRealTargetBreak())
{
getActiveChar().getEffectList().stopSkillEffects(true, AbnormalType.REAL_TARGET);
getActiveChar().getEffectList().stopEffects(AbnormalType.REAL_TARGET);
}
}
}

View File

@@ -394,8 +394,8 @@ public final class Transform implements IIdentifiable
player.sendPacket(ExBasicActionList.STATIC_PACKET);
player.getEffectList().stopSkillEffects(false, AbnormalType.TRANSFORM);
player.getEffectList().stopSkillEffects(false, AbnormalType.CHANGEBODY);
player.getEffectList().stopEffects(AbnormalType.TRANSFORM);
player.getEffectList().stopEffects(AbnormalType.CHANGEBODY);
if (hasTransformSkills)
{

View File

@@ -19,7 +19,6 @@ package com.l2jmobius.gameserver.model.conditions;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.items.L2Item;
import com.l2jmobius.gameserver.model.skills.AbnormalType;
import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
/**
@@ -55,7 +54,11 @@ public class ConditionPlayerCheckAbnormal extends Condition
@Override
public boolean testImpl(L2Character effector, L2Character effected, Skill skill, L2Item item)
{
final BuffInfo info = effector.getEffectList().getBuffInfoByAbnormalType(_type);
return ((info != null) && ((_level == -1) || (_level >= info.getSkill().getAbnormalLvl())));
if (_level == -1)
{
return effector.getEffectList().hasAbnormalType(_type);
}
return effector.getEffectList().hasAbnormalType(_type, info -> _level >= info.getSkill().getAbnormalLvl());
}
}

View File

@@ -75,7 +75,7 @@ public class CubicSkill extends SkillHolder implements ICubicConditionHolder
@Override
public boolean validateConditions(CubicInstance cubic, L2Character owner, L2Character target)
{
return (!_targetDebuff || (_targetDebuff && target.getEffectList().hasDebuffs())) && (_conditions.isEmpty() || _conditions.stream().allMatch(condition -> condition.test(cubic, owner, target)));
return (!_targetDebuff || (_targetDebuff && (target.getEffectList().getDebuffCount() > 0))) && (_conditions.isEmpty() || _conditions.stream().allMatch(condition -> condition.test(cubic, owner, target)));
}
@Override

View File

@@ -48,7 +48,6 @@ import com.l2jmobius.gameserver.model.instancezone.conditions.ConditionGroupMax;
import com.l2jmobius.gameserver.model.instancezone.conditions.ConditionGroupMin;
import com.l2jmobius.gameserver.model.interfaces.IIdentifiable;
import com.l2jmobius.gameserver.model.interfaces.INamable;
import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.model.spawns.SpawnTemplate;
import com.l2jmobius.gameserver.model.variables.PlayerVariables;
@@ -509,13 +508,8 @@ public class InstanceTemplate extends ListenersContainer implements IIdentifiabl
{
for (L2Playable playable : affected)
{
for (BuffInfo info : playable.getEffectList().getBuffs())
{
if (hasRemoveBuffException(info.getSkill()))
{
playable.stopSkillEffects(info.getSkill());
}
}
// Stop all buffs.
playable.getEffectList().stopEffects(info -> !info.getSkill().isIrreplacableBuff() && info.getSkill().getBuffType().isBuff() && hasRemoveBuffException(info.getSkill()), true);
}
}
}

View File

@@ -204,7 +204,7 @@ public class Options
if (info.getOption() == this)
{
player.sendDebugMessage("Removing effects: " + info.getEffects());
player.getEffectList().remove(false, info, this);
player.getEffectList().remove(info, false, true);
}
}
}

View File

@@ -46,6 +46,7 @@ public final class BuffInfo
{
// Data
/** Data. */
private final int _effectorObjectId;
private final L2Character _effector;
private final L2Character _effected;
private final Skill _skill;
@@ -63,9 +64,9 @@ public final class BuffInfo
private int _periodStartTicks;
// Misc
/** If {@code true} then this effect has been cancelled. */
private boolean _isRemoved = false;
private volatile boolean _isRemoved = false;
/** If {@code true} then this effect is in use (or has been stop because an Herb took place). */
private boolean _isInUse = true;
private volatile boolean _isInUse = true;
private final boolean _hideStartMessage;
private final L2ItemInstance _item;
private final Options _option;
@@ -81,6 +82,7 @@ public final class BuffInfo
*/
public BuffInfo(L2Character effector, L2Character effected, Skill skill, boolean hideStartMessage, L2ItemInstance item, Options option)
{
_effectorObjectId = (effector != null) ? effector.getObjectId() : 0;
_effector = effector;
_effected = effected;
_skill = skill;
@@ -235,6 +237,35 @@ public final class BuffInfo
public void setInUse(boolean val)
{
_isInUse = val;
// Send message that the effect is applied or removed.
if ((_skill != null) && !_skill.isHidingMesseges() && _effected.isPlayer())
{
if (val)
{
if (!_hideStartMessage && !_skill.isAura())
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.S1_S_EFFECT_CAN_BE_FELT);
sm.addSkillName(_skill);
_effected.sendPacket(sm);
}
}
else
{
final SystemMessage sm = SystemMessage.getSystemMessage(_skill.isToggle() ? SystemMessageId.S1_HAS_BEEN_ABORTED : SystemMessageId.THE_EFFECT_OF_S1_HAS_BEEN_REMOVED);
sm.addSkillName(_skill);
_effected.sendPacket(sm);
}
}
}
/**
* Gets the character's object id that launched the buff.
* @return the object id of the effector.
*/
public int getEffectorObjectId()
{
return _effectorObjectId;
}
/**
@@ -281,7 +312,7 @@ public final class BuffInfo
}
// When effects are initialized, the successfully landed.
if (!_hideStartMessage && _effected.isPlayer() && !_skill.isPassive() && !_skill.isHidingMesseges() && !_skill.isAura())
if (!_hideStartMessage && _effected.isPlayer() && !_skill.isHidingMesseges() && !_skill.isAura())
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.S1_S_EFFECT_CAN_BE_FELT);
sm.addSkillName(_skill);
@@ -294,9 +325,6 @@ public final class BuffInfo
_scheduledFutureTimeTask = ThreadPoolManager.scheduleAtFixedRate(new BuffTimeTask(this), 0, 1000L);
}
// Reset abnormal visual effects.
resetAbnormalVisualEffects();
for (AbstractEffect effect : _effects)
{
if (effect.isInstant() || (_effected.isDead() && !_skill.isPassive()))
@@ -317,9 +345,6 @@ public final class BuffInfo
// Adds the task for ticking.
addTask(effect, new EffectTaskInfo(effectTask, scheduledFuture));
}
// Recalculate all stats
_effected.getStat().recalculateStats(true);
}
}
@@ -371,12 +396,6 @@ public final class BuffInfo
}
}
// Remove abnormal visual effects.
resetAbnormalVisualEffects();
// Recalculate all stats
_effected.getStat().recalculateStats(true);
// Set the proper system message.
if ((_skill != null) && !(_effected.isSummon() && !((L2Summon) _effected).getOwner().hasSummon()) && !_skill.isHidingMesseges())
{
@@ -401,23 +420,6 @@ public final class BuffInfo
_effected.sendPacket(sm);
}
}
// Remove short buff.
if (this == _effected.getEffectList().getShortBuff())
{
_effected.getEffectList().shortBuffStatusUpdate(null);
}
}
/**
* Applies all the abnormal visual effects to the effected.<br>
* Prevents multiple updates.
*/
private void resetAbnormalVisualEffects()
{
if ((_skill != null) && _skill.hasAbnormalVisualEffects())
{
_effected.resetCurrentAbnormalVisualEffects();
}
}
/**

View File

@@ -109,6 +109,8 @@ public final class Skill implements IIdentifiable
private final int _abnormalLvl;
/** Abnormal type: global effect "group". */
private final AbnormalType _abnormalType;
/** Abnormal type: local effect "group". */
private final AbnormalType _subordinationAbnormalType;
/** Abnormal time: global effect duration time. */
private final int _abnormalTime;
/** Abnormal visual effect: the visual effect displayed ingame. */
@@ -204,6 +206,7 @@ public final class Skill implements IIdentifiable
private final Set<AbnormalType> _abnormalResists;
private final double _magicCriticalRate;
private final SkillBuffType _buffType;
public Skill(StatsSet set)
{
@@ -229,6 +232,7 @@ public final class Skill implements IIdentifiable
_effectRange = set.getInt("effectRange", -1);
_abnormalLvl = set.getInt("abnormalLvl", 0);
_abnormalType = set.getEnum("abnormalType", AbnormalType.class, AbnormalType.NONE);
_subordinationAbnormalType = set.getEnum("subordinationAbnormalType", AbnormalType.class, AbnormalType.NONE);
int abnormalTime = set.getInt("abnormalTime", 0);
if (Config.ENABLE_MODIFY_SKILL_DURATION && Config.SKILL_DURATION_LIST.containsKey(getId()))
@@ -437,6 +441,7 @@ public final class Skill implements IIdentifiable
}
_magicCriticalRate = set.getDouble("magicCriticalRate", 0);
_buffType = isTriggeredSkill() ? SkillBuffType.TRIGGER : isToggle() ? SkillBuffType.TOGGLE : isDance() ? SkillBuffType.DANCE : isDebuff() ? SkillBuffType.DEBUFF : !isHealingPotionSkill() ? SkillBuffType.BUFF : SkillBuffType.NONE;
}
public TraitType getTraitType()
@@ -506,6 +511,15 @@ public final class Skill implements IIdentifiable
return _abnormalType;
}
/**
* Gets the skill subordination abnormal type.
* @return the abnormal type
*/
public AbnormalType getSubordinationAbnormalType()
{
return _subordinationAbnormalType;
}
/**
* Gets the skill abnormal level.
* @return the skill abnormal level
@@ -1327,7 +1341,16 @@ public final class Skill implements IIdentifiable
if (addContinuousEffects)
{
effected.getEffectList().add(info);
// Aura skills reset the abnormal time.
final BuffInfo existingInfo = _operateType.isAura() ? effected.getEffectList().getBuffInfoBySkillId(getId()) : null;
if (existingInfo != null)
{
existingInfo.resetAbnormalTime(info.getAbnormalTime());
}
else
{
effected.getEffectList().add(info);
}
// Check for mesmerizing debuffs and increase resist level.
if (isDebuff() && (getBasicProperty() != BasicProperty.NONE) && effected.hasBasicPropertyResist())
@@ -1362,7 +1385,16 @@ public final class Skill implements IIdentifiable
if (addContinuousEffects)
{
info.getEffector().getEffectList().add(info);
// Aura skills reset the abnormal time.
final BuffInfo existingInfo = _operateType.isAura() ? effector.getEffectList().getBuffInfoBySkillId(getId()) : null;
if (existingInfo != null)
{
existingInfo.resetAbnormalTime(info.getAbnormalTime());
}
else
{
info.getEffector().getEffectList().add(info);
}
}
// Support for buff sharing feature.
@@ -1699,7 +1731,7 @@ public final class Skill implements IIdentifiable
}
//@formatter:off
final int toggleSkillId = activeChar.getEffectList().getToggles().stream()
final int toggleSkillId = activeChar.getEffectList().getEffects().stream()
.filter(info -> info.getSkill().getToggleGroupId() == getAttachToggleGroupId())
.mapToInt(info -> info.getSkill().getId())
.findAny().orElse(0);
@@ -1752,6 +1784,10 @@ public final class Skill implements IIdentifiable
return _deleteAbnormalOnLeave;
}
/**
* @return {@code true} if the buff cannot be replaced, canceled, removed on death, etc.<br>
* It can be only overriden by higher stack, but buff still remains ticking and activates once the higher stack buff has passed away.
*/
public boolean isIrreplacableBuff()
{
return _irreplacableBuff;
@@ -1795,6 +1831,11 @@ public final class Skill implements IIdentifiable
return _magicCriticalRate;
}
public SkillBuffType getBuffType()
{
return _buffType;
}
public boolean isEnchantable()
{
return EnchantSkillGroupsData.getInstance().isEnchantable(this);

View File

@@ -0,0 +1,61 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.model.skills;
/**
* A custom enum representing the buff category type of the skill.
* @author Nik
*/
public enum SkillBuffType
{
NONE,
BUFF,
DEBUFF,
DANCE,
TOGGLE,
TRIGGER;
public boolean isNone()
{
return this == NONE;
}
public boolean isBuff()
{
return this == BUFF;
}
public boolean isDebuff()
{
return this == DEBUFF;
}
public boolean isDance()
{
return this == DANCE;
}
public boolean isToggle()
{
return this == TOGGLE;
}
public boolean isTrigger()
{
return this == TRIGGER;
}
}

View File

@@ -1136,16 +1136,10 @@ public final class Formulas
set.set("rate", rate);
Debug.sendSkillDebug(activeChar, target, skill, set);
}
// Prevent initialization.
final List<BuffInfo> buffs = target.getEffectList().hasBuffs() ? new ArrayList<>(target.getEffectList().getBuffs()) : new ArrayList<>(1);
if (target.getEffectList().hasTriggered())
{
buffs.addAll(target.getEffectList().getTriggered());
}
if (target.getEffectList().hasDances())
{
buffs.addAll(target.getEffectList().getDances());
}
final List<BuffInfo> buffs = target.getEffectList().getBuffs();
for (int i = buffs.size() - 1; i >= 0; i--) // reverse order
{
final BuffInfo info = buffs.get(i);
@@ -1163,11 +1157,11 @@ public final class Formulas
}
case DEBUFF:
{
final List<BuffInfo> debuffs = new ArrayList<>(target.getEffectList().getDebuffs());
final List<BuffInfo> debuffs = target.getEffectList().getDebuffs();
for (int i = debuffs.size() - 1; i >= 0; i--)
{
final BuffInfo info = debuffs.get(i);
if (info.getSkill().isDebuff() && info.getSkill().canBeDispelled() && (Rnd.get(100) <= rate))
if (info.getSkill().canBeDispelled() && (Rnd.get(100) <= rate))
{
canceled.add(info);
if (canceled.size() >= max)
@@ -1497,12 +1491,8 @@ public final class Formulas
// Check if target is stunned and 10% chance.
if (activeChar.hasBlockActions() && (Rnd.get(10) == 0))
{
final BuffInfo info = activeChar.getEffectList().getBuffInfoByAbnormalType(AbnormalType.STUN);
if (info != null)
{
// Any stun that has double duration due to skill mastery, doesn't get removed until its time reaches the usual abnormal time.
return info.getTime() <= info.getSkill().getAbnormalTime();
}
// Any stun that has double duration due to skill mastery, doesn't get removed until its time reaches the usual abnormal time.
return activeChar.getEffectList().hasAbnormalType(AbnormalType.STUN, info -> info.getTime() <= info.getSkill().getAbnormalTime());
}
return false;
}

View File

@@ -70,7 +70,7 @@ public final class Action implements IClientIncomingPacket
return;
}
final BuffInfo info = activeChar.getEffectList().getBuffInfoByAbnormalType(AbnormalType.BOT_PENALTY);
final BuffInfo info = activeChar.getEffectList().getFirstBuffInfoByAbnormalType(AbnormalType.BOT_PENALTY);
if (info != null)
{
for (AbstractEffect effect : info.getEffects())

View File

@@ -73,7 +73,7 @@ public final class Attack implements IClientIncomingPacket
return;
}
final BuffInfo info = activeChar.getEffectList().getBuffInfoByAbnormalType(AbnormalType.BOT_PENALTY);
final BuffInfo info = activeChar.getEffectList().getFirstBuffInfoByAbnormalType(AbnormalType.BOT_PENALTY);
if (info != null)
{
for (AbstractEffect effect : info.getEffects())

View File

@@ -62,7 +62,7 @@ public final class AttackRequest implements IClientIncomingPacket
return;
}
final BuffInfo info = activeChar.getEffectList().getBuffInfoByAbnormalType(AbnormalType.BOT_PENALTY);
final BuffInfo info = activeChar.getEffectList().getFirstBuffInfoByAbnormalType(AbnormalType.BOT_PENALTY);
if (info != null)
{
for (AbstractEffect effect : info.getEffects())

View File

@@ -219,7 +219,7 @@ public class EnterWorld implements IClientIncomingPacket
if (Config.GM_STARTUP_INVISIBLE && AdminData.getInstance().hasAccess("admin_invisible", activeChar.getAccessLevel()))
{
activeChar.setInvisible(true);
activeChar.startAbnormalVisualEffect(AbnormalVisualEffect.STEALTH);
activeChar.getEffectList().startAbnormalVisualEffect(AbnormalVisualEffect.STEALTH);
}
if (Config.GM_STARTUP_SILENCE && AdminData.getInstance().hasAccess("admin_silence", activeChar.getAccessLevel()))
@@ -464,8 +464,6 @@ public class EnterWorld implements IClientIncomingPacket
}
}
activeChar.updateEffectIcons();
// Expand Skill
activeChar.sendPacket(new ExStorageMaxCount(activeChar));

View File

@@ -72,7 +72,7 @@ public final class RequestActionUse implements IClientIncomingPacket
return;
}
final BuffInfo info = activeChar.getEffectList().getBuffInfoByAbnormalType(AbnormalType.BOT_PENALTY);
final BuffInfo info = activeChar.getEffectList().getFirstBuffInfoByAbnormalType(AbnormalType.BOT_PENALTY);
if (info != null)
{
for (AbstractEffect effect : info.getEffects())

View File

@@ -63,7 +63,7 @@ public final class TradeRequest implements IClientIncomingPacket
return;
}
BuffInfo info = player.getEffectList().getBuffInfoByAbnormalType(AbnormalType.BOT_PENALTY);
BuffInfo info = player.getEffectList().getFirstBuffInfoByAbnormalType(AbnormalType.BOT_PENALTY);
if (info != null)
{
for (AbstractEffect effect : info.getEffects())
@@ -107,7 +107,7 @@ public final class TradeRequest implements IClientIncomingPacket
return;
}
info = partner.getEffectList().getBuffInfoByAbnormalType(AbnormalType.BOT_PENALTY);
info = partner.getEffectList().getFirstBuffInfoByAbnormalType(AbnormalType.BOT_PENALTY);
if (info != null)
{
for (AbstractEffect effect : info.getEffects())

View File

@@ -235,7 +235,7 @@ public class CharInfo implements IClientOutgoingPacket
packet.writeD((int) Math.round(_activeChar.getCurrentMp())); // Confirmed
packet.writeC(0x00); // TODO: Find me!
final Set<AbnormalVisualEffect> abnormalVisualEffects = _activeChar.getCurrentAbnormalVisualEffects();
final Set<AbnormalVisualEffect> abnormalVisualEffects = _activeChar.getEffectList().getCurrentAbnormalVisualEffects();
packet.writeD(abnormalVisualEffects.size() + (_gmSeeInvis ? 1 : 0)); // Confirmed
for (AbnormalVisualEffect abnormalVisualEffect : abnormalVisualEffects)
{

View File

@@ -18,6 +18,8 @@ package com.l2jmobius.gameserver.network.serverpackets;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.actor.L2Character;
@@ -60,22 +62,16 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
public ExAbnormalStatusUpdateFromTarget(L2Character character)
{
//@formatter:off
_character = character;
_effects = new ArrayList<>();
for (BuffInfo info : character.getEffectList().getEffects())
{
if ((info != null) && info.isInUse())
{
final Skill skill = info.getSkill();
// TODO: Check on retail if all effects should be displayed
if (skill != null)
{
_effects.add(new Effect(info));
}
}
}
_effects = character.getEffectList().getEffects()
.stream()
.filter(Objects::nonNull)
.filter(BuffInfo::isInUse)
.filter(b -> !b.getSkill().isToggle())
.map(Effect::new)
.collect(Collectors.toList());
//@formatter:on
}
@Override

View File

@@ -62,7 +62,7 @@ public class ExPetInfo extends AbstractMaskPacket<NpcInfoType>
_attacker = attacker;
_title = (summon.getOwner() != null) && summon.getOwner().isOnline() ? summon.getOwner().getName() : "";
_val = val;
_abnormalVisualEffects = summon.getCurrentAbnormalVisualEffects();
_abnormalVisualEffects = summon.getEffectList().getCurrentAbnormalVisualEffects();
if (summon.getTemplate().getDisplayId() != summon.getTemplate().getId())
{

View File

@@ -43,7 +43,7 @@ public class ExUserInfoAbnormalVisualEffect implements IClientOutgoingPacket
packet.writeD(_activeChar.getObjectId());
packet.writeD(_activeChar.getTransformationId());
final Set<AbnormalVisualEffect> abnormalVisualEffects = _activeChar.getCurrentAbnormalVisualEffects();
final Set<AbnormalVisualEffect> abnormalVisualEffects = _activeChar.getEffectList().getCurrentAbnormalVisualEffects();
final boolean isInvisible = _activeChar.isInvisible();
packet.writeD(abnormalVisualEffects.size() + (isInvisible ? 1 : 0));
for (AbnormalVisualEffect abnormalVisualEffect : abnormalVisualEffects)

View File

@@ -60,7 +60,7 @@ public class NpcInfo extends AbstractMaskPacket<NpcInfoType>
public NpcInfo(L2Npc npc)
{
_npc = npc;
_abnormalVisualEffects = npc.getCurrentAbnormalVisualEffects();
_abnormalVisualEffects = npc.getEffectList().getCurrentAbnormalVisualEffects();
addComponentType(NpcInfoType.ATTACKABLE, NpcInfoType.UNKNOWN1, NpcInfoType.ID, NpcInfoType.POSITION, NpcInfoType.ALIVE, NpcInfoType.RUNNING);

View File

@@ -43,7 +43,7 @@ public class NpcInfoAbnormalVisualEffect implements IClientOutgoingPacket
packet.writeD(_npc.getObjectId());
packet.writeD(_npc.getTransformationDisplayId());
final Set<AbnormalVisualEffect> abnormalVisualEffects = _npc.getCurrentAbnormalVisualEffects();
final Set<AbnormalVisualEffect> abnormalVisualEffects = _npc.getEffectList().getCurrentAbnormalVisualEffects();
packet.writeD(abnormalVisualEffects.size());
for (AbnormalVisualEffect abnormalVisualEffect : abnormalVisualEffects)
{

View File

@@ -189,7 +189,7 @@ public class PetInfo implements IClientOutgoingPacket
packet.writeC(_summon.getOwner().getSummonPoints()); // Used Summon Points
packet.writeC(_summon.getOwner().getMaxSummonPoints()); // Maximum Summon Points
final Set<AbnormalVisualEffect> aves = _summon.getCurrentAbnormalVisualEffects();
final Set<AbnormalVisualEffect> aves = _summon.getEffectList().getCurrentAbnormalVisualEffects();
packet.writeH(aves.size()); // Confirmed
for (AbnormalVisualEffect ave : aves)
{

View File

@@ -62,7 +62,7 @@ public class SummonInfo extends AbstractMaskPacket<NpcInfoType>
_attacker = attacker;
_title = (summon.getOwner() != null) && summon.getOwner().isOnline() ? summon.getOwner().getName() : "";
_val = val;
_abnormalVisualEffects = summon.getCurrentAbnormalVisualEffects();
_abnormalVisualEffects = summon.getEffectList().getCurrentAbnormalVisualEffects();
if (summon.getTemplate().getDisplayId() != summon.getTemplate().getId())
{