コード例 #1
0
ファイル: CharStat.java プロジェクト: 3mRe/L2Java
 public boolean isTraitInvul(TraitType traitType) {
   return _traitsInvul[traitType.getId()] > 0;
 }
コード例 #2
0
ファイル: CharStat.java プロジェクト: 3mRe/L2Java
 public boolean hasDefenceTrait(TraitType traitType) {
   return _defenceTraitsCount[traitType.getId()] > 0;
 }
コード例 #3
0
ファイル: CharStat.java プロジェクト: 3mRe/L2Java
 public float getDefenceTrait(TraitType traitType) {
   return _defenceTraits[traitType.getId()];
 }
コード例 #4
0
ファイル: CharStat.java プロジェクト: 3mRe/L2Java
 public boolean hasAttackTrait(TraitType traitType) {
   return _attackTraitsCount[traitType.getId()] > 0;
 }
コード例 #5
0
ファイル: CharStat.java プロジェクト: 3mRe/L2Java
 public float getAttackTrait(TraitType traitType) {
   return _attackTraits[traitType.getId()];
 }
コード例 #6
0
ファイル: CharStat.java プロジェクト: 3mRe/L2Java
public class CharStat {
  private static final int DIVINE_INSPIRATION = 1405;

  private final L2Character _activeChar;
  private long _exp = 0;
  private long _sp = 0;
  private byte _level = 1;
  private final float[] _attackTraits = new float[TraitType.values().length];
  private final int[] _attackTraitsCount = new int[TraitType.values().length];
  private final float[] _defenceTraits = new float[TraitType.values().length];
  private final int[] _defenceTraitsCount = new int[TraitType.values().length];
  private final int[] _traitsInvul = new int[TraitType.values().length];
  /** Creature's maximum buff count. */
  private int _maxBuffCount = Config.BUFFS_MAX_AMOUNT;

  public CharStat(L2Character activeChar) {
    _activeChar = activeChar;
    Arrays.fill(_attackTraits, 1.0f);
    Arrays.fill(_defenceTraits, 1.0f);
  }

  public final double calcStat(Stats stat, double init) {
    return calcStat(stat, init, null, null);
  }

  /**
   * Calculate the new value of the state with modifiers that will be applied on the targeted
   * L2Character.<br>
   * <B><U> Concept</U> :</B><BR
   * A L2Character owns a table of Calculators called <B>
   * _calculators</B>. Each Calculator (a calculator per state) own a table of Func object. A Func
   * object is a mathematic function that permit to calculate the modifier of a state (ex :
   * REGENERATE_HP_RATE...) : <br>
   * FuncAtkAccuracy -> Math.sqrt(_player.getDEX())*6+_player.getLevel()<br>
   * When the calc method of a calculator is launched, each mathematical function is called
   * according to its priority <B>_order</B>.<br>
   * Indeed, Func with lowest priority order is executed firsta and Funcs with the same order are
   * executed in unspecified order.<br>
   * The result of the calculation is stored in the value property of an Env class instance.<br>
   *
   * @param stat The stat to calculate the new value with modifiers
   * @param initVal The initial value of the stat before applying modifiers
   * @param target The L2Charcater whose properties will be used in the calculation (ex : CON,
   *     INT...)
   * @param skill The L2Skill whose properties will be used in the calculation (ex : Level...)
   * @return
   */
  public final double calcStat(Stats stat, double initVal, L2Character target, Skill skill) {
    double value = initVal;
    if (stat == null) {
      return value;
    }

    final int id = stat.ordinal();
    final Calculator c = _activeChar.getCalculators()[id];

    // If no Func object found, no modifier is applied
    if ((c == null) || (c.size() == 0)) {
      return value;
    }

    // Apply transformation stats.
    if (getActiveChar().isPlayer() && getActiveChar().isTransformed()) {
      double val =
          getActiveChar().getTransformation().getStat(getActiveChar().getActingPlayer(), stat);
      if (val > 0) {
        value = val;
      }
    }

    // Launch the calculation
    value = c.calc(_activeChar, target, skill, value);

    // avoid some troubles with negative stats (some stats should never be negative)
    if (value <= 0) {
      switch (stat) {
        case MAX_HP:
        case MAX_MP:
        case MAX_CP:
        case MAGIC_DEFENCE:
        case POWER_DEFENCE:
        case POWER_ATTACK:
        case MAGIC_ATTACK:
        case POWER_ATTACK_SPEED:
        case MAGIC_ATTACK_SPEED:
        case SHIELD_DEFENCE:
        case STAT_CON:
        case STAT_DEX:
        case STAT_INT:
        case STAT_MEN:
        case STAT_STR:
        case STAT_WIT:
        case STAT_LUC:
        case STAT_CHA:
          {
            value = 1.0;
            break;
          }
      }
    }
    return value;
  }

