Use EnumSet instead or Arrays for traits.

Adapted from: L2jUnity free files.
This commit is contained in:
MobiusDevelopment
2019-06-11 03:16:24 +00:00
parent 582f0cc188
commit 9b37677bd4
60 changed files with 1086 additions and 1578 deletions

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; import org.l2jmobius.gameserver.model.stats.TraitType;
@@ -51,35 +49,11 @@ public final class AttackTrait extends AbstractEffect
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _attackTraits.entrySet())
synchronized (charStat.getAttackTraits())
{ {
for (Entry<TraitType, Float> trait : _attackTraits.entrySet()) effected.getStat().mergeAttackTrait(trait.getKey(), trait.getValue());
{
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()]++;
}
} }
} }
} }

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; 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()) for (Entry<String, Object> param : params.getSet().entrySet())
{ {
try _defenceTraits.put(TraitType.valueOf(param.getKey()), (Float.parseFloat((String) param.getValue()) + 100) / 100);
{
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());
}
} }
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _defenceTraits.entrySet())
synchronized (charStat.getDefenceTraits())
{ {
for (Entry<TraitType, Float> trait : _defenceTraits.entrySet()) if (trait.getValue() < 2.0f)
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeDefenceTrait(trait.getKey(), trait.getValue());
{
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()]--;
}
} }
} else
}
@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())
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeInvulnerableTrait(trait.getKey());
{
charStat.getDefenceTraits()[trait.getKey().ordinal()] *= trait.getValue();
charStat.getDefenceTraitsCount()[trait.getKey().ordinal()]++;
}
else
{
charStat.getTraitsInvul()[trait.getKey().ordinal()]++;
}
} }
} }
} }

View File

