feat(runtime): initialize per-clan AI record slots
Docs Deploy / Build and Deploy MkDocs (push) Successful in 1m17s

This commit is contained in:
Valentin Popov committed 2026-10-31 11:26:32 +04:00
1 parent 8c403ab4f7
commit 0b2184429f
3 files changed
+489 -1

No files matched your search

+33
View File
@@ -195,6 +195,39 @@ Rust исполняет подтверждённый поднабор перво
### Первый запуск сценария
Перед настройкой первого шага каждый AI получает начальный массив DWORD. В
`iron3d.dll` SHA-256
`d1dc4ea8535e2069b0a05c9e8be2724dd438ba44cca7a83007d8b2e50f9e35fa`
`FUN_100392e0` (RVA `0x392e0`) повторяет вызов слота AI `+0x38` столько раз,
сколько задаёт `second_resource.tag` этой строки TMA. Этот слот ведёт в
`ai.dll` SHA-256
`c19cd6cd31cd2896f8c4ba0f0e700dd3408aec8182daaf4863d98a7d233a2abc`:
метод RVA `0x2010` передаёт коллекцию при `AI+0x83c` в `FUN_10002980`
(RVA `0x2980`), а она добавляет один DWORD через `FUN_100048f0` (RVA
`0x48f0`). Каждый вызов копирует `0xffffffff`; входное слово не меняется.
Поэтому тег `3` даёт `[0xffffffff, 0xffffffff, 0xffffffff]`. Это число
начальных ячеек, а не назначение трёх ID.
Изолированная x86-проверка вызовом оригинальной `ai.dll` подтвердила пары
«число слотов/ёмкость» `0/0`, `1/17`, `17/17` и `18/34`. Все добавленные слова
равны `0xffffffff`, а входное значение, контрольные поля, память вне заголовка
массива и указатель стека сохраняются. Это подтверждает добавление начального
слова, но не работу последующих обработчиков.
Rust хранит такой снимок в отдельном `MissionAiStartupState` для каждого TMA-клана,
а не в пакете сценария. При полной загрузке (`Full`) создаётся запись для каждого
клана, в том числе если у него нет пути сценария или пути таблицы исследований. Счётчик
берётся из сырых битов `second_resource.tag` как `u32` у обеих форм записи —
`Standard` и `Spatial`; нулевой счётчик даёт существующее состояние с пустым
списком. Статический режим предпросмотра не создаёт состояний AI.
Загрузка отклоняет суммарный объём свыше 1 000 000 DWORD и резервирует память
проверяемой операцией; это защита Rust от чрезмерного выделения памяти, а не
ограничение оригинальной игры. Rust сохраняет начальные слова, но не
восстанавливает работу последующих обработчиков и не назначает этим словам ID
объектов. Этот массив также не является списком
`BehaviorDistributorState.registered_objects`.
До регулярной работы Behavior настраивает расписание своего первого шага. Он
берёт текущее 32-битное время игровой очереди и назначает проверку через три
интервала по 64 мс, добавляя небольшую случайную задержку от 0 до 63 мс. Эта