Skip to content

Skills with a CELL pattern hit their pattern, not a single target - #2289

Open
denislauri1999 wants to merge 3 commits into
NosCoreIO:masterfrom
denislauri1999:pr/skill-cell-patterns
Open

Skills with a CELL pattern hit their pattern, not a single target#2289
denislauri1999 wants to merge 3 commits into
NosCoreIO:masterfrom
denislauri1999:pr/skill-cell-patterns

Conversation

@denislauri1999

@denislauri1999 denislauri1999 commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Sixty-eight skills in Skill.dat carry a CELL section: an explicit list of the cells they hit, relative to the caster and drawn facing north. Sixty-seven of them are declared as area (HitType 3) with an area radius of ZERO — because the area is the pattern, not the radius.

TargetResolver only read the radius, so all sixty-seven hit a single target. No exception, no log, just less damage than the file says:

skill what the file draws what it did
244 Piercing Shot a row of eight cells in front — an arrow that pierces hit one
367 Fire Breath a rectangle of thirty hit one

The rotation

The pattern is authored facing north and cast towards the target, so it is rotated by the angle between the two rather than snapped to eight directions. On the four cardinals the result is exact (sine and cosine are 0 or ±1); on the diagonals it is the nearest approximation.

An approximation worth stating, since it is visible in play: rotating by an arbitrary angle and rounding can turn a row one cell wide into a staircase with the odd gap at its side, and somebody half a cell off the line can slip through. On the cardinals — the overwhelming majority of casts, since the caster lines up with the target — it does not arise.

The table

Generated from the client’s Skill.dat and checked in rather than put in a column: it is static client data, identical for every server, and it reads straight out of the file that ships with the game. 68 skills, 1002 cells.

Tests

Eight, with the expected numbers taken from the file rather than from another implementation: the two example patterns, the four cardinals, a diagonal, and the two cases that fail in silence — a skill with no pattern, and caster and target on the same cell (where normalising divides by zero, every cell becomes NaN and then zero, and the whole pattern stacks on the caster without a word).

Zero warnings, all tests pass. This is the first slice of the BCard/combat work from the roadmap’s W 1.0.7 — the rest is larger and will come separately so each piece stays reviewable.

Summary by CodeRabbit

  • New Features

    • Added support for skill-specific area-of-effect patterns, including directional and irregular layouts.
    • Skill patterns now rotate toward the selected target and resolve affected battlefield cells accurately.
    • Skills without defined patterns continue using standard range-based targeting.
  • Bug Fixes

    • Improved monster and player targeting for patterned area-of-effect skills.
  • Tests

    • Added coverage for directional, diagonal, boundary, duplicate-cell, and zero-distance targeting scenarios.

…arget

Sixty-eight skills in Skill.dat carry a CELL section: an explicit list of the
cells they hit, relative to the caster and drawn facing north. Sixty-seven of
them are declared as area (HitType 3) with an area RADIUS OF ZERO, because the
area is the pattern and not the radius.

TargetResolver only read the radius, so all sixty-seven hit a single target. No
exception, no log - just less damage than the file says, on skills like the
archer's 244 "Piercing Shot" (a row of eight cells, an arrow that pierces) and
367 "Fire Breath" (a rectangle of thirty).

The pattern is authored facing north and cast towards the target, so it is
rotated by the angle between the two rather than snapped to eight directions:
on the four cardinals the result is exact (sine and cosine are 0 or +-1), on
the diagonals it is the nearest approximation.

An approximation worth stating, since it is visible in play: rotating by an
arbitrary angle and rounding can turn a row one cell wide into a staircase with
the odd gap at its side, and somebody half a cell off the line can slip
through. On the cardinals - the overwhelming majority of casts, since the
caster lines up with the target - it does not arise.

The table is generated from the client's Skill.dat and checked in rather than
put in a column: it is static client data, the same for every server, and it
reads straight out of the file that ships with the game.

Eight tests, from the file rather than from another implementation: the two
example patterns, the four cardinals, a diagonal, and the two cases that fail
in silence - a skill with no pattern, and caster and target on the same cell
(where normalising divides by zero, every cell becomes NaN and then zero, and
the whole pattern stacks on the caster without a word).

Zero warnings, all tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 23, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 0c16fff4-7f14-4b3e-b8c9-3dea004f4de5

📥 Commits