@@ -16,10 +16,10 @@
*/ */
package org.l2jmobius.gameserver.model.actor.stat; package org.l2jmobius.gameserver.model.actor.stat;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Deque; import java.util.Deque;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
@@ -72,11 +72,11 @@ public class CreatureStat
private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>(); private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>();
private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>(); private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>();
private final float[] _attackTraits = new float[TraitType.values().length]; private final float[] _attackTraitValues = new float[TraitType.values().length];
private final float[] _defenceTraits = new float[TraitType.values().length]; private final float[] _defenceTraitValues = new float[TraitType.values().length];
private final int[] _attackTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _attackTraits = EnumSet.noneOf(TraitType.class);
private final int[] _defenceTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _defenceTraits = EnumSet.noneOf(TraitType.class);
private final int[] _traitsInvul = new int[TraitType.values().length]; private final Set<TraitType> _invulnerableTraits = EnumSet.noneOf(TraitType.class);
/** Values to be recalculated after every stat update */ /** Values to be recalculated after every stat update */
private double _attackSpeedMultiplier = 1; private double _attackSpeedMultiplier = 1;
@@ -87,8 +87,6 @@ public class CreatureStat
public CreatureStat(Creature creature) public CreatureStat(Creature creature)
{ {
_creature = creature; _creature = creature;
Arrays.fill(_attackTraits, 1.0f);
Arrays.fill(_defenceTraits, 1.0f);
} }
/** /**
@@ -583,54 +581,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) 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) public float getDefenceTrait(TraitType traitType)
{ {
return _defenceTraits[traitType.ordinal()]; _lock.readLock().lock();
} try
{
public float[] getDefenceTraits() return _defenceTraitValues[traitType.ordinal()];
{ }
return _defenceTraits; finally
{
_lock.readLock().unlock();
}
} }
public boolean hasDefenceTrait(TraitType traitType) 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; _lock.readLock().lock();
} try
{
public int[] getTraitsInvul() return _invulnerableTraits.contains(traitType);
{ }
return _traitsInvul; finally
{
_lock.readLock().unlock();
}
} }
/** /**

View File

@@ -1241,7 +1241,7 @@ public final class Formulas
return 1.0; return 1.0;
} }
if (target.getStat().isTraitInvul(traitType)) if (target.getStat().isInvulnerableTrait(traitType))
{ {
return 0; return 0;
} }

View File

@@ -63,6 +63,14 @@ public enum TraitType
PHYSICAL_WEAKNESS(3), PHYSICAL_WEAKNESS(3),
MAGICAL_WEAKNESS(3), MAGICAL_WEAKNESS(3),
DUALDAGGER(1), 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), DUALBLUNT(1),
KNOCKBACK(3), KNOCKBACK(3),
KNOCKDOWN(3), KNOCKDOWN(3),
@@ -75,7 +83,9 @@ public enum TraitType
CHANGEBODY(3), CHANGEBODY(3),
TWOHANDCROSSBOW(1), TWOHANDCROSSBOW(1),
ZONE(3), ZONE(3),
PSYCHIC(3); PSYCHIC(3),
EMBRYO_WEAKNESS(2),
SPIRIT_WEAKNESS(2);
private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; import org.l2jmobius.gameserver.model.stats.TraitType;
@@ -51,35 +49,11 @@ public final class AttackTrait extends AbstractEffect
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _attackTraits.entrySet())
synchronized (charStat.getAttackTraits())
{ {
for (Entry<TraitType, Float> trait : _attackTraits.entrySet()) effected.getStat().mergeAttackTrait(trait.getKey(), trait.getValue());
{
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()]++;
}
} }
} }
} }

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; 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()) for (Entry<String, Object> param : params.getSet().entrySet())
{ {
try _defenceTraits.put(TraitType.valueOf(param.getKey()), (Float.parseFloat((String) param.getValue()) + 100) / 100);
{
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());
}
} }
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _defenceTraits.entrySet())
synchronized (charStat.getDefenceTraits())
{ {
for (Entry<TraitType, Float> trait : _defenceTraits.entrySet()) if (trait.getValue() < 2.0f)
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeDefenceTrait(trait.getKey(), trait.getValue());
{
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()]--;
}
} }
} else
}
@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())
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeInvulnerableTrait(trait.getKey());
{
charStat.getDefenceTraits()[trait.getKey().ordinal()] *= trait.getValue();
charStat.getDefenceTraitsCount()[trait.getKey().ordinal()]++;
}
else
{
charStat.getTraitsInvul()[trait.getKey().ordinal()]++;
}
} }
} }
} }

View File

@@ -16,10 +16,10 @@
*/ */
package org.l2jmobius.gameserver.model.actor.stat; package org.l2jmobius.gameserver.model.actor.stat;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Deque; import java.util.Deque;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
@@ -72,11 +72,11 @@ public class CreatureStat
private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>(); private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>();
private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>(); private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>();
private final float[] _attackTraits = new float[TraitType.values().length]; private final float[] _attackTraitValues = new float[TraitType.values().length];
private final float[] _defenceTraits = new float[TraitType.values().length]; private final float[] _defenceTraitValues = new float[TraitType.values().length];
private final int[] _attackTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _attackTraits = EnumSet.noneOf(TraitType.class);
private final int[] _defenceTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _defenceTraits = EnumSet.noneOf(TraitType.class);
private final int[] _traitsInvul = new int[TraitType.values().length]; private final Set<TraitType> _invulnerableTraits = EnumSet.noneOf(TraitType.class);
/** Values to be recalculated after every stat update */ /** Values to be recalculated after every stat update */
private double _attackSpeedMultiplier = 1; private double _attackSpeedMultiplier = 1;
@@ -87,8 +87,6 @@ public class CreatureStat
public CreatureStat(Creature creature) public CreatureStat(Creature creature)
{ {
_creature = creature; _creature = creature;
Arrays.fill(_attackTraits, 1.0f);
Arrays.fill(_defenceTraits, 1.0f);
} }
/** /**
@@ -583,54 +581,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) 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) public float getDefenceTrait(TraitType traitType)
{ {
return _defenceTraits[traitType.ordinal()]; _lock.readLock().lock();
} try
{
public float[] getDefenceTraits() return _defenceTraitValues[traitType.ordinal()];
{ }
return _defenceTraits; finally
{
_lock.readLock().unlock();
}
} }
public boolean hasDefenceTrait(TraitType traitType) 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; _lock.readLock().lock();
} try
{
public int[] getTraitsInvul() return _invulnerableTraits.contains(traitType);
{ }
return _traitsInvul; finally
{
_lock.readLock().unlock();
}
} }
/** /**

View File

@@ -1241,7 +1241,7 @@ public final class Formulas
return 1.0; return 1.0;
} }
if (target.getStat().isTraitInvul(traitType)) if (target.getStat().isInvulnerableTrait(traitType))
{ {
return 0; return 0;
} }

View File

@@ -63,6 +63,14 @@ public enum TraitType
PHYSICAL_WEAKNESS(3), PHYSICAL_WEAKNESS(3),
MAGICAL_WEAKNESS(3), MAGICAL_WEAKNESS(3),
DUALDAGGER(1), 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), DUALBLUNT(1),
KNOCKBACK(3), KNOCKBACK(3),
KNOCKDOWN(3), KNOCKDOWN(3),
@@ -75,7 +83,9 @@ public enum TraitType
CHANGEBODY(3), CHANGEBODY(3),
TWOHANDCROSSBOW(1), TWOHANDCROSSBOW(1),
ZONE(3), ZONE(3),
PSYCHIC(3); PSYCHIC(3),
EMBRYO_WEAKNESS(2),
SPIRIT_WEAKNESS(2);
private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; import org.l2jmobius.gameserver.model.stats.TraitType;
@@ -51,35 +49,11 @@ public final class AttackTrait extends AbstractEffect
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _attackTraits.entrySet())
synchronized (charStat.getAttackTraits())
{ {
for (Entry<TraitType, Float> trait : _attackTraits.entrySet()) effected.getStat().mergeAttackTrait(trait.getKey(), trait.getValue());
{
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()]++;
}
} }
} }
} }

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; 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()) for (Entry<String, Object> param : params.getSet().entrySet())
{ {
try _defenceTraits.put(TraitType.valueOf(param.getKey()), (Float.parseFloat((String) param.getValue()) + 100) / 100);
{
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());
}
} }
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _defenceTraits.entrySet())
synchronized (charStat.getDefenceTraits())
{ {
for (Entry<TraitType, Float> trait : _defenceTraits.entrySet()) if (trait.getValue() < 2.0f)
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeDefenceTrait(trait.getKey(), trait.getValue());
{
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()]--;
}
} }
} else
}
@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())
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeInvulnerableTrait(trait.getKey());
{
charStat.getDefenceTraits()[trait.getKey().ordinal()] *= trait.getValue();
charStat.getDefenceTraitsCount()[trait.getKey().ordinal()]++;
}
else
{
charStat.getTraitsInvul()[trait.getKey().ordinal()]++;
}
} }
} }
} }

View File

@@ -16,10 +16,10 @@
*/ */
package org.l2jmobius.gameserver.model.actor.stat; package org.l2jmobius.gameserver.model.actor.stat;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Deque; import java.util.Deque;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
@@ -72,11 +72,11 @@ public class CreatureStat
private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>(); private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>();
private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>(); private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>();
private final float[] _attackTraits = new float[TraitType.values().length]; private final float[] _attackTraitValues = new float[TraitType.values().length];
private final float[] _defenceTraits = new float[TraitType.values().length]; private final float[] _defenceTraitValues = new float[TraitType.values().length];
private final int[] _attackTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _attackTraits = EnumSet.noneOf(TraitType.class);
private final int[] _defenceTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _defenceTraits = EnumSet.noneOf(TraitType.class);
private final int[] _traitsInvul = new int[TraitType.values().length]; private final Set<TraitType> _invulnerableTraits = EnumSet.noneOf(TraitType.class);
/** Values to be recalculated after every stat update */ /** Values to be recalculated after every stat update */
private double _attackSpeedMultiplier = 1; private double _attackSpeedMultiplier = 1;
@@ -87,8 +87,6 @@ public class CreatureStat
public CreatureStat(Creature creature) public CreatureStat(Creature creature)
{ {
_creature = creature; _creature = creature;
Arrays.fill(_attackTraits, 1.0f);
Arrays.fill(_defenceTraits, 1.0f);
} }
/** /**
@@ -583,54 +581,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) 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) public float getDefenceTrait(TraitType traitType)
{ {
return _defenceTraits[traitType.ordinal()]; _lock.readLock().lock();
} try
{
public float[] getDefenceTraits() return _defenceTraitValues[traitType.ordinal()];
{ }
return _defenceTraits; finally
{
_lock.readLock().unlock();
}
} }
public boolean hasDefenceTrait(TraitType traitType) 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; _lock.readLock().lock();
} try
{
public int[] getTraitsInvul() return _invulnerableTraits.contains(traitType);
{ }
return _traitsInvul; finally
{
_lock.readLock().unlock();
}
} }
/** /**

View File

@@ -1241,7 +1241,7 @@ public final class Formulas
return 1.0; return 1.0;
} }
if (target.getStat().isTraitInvul(traitType)) if (target.getStat().isInvulnerableTrait(traitType))
{ {
return 0; return 0;
} }

View File

@@ -63,6 +63,14 @@ public enum TraitType
PHYSICAL_WEAKNESS(3), PHYSICAL_WEAKNESS(3),
MAGICAL_WEAKNESS(3), MAGICAL_WEAKNESS(3),
DUALDAGGER(1), 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), DUALBLUNT(1),
KNOCKBACK(3), KNOCKBACK(3),
KNOCKDOWN(3), KNOCKDOWN(3),
@@ -75,7 +83,9 @@ public enum TraitType
CHANGEBODY(3), CHANGEBODY(3),
TWOHANDCROSSBOW(1), TWOHANDCROSSBOW(1),
ZONE(3), ZONE(3),
PSYCHIC(3); PSYCHIC(3),
EMBRYO_WEAKNESS(2),
SPIRIT_WEAKNESS(2);
private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; import org.l2jmobius.gameserver.model.stats.TraitType;
@@ -51,35 +49,11 @@ public final class AttackTrait extends AbstractEffect
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _attackTraits.entrySet())
synchronized (charStat.getAttackTraits())
{ {
for (Entry<TraitType, Float> trait : _attackTraits.entrySet()) effected.getStat().mergeAttackTrait(trait.getKey(), trait.getValue());
{
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()]++;
}
} }
} }
} }

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; 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()) for (Entry<String, Object> param : params.getSet().entrySet())
{ {
try _defenceTraits.put(TraitType.valueOf(param.getKey()), (Float.parseFloat((String) param.getValue()) + 100) / 100);
{
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());
}
} }
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _defenceTraits.entrySet())
synchronized (charStat.getDefenceTraits())
{ {
for (Entry<TraitType, Float> trait : _defenceTraits.entrySet()) if (trait.getValue() < 2.0f)
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeDefenceTrait(trait.getKey(), trait.getValue());
{
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()]--;
}
} }
} else
}
@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())
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeInvulnerableTrait(trait.getKey());
{
charStat.getDefenceTraits()[trait.getKey().ordinal()] *= trait.getValue();
charStat.getDefenceTraitsCount()[trait.getKey().ordinal()]++;
}
else
{
charStat.getTraitsInvul()[trait.getKey().ordinal()]++;
}
} }
} }
} }

View File

@@ -16,10 +16,10 @@
*/ */
package org.l2jmobius.gameserver.model.actor.stat; package org.l2jmobius.gameserver.model.actor.stat;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Deque; import java.util.Deque;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
@@ -72,11 +72,11 @@ public class CreatureStat
private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>(); private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>();
private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>(); private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>();
private final float[] _attackTraits = new float[TraitType.values().length]; private final float[] _attackTraitValues = new float[TraitType.values().length];
private final float[] _defenceTraits = new float[TraitType.values().length]; private final float[] _defenceTraitValues = new float[TraitType.values().length];
private final int[] _attackTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _attackTraits = EnumSet.noneOf(TraitType.class);
private final int[] _defenceTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _defenceTraits = EnumSet.noneOf(TraitType.class);
private final int[] _traitsInvul = new int[TraitType.values().length]; private final Set<TraitType> _invulnerableTraits = EnumSet.noneOf(TraitType.class);
/** Values to be recalculated after every stat update */ /** Values to be recalculated after every stat update */
private double _attackSpeedMultiplier = 1; private double _attackSpeedMultiplier = 1;
@@ -87,8 +87,6 @@ public class CreatureStat
public CreatureStat(Creature creature) public CreatureStat(Creature creature)
{ {
_creature = creature; _creature = creature;
Arrays.fill(_attackTraits, 1.0f);
Arrays.fill(_defenceTraits, 1.0f);
} }
/** /**
@@ -583,54 +581,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) 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) public float getDefenceTrait(TraitType traitType)
{ {
return _defenceTraits[traitType.ordinal()]; _lock.readLock().lock();
} try
{
public float[] getDefenceTraits() return _defenceTraitValues[traitType.ordinal()];
{ }
return _defenceTraits; finally
{
_lock.readLock().unlock();
}
} }
public boolean hasDefenceTrait(TraitType traitType) 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; _lock.readLock().lock();
} try
{
public int[] getTraitsInvul() return _invulnerableTraits.contains(traitType);
{ }
return _traitsInvul; finally
{
_lock.readLock().unlock();
}
} }
/** /**

View File

@@ -1241,7 +1241,7 @@ public final class Formulas
return 1.0; return 1.0;
} }
if (target.getStat().isTraitInvul(traitType)) if (target.getStat().isInvulnerableTrait(traitType))
{ {
return 0; return 0;
} }

View File

@@ -63,6 +63,14 @@ public enum TraitType
PHYSICAL_WEAKNESS(3), PHYSICAL_WEAKNESS(3),
MAGICAL_WEAKNESS(3), MAGICAL_WEAKNESS(3),
DUALDAGGER(1), 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), DUALBLUNT(1),
KNOCKBACK(3), KNOCKBACK(3),
KNOCKDOWN(3), KNOCKDOWN(3),
@@ -75,7 +83,9 @@ public enum TraitType
CHANGEBODY(3), CHANGEBODY(3),
TWOHANDCROSSBOW(1), TWOHANDCROSSBOW(1),
ZONE(3), ZONE(3),
PSYCHIC(3); PSYCHIC(3),
EMBRYO_WEAKNESS(2),
SPIRIT_WEAKNESS(2);
private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; import org.l2jmobius.gameserver.model.stats.TraitType;
@@ -51,35 +49,11 @@ public final class AttackTrait extends AbstractEffect
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _attackTraits.entrySet())
synchronized (charStat.getAttackTraits())
{ {
for (Entry<TraitType, Float> trait : _attackTraits.entrySet()) effected.getStat().mergeAttackTrait(trait.getKey(), trait.getValue());
{
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()]++;
}
} }
} }
} }

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; 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()) for (Entry<String, Object> param : params.getSet().entrySet())
{ {
try _defenceTraits.put(TraitType.valueOf(param.getKey()), (Float.parseFloat((String) param.getValue()) + 100) / 100);
{
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());
}
} }
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _defenceTraits.entrySet())
synchronized (charStat.getDefenceTraits())
{ {
for (Entry<TraitType, Float> trait : _defenceTraits.entrySet()) if (trait.getValue() < 2.0f)
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeDefenceTrait(trait.getKey(), trait.getValue());
{
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()]--;
}
} }
} else
}
@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())
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeInvulnerableTrait(trait.getKey());
{
charStat.getDefenceTraits()[trait.getKey().ordinal()] *= trait.getValue();
charStat.getDefenceTraitsCount()[trait.getKey().ordinal()]++;
}
else
{
charStat.getTraitsInvul()[trait.getKey().ordinal()]++;
}
} }
} }
} }

View File

@@ -16,10 +16,10 @@
*/ */
package org.l2jmobius.gameserver.model.actor.stat; package org.l2jmobius.gameserver.model.actor.stat;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Deque; import java.util.Deque;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
@@ -72,11 +72,11 @@ public class CreatureStat
private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>(); private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>();
private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>(); private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>();
private final float[] _attackTraits = new float[TraitType.values().length]; private final float[] _attackTraitValues = new float[TraitType.values().length];
private final float[] _defenceTraits = new float[TraitType.values().length]; private final float[] _defenceTraitValues = new float[TraitType.values().length];
private final int[] _attackTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _attackTraits = EnumSet.noneOf(TraitType.class);
private final int[] _defenceTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _defenceTraits = EnumSet.noneOf(TraitType.class);
private final int[] _traitsInvul = new int[TraitType.values().length]; private final Set<TraitType> _invulnerableTraits = EnumSet.noneOf(TraitType.class);
/** Values to be recalculated after every stat update */ /** Values to be recalculated after every stat update */
private double _attackSpeedMultiplier = 1; private double _attackSpeedMultiplier = 1;
@@ -87,8 +87,6 @@ public class CreatureStat
public CreatureStat(Creature creature) public CreatureStat(Creature creature)
{ {
_creature = creature; _creature = creature;
Arrays.fill(_attackTraits, 1.0f);
Arrays.fill(_defenceTraits, 1.0f);
} }
/** /**
@@ -583,54 +581,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) 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) public float getDefenceTrait(TraitType traitType)
{ {
return _defenceTraits[traitType.ordinal()]; _lock.readLock().lock();
} try
{
public float[] getDefenceTraits() return _defenceTraitValues[traitType.ordinal()];
{ }
return _defenceTraits; finally
{
_lock.readLock().unlock();
}
} }
public boolean hasDefenceTrait(TraitType traitType) 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; _lock.readLock().lock();
} try
{
public int[] getTraitsInvul() return _invulnerableTraits.contains(traitType);
{ }
return _traitsInvul; finally
{
_lock.readLock().unlock();
}
} }
/** /**

View File

@@ -1241,7 +1241,7 @@ public final class Formulas
return 1.0; return 1.0;
} }
if (target.getStat().isTraitInvul(traitType)) if (target.getStat().isInvulnerableTrait(traitType))
{ {
return 0; return 0;
} }

View File

@@ -63,6 +63,14 @@ public enum TraitType
PHYSICAL_WEAKNESS(3), PHYSICAL_WEAKNESS(3),
MAGICAL_WEAKNESS(3), MAGICAL_WEAKNESS(3),
DUALDAGGER(1), 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), DUALBLUNT(1),
KNOCKBACK(3), KNOCKBACK(3),
KNOCKDOWN(3), KNOCKDOWN(3),
@@ -75,7 +83,9 @@ public enum TraitType
CHANGEBODY(3), CHANGEBODY(3),
TWOHANDCROSSBOW(1), TWOHANDCROSSBOW(1),
ZONE(3), ZONE(3),
PSYCHIC(3); PSYCHIC(3),
EMBRYO_WEAKNESS(2),
SPIRIT_WEAKNESS(2);
private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; import org.l2jmobius.gameserver.model.stats.TraitType;
@@ -51,35 +49,11 @@ public final class AttackTrait extends AbstractEffect
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _attackTraits.entrySet())
synchronized (charStat.getAttackTraits())
{ {
for (Entry<TraitType, Float> trait : _attackTraits.entrySet()) effected.getStat().mergeAttackTrait(trait.getKey(), trait.getValue());
{
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()]++;
}
} }
} }
} }

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; 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()) for (Entry<String, Object> param : params.getSet().entrySet())
{ {
try _defenceTraits.put(TraitType.valueOf(param.getKey()), (Float.parseFloat((String) param.getValue()) + 100) / 100);
{
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());
}
} }
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _defenceTraits.entrySet())
synchronized (charStat.getDefenceTraits())
{ {
for (Entry<TraitType, Float> trait : _defenceTraits.entrySet()) if (trait.getValue() < 2.0f)
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeDefenceTrait(trait.getKey(), trait.getValue());
{
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()]--;
}
} }
} else
}
@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())
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeInvulnerableTrait(trait.getKey());
{
charStat.getDefenceTraits()[trait.getKey().ordinal()] *= trait.getValue();
charStat.getDefenceTraitsCount()[trait.getKey().ordinal()]++;
}
else
{
charStat.getTraitsInvul()[trait.getKey().ordinal()]++;
}
} }
} }
} }

View File

@@ -16,10 +16,10 @@
*/ */
package org.l2jmobius.gameserver.model.actor.stat; package org.l2jmobius.gameserver.model.actor.stat;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Deque; import java.util.Deque;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
@@ -72,11 +72,11 @@ public class CreatureStat
private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>(); private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>();
private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>(); private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>();
private final float[] _attackTraits = new float[TraitType.values().length]; private final float[] _attackTraitValues = new float[TraitType.values().length];
private final float[] _defenceTraits = new float[TraitType.values().length]; private final float[] _defenceTraitValues = new float[TraitType.values().length];
private final int[] _attackTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _attackTraits = EnumSet.noneOf(TraitType.class);
private final int[] _defenceTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _defenceTraits = EnumSet.noneOf(TraitType.class);
private final int[] _traitsInvul = new int[TraitType.values().length]; private final Set<TraitType> _invulnerableTraits = EnumSet.noneOf(TraitType.class);
/** Values to be recalculated after every stat update */ /** Values to be recalculated after every stat update */
private double _attackSpeedMultiplier = 1; private double _attackSpeedMultiplier = 1;
@@ -87,8 +87,6 @@ public class CreatureStat
public CreatureStat(Creature creature) public CreatureStat(Creature creature)
{ {
_creature = creature; _creature = creature;
Arrays.fill(_attackTraits, 1.0f);
Arrays.fill(_defenceTraits, 1.0f);
} }
/** /**
@@ -583,54 +581,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) 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) public float getDefenceTrait(TraitType traitType)
{ {
return _defenceTraits[traitType.ordinal()]; _lock.readLock().lock();
} try
{
public float[] getDefenceTraits() return _defenceTraitValues[traitType.ordinal()];
{ }
return _defenceTraits; finally
{
_lock.readLock().unlock();
}
} }
public boolean hasDefenceTrait(TraitType traitType) 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; _lock.readLock().lock();
} try
{
public int[] getTraitsInvul() return _invulnerableTraits.contains(traitType);
{ }
return _traitsInvul; finally
{
_lock.readLock().unlock();
}
} }
/** /**

View File

@@ -1241,7 +1241,7 @@ public final class Formulas
return 1.0; return 1.0;
} }
if (target.getStat().isTraitInvul(traitType)) if (target.getStat().isInvulnerableTrait(traitType))
{ {
return 0; return 0;
} }

View File

@@ -63,6 +63,14 @@ public enum TraitType
PHYSICAL_WEAKNESS(3), PHYSICAL_WEAKNESS(3),
MAGICAL_WEAKNESS(3), MAGICAL_WEAKNESS(3),
DUALDAGGER(1), 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), DUALBLUNT(1),
KNOCKBACK(3), KNOCKBACK(3),
KNOCKDOWN(3), KNOCKDOWN(3),
@@ -75,7 +83,9 @@ public enum TraitType
CHANGEBODY(3), CHANGEBODY(3),
TWOHANDCROSSBOW(1), TWOHANDCROSSBOW(1),
ZONE(3), ZONE(3),
PSYCHIC(3); PSYCHIC(3),
EMBRYO_WEAKNESS(2),
SPIRIT_WEAKNESS(2);
private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; import org.l2jmobius.gameserver.model.stats.TraitType;
@@ -51,35 +49,11 @@ public final class AttackTrait extends AbstractEffect
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _attackTraits.entrySet())
synchronized (charStat.getAttackTraits())
{ {
for (Entry<TraitType, Float> trait : _attackTraits.entrySet()) effected.getStat().mergeAttackTrait(trait.getKey(), trait.getValue());
{
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()]++;
}
} }
} }
} }

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; 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()) for (Entry<String, Object> param : params.getSet().entrySet())
{ {
try _defenceTraits.put(TraitType.valueOf(param.getKey()), (Float.parseFloat((String) param.getValue()) + 100) / 100);
{
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());
}
} }
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _defenceTraits.entrySet())
synchronized (charStat.getDefenceTraits())
{ {
for (Entry<TraitType, Float> trait : _defenceTraits.entrySet()) if (trait.getValue() < 2.0f)
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeDefenceTrait(trait.getKey(), trait.getValue());
{
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()]--;
}
} }
} else
}
@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())
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeInvulnerableTrait(trait.getKey());
{
charStat.getDefenceTraits()[trait.getKey().ordinal()] *= trait.getValue();
charStat.getDefenceTraitsCount()[trait.getKey().ordinal()]++;
}
else
{
charStat.getTraitsInvul()[trait.getKey().ordinal()]++;
}
} }
} }
} }

View File

@@ -16,10 +16,10 @@
*/ */
package org.l2jmobius.gameserver.model.actor.stat; package org.l2jmobius.gameserver.model.actor.stat;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Deque; import java.util.Deque;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
@@ -72,11 +72,11 @@ public class CreatureStat
private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>(); private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>();
private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>(); private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>();
private final float[] _attackTraits = new float[TraitType.values().length]; private final float[] _attackTraitValues = new float[TraitType.values().length];
private final float[] _defenceTraits = new float[TraitType.values().length]; private final float[] _defenceTraitValues = new float[TraitType.values().length];
private final int[] _attackTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _attackTraits = EnumSet.noneOf(TraitType.class);
private final int[] _defenceTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _defenceTraits = EnumSet.noneOf(TraitType.class);
private final int[] _traitsInvul = new int[TraitType.values().length]; private final Set<TraitType> _invulnerableTraits = EnumSet.noneOf(TraitType.class);
/** Values to be recalculated after every stat update */ /** Values to be recalculated after every stat update */
private double _attackSpeedMultiplier = 1; private double _attackSpeedMultiplier = 1;
@@ -87,8 +87,6 @@ public class CreatureStat
public CreatureStat(Creature creature) public CreatureStat(Creature creature)
{ {
_creature = creature; _creature = creature;
Arrays.fill(_attackTraits, 1.0f);
Arrays.fill(_defenceTraits, 1.0f);
} }
/** /**
@@ -583,54 +581,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) 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) public float getDefenceTrait(TraitType traitType)
{ {
return _defenceTraits[traitType.ordinal()]; _lock.readLock().lock();
} try
{
public float[] getDefenceTraits() return _defenceTraitValues[traitType.ordinal()];
{ }
return _defenceTraits; finally
{
_lock.readLock().unlock();
}
} }
public boolean hasDefenceTrait(TraitType traitType) 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; _lock.readLock().lock();
} try
{
public int[] getTraitsInvul() return _invulnerableTraits.contains(traitType);
{ }
return _traitsInvul; finally
{
_lock.readLock().unlock();
}
} }
/** /**

View File

@@ -1241,7 +1241,7 @@ public final class Formulas
return 1.0; return 1.0;
} }
if (target.getStat().isTraitInvul(traitType)) if (target.getStat().isInvulnerableTrait(traitType))
{ {
return 0; return 0;
} }

View File

@@ -1,91 +1,101 @@
/* /*
* This file is part of the L2J Mobius project. * This file is part of the L2J Mobius project.
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.l2jmobius.gameserver.model.stats; package org.l2jmobius.gameserver.model.stats;
/** /**
* @author UnAfraid, NosBit * @author UnAfraid, NosBit
*/ */
public enum TraitType public enum TraitType
{ {
NONE(0), NONE(0),
SWORD(1), SWORD(1),
BLUNT(1), BLUNT(1),
DAGGER(1), DAGGER(1),
POLE(1), POLE(1),
FIST(1), FIST(1),
BOW(1), BOW(1),
ETC(1), ETC(1),
UNK_8(0), UNK_8(0),
POISON(3), POISON(3),
HOLD(3), HOLD(3),
BLEED(3), BLEED(3),
SLEEP(3), SLEEP(3),
SHOCK(3), SHOCK(3),
DERANGEMENT(3), DERANGEMENT(3),
BUG_WEAKNESS(2), BUG_WEAKNESS(2),
ANIMAL_WEAKNESS(2), ANIMAL_WEAKNESS(2),
PLANT_WEAKNESS(2), PLANT_WEAKNESS(2),
BEAST_WEAKNESS(2), BEAST_WEAKNESS(2),
DRAGON_WEAKNESS(2), DRAGON_WEAKNESS(2),
PARALYZE(3), PARALYZE(3),
DUAL(1), DUAL(1),
DUALFIST(1), DUALFIST(1),
BOSS(3), BOSS(3),
GIANT_WEAKNESS(2), GIANT_WEAKNESS(2),
CONSTRUCT_WEAKNESS(2), CONSTRUCT_WEAKNESS(2),
DEATH(3), DEATH(3),
VALAKAS(2), VALAKAS(2),
ANESTHESIA(2), ANESTHESIA(2),
CRITICAL_POISON(3), CRITICAL_POISON(3),
ROOT_PHYSICALLY(3), ROOT_PHYSICALLY(3),
ROOT_MAGICALLY(3), ROOT_MAGICALLY(3),
RAPIER(1), RAPIER(1),
CROSSBOW(1), CROSSBOW(1),
ANCIENTSWORD(1), ANCIENTSWORD(1),
TURN_STONE(3), TURN_STONE(3),
GUST(3), GUST(3),
PHYSICAL_BLOCKADE(3), PHYSICAL_BLOCKADE(3),
TARGET(3), TARGET(3),
PHYSICAL_WEAKNESS(3), PHYSICAL_WEAKNESS(3),
MAGICAL_WEAKNESS(3), MAGICAL_WEAKNESS(3),
DUALDAGGER(1), DUALDAGGER(1),
DUALBLUNT(1), DEMONIC_WEAKNESS(2), // CT26_P4
KNOCKBACK(3), DIVINE_WEAKNESS(2),
KNOCKDOWN(3), ELEMENTAL_WEAKNESS(2),
PULL(3), FAIRY_WEAKNESS(2),
HATE(3), HUMAN_WEAKNESS(2),
AGGRESSION(3), HUMANOID_WEAKNESS(2),
AIRBIND(3), UNDEAD_WEAKNESS(2),
DISARM(3), // The values from below are custom.
DEPORT(3), DUALBLUNT(1),
CHANGEBODY(3), KNOCKBACK(3),
TWOHANDCROSSBOW(1), KNOCKDOWN(3),
ZONE(3), PULL(3),
PSYCHIC(3); HATE(3),
AGGRESSION(3),
private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance AIRBIND(3),
DISARM(3),
TraitType(int type) DEPORT(3),
{ CHANGEBODY(3),
_type = type; TWOHANDCROSSBOW(1),
} ZONE(3),
PSYCHIC(3),
public int getType() EMBRYO_WEAKNESS(2),
{ SPIRIT_WEAKNESS(2);
return _type;
} private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance
}
TraitType(int type)
{
_type = type;
}
public int getType()
{
return _type;
}
}

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; import org.l2jmobius.gameserver.model.stats.TraitType;
@@ -51,35 +49,11 @@ public final class AttackTrait extends AbstractEffect
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _attackTraits.entrySet())
synchronized (charStat.getAttackTraits())
{ {
for (Entry<TraitType, Float> trait : _attackTraits.entrySet()) effected.getStat().mergeAttackTrait(trait.getKey(), trait.getValue());
{
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()]++;
}
} }
} }
} }

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; 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()) for (Entry<String, Object> param : params.getSet().entrySet())
{ {
try _defenceTraits.put(TraitType.valueOf(param.getKey()), (Float.parseFloat((String) param.getValue()) + 100) / 100);
{
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());
}
} }
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _defenceTraits.entrySet())
synchronized (charStat.getDefenceTraits())
{ {
for (Entry<TraitType, Float> trait : _defenceTraits.entrySet()) if (trait.getValue() < 2.0f)
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeDefenceTrait(trait.getKey(), trait.getValue());
{
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()]--;
}
} }
} else
}
@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())
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeInvulnerableTrait(trait.getKey());
{
charStat.getDefenceTraits()[trait.getKey().ordinal()] *= trait.getValue();
charStat.getDefenceTraitsCount()[trait.getKey().ordinal()]++;
}
else
{
charStat.getTraitsInvul()[trait.getKey().ordinal()]++;
}
} }
} }
} }

