Skip to content

Harden Papyrus marshaling boundary and add per-hit diagnostics - #2

Open
kotarf wants to merge 1 commit into
masterfrom
claude/skyrim-targeting-accuracy-issue-l5tti0
Open

Harden Papyrus marshaling boundary and add per-hit diagnostics#2
kotarf wants to merge 1 commit into
masterfrom
claude/skyrim-targeting-accuracy-issue-l5tti0

Conversation

@kotarf

@kotarf kotarf commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Summary

Investigation into hit zones being misclassified in Special Edition (usually as limbs). The zone math itself is unchanged; this PR hardens the Papyrus-to-native boundary and adds diagnostics so real in-game inputs can be captured.

Classification is byte-for-byte identical to the previous code, verified against the original math over a scenario sweep and 2000 fuzzed inputs.

Changes

  • Array-length validation in GetHitZone. CommonLibSSE turns a None or short Papyrus array into an empty/short std::vector; the previous d[5], p[4], s[5] reads were undefined behaviour in that case. Now logs an error and returns 0.
  • Per-hit trace line. All pitch thresholds and lateral ranges are computed up front, then one trace line is emitted with every input and every threshold. Zone thresholds are independent of one another, so this refactor does not change any result.
  • Warnings for degenerate inputs. dist not positive, or asin() producing NaN (dispWidth / dx outside [-1, 1]). NaN ranges previously fell through to chest/back silently.
  • std::fabs instead of unqualified abs on floats. MSVC's ucrt resolves the float overload so the shipped build was fine, but a conforming libstdc++ picks abs(int) and truncates.
  • ArmHitCalcSKSE takes float armRange, matching the LDHitZones.psc declaration and the original SKSE64 registration.
  • Header now includes <cstdint> and SKSE/SKSE.h so it stands alone without the PCH.

Findings (not changed in this PR)

  • The Papyrus script passes dx = xPos - xPosMe (signed world X delta) while the plugin uses it as the denominator in asin(dispWidth / dx). This makes the arm/shoulder tolerance depend on the compass direction of the attack: along world X the tolerance is ~1.5° to 3° (torso hits become arms/shoulders), along world Y it is NaN (hits become chest). Using p.dist instead would make it geometric. Left as-is pending review since it alters classification.
  • CommonLibSSE marshaling was verified against source: std::vector<float> / std::vector<uint32_t> deduce the same Papyrus signature the SKSE64 build registered, so no marshaling bug was found.

Testing

  • Syntax-checked with GCC against stub headers (CommonLibSSE is Windows-only, so no MSVC build was run here). Please confirm the MSVC build.
  • Equivalence test: refactored hitDetection vs. original math, identical on all scenarios and 2000 fuzz cases.
  • Note: plugin.cpp sets flush_on(trace), so the new per-hit trace line flushes to disk on every hit. Fine for debugging; worth lowering before release.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VxJjofpgPX8JaNDtgDcZ28


Generated by Claude Code

Hit-zone classification is unchanged (verified bit-for-bit against the
previous math over a scenario sweep and 2000 fuzzed inputs). Changes:

- GetHitZone validates array lengths before indexing. CommonLibSSE turns
  a None or short Papyrus array into an empty/short std::vector, and the
  old d[5]/p[4]/s[5] reads were undefined behaviour in that case. Now logs
  an error and returns 0.
- Compute all pitch thresholds and lateral ranges up front, then emit one
  trace line per hit with every input and threshold so real in-game values
  can be captured when debugging misclassified hits.
- Warn when dist is not positive or when asin() produces NaN (dispWidth/dx
  outside [-1,1]); NaN ranges silently fall through to chest/back.
- Use std::fabs instead of unqualified abs on floats. MSVC's ucrt resolves
  abs(float) to the float overload, but a conforming libstdc++ picks
  abs(int) and truncates.
- ArmHitCalcSKSE takes float armRange (matches Papyrus Float and the
  original registration), add <cstdint>, include SKSE/SKSE.h for logging.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VxJjofpgPX8JaNDtgDcZ28
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.

2 participants