# Attributes

All heroes share the same six base attributes but have different minimum and maximum limits based on their classes and different primary and secondary stats.

All classes will share the same attribute rarity system, where heroes whose total attributes add up to 0 \~ 299 will be common, 300 \~ 375 will be epic, and 376+ will be legendary.

| Class        | Primary Stat | Secondary Stat |
| ------------ | ------------ | -------------- |
| Warrior      | Strength     | Vitality       |
| Assassin     | Agility      | Strength       |
| Mage         | Intelligence | Will           |
| Ranger       | Strength     | Agility        |
| Berserker    | Vitality     | Endurance      |
| Ninja        | Agility      | Vitality       |
| Spiritualist | Intelligence | Endurance      |
| Machinist    | Intelligence | Agility        |

### Strength

Strength affects the hero's physical damage dealt through attacks and skills in combat.

### Agility

Agility affects the hero's turn order and critical rate % in combat.

### Vitality

Vitality affects the hero's maximum HP in combat.

### Endurance

Endurance affects the hero's physical defense in combat.

### Intelligence

Intelligence affects the hero's magical damage dealt through attacks and skills in combat.

### Will

Will affects the hero's magical defense in combat.

## Combat Attributes

This section contains our formulas for calculating your heroes' combat attributes.

{% hint style="info" %}
Level 1-10 has only 9 levels while every other tier has 10. To maintain the same combat stats as before, **heroes under level 10 will have a 1-level penalty when applying the formula.**
{% endhint %}

### Health Points (HP)

```javascript
  // Get the raw max HP based on all sources of VIT.
  const rawMaxHp = 5 * VIT * (1.5 + (LEVEL / 100) * 15);
  // Get the raw equipment boosts ('HP %', 'HP')
  const rawEquipmentHpBoost = ((rawMaxHp / 100) * HP% + HP); 
  // Get the total equipment boosts ('Equipment HP% Bonus')
  const totalEquipmentHpBoost = (rawEquipmentHpBoost / 100) * (100 + EQP.HP%);
  // Get the total HP (including combat boosts)
  const baseMaxHp = Math.round((rawMaxHp + totalEquipmentHpBoost) * BOOSTS.HP%);
```

The hero's HP resets for every quest. You lose when your HP reaches 0.

### Attack (P.ATK / M.ATK)

```javascript
  // Get the raw magic attack based on all sources of INT.
  const baseMagicAttack = intelligence * (1.5 + (combatStatLevel / 100) * 15);
  // Get the total M. ATK after applying raw and total equipment boosts.
  const magicAttack = Math.round(
      baseMagicAttack +
        (((baseMagicAttack / 100) * M.ATK% +
          M.ATK) /
          100) *
          (100 + EQP.ATK%)
    );

  // Same for physicalAttack. Replace M.ATK with P.ATK.
```

Basic attacks will deal damage based on your class's attribute.

STR is used for Physical Attack, INT is used for Magic Attack.

### Physical Defense/Magic Resistance (DEF/RES)

<pre class="language-javascript"><code class="lang-javascript"><strong>  // Get the raw defense based on all sources of END
</strong>  const baseDefense = END * (1.5 + (LEVEL / 100) * 15);
  // Get the total DEF after raw/total equipment and combat boosts.
  // The flow is the same as in the HP formula, just substitute the values.
  const defense = Math.round(
      (baseDefense +
        (((baseDefense / 100) * DEF% + DEF) / 100) *
          (100 + EQP.DEF%)) *
        BOOSTS.DEF%
      );

</code></pre>

DEF reduces the amount of physical damage received.

RES reduces the amount of magic damage received.

### Other Formulas

{% hint style="warning" %}
The provided formulas below is pseudo-code for players to be able to follow the logic for analytics/calculations.

DISCLAIMER: Correct as of 29th November 2023, all subject to change.
{% endhint %}

**Skill Damage (userSkillDamage%)**

```javascript
const userSkillDamage% = roundToTwo(
      0 +
        (SKILLDMG% / 100) *
        (100 + EQP.SKILLDMG%)
    );
```

