Mise à jour 2.127
16/06/2026
updatemonster-ai
Cascade de Capture Cap-1 Phase C : écrivain `capturable` d'1 octet (`MonsterCaptureFlagWriter`) + porte `--monster-capture-bit-rt0` PASS 361/361 sur le corpus vanilla. Voie Jarvis-CAPCAS-WRITE. MINOR (nouvelle capacité : premier écrivain pour la fonctionnalité `Capture Cascade` / `Yoke of Spira` ; lib + porte, toujours PAS d'UI). Implémente la Phase C du plan Cap-1 (la Phase B `v2.123.3.1` a localisé l'octet ; la Phase C y écrit). Écrivain (`FFXProjectEditor/FfxLib/Monster/MonsterCaptureFlagWriter.cs`): au niveau octet (pas de round-trip complet de struct `Monster_File.Read(...).Write()`), opère directement sur `bytes[StatSheetPointer + 0x78]` avec `StatSheetPointer = uint32_le(bytes[0x0C])`. API : `TryGetStatSheetPointer`, `GetCaptureFlagFileOffset`, `ReadCaptureFlag`, `ReadPaddingByte`, `WriteCaptureFlag(monBin, newSlot)` (clone le tableau, retourne l'octet, garde le padding `0x00`, refuse les monstres avec padding non nul comme variante inconnue) ; helpers `IsUncapturable`/`IsVanillaArenaSlot`/`IsSidecarArenaSlot`. Constantes `Uncapturable = 0xFF`, `VanillaArenaSlotMin/Max = 0x00..0x67`, `SidecarArenaSlotMin/Max = 0x68..0xFE` (MA vanilla = 104 slots, sidecar = région Capture Cascade sans collision de bestiaire). Porte (`FFXProjectEditor/Tools/MonsterCaptureFlagRt0.cs`): invoquée via `FFXProjectEditor.exe --monster-capture-bit-rt0 [monsterRoot]`, prouve 3 propriétés par monstre : (1) identité d'octets même-valeur — `WriteCaptureFlag(bin, current)` == `bin` (l'écrivain est un no-op quand newSlot==current) ; (2) diff slot-only — `WriteCaptureFlag(bin, target)` diffère de `bin` en exactement 1 octet, à `[StatSheetPointer + 0x78]`, avec padding `0x00`, chaque autre octet byte-identique ; (3) RT0 flip-et-restore — `WriteCaptureFlag(WriteCaptureFlag(bin, target), original)` == `bin` (idempotence complète). La cible est choisie hors-bande par catégorie : uncap (0xFF) bascule vers 0x68 (sidecar), MA vanilla bascule vers 0xFF, etc. Résultat contre `FFX Extracted\...\jppc\battle\mon` (vanilla) : VERDICT PASS — 361/361 monstres, 251 uncap (0xFF), 110 slots MA vanilla, 0 sidecar, 0 padding non nul, parse d'en-tête 361/361, RT0 même-valeur 361/361, diff slot-only 361/361, RT0 flip-et-restore 361/361. Dépasse le corpus de preuves de la Phase B (58 échantillons) de 6×. Câblé dans `RuntimeTools/offline_ci.ps1` de `$editorGates` (entre `monster` et `encounter`) — porte interne permanente. Nouveaux fichiers : `FfxLib/Monster/MonsterCaptureFlagWriter.cs`, `Tools/MonsterCaptureFlagRt0.cs`. Touchés : `Program.cs` (câblé `--monster-capture-bit-rt0`), `RuntimeTools/offline_ci.ps1` (`$editorGates`). Ne touche pas : `m###.bin` (la porte est en lecture seule — ne lit que les fichiers vanilla, n'écrit jamais sur disque), DLL, runtime, sauvegarde, hook. Build C# Release PASS (0 erreurs, 384 avertissements de baseline). UI Phase C pas câblée dans cette livraison — toujours lib + porte, pas de bouton public. Prochaine étape sûre : Phase D (case `Capturable` UI dans `MonEditor` + écrivain en masse pour Dark Aeons + Penance) ou RT2 en jeu (Halyson édite 1 monstre jetable `0xFF→0x68` dans un vrai `m###.bin`, sauvegarde, lance le jeu, capture le monstre pour confirmer que le moteur accepte un slot hors de la plage vanilla 0x00..0x67). Doc : `docs/reverse/FFX_SPIRA_REFORGE_CAPTURE_BIT_M_HEADER_RE_RESULT_2026-06-16.md` §5.1.
Lire les notes