  /**
   * @return the Accuracy (base+modifier) of the L2Character in function of the Weapon Expertise
   *     Penalty.
   */
  public int getAccuracy() {
    return (int) Math.round(calcStat(Stats.ACCURACY_COMBAT, 0, null, null));
  }

  /** @return the Magic Accuracy (base+modifier) of the L2Character */
  public int getMagicAccuracy() {
    return (int) Math.round(calcStat(Stats.ACCURACY_MAGIC, 0, null, null));
  }

  public L2Character getActiveChar() {
    return _activeChar;
  }

  /**
   * @return the Attack Speed multiplier (base+modifier) of the L2Character to get proper
   *     animations.
   */
  public final float getAttackSpeedMultiplier() {
    return (float) (((1.1) * getPAtkSpd()) / _activeChar.getTemplate().getBasePAtkSpd());
  }

  /** @return the CON of the L2Character (base+modifier). */
  public final int getCON() {
    return (int) calcStat(Stats.STAT_CON, _activeChar.getTemplate().getBaseCON());
  }

  /**
   * @param target
   * @param init
   * @return the Critical Damage rate (base+modifier) of the L2Character.
   */
  public final double getCriticalDmg(L2Character target, double init) {
    return calcStat(Stats.CRITICAL_DAMAGE, init, target, null);
  }

  /**
   * @param target
   * @param skill
   * @return the Critical Hit rate (base+modifier) of the L2Character.
   */
  public int getCriticalHit(L2Character target, Skill skill) {
    double val =
        (int)
            calcStat(
                Stats.CRITICAL_RATE, _activeChar.getTemplate().getBaseCritRate(), target, skill);

    int maxCrit = (int) _activeChar.getStat().calcStat(Stats.MAX_PHYS_CRIT_RATE, 0, null, null);

    if (!_activeChar.canOverrideCond(PcCondOverride.MAX_STATS_VALUE)) {
      if (maxCrit > 0) {
        val = Math.min(val, (Config.MAX_PCRIT_RATE + maxCrit));
      } else {
        val = Math.min(val, Config.MAX_PCRIT_RATE);
      }
    }

    return (int) (val + .5);
  }

  /**
   * @param base
   * @return the Critical Hit Pos rate of the L2Character
   */
  public int getCriticalHitPos(int base) {
    return (int) calcStat(Stats.CRITICAL_RATE_POS, base);
  }

  /** @return the DEX of the L2Character (base+modifier). */
  public final int getDEX() {
    return (int) calcStat(Stats.STAT_DEX, _activeChar.getTemplate().getBaseDEX());
  }

  /**
   * @param target
   * @return the Attack Evasion rate (base+modifier) of the L2Character.
   */
  public int getEvasionRate(L2Character target) {
    int val = (int) Math.round(calcStat(Stats.EVASION_RATE, 0, target, null));

    if (!_activeChar.canOverrideCond(PcCondOverride.MAX_STATS_VALUE)) {
      val = Math.min(val, Config.MAX_EVASION);
    }

    return val;
  }

  /**
   * @param target
   * @return the Attack Evasion rate (base+modifier) of the L2Character.
   */
  public int getMagicEvasionRate(L2Character target) {
    int val = (int) Math.round(calcStat(Stats.MAGIC_EVASION_RATE, 0, target, null));

    if (!_activeChar.canOverrideCond(PcCondOverride.MAX_STATS_VALUE)) {
      val = Math.min(val, Config.MAX_EVASION);
    }

    return val;
  }

  public long getExp() {
    return _exp;
  }

  public void setExp(long value) {
    _exp = value;
  }

  /** @return the INT of the L2Character (base+modifier). */
  public int getINT() {
    return (int) calcStat(Stats.STAT_INT, _activeChar.getTemplate().getBaseINT());
  }

  public byte getLevel() {
    return _level;
  }

  public void setLevel(byte value) {
    _level = value;
  }

  /**
   * @param skill
   * @return the Magical Attack range (base+modifier) of the L2Character.
   */
  public final int getMagicalAttackRange(Skill skill) {
    if (skill != null) {
      return (int) calcStat(Stats.MAGIC_ATTACK_RANGE, skill.getCastRange(), null, skill);
    }

    return _activeChar.getTemplate().getBaseAttackRange();
  }