{% tabs %}
{% tab title="Critical Rate Formula" %}

```javascript
// Crit Rate
const a = 6.26415119;
const b = 46.6345086;
const c = 0.58114342;
const d = 0.16064906;
const e = 86.56111256;

const critRate = a + b / (c + Math.exp(-d * (agi - e)));
```

{% hint style="info" %}
Critical Damage/Resistance is applied after Final Attack!\
See Base Damage Formula for where exactly it's applied.
{% endhint %}
{% endtab %}

{% tab title="Full Damage Logic" %}

```javascript
  // Return without deducting SP if dazed.
 
  // Deduct SP cost of skill if necessary.

  // If the skill can be shut down and the corresponding shutdown
  // type matching the skill type is in effect, return.

  // Start with our attack stat calculated from the hero + eqp + boosts.
  const baseAttack = userPhysicalAttack || userMagicAttack;

  // Roll for accuracy.
  const accuracyRoll = RandomBetween(0, 100);

  // Check for accuracy. The attack misses if:
  // The user has no 'lock on' effect
  // and skill is not guaranteed to hit
  // and accuracyRoll > skillAccuracy%
  
  // Check for crit. hasCritOnEffect is a status effect belonging to the user..
  const critRoll = RandomBetween(0, 100);
  const isCrit = hasCritOnEffect || critRoll < userCriticalRate;
  
  // Track the actual damage dealt for recoil.
  let actualDealtDamage = 0;

  // For all targets... (including self if applicable, such as in status effect)
  for (allTargets) {

    // Check for requirements.
    // etc. Check for requireBleed. Fail if target is not bleeding. 
    // etc. Check for requirePoison. Fail if target is not poisoned. 
    // etc. Check for requireDebuff. Fail if target is not debuffed.
    
    // Calculated Defense = DEF/RES (based on skillProperty) * F.DEF%.
    const calcDefense = 
      (targetDefense || targetResistance) / 100) *
      (100 + targetFinalDefense%);

    // Calculate total attack stat. getBaseAttack is used on skills with custom damage logic and overrides the attack stat
    // etc. Berserk (based on HP%), Devour (*2), StatusEffects-only skills (0)
    const calcAttack =
      ((isFunction(skill.getBaseAttack)
        ? skill.getBaseAttack()
        : baseAttack) /
        100) *
      (100 + userFinalAttack%);

    // Apply defense reduction to attack stat.
    const initialDamage = 
      (calcAttack * RandomBetween(70, 130)) /
      (calcDefense + 100);

    // If this is a healing skill, apply heal instead and return.
    if (isHealingSkill) {
      // Calculate HP to recover/necro.
      const extraHpToRecover = (initialDamage / 100) * targetLifeGain%;
      const hpToRecover = initialDamage + extraHpToRecover;
 
      // If target is necro-ed, this will deal damage instead of heal.
      return;
    }

    const extraSkillDamage = isSkill
        ? (initialDamage / 100) * Math.max(0, userSkillDamage%)
        : 0;

    // Calculate extra revenge damage (30% damage increase if user below X% HP)
    const userHpPerc = userHp / userMaxHp * 100;
    const extraRevengeDamage =
      userHpPerc < userRevengeThreshold% ? initialDamage * 0.3 : 0;

    // Calculate skill damage reduction if skill.
    const skillDefendedDamage = isSkill 
       ? Math.max(
            0,
            ((initialDamage + extraSkillDamage + extraRevengeDamage) / 100) * targetSkillDefense%
          )
        : 0;

    // Finally, we get the hit damage. Return if this is <= 0.
    const baseHitDamage =
      initialDamage + extraSkillDamage + extraRevengeDamage - skillDefendedDamage;

    // Check for dodge
    const dodgeRoll = RandomBetween(0, 100);
    
    // Check for target dodge. The attack is dodged if:
    // The user has no 'lock on' effect
    // and skill is not guaranteed to hit
    // and dodgeRoll < targetDodgeRate%
    
    // If target has protect status and skill can be protected against,
    // Negate damage and return.

    // Check for effects to apply on hit damage.
    // Check for Lethal (+X% damage increase if target HP below 50%).
    const targetHpPerc = target.hp / target.maxHp;
    const extraLethalDamage =
      targetHpPerc < 0.5 ? (baseHitDamage / 100) * userLethal% : 0;

    // Calculate base damage after hit effects.
    const baseDamage = Math.round(baseHitDamage + extraLethalDamage);

    // Calculate critical damage bonus.
    const rawCrit = (baseHitDamage / 100) * Math.max(0, userCriticalDamage%);
    const rawCritRes = 100 - Math.min(100, targetCriticalResistance%);
    const criticalDamage = isCrit ? (rawCrit / 100) * rawCritRes : 0;

    // Get damage factoring armor.
    const damageToReceive = baseDamage + criticalDamage - targetFlatDamageReduce;

    // Apply modifiers to the damage itself, and generates status efects.
    // etc. Aimed Shot, Convert X% HP into damage, attack for min. % HP
    const { statusEffects, correctedDamage } =
      getFunctionCodeResponse[skill.functionCode]({...});
    

    if (correctedDamage > 0) {
      const roundedDamage = Math.round(correctedDamage);
      // Track the actual dealt damage.
      actualDealtDamage += roundedDamage;
     
      // Apply Damage Reflect
      if (targetReflectHitRate% > 0) {
        const reflectedDamage = Math.round((correctedDamage / 100) * targetReflectHitRate%);    
      }

      // Apply Life Drain
      if (userLifeDrainRate% > 0) {
        const drainDamage = Math.round(
          (correctedDamage / 100) * userLifeDrainRate%
        );
      }

      // Apply Backlash Damage
      if (userBacklashRate% > 0) {
        const backlashDamage = Math.round(
          (correctedDamage / 100) * userBacklashRate
        );
      }
    }
  }

  // Handle Effects here.

  // Handle Recoil.
  if (skillHasRecoil) {
    const recoilDamage = Math.round(actualDealtDamage * skillRecoil%);
    if (recoilDamage > 0) {
      // Apply Recoil Damage.
  }
  
  // END, continue to next user.
```

