re: mission scoring and the S/A/B/C/D rank thresholds
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
This commit is contained in:
80
docs/re/structures/mission-scoring.md
Normal file
80
docs/re/structures/mission-scoring.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# 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`](../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.
|
||||
Reference in New Issue
Block a user