  public int getMaxCp() {
    return (int) calcStat(Stats.MAX_CP, _activeChar.getTemplate().getBaseCpMax());
  }

  public int getMaxRecoverableCp() {
    return (int) calcStat(Stats.MAX_RECOVERABLE_CP, getMaxCp());
  }

  public int getMaxHp() {
    return (int) calcStat(Stats.MAX_HP, _activeChar.getTemplate().getBaseHpMax());
  }

  public int getMaxRecoverableHp() {
    return (int) calcStat(Stats.MAX_RECOVERABLE_HP, getMaxHp());
  }

  public int getMaxMp() {
    return (int) calcStat(Stats.MAX_MP, _activeChar.getTemplate().getBaseMpMax());
  }

  public int getMaxRecoverableMp() {
    return (int) calcStat(Stats.MAX_RECOVERABLE_MP, getMaxMp());
  }

  /**
   * Return the MAtk (base+modifier) of the L2Character.<br>
   * <B><U>Example of use</U>: Calculate Magic damage
   *
   * @param target The L2Character targeted by the skill
   * @param skill The L2Skill used against the target
   * @return
   */
  public double getMAtk(L2Character target, Skill skill) {
    float bonusAtk = 1;
    if (Config.L2JMOD_CHAMPION_ENABLE && _activeChar.isChampion()) {
      bonusAtk = Config.L2JMOD_CHAMPION_ATK;
    }
    if (_activeChar.isRaid()) {
      bonusAtk *= Config.RAID_MATTACK_MULTIPLIER;
    }

    // Calculate modifiers Magic Attack
    return calcStat(
        Stats.MAGIC_ATTACK, _activeChar.getTemplate().getBaseMAtk() * bonusAtk, target, skill);
  }

  /**
   * @return the MAtk Speed (base+modifier) of the L2Character in function of the Armour Expertise
   *     Penalty.
   */
  public int getMAtkSpd() {
    float bonusSpdAtk = 1;
    if (Config.L2JMOD_CHAMPION_ENABLE && _activeChar.isChampion()) {
      bonusSpdAtk = Config.L2JMOD_CHAMPION_SPD_ATK;
    }

    double val =
        calcStat(
            Stats.MAGIC_ATTACK_SPEED, _activeChar.getTemplate().getBaseMAtkSpd() * bonusSpdAtk);

    if (!_activeChar.canOverrideCond(PcCondOverride.MAX_STATS_VALUE)) {
      val = Math.min(val, Config.MAX_MATK_SPEED);
    }

    return (int) val;
  }

  /**
   * @param target
   * @param skill
   * @return the Magic Critical Hit rate (base+modifier) of the L2Character.
   */
  public final int getMCriticalHit(L2Character target, Skill skill) {
    int val =
        (int)
            calcStat(
                Stats.MCRITICAL_RATE,
                getActiveChar().getTemplate().getBaseMCritRate(),
                target,
                skill);

    if (!_activeChar.canOverrideCond(PcCondOverride.MAX_STATS_VALUE)) {
      val = Math.min(val, Config.MAX_MCRIT_RATE);
    }

    return val;
  }

  /**
   * <B><U>Example of use </U>: Calculate Magic damage.
   *
   * @param target The L2Character targeted by the skill
   * @param skill The L2Skill used against the target
   * @return the MDef (base+modifier) of the L2Character against a skill in function of abnormal
   *     effects in progress.
   */
  public double getMDef(L2Character target, Skill skill) {
    // Get the base MDef of the L2Character
    double defence = _activeChar.getTemplate().getBaseMDef();

    // Calculate modifier for Raid Bosses
    if (_activeChar.isRaid()) {
      defence *= Config.RAID_MDEFENCE_MULTIPLIER;
    }

    // Calculate modifiers Magic Attack
    return calcStat(Stats.MAGIC_DEFENCE, defence, target, skill);
  }

  /** @return the MEN of the L2Character (base+modifier). */
  public final int getMEN() {
    return (int) calcStat(Stats.STAT_MEN, _activeChar.getTemplate().getBaseMEN());
  }

  public final int getLUC() {
    return (int) calcStat(Stats.STAT_LUC, _activeChar.getTemplate().getBaseLUC());
  }

  public final int getCHA() {
    return (int) calcStat(Stats.STAT_CHA, _activeChar.getTemplate().getBaseCHA());
  }

