docs(runtime): correct Control and collision interface contracts
Docs Deploy / Build and Deploy MkDocs (push) Successful in 41s

This commit is contained in:
Valentin Popov committed 2026-10-31 13:59:28 +04:00
1 parent a9f84d4be0
commit 5adefa6714
2 files changed
+47 -17

No files matched your search

+34 -7
View File
@@ -1410,18 +1410,36 @@ payload. Позже та же функция `World3D+0x7cb0` повторяет
времени из `DATWorld+0x32a38` (`0x7e6e`); `World3D+0x7ea0` передаёт туда же
время в `0x80a9`. Setter `World3D+0x5140` записывает входной DWORD в эту ячейку.
Нулевой вызов связывает интерфейсы, а ненулевой `NumericTime` запускает отдельную
ветвь активации. Конструктор AniMesh задаёт `+0x158/+0x15c/+0x160` равными `1.0`.
Обработчик модели `0x75b0/0x6fc0` привязывает интерфейсы и матрицу, Effect RVA
`0x3d30` и Control RVA `0x1ce00` сохраняют host/service указатели, а Control
`0x1fe00` меняет только локальный collision-флаг. Эти ветви не вызывают AniMesh
scale setter `0x14770` и не пишут поля масштаба. При загрузке AniMesh получает
Control secondary owner с QI selector `0xa` и сохраняет возвращённый base owner
ветвь активации. Модель занимает отдельный объект в памяти: её конструктор
AniMesh RVA `0x68a0` задаёт `Model+0x158/+0x15c/+0x160 = 1.0`.
Поле `Agent+0x158` хранит указатель на Control. Проверенные ветви модели
`0x75b0/0x6fc0`, Effect RVA `0x3d30` и CollManager RVA `0x1ce00` сохраняют
матрицу и служебные указатели, оставляя масштаб модели неизменным.
Фабрика CollObject возвращает вторичный интерфейс `object+4`. QI `0x28`
вычитает `4` и сохраняет в `Agent+0x170` основной объект с vtable `0x3c2fc`.
Его event slot `+0x08` ведёт в Control RVA `0x1f530`. При event `4/null`
обработчик кэширует семь host-интерфейсов; при наличии QI `0x203` вызывает
CollManager slot `+0x10` таблицы `0x3c178`. Этот метод, RVA `0x1c330`,
сохраняет только указатель `CollObject+0x20` в `CollManager+0x3c`.
Для свежего BULL Agent без внешнего host QI `6` при привязке даёт основной Agent
с vtable `0x201d4`. Ненулевой event `4` вызывает его slot `+0x24`, AniMesh
RVA `0x17d60`, который читает `[Agent+0x120]`; вызывающий код сохраняет
результат в `CollObject+0x24`.
Затем CollObject slot `+0x0c`, Control RVA `0x1fe00`, сбрасывает бит `0`
поля `CollObject+0x30`. Event `0x15` с первым DWORD payload `9` завершается
без вызовов и записей. Поле Control `owner+0x34` хранит указатель на CollObject;
его slot `+0x14`, RVA `0x1f670`, меняет флаги `CollObject+0x30`.
Перечисленные ветви не вызывают AniMesh setter `0x14770`.
При загрузке AniMesh получает Control secondary owner с QI selector `0xa`
и сохраняет возвращённый base owner
в `Agent+0x158`: `AniMesh.dll+0x2ff0` делает этот вызов в RVA `0x32ee..0x3300`,
а `Control.dll+0x76f0` для selector `0xa` вычитает `0x14` из `ECX` и возвращает
указатель. Диспетчер AniMesh RVA `0x1afb..0x1b0d` посылает через `Agent+0x158`
событие `4` в slot `+0x08`. Его base-owner vtable — Control RVA `0x3d298`, и
slot ведёт прямо в `0x314f0`; при нулевом payload исходный обработчик проходит
`0x7830 -> 0xf940`, поэтому FAC0 входит с constructor scales `[1, 1, 1]`.
`0x7830 -> 0xf940`, поэтому FAC0 получает Model scale `[1, 1, 1]`.
Встречающиеся рядом переходники относятся к другим интерфейсам: Control owner
`+4` с таблицей `0x3d254` проходит через `0x31ae0` (adjust `-4`), а owner `+8`
с таблицей `0x3d1fc` — через `0x31b00` (adjust `-8`). Последний путь не является
@@ -1477,6 +1495,15 @@ descriptor word `8`. Текущий tag `26` тем же общим reader-ом
умножает на `M`. Это правило не меняет отдельные callbacks бюджета или запись
factory-26 selector `0x500`.
Сырой selector `6` в `FUN_1002bb40` выбирает устройство по ordinal через
интерфейс `owner+0x0c`: таблица `this+0x5b0` соответствует `owner+0x5bc`.
RVA `0x2bb91` проверяет тег текущего descriptor на равенство `2`. При совпадении
RVA `0x2bb9a` загружает `device+0x174` как `f32`, сохраняет значение в выходной
буфер и возвращает `AL=1`/`RET 8`; другие текущие теги возвращают false.
Наличие поля `+0x174` подтверждено для экземпляра фабрики `2`. INTO сохраняет
исходный тип экземпляра, поэтому проверка тега descriptor отдельно не доказывает
наличие этого поля у другой фабрики. В Rust selector `6` пока не поддержан.
FCA0 передаёт в owner query порядковый номер `i`; query `0x2bb40` находит
устройство `i` и вызывает его reader. Уже reader `FUN_10021d00` получает provider
key из поля устройства `+0x04`. Provider getter `FUN_1000dc40` (RVA `0x0dc40`)