sub_8230D1F8 -- the loader that contaminated the AA_/AV_ offset search -- is the stage-settings loader. Reading its 122 field NAMES instead of its offsets found the scoring block, which nothing in docs/re owned. 24 IDXD objects per language pack x 6 = 144, each holding Score_Easy / Score_Normal / Score_Hard: 72 records per pack on one 22-field schema, no variants. Difficulty moves 10 of the 22 fields and never the five RankScore_* thresholds -- the rank bar is per stage, difficulty scales the earning rate (x0.5 / x1.0 / x2.0) and the penalties. 23 of 24 objects differ from the commonest Normal record; 9 of 72 records zero the scoring entirely. Not settled: which object is which stage. None of AUTO_SETTINGS's 28 filenames resolves to any of the 24 under 19 prefixes, and 24 vs 28 is unexplained. New doc structures/mission-scoring.md, regenerator mission_scoring.py, artefact data/mission-scoring.txt. Twelve artefacts now. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE
4.3 KiB
Mission scoring and the S/A/B/C/D rank thresholds
✅ Settled 2026-08-27 (static; regenerator
tools/re-capture/mission_scoring.py, artefact
data/mission-scoring.txt).
Found by following sub_8230D1F8 — the loader that the AA_/AV_ investigation
turned up as a contaminant, because it stores at the same object offsets the
unit definition uses. Reading its field names instead of its offsets identified
it as the stage-settings loader, and the scoring block is the part of it the
corpus did not have.
Docs checked: isl-condition-builtins.md owns AUTO_SETTINGS — the 28
stageNN_settings.tbl / tutorialNN / challengeNN filenames;
unit-datasheet-static.md and unit-struct-runtime.md own the per-unit
ScorePoint / DamageScore / MassScore fields. What none of them says is how
a mission score is assembled or what earns a rank — RankScore, TimeBonus,
KillBonus, FFPenalty, Difficulty_* appear nowhere in docs/re/.
The tables
24 IDXD objects per language pack × 6 packs = 144. Each holds exactly three
records — Score_Easy, Score_Normal, Score_Hard — so 72 scoring records
per pack, and they share one 22-field schema with no variants.
| group | fields |
|---|---|
| rank thresholds | RankScore_S _A _B _C _D |
| score multipliers | CraftScore_Adjustment, VesselScore_Adjustment, OtherScore_Adjustment |
| objective bonus | MainMissionCount, MainMissionBonus |
| time bonus | TimeBonus_Maximun (sic), TimeBonus_Basis_Minimum, TimeBonus_Basis_Maximum |
| kill / escort bonus | KillBonus_Maximum, FriendlyVesselDamageBonus, GettingScoreBasis_Minimum, GettingScoreBasis_Maximum |
| penalties | LostWingmanPenalty, FFPenalty_Craft_Basis, FFPenalty_Craft_Maximum, FFPenalty_Vessel_Basis, FFPenalty_Zessel_Maximum (sic — "Vessel") |
Two of the game's own misspellings are load-bearing as join keys:
TimeBonus_Maximun and FFPenalty_Zessel_Maximum.
✅ Difficulty changes the earning rate, not the bar
Comparing the three difficulty records inside each object, 10 of the 22 fields
move and 12 never do — and the ones that never move include all five
RankScore_* thresholds:
differ between Easy/Normal/Hard CraftScore_Adjustment 21 VesselScore_Adjustment 21
(count = objects out of 24) OtherScore_Adjustment 21 LostWingmanPenalty 21
FFPenalty_Craft_Maximum 21 FFPenalty_Zessel_Maximum 21
KillBonus_Maximum 18 MainMissionBonus 18
TimeBonus_Maximun 18 FriendlyVesselDamageBonus 13
never differ RankScore_S/A/B/C/D, MainMissionCount,
GettingScoreBasis_*, TimeBonus_Basis_*,
FFPenalty_*_Basis
So a rank bar is per stage, identical on every difficulty; what difficulty
changes is how fast you earn against it (×0.5 / ×1.0 / ×2.0 on the three
*Score_Adjustment multipliers) and how hard the penalties bite. That is a
design statement a port has to reproduce exactly, and it is measured, not read
off the names.
Per-stage variation
23 of the 24 objects differ from the commonest Score_Normal record, almost
always in the RankScore_* thresholds and the objective count/bonus — as
expected for per-mission tuning. Nine of the 72 records (three objects × three
difficulties) zero the multipliers, the penalties and TimeBonus_Maximun
outright: missions that are not scored. Full per-object diffs are in the
artefact.
❔ Which object is which stage
Not settled. AUTO_SETTINGS names 28 files (stage01…16, tutorial01…06,
challenge01…06, tags 1–16/18–23/24–29 — tag 17 absent, the cut S17), but
none of those 28 names resolves to any of the 24 objects under 19 prefixes
(bare, stage\, Stage\, message\, settings\, 2d\, ui\, system\,
dat\, prt\, view\, language\, eng\, script\, Script\, mission\,
Mission\, param\, Param\). So either the settings files are loaded outside
the pak namespace, or the scoring objects are keyed by something else entirely.
24 objects against 28 declared files is itself unexplained — do not assume
the missing four are the tutorials without checking.