{% endtab %}
{% endtabs %}

## Attributes and Effects Glossary

Accuracy - % Chance for an attack/skill to succeed.&#x20;

Critical Hit - Roll for critical hit based on Critical Rate % (unless the skill has special conditions). Deal additional damage based on Critical Damage %, reduced by the target's Critical Resistance %.

Require Bleed/Poison/Debuff/etc... - Attack/Skill will fail if target is not bleeding/poisoned/debuffed/etc...

Final Defense - A bonus applied on top of base Defense/Resistance depending on the incoming attack/skill type.

Final Attack - A bonus applied on top of the attack/skill base attack calculated

Necro - All sources of healing effects will deal damage instead

Skill Damage - Skills will deal an additional % damage. For players, skills are everything other than 'Attack'. For monsters, skills are everything except the monster's basic attack (which can have varying names and effects)

Revenge - Deal an extra fixed 30% damage if the user is below a % HP depending on the revenge threshold.

Skill Defense - Receive a % damage reduction against an incoming skill (revenge damage included). (Already applied DoTs do not count)

Dodge - % to avoid an attack/skill if the skill is not guaranteed to hit.

Protect - Negates all damage by an incoming attack/skill within the same turn.&#x20;

Lethal - Deal extra % damage based on user's lethal threshold if target HP is below 50%.

Armor (flat damage reduce) - Reduces a FLAT amount of damage after all other effects are calculated.

Damage Reflect - User reflects % of true direct damage received to the attack/skill's user.

Life Drain - User drains % of true direct damage received. (affected by Necro)

Backlash - User receives a % of direct damage dealt as recoil.

Recoil Damage - User receives fixed damage based on a % of damage dealt.

{% hint style="info" %}
The glossary is accurate as of v1.106.6 and may be changed further down as skills are implemented and balanced.
{% endhint %}
