← All scenarios
PHYS-005autoAttack

DEF-ignore variants — full vs hard-only vs soft-only vs none

Same attacker, same high-DEF/high-soft-DEF defender. Four skills with different defIgnore configurations. Damage should clearly differ: full-ignore highest, then hard-only or soft-only depending on which dominates, then no-ignore lowest. Verifies that skill.defIgnore.{hard,soft} is wired through correctly.

physicalDamagedefIgnorehardDEFvsSoftDEF
Action
autoAttack
Auto-attack in expected mode
mode
expected
context.mapType
pvp

Actors

Knight
player · knight · Lv80
attacker
Primary stats
str
80
agi
30
vit
60
int
1
dex
40
luk
10
Equipment
  • mainhand: claymore · sword_2h · +7 · ATK 180
High-VIT tank (high soft DEF) wearing plate (high hard DEF)
player · Lv90
defender
Primary stats
str
30
agi
30
vit
99
int
30
dex
30
luk
30
demihumanneutral 1mediumnormal
HP 12000 / 12000
Hard DEF 80
Hard MDEF 30
Expected output
From the scenario fixture. Numerical values marked as null are placeholders pending rAthena verification.

Implementation note: this scenario is illustrative — 'normal attack' doesn't take a skillId, so the test runner needs to model each variant as a different action shape OR define fake test-only skills with the listed defIgnore configs. In practice, you'd use real RO skills with these properties (e.g., Asura ignores both, certain skills ignore hard only).

Show full expected JSON
{
  "propertyAssertions": [
    "damage(full ignore) > damage(hard only ignore)",
    "damage(full ignore) > damage(soft only ignore)",
    "damage(hard only ignore) > damage(no ignore)",
    "damage(soft only ignore) > damage(no ignore)",
    "(damage(full) - damage(none)) == (damage(full) - damage(hard)) + (damage(full) - damage(soft))",
    "// last assertion: ignoring both should equal sum of individual contributions in flat DEF model"
  ]
}

Computed: DamageResult

Server-evaluated by calculatePhysicalDamage() from @ro/core.

Outcome
hit
1 hit · 335 damage
335
Pipeline breakdown
D-003 steps 2–13
WeaponratioATK303
× size × skill303
× (1 + 0.0% ATK%)303
+ StatusATK (195)498
× 1.00 element498
× (1 + 0.0% race/elem/size/class)498
crit none498
− 0 hard DEF498
− 163 soft DEF335
× (1 − 0.0% taken%)335
+ MasteryATK (0)335
floor + min(1)335
Inputs
From attacker / defender ResolvedStats
StatusATK195
WeaponATK303
EquipATK0
MasteryATK0
Size mult1.00×
Element mult1.00×
Race%0.0%
Element%0.0%
Size%0.0%
Class%0.0%
Taken%0.0%

Hits (1): hit 335

Variant matrix · 4 cells

Each cell re-applies the variant's overrides to the base scenario and re-runs the same pipeline that produced the single result above.

skillId × defIgnore
Highest in row is highlighted emerald; lowest rose. Hover any cell to see the full variant label.
skillId \ defIgnore[object Object][object Object][object Object][object Object]
_normal335
_hardOnly335
_softOnly335
_full335
Property assertions
Pattern-matched checks from the scenario's expected. ⊙ marks assertions the parser doesn't recognize (the raw string is shown so devs can verify by eye).
  • damage(full ignore) > damage(hard only ignore)
  • damage(full ignore) > damage(soft only ignore)
  • damage(hard only ignore) > damage(no ignore)
  • damage(soft only ignore) > damage(no ignore)
  • (damage(full) - damage(none)) == (damage(full) - damage(hard)) + (damage(full) - damage(soft))
  • // last assertion: ignoring both should equal sum of individual contributions in flat DEF model