Gothic Remake Готика ремейк - общие впечатления и обсуждение
  • 30.304
  • 311
Тема для общего обсуждения Gothic 1 Remake: первых впечатлений, ожиданий, атмосферы, визуального стиля, геймплея, боевой системы, персонажей, локаций и отличий от оригинальной Gothic. Здесь можно...
Новости Релиз Of Ash and Steel состоится 6 ноября
  • 11.425
  • 12
Of Ash and Steel: атмосферный экшен выходит 6 ноября 6 ноября станет важной датой для поклонников сложных и атмосферных игр - именно в этот день состоится релиз долгожданного проекта Of Ash and...
Новости В Of Ash and Steel начался закрытый плейтест
  • 13.923
  • 12
Разработчики "Русской Готики" объявили о старте закрытого плейтеста. Если вы оставляли заявку на участие, не забудьте проверить электронную почту или посмотреть свою библиотеку - возможно игра уже...
Новости Анонсирован Atomic Heart II

Гайд Как работают анимации в Gothic 2 - разбираем MDS

Exoda

Постоялец
Участник форума
Регистрация
10 Окт 2025
Сообщения
97
Реакции
103
Баллы
28
Лучшие ответы
0
#1
Что такое MDS файл?

MDS - это скриптовый файл, который управляет анимацией модели. Если ASC-файл хранит только саму анимацию (координаты костей в каждом кадре), то MDS - это инструкция, которая указывает движку игры:
  • Какой файл анимации использовать
  • Какой отрезок анимации взять
  • Когда проигрывать звуки и эффекты
  • Когда наносить урон и много чего еще
MDS-файлы обычно не лежат в папке с игрой. Для их получения необходимо сначала декомпилировать соответствующий MSB-файл, в который входит набор анимаций (ASC-файлы) и сам MDS-файл, который описывает, как эти анимации использовать в игре.

Структура MDS-файла

Код:
Model ("Имя_модели")
{
    meshAndTree ("Файл.ASC" DONT_USE_MESH)
    registerMesh ("Файл.ASC")
    
    aniEnum
    {
        // Здесь перечисляются все анимации
    }
}
meshAndTree - загружает скелет из ASC-файла. Например, для MDS, описывающего анимации людей, используется HUM_BODY_NAKED0.ASC. Параметр DONT_USE_MESH указывает движку, чтобы он взял только кости скелета, а визуальную модель проигнорировал. Это нужно, чтобы на один скелет можно было вешать разные "тела" (броню).

registerMesh - регистрирует визуальную модель (тело, броню), которую можно динамически надевать на скелет через скрипты. Эту строку можно пропустить, если вы используете модели (меши), которые уже есть в игре

Основные команды внутри aniEnum

1. ani - основная анимация
Разберем пример ниже:
Код:
ani ("s_stand" 1 "s_stand" 0.5 0.5 M. "stand_pause2.asc" F 0 -1)

Параметр

Значение

"s_stand"

Название анимации. Префис s_ - это state-анимация (циклическое состояние: стоим, бежим и т.п.). Префикс t_ - transition-анимация (переход между состояниями: стояли, потом побежали)

1

Слой (чем выше число, тем выше приоритет анимации)

"s_stand"

Следующая анимация (указывается для зацикливания, либо для перехода состояния, если бы мы использовали transition-анимацию)

0.5

Blend-in - время плавного входа их предыдущей анимации (сек.)

0.5

Blend-out - время плавного выхода после окончания анимации (сек.)

M.

Флаги:

  • M - Move: движение персонажа
  • R - Rotation: поворот персонажа
  • E - Earliest: анимация запустится только после завершения предыдущей на этом слое
  • F - Flying: игнорирование высоты ландшафта (полет/падение)
  • I - Idle: неважная анимация (дыхание, мелкие движения), может быть пропущена для оптимизации
  • . - Точка, если флагов нет

"stand_pause2.asc"

Название ASC-файла с анимацией

F

Направление анимации.

  • F - Forward: анимация воспроизведется от начала до конца
  • R - Reverse: анимация воспроизведется задом наперед

0

Начальный кадр анимации

-1

Конечный кадр (-1 значит до конца файла). Лучше указывать реальное количество кадров в анимации