  public double getMovementSpeedMultiplier() {
    double baseSpeed;
    if (_activeChar.isInsideZone(ZoneId.WATER)) {
      baseSpeed =
          getBaseMoveSpeed(_activeChar.isRunning() ? MoveType.FAST_SWIM : MoveType.SLOW_SWIM);
    } else {
      baseSpeed = getBaseMoveSpeed(_activeChar.isRunning() ? MoveType.RUN : MoveType.WALK);
    }
    return getMoveSpeed() * (1. / baseSpeed);
  }

  /**
   * @return the RunSpeed (base+modifier) of the L2Character in function of the Armour Expertise
   *     Penalty.
   */
  public double getRunSpeed() {
    final double baseRunSpd =
        _activeChar.isInsideZone(ZoneId.WATER) ? getSwimRunSpeed() : getBaseMoveSpeed(MoveType.RUN);
    if (baseRunSpd <= 0) {
      return 0;
    }

    return calcStat(Stats.MOVE_SPEED, baseRunSpd, null, null);
  }

  /** @return the WalkSpeed (base+modifier) of the L2Character. */
  public double getWalkSpeed() {
    final double baseWalkSpd =
        _activeChar.isInsideZone(ZoneId.WATER)
            ? getSwimWalkSpeed()
            : getBaseMoveSpeed(MoveType.WALK);
    if (baseWalkSpd <= 0) {
      return 0;
    }

    return calcStat(Stats.MOVE_SPEED, baseWalkSpd);
  }

  /** @return the SwimRunSpeed (base+modifier) of the L2Character. */
  public double getSwimRunSpeed() {
    final double baseRunSpd = getBaseMoveSpeed(MoveType.FAST_SWIM);
    if (baseRunSpd <= 0) {
      return 0;
    }

    return calcStat(Stats.MOVE_SPEED, baseRunSpd, null, null);
  }

  /** @return the SwimWalkSpeed (base+modifier) of the L2Character. */
  public double getSwimWalkSpeed() {
    final double baseWalkSpd = getBaseMoveSpeed(MoveType.SLOW_SWIM);
    if (baseWalkSpd <= 0) {
      return 0;
    }

    return calcStat(Stats.MOVE_SPEED, baseWalkSpd);
  }

  /**
   * @param type movement type
   * @return the base move speed of given movement type.
   */
  public double getBaseMoveSpeed(MoveType type) {
    return _activeChar.getTemplate().getBaseMoveSpeed(type);
  }

  /**
   * @return the RunSpeed (base+modifier) or WalkSpeed (base+modifier) of the L2Character in
   *     function of the movement type.
   */
  public double getMoveSpeed() {
    if (_activeChar.isInsideZone(ZoneId.WATER)) {
      return _activeChar.isRunning() ? getSwimRunSpeed() : getSwimWalkSpeed();
    }
    return _activeChar.isRunning() ? getRunSpeed() : getWalkSpeed();
  }

  /**
   * @param skill
   * @return the MReuse rate (base+modifier) of the L2Character.
   */
  public final double getMReuseRate(Skill skill) {
    return calcStat(Stats.MAGIC_REUSE_RATE, 1, null, skill);
  }

  /**
   * @param target
   * @return the PAtk (base+modifier) of the L2Character.
   */
  public double getPAtk(L2Character target) {
    float bonusAtk = 1;
    if (Config.L2JMOD_CHAMPION_ENABLE && _activeChar.isChampion()) {
      bonusAtk = Config.L2JMOD_CHAMPION_ATK;
    }
    if (_activeChar.isRaid()) {
      bonusAtk *= Config.RAID_PATTACK_MULTIPLIER;
    }
    return calcStat(
        Stats.POWER_ATTACK, _activeChar.getTemplate().getBasePAtk() * bonusAtk, target, null);
  }

  /**
   * @return the PAtk Speed (base+modifier) of the L2Character in function of the Armour Expertise
   *     Penalty.
   */
  public double getPAtkSpd() {
    float bonusAtk = 1;
    if (Config.L2JMOD_CHAMPION_ENABLE && _activeChar.isChampion()) {
      bonusAtk = Config.L2JMOD_CHAMPION_SPD_ATK;
    }
    return Math.round(
        calcStat(
            Stats.POWER_ATTACK_SPEED,
            _activeChar.getTemplate().getBasePAtkSpd() * bonusAtk,
            null,
            null));
  }

