Use EnumSet instead or Arrays for traits.
Adapted from: L2jUnity free files.
This commit is contained in:
		@@ -22,9 +22,7 @@ import java.util.Map.Entry;
 | 
			
		||||
 | 
			
		||||
import org.l2jmobius.gameserver.model.StatsSet;
 | 
			
		||||
import org.l2jmobius.gameserver.model.actor.Creature;
 | 
			
		||||
import org.l2jmobius.gameserver.model.actor.stat.CreatureStat;
 | 
			
		||||
import org.l2jmobius.gameserver.model.effects.AbstractEffect;
 | 
			
		||||
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
 | 
			
		||||
import org.l2jmobius.gameserver.model.skills.Skill;
 | 
			
		||||
import org.l2jmobius.gameserver.model.stats.TraitType;
 | 
			
		||||
 | 
			
		||||
@@ -51,35 +49,11 @@ public final class AttackTrait extends AbstractEffect
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	@Override
 | 
			
		||||
	public void onExit(Creature effector, Creature effected, Skill skill)
 | 
			
		||||
	public void pump(Creature effected, Skill skill)
 | 
			
		||||
	{
 | 
			
		||||
		final CreatureStat charStat = effected.getStat();
 | 
			
		||||
		synchronized (charStat.getAttackTraits())
 | 
			
		||||
		for (Entry<TraitType, Float> trait : _attackTraits.entrySet())
 | 
			
		||||
		{
 | 
			
		||||
			for (Entry<TraitType, Float> trait : _attackTraits.entrySet())
 | 
			
		||||
			{
 | 
			
		||||
				if (charStat.getAttackTraitsCount()[trait.getKey().ordinal()] == 0)
 | 
			
		||||
				{
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				charStat.getAttackTraits()[trait.getKey().ordinal()] /= trait.getValue();
 | 
			
		||||
				charStat.getAttackTraitsCount()[trait.getKey().ordinal()]--;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	@Override
 | 
			
		||||
	public void onStart(Creature effector, Creature effected, Skill skill, ItemInstance item)
 | 
			
		||||
	{
 | 
			
		||||
		final CreatureStat charStat = effected.getStat();
 | 
			
		||||
		synchronized (charStat.getAttackTraits())
 | 
			
		||||
		{
 | 
			
		||||
			for (Entry<TraitType, Float> trait : _attackTraits.entrySet())
 | 
			
		||||
			{
 | 
			
		||||
				charStat.getAttackTraits()[trait.getKey().ordinal()] *= trait.getValue();
 | 
			
		||||
				charStat.getAttackTraitsCount()[trait.getKey().ordinal()]++;
 | 
			
		||||
			}
 | 
			
		||||
			effected.getStat().mergeAttackTrait(trait.getKey(), trait.getValue());
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,9 +22,7 @@ import java.util.Map.Entry;
 | 
			
		||||
 | 
			
		||||
import org.l2jmobius.gameserver.model.StatsSet;
 | 
			
		||||
import org.l2jmobius.gameserver.model.actor.Creature;
 | 
			
		||||
import org.l2jmobius.gameserver.model.actor.stat.CreatureStat;
 | 
			
		||||
import org.l2jmobius.gameserver.model.effects.AbstractEffect;
 | 
			
		||||
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
 | 
			
		||||
import org.l2jmobius.gameserver.model.skills.Skill;
 | 
			
		||||
import org.l2jmobius.gameserver.model.stats.TraitType;
 | 
			
		||||
 | 
			
		||||
@@ -46,75 +44,22 @@ public final class DefenceTrait extends AbstractEffect
 | 
			
		||||
		
 | 
			
		||||
		for (Entry<String, Object> param : params.getSet().entrySet())
 | 
			
		||||
		{
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
				final TraitType traitType = TraitType.valueOf(param.getKey());
 | 
			
		||||
				final float value = Float.parseFloat((String) param.getValue());
 | 
			
		||||
				if (value == 0)
 | 
			
		||||
				{
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				_defenceTraits.put(traitType, (value + 100) / 100);
 | 
			
		||||
			}
 | 
			
		||||
			catch (NumberFormatException e)
 | 
			
		||||
			{
 | 
			
		||||
				LOGGER.warning(getClass().getSimpleName() + ": value of " + param.getKey() + " must be float value " + param.getValue() + " found.");
 | 
			
		||||
			}
 | 
			
		||||
			catch (Exception e)
 | 
			
		||||
			{
 | 
			
		||||
				LOGGER.warning(getClass().getSimpleName() + ": value of TraitType enum required but found: " + param.getKey());
 | 
			
		||||
			}
 | 
			
		||||
			_defenceTraits.put(TraitType.valueOf(param.getKey()), (Float.parseFloat((String) param.getValue()) + 100) / 100);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	@Override
 | 
			
		||||
	public void onExit(Creature effector, Creature effected, Skill skill)
 | 
			
		||||
	public void pump(Creature effected, Skill skill)
 | 
			
		||||
	{
 | 
			
		||||
		final CreatureStat charStat = effected.getStat();
 | 
			
		||||
		synchronized (charStat.getDefenceTraits())
 | 
			
		||||
		for (Entry<TraitType, Float> trait : _defenceTraits.entrySet())
 | 
			
		||||
		{
 | 
			
		||||
			for (Entry<TraitType, Float> trait : _defenceTraits.entrySet())
 | 
			
		||||
			if (trait.getValue() < 2.0f)
 | 
			
		||||
			{
 | 
			
		||||
				if (trait.getValue() < 2.0f)
 | 
			
		||||
				{
 | 
			
		||||
					if (charStat.getDefenceTraitsCount()[trait.getKey().ordinal()] == 0)
 | 
			
		||||
					{
 | 
			
		||||
						continue;
 | 
			
		||||
					}
 | 
			
		||||
					
 | 
			
		||||
					charStat.getDefenceTraits()[trait.getKey().ordinal()] /= trait.getValue();
 | 
			
		||||
					charStat.getDefenceTraitsCount()[trait.getKey().ordinal()]--;
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					if (charStat.getTraitsInvul()[trait.getKey().ordinal()] == 0)
 | 
			
		||||
					{
 | 
			
		||||
						continue;
 | 
			
		||||
					}
 | 
			
		||||
					
 | 
			
		||||
					charStat.getTraitsInvul()[trait.getKey().ordinal()]--;
 | 
			
		||||
				}
 | 
			
		||||
				effected.getStat().mergeDefenceTrait(trait.getKey(), trait.getValue());
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	@Override
 | 
			
		||||
	public void onStart(Creature effector, Creature effected, Skill skill, ItemInstance item)
 | 
			
		||||
	{
 | 
			
		||||
		final CreatureStat charStat = effected.getStat();
 | 
			
		||||
		synchronized (charStat.getDefenceTraits())
 | 
			
		||||
		{
 | 
			
		||||
			for (Entry<TraitType, Float> trait : _defenceTraits.entrySet())
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				if (trait.getValue() < 2.0f)
 | 
			
		||||
				{
 | 
			
		||||
					charStat.getDefenceTraits()[trait.getKey().ordinal()] *= trait.getValue();
 | 
			
		||||
					charStat.getDefenceTraitsCount()[trait.getKey().ordinal()]++;
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					charStat.getTraitsInvul()[trait.getKey().ordinal()]++;
 | 
			
		||||
				}
 | 
			
		||||
				effected.getStat().mergeInvulnerableTrait(trait.getKey());
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -16,10 +16,10 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.l2jmobius.gameserver.model.actor.stat;
 | 
			
		||||
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.Deque;
 | 
			
		||||
import java.util.EnumMap;
 | 
			
		||||
import java.util.EnumSet;
 | 
			
		||||
import java.util.HashSet;
 | 
			
		||||
import java.util.Iterator;
 | 
			
		||||
import java.util.LinkedList;
 | 
			
		||||
@@ -72,11 +72,11 @@ public class CreatureStat
 | 
			
		||||
	private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>();
 | 
			
		||||
	private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>();
 | 
			
		||||
	
 | 
			
		||||
	private final float[] _attackTraits = new float[TraitType.values().length];
 | 
			
		||||
	private final float[] _defenceTraits = new float[TraitType.values().length];
 | 
			
		||||
	private final int[] _attackTraitsCount = new int[TraitType.values().length];
 | 
			
		||||
	private final int[] _defenceTraitsCount = new int[TraitType.values().length];
 | 
			
		||||
	private final int[] _traitsInvul = new int[TraitType.values().length];
 | 
			
		||||
	private final float[] _attackTraitValues = new float[TraitType.values().length];
 | 
			
		||||
	private final float[] _defenceTraitValues = new float[TraitType.values().length];
 | 
			
		||||
	private final Set<TraitType> _attackTraits = EnumSet.noneOf(TraitType.class);
 | 
			
		||||
	private final Set<TraitType> _defenceTraits = EnumSet.noneOf(TraitType.class);
 | 
			
		||||
	private final Set<TraitType> _invulnerableTraits = EnumSet.noneOf(TraitType.class);
 | 
			
		||||
	
 | 
			
		||||
	/** Values to be recalculated after every stat update */
 | 
			
		||||
	private double _attackSpeedMultiplier = 1;
 | 
			
		||||
@@ -87,8 +87,6 @@ public class CreatureStat
 | 
			
		||||
	public CreatureStat(Creature creature)
 | 
			
		||||
	{
 | 
			
		||||
		_creature = creature;
 | 
			
		||||
		Arrays.fill(_attackTraits, 1.0f);
 | 
			
		||||
		Arrays.fill(_defenceTraits, 1.0f);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
@@ -573,54 +571,86 @@ public class CreatureStat
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public float getAttackTrait(TraitType traitType)
 | 
			
		||||
	public void mergeAttackTrait(TraitType traitType, float value)
 | 
			
		||||
	{
 | 
			
		||||
		return _attackTraits[traitType.ordinal()];
 | 
			
		||||
		_attackTraitValues[traitType.ordinal()] *= value;
 | 
			
		||||
		_attackTraits.add(traitType);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public float[] getAttackTraits()
 | 
			
		||||
	public float getAttackTrait(TraitType traitType)
 | 
			
		||||
	{
 | 
			
		||||
		return _attackTraits;
 | 
			
		||||
		_lock.readLock().lock();
 | 
			
		||||
		try
 | 
			
		||||
		{
 | 
			
		||||
			return _attackTraitValues[traitType.ordinal()];
 | 
			
		||||
		}
 | 
			
		||||
		finally
 | 
			
		||||
		{
 | 
			
		||||
			_lock.readLock().unlock();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public boolean hasAttackTrait(TraitType traitType)
 | 
			
		||||
	{
 | 
			
		||||
		return _attackTraitsCount[traitType.ordinal()] > 0;
 | 
			
		||||
		_lock.readLock().lock();
 | 
			
		||||
		try
 | 
			
		||||
		{
 | 
			
		||||
			return _attackTraits.contains(traitType);
 | 
			
		||||
		}
 | 
			
		||||
		finally
 | 
			
		||||
		{
 | 
			
		||||
			_lock.readLock().unlock();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public int[] getAttackTraitsCount()
 | 
			
		||||
	public void mergeDefenceTrait(TraitType traitType, float value)
 | 
			
		||||
	{
 | 
			
		||||
		return _attackTraitsCount;
 | 
			
		||||
		_defenceTraitValues[traitType.ordinal()] *= value;
 | 
			
		||||
		_defenceTraits.add(traitType);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public float getDefenceTrait(TraitType traitType)
 | 
			
		||||
	{
 | 
			
		||||
		return _defenceTraits[traitType.ordinal()];
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public float[] getDefenceTraits()
 | 
			
		||||
	{
 | 
			
		||||
		return _defenceTraits;
 | 
			
		||||
		_lock.readLock().lock();
 | 
			
		||||
		try
 | 
			
		||||
		{
 | 
			
		||||
			return _defenceTraitValues[traitType.ordinal()];
 | 
			
		||||
		}
 | 
			
		||||
		finally
 | 
			
		||||
		{
 | 
			
		||||
			_lock.readLock().unlock();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public boolean hasDefenceTrait(TraitType traitType)
 | 
			
		||||
	{
 | 
			
		||||
		return _defenceTraitsCount[traitType.ordinal()] > 0;
 | 
			
		||||
		_lock.readLock().lock();
 | 
			
		||||
		try
 | 
			
		||||
		{
 | 
			
		||||
			return _defenceTraits.contains(traitType);
 | 
			
		||||
		}
 | 
			
		||||
		finally
 | 
			
		||||
		{
 | 
			
		||||
			_lock.readLock().unlock();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public int[] getDefenceTraitsCount()
 | 
			
		||||
	public void mergeInvulnerableTrait(TraitType traitType)
 | 
			
		||||
	{
 | 
			
		||||
		return _defenceTraitsCount;
 | 
			
		||||
		_invulnerableTraits.add(traitType);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public boolean isTraitInvul(TraitType traitType)
 | 
			
		||||
	public boolean isInvulnerableTrait(TraitType traitType)
 | 
			
		||||
	{
 | 
			
		||||
		return _traitsInvul[traitType.ordinal()] > 0;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public int[] getTraitsInvul()
 | 
			
		||||
	{
 | 
			
		||||
		return _traitsInvul;
 | 
			
		||||
		_lock.readLock().lock();
 | 
			
		||||
		try
 | 
			
		||||
		{
 | 
			
		||||
			return _invulnerableTraits.contains(traitType);
 | 
			
		||||
		}
 | 
			
		||||
		finally
 | 
			
		||||
		{
 | 
			
		||||
			_lock.readLock().unlock();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
 
 | 
			
		||||
@@ -1241,7 +1241,7 @@ public final class Formulas
 | 
			
		||||
			return 1.0;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		if (target.getStat().isTraitInvul(traitType))
 | 
			
		||||
		if (target.getStat().isInvulnerableTrait(traitType))
 | 
			
		||||
		{
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -63,6 +63,14 @@ public enum TraitType
 | 
			
		||||
	PHYSICAL_WEAKNESS(3),
 | 
			
		||||
	MAGICAL_WEAKNESS(3),
 | 
			
		||||
	DUALDAGGER(1),
 | 
			
		||||
	DEMONIC_WEAKNESS(2), // CT26_P4
 | 
			
		||||
	DIVINE_WEAKNESS(2),
 | 
			
		||||
	ELEMENTAL_WEAKNESS(2),
 | 
			
		||||
	FAIRY_WEAKNESS(2),
 | 
			
		||||
	HUMAN_WEAKNESS(2),
 | 
			
		||||
	HUMANOID_WEAKNESS(2),
 | 
			
		||||
	UNDEAD_WEAKNESS(2),
 | 
			
		||||
	// The values from below are custom.
 | 
			
		||||
	DUALBLUNT(1),
 | 
			
		||||
	KNOCKBACK(3),
 | 
			
		||||
	KNOCKDOWN(3),
 | 
			
		||||
@@ -75,7 +83,9 @@ public enum TraitType
 | 
			
		||||
	CHANGEBODY(3),
 | 
			
		||||
	TWOHANDCROSSBOW(1),
 | 
			
		||||
	ZONE(3),
 | 
			
		||||
	PSYCHIC(3);
 | 
			
		||||
	PSYCHIC(3),
 | 
			
		||||
	EMBRYO_WEAKNESS(2),
 | 
			
		||||
	SPIRIT_WEAKNESS(2);
 | 
			
		||||
	
 | 
			
		||||
	private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance
 | 
			
		||||
	
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user