2. aniAlias - анимация-псевдоним
Создает новую анимацию на основе существующей, зачастую с обратным направлением:
Код:
aniAlias ("t_strafe_r" 1 "s_stand" 0.1 0.1 M. "t_strafe_l" R)
Анимация t_strafe_r будет проигрывать анимацию t_strafe_l задом наперед (флаг R). Это экономит место, поскольку не нужно создавать отдельную анимацию для движения вправо, если мы можем вопроизвести анимацию движения влево задом наперед.

3. aniBlend - смешивание анимаций
Создает переход между двумя анимациями без отдельного ASC-файла. Используется для плавной смены скоростей (например, стояние -> бег):
Код:
aniBlend("t_stand_2_run" "s_run" 0.2 0.2)
Движок сам создаст плавную анимацию перехода из стояния в бег. Также можно указать Blend-in и Blend-out

4. aniComb - комбинирование анимаций
Собирает одну анимацию из нескольких заранее подготовленных кусков. Пример ситуации: прицеливание из лука. Персонаж может поворачиваться в разные стороны, но анимания наклона лука и натяжения тетивы остается одниаковой. Вместо того, чтобы создавать 36 отдельных анимаций для всех углов поворота, создаются 9 базовых фаз, а aniComb плавно смешивает их между собой:
Код:
ani ("C_BOW_1"    4   ""   0.0  0.0   ..   "HUM_BOWAUTOAIMT.ASC"    F   1   1)                      
ani ("C_BOW_2"    4   ""   0.0  0.0   ..   "HUM_BOWAUTOAIMT.ASC"    F   1   1)                      
ani ("C_BOW_3"    4   ""   0.0  0.0   ..   "HUM_BOWAUTOAIMT.ASC"    F   1   1)                      
ani ("C_BOW_4"    4   ""   0.0  0.0   ..   "HUM_BOWAUTOAIMC.ASC"    F   1   1)                      
ani ("C_BOW_5"    4   ""   0.0  0.0   ..   "HUM_BOWAUTOAIMC.ASC"    F   1   1)                      
ani ("C_BOW_6"    4   ""   0.0  0.0   ..   "HUM_BOWAUTOAIMC.ASC"    F   1   1)                      
ani ("C_BOW_7"    4   ""   0.0  0.0   ..   "HUM_BOWAUTOAIMD.ASC"    F   1   1)                      
ani ("C_BOW_8"    4   ""   0.0  0.0   ..   "HUM_BOWAUTOAIMD.ASC"    F   1   1)                      
ani ("C_BOW_9"    4   ""   0.0  0.0   ..   "HUM_BOWAUTOAIMD.ASC"    F   1   1)                      
aniComb ("S_BOWAIM"   1   "S_BOWAIM"   0.0   0.0   M.   "C_BOW_"   9)

Параметр

Значение

"S_BOWAIM"

Название новой (собираемой) анимации

1

Слой анимации

"S_BOWAIM"

Следующая анимация (обычно она же для зацикливания)

0.0

Blend-in

0.0

Blend-out

M.

Флаги (M - движение)

"C_BOW_"

Префикс анимаций-частей

9

Количество частей для комбинирования


Анимации с префиксом C_BOW_ - это отдельные кадрый или короткие отрезки, каждый из которых соответствует определенному углу наклона/поворота. Когда в игре запускается S_BOWAIM, движок берет все 9 частей (C_BOW_1 ... C_BOW_9). Поскольку у каждой части одинаковое количество кадров, движок может плавно переходить между ними, создавая анимацию прицеливания под любым углом.
Также может применяться для анимаций заклинаний с разными направлениями, прицеливании из арбалета.

5. modelTag - метка модели
Задает глобальные свойства для всей модели:
Код:
modelTag ("DEF_HIT_LIMB" "ZS_RIGHTHAND")
Код выше закрепляет, какая кость используется для расчетов попаданий при атаке (закреплено за правой рукой)


События внутри анимации

Внутри блока ani можно размещать события, которые срабатывают на определенных кадрах.

1. *eventTag - управление логикой боя
В качестве примера возьмем код анимации комбо-удара двуручного меча:
Код:
ani ("S_2HATTACK"  1  "S_2HATTACK"  0.0 0.2  M.  "HUM_2HATTACKCOMBOT2_M03.ASC"  F  1  116)                 
{
    *eventTag (0  "DEF_HIT_LIMB"  "ZS_RIGHTHAND")
    *eventTag (0  "DEF_OPT_FRAME" "6 46 86")     
    *eventTag (0  "DEF_HIT_END"   "35 75 100")   
    *eventTag (0  "DEF_WINDOW"    "15 40 55 80")
    *eventSFX (5  "WHOOSH"        EMPTY_SLOT)  
    *eventSFX (86 "BACK"          EMPTY_SLOT)   
}
Синтаксис: *eventTag (номер_стартового_кадра тип_события параметр). Разберем подробнее указанные типы событий

Тег

Что делает

DEF_HIT_LIMB

Указывает, какая кость наносит урон (рука, оружие). Проще говоря, вы указывает движку какая часть модели является точкой удара. В примере указывается правая рука

DEF_OPT_FRAME

Задает номера кадров, на которых происходит проверка на попадание. Именно в эти моменты игра проверяет, пересекается ли кость удара (DEF_HIT_LIMB) с врагом. Несколько чисел = несколько ударов в комбо

DEF_HIT_END

Последний кадр, в котором система еще ждет нажатия кнопки атаки для продолжения комбо. Если нажали кнопку атаки до того, как анимация дошла до этого кадра, то после окончания текущего удара начнется следующий. Если нажали после - комбо прервется. В примере выше если игрок нажал удар, скажем, на 25 кадре, то после 30-го кадра начнется второй удар. Если нажал на 35 кадре - анимация прервется и пресонаж вернется в изначальную стойку

DEF_WINDOW

Этот тег связан с предыдущим. Если DEF_HIT_END определяет до какого кадра можно нажать кнопку атаки для продолжения комбо, то DEF_WINDOW определяет длительность окна, в течение которого нажатие кнопки атаки будет засчитано для продолжения комбо-удара. В примере выше это окна 15 -> 40, 40 -> 55, 55 -> 80 кадров. Разные интервалы означают, что меняется темп атаки: где-то удар наносится медленне, где-то быстрее.


Существуют и другие события. Например, события, отвечающие за появление/исчезновение предметов в руках:
DEF_CREATE_ITEM - создает новый предмет (не из инвентаря) и вставляет его в указанную часть модели. Предмет берется "из воздуха".
Код:
ani ("T_BSANVIL_S0_2_S1"  1  "S_BSANVIL_S1"  0.0  0.0  M. "HUM_BSANVIL_JUE00.ASC"  F  4   9)                     
{
    *eventTag (4 "DEF_INSERT_ITEM" "ZS_LEFTHAND")                     
    *eventTag (4 "DEF_CREATE_ITEM" "ZS_RIGHTHAND" "Itmw_1H_Mace_L_04")
}
В коде выше показана анимация работы на наковальне. В левую руку вставляется заготовка (из инвентаря), а в правой руке создается молот (которого в инвентаре нет). Персонаж не достает молот из инвентаря, он сам появляется в руке у нужный момент (с 4-го кадра)

DEF_INSERT_ITEM - вставляет предмет из инвентаря в указанную часть модели.
DEF_REMOVE_ITEM - убирает предмет обратно в инвентарь. Противоположность DEF_INSERT_ITEM, часто применяется с ним в связке.
Код:
ani ("T_DUDEL_STAND_2_S0"              1               "S_DUDEL_S0"                  0.0  0.0  M. "EXTREMO_DUDEL.ASC"                            F  0   35)                     
{
    // Взять предмет в руку
    *eventPFX     (15 1 "PAUKEFX" "ZS_CROSSBOW" ATTACH)
    *eventTag     (21 "DEF_INSERT_ITEM" "ZS_LEFTHAND")                     
    *eventPFXStop (33 1)                                                   
}
ani ("S_DUDEL_S0"  1  "S_DUDEL_S0"  0.1  0.1  M. "EXTREMO_DUDEL.ASC"  F  35  70)                     
ani ("T_DUDEL_S0_2_STAND"  1  ""  0.0  0.0  M. "EXTREMO_DUDEL.ASC"  R  0   35)                     
{
    // Убрать предмет из руки
    *eventPFXStop (15 1)                                               
    *eventTag     (18 "DEF_REMOVE_ITEM")                               
    *eventPFX     (34 1 "PAUKEFX" "ZS_CROSSBOW" ATTACH)
}
В коде выше показан пример использования музыкального инструмента. В этом случае удаление предмета (REMOVE) является обязательным условием для того, чтобы предмет можно было снова использовать или переместить в инвентарь без дублирования.

DEF_DESTROY_ITEM - уничтожает предмет. Используется для расходников (например косяков).
Код:
ani ("T_JOINT_S0_2_STAND"   1   ""   0.0  0.2  M. "HUM_SMOKEHERB_LAYER_M01.ASC"   F  41  200   FPS:10)           
{
    *eventPFX     (60  1                   "LIGHTSMOKE" "ZS_RIGHTHAND" ATTACH)
    *eventPFXStop (85  1)                                                     
    *eventSFX     (100 "SMOKE_JOINT"       R:1000       EMPTY_SLOT)           
    *eventPFX     (100 2                   "LIGHTSMOKE" "ZS_RIGHTHAND" ATTACH)
    *eventPFXStop (125 2)                                                     
    *eventTag     (192 "DEF_DESTROY_ITEM")                                   
}
В коде выше показана анимация курения косяка. Предмет не возвращается в инвентарь, а уничтожается.

2. *eventSFX и *eventSFXGrnd - управление звуками
*eventSFX - проигрывает обычный звуковой эффект. В примере с анимацией комбо-удара двуручного меча была такая строка:
Код:
*eventSFX (5  "WHOOSH"   R:1000     EMPTY_SLOT)
Она означает, что на 5-м кадре воспроизведется звук "WHOOSH" (свист меча). Но имейте в виду, что это просто наименование звука, а не реальное название WAV файла с этим звуком. Параметр R:[число] - это радиус распространения звука. Параметр EMTPY_SLOT позволяет звуку не прерывать предыдущий (если вы нанесли новый удар, пока играет звук прошлого удара). Если его не указать, то новый звук будет прерывать предыдущий.

*eventSFXGrnd - звук с привязкой к поверхности. Делает то же самое, что и eventSFX, но с привязкой к материалу поверхности, на которой стоит персонаж.
Код:
*eventSFXGrnd (8 "RUN")
Следуя коду выше, движок смотрит что под ногами персонажа (трава, камень, дерево и т.д.), берет нашу базу "RUN" (бег) и добавляет соответствующий суффикс. Например, если персонаж бежит по траве (материал EARTH), то игра попытается проиграть звук RUN_Earth.
Список материалов:
  • EARTH - Земля/трава (суффикс _Earth)
  • STONE - Камень (суффикс _Stone)
  • METAL - Металл (суффикс _Metal)
  • WOOD - Дерево (суффикс _Wood)
  • WATER - Вода (суффикс _Water)
  • SAND - Песок (суффикс _Sand)
  • SNOW - Снег (суффикс _Snow)

3. *eventPFX и *eventPFXStop - управление частицами
*eventPFX - запускает эффект частиц (искры, магическое свечение).
Код:
*eventPFX (27 2 "FIRE_MEDIUM" "BIP01 R HAND" ATTACH)
Синтаксис: *eventPFX (номер_кадра ID_эффекта наименование_PFX_эффекта наименование_кости ATTACH)
ATTACH
привязывает эффект к кости (двигается с персонажем). Без него эффект частиц останется висеть в воздухе.

*eventPFXStop - останавливает ранее запущенный эффект по его ID.
Код:
*eventPFX (27 2 "FIRE_MEDIUM" "BIP01 R HAND" ATTACH)
*eventPFXStop (47 2)
4. *eventMMStartAni - управление мимикой
*eventMMStartAni - запускает морф-анимацию (независимая анимация, наложенная поверх основного скелета). Главное применение - анимация лица (мимики)
Код:
*eventMMStartAni (1 "T_HURT")   
*eventMMStartAni (7 "S_NEUTRAL")
В коде выше на 1-м кадре запускается мимическая анимация боли, а на 7-м нейтральная мимическая анимация.
 
Сверху Снизу