  /**
   * @param target
   * @return the PDef (base+modifier) of the L2Character.
   */
  public double getPDef(L2Character target) {
    return calcStat(
        Stats.POWER_DEFENCE,
        (_activeChar.isRaid())
            ? _activeChar.getTemplate().getBasePDef() * Config.RAID_PDEFENCE_MULTIPLIER
            : _activeChar.getTemplate().getBasePDef(),
        target,
        null);
  }

  /** @return the Physical Attack range (base+modifier) of the L2Character. */
  public final int getPhysicalAttackRange() {
    final L2Weapon weapon = _activeChar.getActiveWeaponItem();
    int baseAttackRange;
    if (_activeChar.isTransformed() && _activeChar.isPlayer()) {
      baseAttackRange =
          _activeChar.getTransformation().getBaseAttackRange(_activeChar.getActingPlayer());
    } else if (weapon != null) {
      baseAttackRange = weapon.getBaseAttackRange();
    } else {
      baseAttackRange = _activeChar.getTemplate().getBaseAttackRange();
    }

    return (int) calcStat(Stats.POWER_ATTACK_RANGE, baseAttackRange, null, null);
  }

  public int getPhysicalAttackAngle() {
    final L2Weapon weapon = _activeChar.getActiveWeaponItem();
    final int baseAttackAngle;
    if (weapon != null) {
      baseAttackAngle = weapon.getBaseAttackAngle();
    } else {
      baseAttackAngle = 120;
    }
    return baseAttackAngle;
  }

  /**
   * @param target
   * @return the weapon reuse modifier.
   */
  public final double getWeaponReuseModifier(L2Character target) {
    return calcStat(Stats.ATK_REUSE, 1, target, null);
  }

  /** @return the ShieldDef rate (base+modifier) of the L2Character. */
  public final int getShldDef() {
    return (int) calcStat(Stats.SHIELD_DEFENCE, 0);
  }

  public long getSp() {
    return _sp;
  }

  public void setSp(long value) {
    _sp = value;
  }

  /** @return the STR of the L2Character (base+modifier). */
  public final int getSTR() {
    return (int) calcStat(Stats.STAT_STR, _activeChar.getTemplate().getBaseSTR());
  }

  /** @return the WIT of the L2Character (base+modifier). */
  public final int getWIT() {
    return (int) calcStat(Stats.STAT_WIT, _activeChar.getTemplate().getBaseWIT());
  }

  /**
   * @param skill
   * @return the mpConsume.
   */
  public final int getMpConsume(Skill skill) {
    if (skill == null) {
      return 1;
    }
    double mpConsume = skill.getMpConsume();
    double nextDanceMpCost = Math.ceil(skill.getMpConsume() / 2.);
    if (skill.isDance()) {
      if (Config.DANCE_CONSUME_ADDITIONAL_MP
          && (_activeChar != null)
          && (_activeChar.getDanceCount() > 0)) {
        mpConsume += _activeChar.getDanceCount() * nextDanceMpCost;
      }
    }

    mpConsume = calcStat(Stats.MP_CONSUME, mpConsume, null, skill);

    if (skill.isDance()) {
      return (int) calcStat(Stats.DANCE_MP_CONSUME_RATE, mpConsume);
    } else if (skill.isMagic()) {
      return (int) calcStat(Stats.MAGICAL_MP_CONSUME_RATE, mpConsume);
    } else {
      return (int) calcStat(Stats.PHYSICAL_MP_CONSUME_RATE, mpConsume);
    }
  }

  /**
   * @param skill
   * @return the mpInitialConsume.
   */
  public final int getMpInitialConsume(Skill skill) {
    if (skill == null) {
      return 1;
    }

    return (int) calcStat(Stats.MP_CONSUME, skill.getMpInitialConsume(), null, skill);
  }

  public byte getAttackElement() {
    L2ItemInstance weaponInstance = _activeChar.getActiveWeaponInstance();
    // 1st order - weapon element
    if ((weaponInstance != null) && (weaponInstance.getAttackElementType() >= 0)) {
      return weaponInstance.getAttackElementType();
    }

    // temp fix starts
    int tempVal = 0, stats[] = {0, 0, 0, 0, 0, 0};

    byte returnVal = -2;
    stats[0] = (int) calcStat(Stats.FIRE_POWER, _activeChar.getTemplate().getBaseFire());
    stats[1] = (int) calcStat(Stats.WATER_POWER, _activeChar.getTemplate().getBaseWater());
    stats[2] = (int) calcStat(Stats.WIND_POWER, _activeChar.getTemplate().getBaseWind());
    stats[3] = (int) calcStat(Stats.EARTH_POWER, _activeChar.getTemplate().getBaseEarth());
    stats[4] = (int) calcStat(Stats.HOLY_POWER, _activeChar.getTemplate().getBaseHoly());
    stats[5] = (int) calcStat(Stats.DARK_POWER, _activeChar.getTemplate().getBaseDark());

    for (byte x = 0; x < 6; x++) {
      if (stats[x] > tempVal) {
        returnVal = x;
        tempVal = stats[x];
      }
    }

    return returnVal;
    // temp fix ends

    /*
     * uncomment me once deadlocks in getAllEffects() fixed return _activeChar.getElementIdFromEffects();
     */
  }