Reviewing files that changed from the base of the PR and between 55dc38c and 73f2f67.

📒 Files selected for processing (4)
  • src/NosCore.GameObject/Services/BattleService/SkillCellTable.g.cs
  • src/NosCore.GameObject/Services/BattleService/SkillCells.cs
  • src/NosCore.GameObject/Services/BattleService/TargetResolver.cs
  • test/NosCore.GameObject.Tests/Services/BattleService/SkillCellsTests.cs

Included review availability: Your plan provides up to 2 included reviews per hour; 1 remains after this review.


Walkthrough

The change adds generated skill cell patterns, resolves relative coordinates toward a target, and applies exact pattern membership during area target selection. Skills without patterns retain rectangular range checks. Tests cover geometry, direction, boundaries, and missing patterns.

Changes

Skill cell targeting

Layer / File(s) Summary
Skill pattern catalog
src/NosCore.GameObject/Services/BattleService/SkillCellTable.g.cs
Adds the generated SkillCellTable with coordinate patterns keyed by skill ID.
Pattern coordinate resolution
src/NosCore.GameObject/Services/BattleService/SkillCells.cs
Adds pattern lookup, availability checks, and target-oriented coordinate resolution.
Pattern-aware target selection
src/NosCore.GameObject/Services/BattleService/TargetResolver.cs, test/NosCore.GameObject.Tests/Services/BattleService/SkillCellsTests.cs
Uses pattern membership for monsters and players, falls back to IsHit range checks when no pattern exists, and tests geometry and edge cases.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Merge Risk: ⚪ Minimal · up to 73f2f

The PR enables skills with authored cell patterns to affect their intended areas rather than a single target, with focused tests covering the documented cases; no actionable merge-blocking risk remains beyond normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant TargetResolver
  participant SkillCells
  participant SkillCellTable
  participant BattlefieldTargets
  TargetResolver->>SkillCells: resolve skill pattern toward primary target
  SkillCells->>SkillCellTable: look up skill ID
  SkillCellTable-->>SkillCells: return relative coordinate pairs
  SkillCells-->>TargetResolver: return absolute battlefield cells
  TargetResolver->>BattlefieldTargets: test target positions with IsHit
  BattlefieldTargets-->>TargetResolver: include matching monsters and players
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: CELL-pattern skills now hit their defined patterns instead of only one target.
Docstring Coverage ✅ Passed Docstring check was indeterminate for this PR — some files could not be analyzed in time. Not blocking.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

denislauri1999 and others added 2 commits August 24, 2026 00:11
62 comment lines down to 35, and the long ones down to a line or two. What is
left is what a reader would otherwise get wrong: the radius being zero because
the area is the pattern, the authored basis, and the zero-distance guard.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The CELL section holds two header fields plus thirty triplets (dx, dy, continues) and stops -
there is no room for a thirty-first. Patterns that need more continue in the unused tail of
COST, whose thirty-three fields are three real ones (CP, price, and a third nothing reads)
followed by ten more triplets in the same format.

Ten skills use it, and the table clipped every one of them at thirty. Fireblast lost the last
six squares of one column of its 3x12 rectangle; Armour Piercing Round lost the tip of its
beam. Nothing raised and nothing logged - they simply covered less ground than the client
draws.

How the continuation was established, since a wrong reading here is silent:

  - the tail is non-zero only on the skills whose CELL is full;
  - it holds triplets in the same format and orientation;
  - it never repeats a cell CELL already gave, across all ten;
  - Fireblast and Dragon's Breath close into exact full rectangles - 3x12 and 3x13 - and the
    cells the tail supplies are precisely the corner that was missing.

The eleventh skill that fills CELL, Reaper's Scythe, has an empty tail and a closed thirty-cell
figure: a "continues" flag on the last triplet CELL can hold does not mean there is more, it
means you cannot tell from there. So the tail is read rather than assumed, and there is a test
pinning Reaper's Scythe at thirty - it is the skill that assuming would give cells it has not
got.

Fireblast 36, Ice Chain 39, Dragon's Breath 39, Armour Piercing Round 40, Triple Bolt 37,
Triple Arrow and Lucky Wideshot 32, and three more at 34 to 39. Sixty-seven cells in all.

The test that asserted thirty for Fireblast asserted the old reading, so it now asserts the
rectangle instead, and two guards join it: no pattern lists a cell twice, and none exceeds what
the two sections can hold.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant