aboutsummaryrefslogtreecommitdiff
path: root/docs/reference/environment-effects.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/reference/environment-effects.md')
-rw-r--r--docs/reference/environment-effects.md77
1 files changed, 77 insertions, 0 deletions
diff --git a/docs/reference/environment-effects.md b/docs/reference/environment-effects.md
index fdc29f0..29d85f9 100644
--- a/docs/reference/environment-effects.md
+++ b/docs/reference/environment-effects.md
@@ -236,6 +236,83 @@ Native `z = 0.999` не означает, что спрайт гарантиро
native значение сохраняется для совместимости, но само по себе не обещает
окклюзию солнца всей геометрией местности.
+## Геометрия визуальных FX-команд
+
+`fparkan-fx::fx_visual` формирует кадры для двух подтверждённых вариантов
+`f_gener_ball`. Op4 принимает mode 0 с положительным знаменателем в `body+0xC4`
+и выдаёт camera-facing quad; расстояние камеры считается через native
+component-wise projection родительской матрицы. Op9 принимает mode 2:
+селектор `body+0xC4` со значением 0, 1 или 2 отображается в native flag base
+3, 5 или 6 и выбирает одну из трёх сеток; категория render flags выбирает её
+детализацию. `body+0xC8` выбирает UV path:
+нулевое значение проецирует позицию вершины на XY, ненулевое использует
+фиксированные координаты quad и cap. Кадр сохраняет MAT0 resource, фазу,
+opacity, вершины и triangle indices для renderer.
+
+Evaluator получает готовые command body, phase, camera point и внешнюю
+матрицу. Выбор Control row, manager gates, owner attachment, header jitter и
+global RNG остаются задачей владельца. `fparkan-game` пока использует для Op9
+категорию 0 с наибольшей детализацией; выбор категории по projected size ещё
+не реализован.
+
+Для Op3 поддерживаются body-типы 0, 1 и 2. Поля отсчитываются от
+`FxCommand.raw_body`, то есть после 4-байтового command word. Типы 0 и 1
+используют общие position/scale/phase/opacity tracks и camera-facing основу;
+тип 1 и тип 2 также интерполируют ось, а тип 2 строит basis через native
+D110-порядок. Все три evaluator-а принимают уже собранную матрицу владельца и
+не выбирают Control row или attachment. Текущий путь для типов 0 и 1
+предполагает native render context 0: `Effect.dll` проверяет общий gate
+`context + 0x60 < 8`, а API этих evaluator-ов не выбирает другой context.
+Evaluator типа 2 принимает индекс context явно и учитывает этот gate в `active`.
+
+## Частицы Op7
+
+`fparkan-fx::op7` вычисляет фиксированный набор частиц Op7 по body команды,
+фазе эффекта, матрице владельца, позиции камеры и render context. После
+инициализации состояние команды сохраняет случайно изменённые треки позиции
+и масштаба. Body задаёт время групп, opacity, фазу материала и вертикальное
+ускорение; последнее масштабируется переданным world scalar и применяется к
+копии матрицы владельца каждой активной группы. Текущий preview
+`fparkan-game` передаёт `world_scalar = 10.0`; чтение действующей настройки
+мира пока не подключено.
+
+Часы активной группы обновляются до применения detail cutoff отдельной
+частицы. Cutoff сравнивает ordinal render context с постоянным порогом слота.
+`Effect.dll` `0x1300` использует тот же порядок, поэтому скрытие слота не
+останавливает часы его активной группы. Поток частиц последовательно задаёт
+случайные изменения позиции и масштаба; для порогов видимости используется
+отдельный поток. Шаг LFSR совпадает с нативным переходом двух половин, однако
+семена отдельных экземпляров лишь детерминированно заменяют process-global
+состояние и не воспроизводят общий порядок вызовов.
+
+## Частицы Op8
+
+`fparkan-fx::smoke` разбирает body Op8, хранит кольцевой пул команды и выдаёт
+quad-ы с ориентацией к камере для активных слотов. Нативная нормализованная
+фаза окна ограничивается диапазоном 0–1 и задаёт интервал проверки следующего события;
+сравнение строгое (`schedule_base + interval < update_clock`). Все события
+catch-up в одном обновлении проверяются по тому же нормализованному интервалу;
+после события нативный код продвигает базу расписания интервалом, вычисленным
+по сырой фазе эффекта, а возраст слота считает по нормализованному интервалу.
+Когда фаза равна единственной границе окна, деление `0/0` даёт NaN, который
+нативный unordered-путь сравнения ограничивает нулём.
+
+Нулевая база расписания служит признаком начального состояния: обновление
+сохраняет текущую опору эмиттера и базу времени, не создавая частицу. Если
+первое время равно нулю, следующее обновление повторно захватывает опору. При
+событии скорость опоры считается от сохранённой позиции до текущей за время
+от базы расписания; слот смещает сохранённую опору на `скорость * due_interval`.
+Обновление без событий не переносит сохранённую опору к текущему владельцу.
+Откат часов корректирует только базу расписания до текущего времени: слоты,
+опора и три потока случайных
+чисел не сбрасываются.
+
+Evaluator принимает отдельные начальные состояния для эмиттера, знаковых
+отклонений и материала. Переход каждого потока совпадает с общим native LFSR,
+но эти локальные seed не воспроизводят порядок process-global вызовов игры.
+Предел 100000 событий catch-up — защитная граница evaluator-а; соответствующего
+лимита в исследованном native цикле не обнаружено.
+
## Что остаётся за владельцем
`EnvironmentSystem` не извлекает камеру из renderer, не разрешает материалы