View File

@@ -16,10 +16,10 @@
*/ */
package org.l2jmobius.gameserver.model.actor.stat; package org.l2jmobius.gameserver.model.actor.stat;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Deque; import java.util.Deque;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
@@ -72,11 +72,11 @@ public class CreatureStat
private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>(); private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>();
private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>(); private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>();
private final float[] _attackTraits = new float[TraitType.values().length]; private final float[] _attackTraitValues = new float[TraitType.values().length];
private final float[] _defenceTraits = new float[TraitType.values().length]; private final float[] _defenceTraitValues = new float[TraitType.values().length];
private final int[] _attackTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _attackTraits = EnumSet.noneOf(TraitType.class);
private final int[] _defenceTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _defenceTraits = EnumSet.noneOf(TraitType.class);
private final int[] _traitsInvul = new int[TraitType.values().length]; private final Set<TraitType> _invulnerableTraits = EnumSet.noneOf(TraitType.class);
/** Values to be recalculated after every stat update */ /** Values to be recalculated after every stat update */
private double _attackSpeedMultiplier = 1; private double _attackSpeedMultiplier = 1;
@@ -87,8 +87,6 @@ public class CreatureStat
public CreatureStat(Creature creature) public CreatureStat(Creature creature)
{ {
_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) 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) public float getDefenceTrait(TraitType traitType)
{ {
return _defenceTraits[traitType.ordinal()]; _lock.readLock().lock();
} try
{
public float[] getDefenceTraits() return _defenceTraitValues[traitType.ordinal()];
{ }
return _defenceTraits; finally
{
_lock.readLock().unlock();
}
} }
public boolean hasDefenceTrait(TraitType traitType) 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; _lock.readLock().lock();
} try
{
public int[] getTraitsInvul() return _invulnerableTraits.contains(traitType);
{ }
return _traitsInvul; finally
{
_lock.readLock().unlock();
}
} }
/** /**

View File

@@ -1241,7 +1241,7 @@ public final class Formulas
return 1.0; return 1.0;
} }
if (target.getStat().isTraitInvul(traitType)) if (target.getStat().isInvulnerableTrait(traitType))
{ {
return 0; return 0;
} }

View File

@@ -63,6 +63,14 @@ public enum TraitType
PHYSICAL_WEAKNESS(3), PHYSICAL_WEAKNESS(3),
MAGICAL_WEAKNESS(3), MAGICAL_WEAKNESS(3),
DUALDAGGER(1), 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), DUALBLUNT(1),
KNOCKBACK(3), KNOCKBACK(3),
KNOCKDOWN(3), KNOCKDOWN(3),
@@ -75,7 +83,9 @@ public enum TraitType
CHANGEBODY(3), CHANGEBODY(3),
TWOHANDCROSSBOW(1), TWOHANDCROSSBOW(1),
ZONE(3), ZONE(3),
PSYCHIC(3); PSYCHIC(3),
EMBRYO_WEAKNESS(2),
SPIRIT_WEAKNESS(2);
private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; import org.l2jmobius.gameserver.model.stats.TraitType;
@@ -51,35 +49,11 @@ public final class AttackTrait extends AbstractEffect
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _attackTraits.entrySet())
synchronized (charStat.getAttackTraits())
{ {
for (Entry<TraitType, Float> trait : _attackTraits.entrySet()) effected.getStat().mergeAttackTrait(trait.getKey(), trait.getValue());
{
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()]++;
}
} }
} }
} }

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; 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()) for (Entry<String, Object> param : params.getSet().entrySet())
{ {
try _defenceTraits.put(TraitType.valueOf(param.getKey()), (Float.parseFloat((String) param.getValue()) + 100) / 100);
{
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());
}
} }
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _defenceTraits.entrySet())
synchronized (charStat.getDefenceTraits())
{ {
for (Entry<TraitType, Float> trait : _defenceTraits.entrySet()) if (trait.getValue() < 2.0f)
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeDefenceTrait(trait.getKey(), trait.getValue());
{
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()]--;
}
} }
} else
}
@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())
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeInvulnerableTrait(trait.getKey());
{
charStat.getDefenceTraits()[trait.getKey().ordinal()] *= trait.getValue();
charStat.getDefenceTraitsCount()[trait.getKey().ordinal()]++;
}
else
{
charStat.getTraitsInvul()[trait.getKey().ordinal()]++;
}
} }
} }
} }

View File

@@ -16,10 +16,10 @@
*/ */
package org.l2jmobius.gameserver.model.actor.stat; package org.l2jmobius.gameserver.model.actor.stat;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Deque; import java.util.Deque;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
@@ -72,11 +72,11 @@ public class CreatureStat
private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>(); private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>();
private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>(); private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>();
private final float[] _attackTraits = new float[TraitType.values().length]; private final float[] _attackTraitValues = new float[TraitType.values().length];
private final float[] _defenceTraits = new float[TraitType.values().length]; private final float[] _defenceTraitValues = new float[TraitType.values().length];
private final int[] _attackTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _attackTraits = EnumSet.noneOf(TraitType.class);
private final int[] _defenceTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _defenceTraits = EnumSet.noneOf(TraitType.class);
private final int[] _traitsInvul = new int[TraitType.values().length]; private final Set<TraitType> _invulnerableTraits = EnumSet.noneOf(TraitType.class);
/** Values to be recalculated after every stat update */ /** Values to be recalculated after every stat update */
private double _attackSpeedMultiplier = 1; private double _attackSpeedMultiplier = 1;
@@ -87,8 +87,6 @@ public class CreatureStat
public CreatureStat(Creature creature) public CreatureStat(Creature creature)
{ {
_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) 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) public float getDefenceTrait(TraitType traitType)
{ {
return _defenceTraits[traitType.ordinal()]; _lock.readLock().lock();
} try
{
public float[] getDefenceTraits() return _defenceTraitValues[traitType.ordinal()];
{ }
return _defenceTraits; finally
{
_lock.readLock().unlock();
}
} }
public boolean hasDefenceTrait(TraitType traitType) 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; _lock.readLock().lock();
} try
{
public int[] getTraitsInvul() return _invulnerableTraits.contains(traitType);
{ }
return _traitsInvul; finally
{
_lock.readLock().unlock();
}
} }
/** /**

View File

@@ -1241,7 +1241,7 @@ public final class Formulas
return 1.0; return 1.0;
} }
if (target.getStat().isTraitInvul(traitType)) if (target.getStat().isInvulnerableTrait(traitType))
{ {
return 0; return 0;
} }

View File

@@ -63,6 +63,14 @@ public enum TraitType
PHYSICAL_WEAKNESS(3), PHYSICAL_WEAKNESS(3),
MAGICAL_WEAKNESS(3), MAGICAL_WEAKNESS(3),
DUALDAGGER(1), 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), DUALBLUNT(1),
KNOCKBACK(3), KNOCKBACK(3),
KNOCKDOWN(3), KNOCKDOWN(3),
@@ -75,7 +83,9 @@ public enum TraitType
CHANGEBODY(3), CHANGEBODY(3),
TWOHANDCROSSBOW(1), TWOHANDCROSSBOW(1),
ZONE(3), ZONE(3),
PSYCHIC(3); PSYCHIC(3),
EMBRYO_WEAKNESS(2),
SPIRIT_WEAKNESS(2);
private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; import org.l2jmobius.gameserver.model.stats.TraitType;
@@ -51,35 +49,11 @@ public final class AttackTrait extends AbstractEffect
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _attackTraits.entrySet())
synchronized (charStat.getAttackTraits())
{ {
for (Entry<TraitType, Float> trait : _attackTraits.entrySet()) effected.getStat().mergeAttackTrait(trait.getKey(), trait.getValue());
{
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()]++;
}
} }
} }
} }

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; 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()) for (Entry<String, Object> param : params.getSet().entrySet())
{ {
try _defenceTraits.put(TraitType.valueOf(param.getKey()), (Float.parseFloat((String) param.getValue()) + 100) / 100);
{
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());
}
} }
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _defenceTraits.entrySet())
synchronized (charStat.getDefenceTraits())
{ {
for (Entry<TraitType, Float> trait : _defenceTraits.entrySet()) if (trait.getValue() < 2.0f)
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeDefenceTrait(trait.getKey(), trait.getValue());
{
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()]--;
}
} }
} else
}
@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())
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeInvulnerableTrait(trait.getKey());
{
charStat.getDefenceTraits()[trait.getKey().ordinal()] *= trait.getValue();
charStat.getDefenceTraitsCount()[trait.getKey().ordinal()]++;
}
else
{
charStat.getTraitsInvul()[trait.getKey().ordinal()]++;
}
} }
} }
} }

View File

@@ -16,10 +16,10 @@
*/ */
package org.l2jmobius.gameserver.model.actor.stat; package org.l2jmobius.gameserver.model.actor.stat;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Deque; import java.util.Deque;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
@@ -72,11 +72,11 @@ public class CreatureStat
private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>(); private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>();
private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>(); private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>();
private final float[] _attackTraits = new float[TraitType.values().length]; private final float[] _attackTraitValues = new float[TraitType.values().length];
private final float[] _defenceTraits = new float[TraitType.values().length]; private final float[] _defenceTraitValues = new float[TraitType.values().length];
private final int[] _attackTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _attackTraits = EnumSet.noneOf(TraitType.class);
private final int[] _defenceTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _defenceTraits = EnumSet.noneOf(TraitType.class);
private final int[] _traitsInvul = new int[TraitType.values().length]; private final Set<TraitType> _invulnerableTraits = EnumSet.noneOf(TraitType.class);
/** Values to be recalculated after every stat update */ /** Values to be recalculated after every stat update */
private double _attackSpeedMultiplier = 1; private double _attackSpeedMultiplier = 1;
@@ -87,8 +87,6 @@ public class CreatureStat
public CreatureStat(Creature creature) public CreatureStat(Creature creature)
{ {
_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) 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) public float getDefenceTrait(TraitType traitType)
{ {
return _defenceTraits[traitType.ordinal()]; _lock.readLock().lock();
} try
{
public float[] getDefenceTraits() return _defenceTraitValues[traitType.ordinal()];
{ }
return _defenceTraits; finally
{
_lock.readLock().unlock();
}
} }
public boolean hasDefenceTrait(TraitType traitType) 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; _lock.readLock().lock();
} try
{
public int[] getTraitsInvul() return _invulnerableTraits.contains(traitType);
{ }
return _traitsInvul; finally
{
_lock.readLock().unlock();
}
} }
/** /**

View File

@@ -1241,7 +1241,7 @@ public final class Formulas
return 1.0; return 1.0;
} }
if (target.getStat().isTraitInvul(traitType)) if (target.getStat().isInvulnerableTrait(traitType))
{ {
return 0; return 0;
} }

View File

@@ -63,6 +63,14 @@ public enum TraitType
PHYSICAL_WEAKNESS(3), PHYSICAL_WEAKNESS(3),
MAGICAL_WEAKNESS(3), MAGICAL_WEAKNESS(3),
DUALDAGGER(1), 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), DUALBLUNT(1),
KNOCKBACK(3), KNOCKBACK(3),
KNOCKDOWN(3), KNOCKDOWN(3),
@@ -75,7 +83,9 @@ public enum TraitType
CHANGEBODY(3), CHANGEBODY(3),
TWOHANDCROSSBOW(1), TWOHANDCROSSBOW(1),
ZONE(3), ZONE(3),
PSYCHIC(3); PSYCHIC(3),
EMBRYO_WEAKNESS(2),
SPIRIT_WEAKNESS(2);
private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; import org.l2jmobius.gameserver.model.stats.TraitType;
@@ -51,35 +49,11 @@ public final class AttackTrait extends AbstractEffect
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _attackTraits.entrySet())
synchronized (charStat.getAttackTraits())
{ {
for (Entry<TraitType, Float> trait : _attackTraits.entrySet()) effected.getStat().mergeAttackTrait(trait.getKey(), trait.getValue());
{
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()]++;
}
} }
} }
} }

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; 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()) for (Entry<String, Object> param : params.getSet().entrySet())
{ {
try _defenceTraits.put(TraitType.valueOf(param.getKey()), (Float.parseFloat((String) param.getValue()) + 100) / 100);
{
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());
}
} }
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _defenceTraits.entrySet())
synchronized (charStat.getDefenceTraits())
{ {
for (Entry<TraitType, Float> trait : _defenceTraits.entrySet()) if (trait.getValue() < 2.0f)
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeDefenceTrait(trait.getKey(), trait.getValue());
{
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()]--;
}
} }
} else
}
@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())
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeInvulnerableTrait(trait.getKey());
{
charStat.getDefenceTraits()[trait.getKey().ordinal()] *= trait.getValue();
charStat.getDefenceTraitsCount()[trait.getKey().ordinal()]++;
}
else
{
charStat.getTraitsInvul()[trait.getKey().ordinal()]++;
}
} }
} }
} }

View File

@@ -16,10 +16,10 @@
*/ */
package org.l2jmobius.gameserver.model.actor.stat; package org.l2jmobius.gameserver.model.actor.stat;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Deque; import java.util.Deque;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
@@ -72,11 +72,11 @@ public class CreatureStat
private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>(); private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>();
private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>(); private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>();
private final float[] _attackTraits = new float[TraitType.values().length]; private final float[] _attackTraitValues = new float[TraitType.values().length];
private final float[] _defenceTraits = new float[TraitType.values().length]; private final float[] _defenceTraitValues = new float[TraitType.values().length];
private final int[] _attackTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _attackTraits = EnumSet.noneOf(TraitType.class);
private final int[] _defenceTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _defenceTraits = EnumSet.noneOf(TraitType.class);
private final int[] _traitsInvul = new int[TraitType.values().length]; private final Set<TraitType> _invulnerableTraits = EnumSet.noneOf(TraitType.class);
/** Values to be recalculated after every stat update */ /** Values to be recalculated after every stat update */
private double _attackSpeedMultiplier = 1; private double _attackSpeedMultiplier = 1;
@@ -87,8 +87,6 @@ public class CreatureStat
public CreatureStat(Creature creature) public CreatureStat(Creature creature)
{ {
_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) 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) public float getDefenceTrait(TraitType traitType)
{ {
return _defenceTraits[traitType.ordinal()]; _lock.readLock().lock();
} try
{
public float[] getDefenceTraits() return _defenceTraitValues[traitType.ordinal()];
{ }
return _defenceTraits; finally
{
_lock.readLock().unlock();
}
} }
public boolean hasDefenceTrait(TraitType traitType) 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; _lock.readLock().lock();
} try
{
public int[] getTraitsInvul() return _invulnerableTraits.contains(traitType);
{ }
return _traitsInvul; finally
{
_lock.readLock().unlock();
}
} }
/** /**

View File

@@ -1241,7 +1241,7 @@ public final class Formulas
return 1.0; return 1.0;
} }
if (target.getStat().isTraitInvul(traitType)) if (target.getStat().isInvulnerableTrait(traitType))
{ {
return 0; return 0;
} }

View File

@@ -63,6 +63,14 @@ public enum TraitType
PHYSICAL_WEAKNESS(3), PHYSICAL_WEAKNESS(3),
MAGICAL_WEAKNESS(3), MAGICAL_WEAKNESS(3),
DUALDAGGER(1), 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), DUALBLUNT(1),
KNOCKBACK(3), KNOCKBACK(3),
KNOCKDOWN(3), KNOCKDOWN(3),
@@ -75,7 +83,9 @@ public enum TraitType
CHANGEBODY(3), CHANGEBODY(3),
TWOHANDCROSSBOW(1), TWOHANDCROSSBOW(1),
ZONE(3), ZONE(3),
PSYCHIC(3); PSYCHIC(3),
EMBRYO_WEAKNESS(2),
SPIRIT_WEAKNESS(2);
private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; import org.l2jmobius.gameserver.model.stats.TraitType;
@@ -51,35 +49,11 @@ public final class AttackTrait extends AbstractEffect
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _attackTraits.entrySet())
synchronized (charStat.getAttackTraits())
{ {
for (Entry<TraitType, Float> trait : _attackTraits.entrySet()) effected.getStat().mergeAttackTrait(trait.getKey(), trait.getValue());
{
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()]++;
}
} }
} }
} }

View File

@@ -22,9 +22,7 @@ import java.util.Map.Entry;
import org.l2jmobius.gameserver.model.StatsSet; import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Creature; 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.effects.AbstractEffect;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.TraitType; 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()) for (Entry<String, Object> param : params.getSet().entrySet())
{ {
try _defenceTraits.put(TraitType.valueOf(param.getKey()), (Float.parseFloat((String) param.getValue()) + 100) / 100);
{
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());
}
} }
} }
@Override @Override
public void onExit(Creature effector, Creature effected, Skill skill) public void pump(Creature effected, Skill skill)
{ {
final CreatureStat charStat = effected.getStat(); for (Entry<TraitType, Float> trait : _defenceTraits.entrySet())
synchronized (charStat.getDefenceTraits())
{ {
for (Entry<TraitType, Float> trait : _defenceTraits.entrySet()) if (trait.getValue() < 2.0f)
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeDefenceTrait(trait.getKey(), trait.getValue());
{
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()]--;
}
} }
} else
}
@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())
{ {
if (trait.getValue() < 2.0f) effected.getStat().mergeInvulnerableTrait(trait.getKey());
{
charStat.getDefenceTraits()[trait.getKey().ordinal()] *= trait.getValue();
charStat.getDefenceTraitsCount()[trait.getKey().ordinal()]++;
}
else
{
charStat.getTraitsInvul()[trait.getKey().ordinal()]++;
}
} }
} }
} }

View File

@@ -16,10 +16,10 @@
*/ */
package org.l2jmobius.gameserver.model.actor.stat; package org.l2jmobius.gameserver.model.actor.stat;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Deque; import java.util.Deque;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
@@ -72,11 +72,11 @@ public class CreatureStat
private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>(); private final Deque<StatsHolder> _additionalMul = new ConcurrentLinkedDeque<>();
private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>(); private final Map<Stats, Double> _fixedValue = new ConcurrentHashMap<>();
private final float[] _attackTraits = new float[TraitType.values().length]; private final float[] _attackTraitValues = new float[TraitType.values().length];
private final float[] _defenceTraits = new float[TraitType.values().length]; private final float[] _defenceTraitValues = new float[TraitType.values().length];
private final int[] _attackTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _attackTraits = EnumSet.noneOf(TraitType.class);
private final int[] _defenceTraitsCount = new int[TraitType.values().length]; private final Set<TraitType> _defenceTraits = EnumSet.noneOf(TraitType.class);
private final int[] _traitsInvul = new int[TraitType.values().length]; private final Set<TraitType> _invulnerableTraits = EnumSet.noneOf(TraitType.class);
/** Values to be recalculated after every stat update */ /** Values to be recalculated after every stat update */
private double _attackSpeedMultiplier = 1; private double _attackSpeedMultiplier = 1;
@@ -87,8 +87,6 @@ public class CreatureStat
public CreatureStat(Creature creature) public CreatureStat(Creature creature)
{ {
_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) 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) public float getDefenceTrait(TraitType traitType)
{ {
return _defenceTraits[traitType.ordinal()]; _lock.readLock().lock();
} try
{
public float[] getDefenceTraits() return _defenceTraitValues[traitType.ordinal()];
{ }
return _defenceTraits; finally
{
_lock.readLock().unlock();
}
} }
public boolean hasDefenceTrait(TraitType traitType) 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; _lock.readLock().lock();
} try
{
public int[] getTraitsInvul() return _invulnerableTraits.contains(traitType);
{ }
return _traitsInvul; finally
{
_lock.readLock().unlock();
}
} }
/** /**

View File

@@ -1241,7 +1241,7 @@ public final class Formulas
return 1.0; return 1.0;
} }
if (target.getStat().isTraitInvul(traitType)) if (target.getStat().isInvulnerableTrait(traitType))
{ {
return 0; return 0;
} }

View File

@@ -63,6 +63,14 @@ public enum TraitType
PHYSICAL_WEAKNESS(3), PHYSICAL_WEAKNESS(3),
MAGICAL_WEAKNESS(3), MAGICAL_WEAKNESS(3),
DUALDAGGER(1), 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), DUALBLUNT(1),
KNOCKBACK(3), KNOCKBACK(3),
KNOCKDOWN(3), KNOCKDOWN(3),
@@ -75,7 +83,9 @@ public enum TraitType
CHANGEBODY(3), CHANGEBODY(3),
TWOHANDCROSSBOW(1), TWOHANDCROSSBOW(1),
ZONE(3), ZONE(3),
PSYCHIC(3); PSYCHIC(3),
EMBRYO_WEAKNESS(2),
SPIRIT_WEAKNESS(2);
private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance private final int _type; // 1 = weapon, 2 = weakness, 3 = resistance