Battle System
The battle system is quite complex to allow almost any entity to get damaged in the game. Usually a battle context is established before damage calculation takes place and then used throughout the damage calculation. The attack outcome is then calculated with a strategy which is chosen depending on the type of attack used (melee, ranged or magic).
Attacks can also be defined by a script alone and thus sidestepping the damage calculation completly to do script controlled effects (e.g. reduce enemy health by 50%).
Attack Pre-Check
The stages of a battle are visualized in the following flow diagram, first a check is done to see if the attack actually was a hit.
graph TD step1(Attacker has Attack?) step1 -->|No| abort((Abort attack)) step1 -->|Yes| step2[Calculate mana cost] step2 --> step3(Has enough mana?) step3 -->|No| abort step3 --> |Yes| step4("Does attack need Line Of Sight (LOS)"?) step4 --> |No| step6(Is ammo needed and present?) step4 --> |Yes| step5[Calculate LOS and check if blocked] step5 --> |Blocked| abort step5 --> |Not blocked| step6 step6 --> |No| abort step6 --> |Yes| bla((Perform attack))
Damage Calculation
The damage calculation is roughly based on the system used by Ragnarök Online. In certain areas it is refined in order to better express the design philosophy of Bestia as well as be extensible. Modifier (MOD suffix) are float values representing percentage values (e.g. 0.25). Bonus mods are bigger than 1 (bonus 5% is 1.05) while reduction modifier are less than 1.
The damage at the end is rounded down but the damage is capped at 0. The calculation of the BASE_ATK is rather complex and is explained inside a own section. The parts written in pink are variables provided by bonuses from equips, stats, buffs etc.
val damage = floor(BASE_ATK * ATK_MOD * HARD_DEF_MOD * CRIT_MOD - SOFT_DEF)
Value: BASE_ATK
The base attack represents the attack strength of an entity. This attack strength is based on the status values important to perform the attack as well as the properties of the currently equipped weapon. Equipment might also alter the status values by which the base attack is indirectly influenced.
The base attack is capped at a minimum of 1. Default formula is:
val BASE_ATK = (2 * STATUS_ATK * VAR_MOD + WEAPON_ATK * VAR_MOD_RED + SKILL_ATK + BONUS_ATK + AMMO_ATK) * ELEMENT_MOD * ELEMENT_BONUS_MOD
Value: STATUS_ATK
The status attack value is determined by the capabilities of the character to attack and inflict damage. The formula is different for magic and physical based attacks.
For physical melee attacks:
val STATUS_ATK = LV / 4 + STR + DEX / 5
For physical ranged attacks:
val STATUS_ATK = LV / 4 + DEX + STR / 5
For magical attacks (both melee and ranged):
val STATUS_ATK = LV / 4 + INT + WILL / 5
Value: VAR_MOD
Is a variable status modifier. The variance is reduced as the DEX
value rises. It is defined as:
val VAR_MOD = 1 - RAND(1,0) * 0.15
Value: WEAPON_ATK
The weapon attack value for physical attacks is given by:
val WEAPON_ATK = (BASE_ATK * QUALY_MOD + REFINE_BONUS) * SIZE_MOD * RACE_MOD * WEAPON_BONUS_MOD
Where as the WEAPON_ATK
value for magical attacks is given by:
val WEAPON_ATK = (BASE_ATK * QUALY_MOD + REFINE_BONUS) * RACE_MOD
Value: QUALY_MOD
The QUALY_MOD is a modification depending of the durability of the weapon. The max quali damage mod should converge to +15% at maximum.
From this rating the mod damage is calculated as follow
val QUALI_MOD = if(DURABILITY > 30) {
1.15
} else {
1.15 - 0.15 + DURABILITY / 200
}
Value: SIZE_MOD
The attack is physically based.
Weapon size | Enemy size | Modifier |
Small | Small | 1.3 |
Medium | Small | 1 |
Big | Small | 0.75 |
Small | Medium | 1 |
Medium | Medium | 1.15 |
Big | Medium | 1 |
Small | Big | 0.70 |
Medium | Big | 1.1 |
Big | Big | 1.3 |
Value: VAR_MOD_RED
This is the reduced variance mod.
val VAR_MOD_RED = VAR_MOD - VAR_MOD / 2 + 1/2
Value: AMMO_ATK
If special ammunition is used this value is used. Only ranged physical attacks can make use of ammunition.
Value: BONUS_AMMO
This value is determined by the equipment and status effects applied to an entity.
Value: ATK_MOD
The ATK_MOD
is calculated depending which type the attack was. If it was a ranged physical attack, ranged magic attack or a melee physical or a melee magic based attack. The attack mod is capped to a minimum of 0.05.
If attack is physical melee:
val ATK_MOD = bonus_physical_melee
If attack is physical ranged:
val ATK_MOD = bonus_physical_ranged
If attack is magical melee:
val ATK_MOD = bonus_magical_melee
If attack is physical melee:
val ATK_MOD = bonus_physical_melee
Value: HARD_DEF
Hard defense represents mostly the damage reduction via armor and other natural defenses. It can of course modified by scripts. The hard defense is capped between 0 and 95%. Depending of the nature of the attack (physical or magical) either the normal armor or magic armor (magic resist) is used.
If normal attack (ranged or melee):
val HARD_DEF = 100 - (TOTAL_ARMOR_MOD + PHYSICAL_DEF_MOD) / 100
If magic attack (ranged or melee):
val HARD_DEF = 100 - (TOTAL_MAGIC_RESIST_MOD + MAGIC_DEF_MOD) / 100
Value: SOFT_DEF
Soft defense represents the natural defense of entities against damage of a specific domain. Soft def is a natural number and NO modifier. Its minimum value is capped to 0.
If attack is physical based (regardless if melee or ranged):
val SOFT_DEF = LV / 2 + VIT + STR / 3
If the attack is magic based (regardless if melee or ranged):
val SOFT_DEF= LV / 2 + VIT + WILL / 4 + INT / 5
Value: CRIT_MOD
The base crit mod is set so 1.4 (bonus of 40% damage) if a critical hit has occurred. The chance to land a critical hit is determined before the actual damage is calculated. If no critical hit has occurred the crit mod is hardcoded set to 1. Magic based attacks can not land a critical hit (they also are hitting a target easier).
The crit mod is capped at 1.
CRIT_MOD = BASE_CRIT_MOD * CRIT_DAMAGE_MOD
Damage Variables
Total damage calculation modifiers which are gathered from equipment and status effects. They are re-calculated upon change of the entities properties and then stored. The variables are feed into the attack scripts so their values can be accessed and altered via scripts on a per attack basis. These values are called damage variables.
Variable Name | Description |
---|---|
bonusAttackPhysicalMelee | Bonus damage on physical melee attacks. |
bonusAttackPhysicalRanged | Bonus damage on physical ranged attacks. |
bonusAttackMagicMelee | Bonus damage on magical melee attacks. |
bonusAttackMagicRanged | Bonus damage on magical ranged attacks. |
physicalDefMod | Bonus or reduction on armor. |
magicDefMod | Bonus or reduction on magic resist. |
criticalChanceMod | Bonus or Reduction to critical hit chance. |
criticalDamageMod | Bonus or reduction in critical damage. |