  public int getAttackElementValue(byte attackAttribute) {
    double additionalPower =
        _activeChar.getStat().calcStat(Stats.WEAPON_ELEMENT_POWER, 0, null, null);
    switch (attackAttribute) {
      case Elementals.FIRE:
        return (int)
            (calcStat(Stats.FIRE_POWER, _activeChar.getTemplate().getBaseFire()) + additionalPower);
      case Elementals.WATER:
        return (int)
            (calcStat(Stats.WATER_POWER, _activeChar.getTemplate().getBaseWater())
                + additionalPower);
      case Elementals.WIND:
        return (int)
            (calcStat(Stats.WIND_POWER, _activeChar.getTemplate().getBaseWind()) + additionalPower);
      case Elementals.EARTH:
        return (int)
            (calcStat(Stats.EARTH_POWER, _activeChar.getTemplate().getBaseEarth())
                + additionalPower);
      case Elementals.HOLY:
        return (int)
            (calcStat(Stats.HOLY_POWER, _activeChar.getTemplate().getBaseHoly()) + additionalPower);
      case Elementals.DARK:
        return (int)
            (calcStat(Stats.DARK_POWER, _activeChar.getTemplate().getBaseDark()) + additionalPower);
      default:
        return 0;
    }
  }

  public int getDefenseElementValue(byte defenseAttribute) {
    switch (defenseAttribute) {
      case Elementals.FIRE:
        return (int) calcStat(Stats.FIRE_RES, _activeChar.getTemplate().getBaseFireRes());
      case Elementals.WATER:
        return (int) calcStat(Stats.WATER_RES, _activeChar.getTemplate().getBaseWaterRes());
      case Elementals.WIND:
        return (int) calcStat(Stats.WIND_RES, _activeChar.getTemplate().getBaseWindRes());
      case Elementals.EARTH:
        return (int) calcStat(Stats.EARTH_RES, _activeChar.getTemplate().getBaseEarthRes());
      case Elementals.HOLY:
        return (int) calcStat(Stats.HOLY_RES, _activeChar.getTemplate().getBaseHolyRes());
      case Elementals.DARK:
        return (int) calcStat(Stats.DARK_RES, _activeChar.getTemplate().getBaseDarkRes());
      default:
        return (int) _activeChar.getTemplate().getBaseElementRes();
    }
  }

  public float getAttackTrait(TraitType traitType) {
    return _attackTraits[traitType.getId()];
  }

  public float[] getAttackTraits() {
    return _attackTraits;
  }

  public boolean hasAttackTrait(TraitType traitType) {
    return _attackTraitsCount[traitType.getId()] > 0;
  }

  public int[] getAttackTraitsCount() {
    return _attackTraitsCount;
  }

  public float getDefenceTrait(TraitType traitType) {
    return _defenceTraits[traitType.getId()];
  }

  public float[] getDefenceTraits() {
    return _defenceTraits;
  }

  public boolean hasDefenceTrait(TraitType traitType) {
    return _defenceTraitsCount[traitType.getId()] > 0;
  }

  public int[] getDefenceTraitsCount() {
    return _defenceTraitsCount;
  }

  public boolean isTraitInvul(TraitType traitType) {
    return _traitsInvul[traitType.getId()] > 0;
  }

  public int[] getTraitsInvul() {
    return _traitsInvul;
  }

  /**
   * Gets the maximum buff count.
   *
   * @return the maximum buff count
   */
  public int getMaxBuffCount() {
    final int extraSlots = _activeChar.getSkillLevel(DIVINE_INSPIRATION);
    if (extraSlots > -1) {
      return _maxBuffCount + extraSlots;
    }
    return _maxBuffCount;
  }

  /**
   * Sets the maximum buff count.
   *
   * @param buffCount the buff count
   */
  public void setMaxBuffCount(int buffCount) {
    _maxBuffCount = buffCount;
  }
}