Описание формата MDS-файлов можно прочитать на «этой странице»:http://mod.worldofgothic.ru/4meshes/58/dinamicheskaya-model-3ds-max-animatsiya-i-meshi. Однако тот документ не содержит информации о событии eventTag, встречающейся в MDS-файле. Что ж, восполним пробел.
Замечание. Информация, приведенная ниже, может быть местами неполной или даже неверной. Если у кого-то из моддеров будут дополнения/возражения, пишите, не стесняйтесь.
Событие eventTag опционально и помещается в блок событий, который следует сразу за фазой анимации ani. Событие – это определенное действие, которое запускается во время проигрывания фазы анимации в определённом кадре или кадрах.
Синтаксис:
ani ( ... НАЧ_КАДР КОН_КАДР ) { *eventTag (КАДР "ИМЯ" "ПАРАМ1" "ПАРАМ2" "ПАРАМ3" "ПАРАМ4") }
Здесь КАДР - целое число, НАЧ_КАДР ⇐ КАДР ⇐ КОН_КАДР. КАДР указывает время, когда движок должен выполнить дополнительное действие. Имя и параметры всегда в кавычках. Разделителями могут быть пробелы и знаки табуляции.
Имя указывает тип eventTag'а - см. ниже. Число параметров может меняться от 0 до 4.
Каждый eventTag имеет локальный характер - то есть указывает действия во время конкретной анимации. Еще применяется команда
modelTag (КАДР "ИМЯ" "ПАРАМ1" "ПАРАМ2" "ПАРАМ3" "ПАРАМ4")
которая работает аналогично eventTag'у, но записывается внутри блока aniEnum и распространяется на все анимации модели.
Проверка допустимости параметров eventTag'а выполняется не во время компиляции динамической модели, а непосредственно во время анимации - то есть в процессе игры. Недопустимое имя просто не обрабатывается, вылета в Windows не будет.
Действие, выполняемое eventTag'ом, зависит от имени. Ниже приведен список вариантов eventTag'а с разными именами.
Синтаксис:
*eventTag(КАДР "DEF_CREATE_ITEM" "СЛОТ" "ПРЕДМЕТ")
Создает предмет в слоте. При этом новый предмет вставляется в мир, т.е. предмет берется не из инвентаря NPC. «ПРЕДМЕТ» - это имя инстанции предмета. Предмет вставляется в мир не насовсем, а только до конца выполнения текущего набора анимаций, связанного с использованием предмета/MOB'а.
Пример (использование наковальни):
ani ("t_BSANVIL_Stand_2_S0" 1 "s_BSANVIL_S0" 0.1 0.0 M. "Hum_BSAnvil_Jue00.asc" F 0 2) ani ("s_BSANVIL_S0" 1 "s_BSANVIL_S0" 0.0 0.0 M. "Hum_BSAnvil_Jue00.asc" F 3 3) ani ("t_BSANVIL_S0_2_Stand" 1 "" 0.0 0.1 M. "Hum_BSAnvil_Jue00.asc" R 0 2) 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") // (1) *eventTag (4 "DEF_CREATE_ITEM" "ZS_RIGHTHAND" "ItMw_1H_Mace_L_04") // (2) } ani ("s_BSANVIL_S1" 1 "s_BSANVIL_S1" 0.0 0.0 M. "Hum_BSAnvil_Jue00.asc" F 10 47) ani ("t_BSANVIL_S1_2_S0" 1 "s_BSANVIL_S0" 0.0 0.0 M. "Hum_BSAnvil_Jue00.asc" R 4 9) { *eventTag (4 "DEF_DESTROY_ITEM") // (3) }
В Spacer'е определено, что наковальня используется с предметом «ItMiSwordrawhot» (Раскаленная сталь), поэтому строка (1) на 4-м кадре вставит в левую руку NPC предмет ItMiSwordrawhot. Далее, строка (2) создаст в правой руке NPC предмет «ItMw_1H_Mace_L_04» (Кузнечный молот). В строке (3) используемый предмет «ItMiSwordrawhot» удаляется из мира. Вместо раскаленной стали уже скриптом вставляется тот или иной меч.
Синтаксис:
*eventTag(КАДР "DEF_INSERT_ITEM" "СЛОТ")
Вставляет предмет из инвентаря в указанный слот. Предмет из инвентаря удаляется. eventTag «DEF_INSERT_ITEM» применяется в анимации использования предмета в инвентаре, пример:
// POTIONFAST ani ("t_potionfast_Stand_2_S0" 1 "s_potionfast_S0" 0.1 0.0 M. "Hum_DrinkPotion_M02.ASC" F 1 5) { *eventTag (5 "DEF_INSERT_ITEM" "ZS_LEFTHAND") // (1) } ani ("s_potionfast_S0" 1 "s_potionfast_S0" 0.0 0.0 M. "Hum_DrinkPotion_M02.asc" F 6 6) ani ("t_potionfast_S0_2_Stand" 1 "" 0.0 0.1 M. "Hum_DrinkPotion_M02.asc" F 7 39) { *eventSFX (19 "DrinkBottle" R:1000 ) *eventTag (35 "DEF_DESTROY_ITEM") // (2) }
Строка (1) на 5-м кадре анимации удаляет напиток из инвентаря и вставляет в левую руку NPC. Строка (2) удаляет напиток из левой руки NPC и из мира.
Замечание. Один известный баг Готик: если ГГ пьет напиток и его в этот момент кто-то бьет, то эффект напитка применяется, однако напиток остается в инвентаре. Причина бага в том, что использованный напиток удаляется из мира в конце анимации питья, в то время как эффект напитка (скриптовая функция, увеличивающая характеристику ГГ) применяется в самом начале анимации. Когда ГГ бьют, анимация питья до конца не проигрывается, и напиток не успевает удалиться из мира.
Другой пример (использование MOB'а):
В Spacer'е записывается (поле useWithItem), какой предмет нужен для использования MOB'а. Этот предмет и будет вставлен в слот по команде eventTag «DEF_INSERT_ITEM».
Синтаксис:
*eventTag(КАДР "DEF_REMOVE_ITEM")
Убирает предмет, вставленный в слот через «DEF_INSERT_ITEM», из слота назад в инвентарь.
Синтаксис:
*eventTag(КАДР "DEF_DESTROY_ITEM")
Уничтожает предмет, вставленный в слот через «DEF_INSERT_ITEM». Предмет удаляется из мира.
Синтаксис:
*eventTag(КАДР "DEF_PLACE_ITEM")
Удаляет предмет, вставленный через eventTag «DEF_INSERT_ITEM», из слота и из мира. По своему действию eventTag «DEF_INSERT_ITEM» является синонимом «DEF_DESTROY_ITEM».
Замечание. Предположительно, изначально подразумевалось другое поведение eventTag'а «DEF_PLACE_ITEM», а именно: Если NPC взаимодействует с MOB'ом и у этого MOB'а есть слот «ZS_SLOT», то переместить предмет, вставленный через «DEF_INSERT_ITEM», из слота NPC в слот «ZS_SLOT» MOB'а. Пример (сердца орочьих жрецов в храме Спящего, Г1):
// Sleeper Portal ani ("t_SPORTAL_Stand_2_S0" 1 "s_SPORTAL_S0" 0.0 0.0 M. "Hum_SleeperPortal_M01.asc" F 0 19) ani ("s_SPORTAL_S0" 1 "s_SPORTAL_S0" 0.0 0.0 M. "Hum_SleeperPortal_M01.asc" F 20 20) ani ("t_SPORTAL_S0_2_Stand" 1 "" 0.0 0.2 M. "Hum_SleeperPortal_M01.asc" R 0 19) ani ("t_SPORTAL_S0_2_S1" 1 "s_SPORTAL_S1" 0.0 0.0 M. "Hum_SleeperPortal_M01.asc" F 21 90 FPS:10) { *eventTag (60 "DEF_INSERT_ITEM" "ZS_RIGHTHAND") // (1) *eventTag (90 "DEF_PLACE_ITEM") // (2) } ani ("s_SPORTAL_S1" 1 "s_SPORTAL_S1" 0.0 0.0 M. "Hum_SleeperPortal_M01.asc" F 91 91) ani ("t_SPORTAL_S1_2_Stand" 1 "" 0.0 0.2 M. "Hum_SleeperPortal_M01.asc" F 90 100)
Выполнение строки (1) приводит к тому, что на 60-м кадре ГГ достает меч орочьего жреца (из инвентаря), а строка (2), предположительно, должна была оставлять вставленный в сердце меч торчащим из этого сердца. Для этого слот «ZS_SLOT» для MOB'а и нужен - чтобы указать местонахождение меча после вставки в сердце.
На самом деле, строка (2) просто удаляет меч из мира, как «DEF_DESTROY_ITEM». Предположительно, eventTag «DEF_PLACE_ITEM» -это еще одна задумка Пираний, не доведенная до конца в Г1. В Г2 eventTag «DEF_PLACE_ITEM» не используется.
Синтаксис:
*eventTag(КАДР "DEF_EXCHANGE_ITEM" "СЛОТ" "ПРЕДМЕТ")
Заменяет предмет в слоте другим предметом. Предмет удаляется из слота и из мира, а вместо него создается другой предмет (имя инстанции которого указывается) в том же слоте.
Синтаксис:
*eventTag(КАДР "DEF_FIGHTMODE" "БОЕВОЙ_РЕЖИМ")
Используется в переходных анимациях типа «t_1h_2_1hRun»
и выполняет переключение NPC в один из боевых режимов.
Здесь «БОЕВОЙ_РЕЖИМ» - одно из значений:
Например, для параметра «1H» выполняется удаление меча из слота «ZS_SWORD» и вставка меча в слот «ZS_RIGHTHAND», устанавливается следующая анимация (запустится после завершения текущей) «s_1h».
Синтаксис:
*eventTag(КАДР "DEF_PLACE_MUNITION" "СЛОТ")
Создает амуницию, например стрелу для лука в процессе перезарядки после выстрела. «СЛОТ» - это имя слота, где создается амуниция.
Допустимы только два наименования слота: «ZS_LEFTHAND» и «ZS_RIGHTHAND». Амуниция всегда соответствует экипированному оружию стрелковому оружию(поле munition в описании инстанции C_Item). Пример:
instance ItRw_Sld_Bow(C_Item) { name = "Лук"; mainflag = ITEM_KAT_FF; flags = ITEM_BOW; material = MAT_WOOD; value = Value_SldBogen; damageTotal = Damage_SldBogen; damagetype = DAM_POINT; munition = ItRw_Arrow; cond_atr[2] = ATR_DEXTERITY; cond_value[2] = Condition_SldBogen; visual = "ItRw_Sld_Bow.mms"; description = name; text[2] = NAME_Damage; count[2] = damageTotal; text[3] = NAME_Dex_needed; count[3] = cond_value[2]; text[5] = NAME_Value; count[5] = value; };
Синтаксис:
*eventTag(КАДР "DEF_REMOVE_MUNITION")
Удаляет ранее экипированную амуницию (см. описание DEF_PLACE_MUNITION).
Синтаксис:
*eventTag(КАДР "DEF_DRAWSOUND")
Начинает проигрывание звукового эффекта вытаскивания оружия:
Синтаксис:
*eventTag(КАДР "DEF_UNDRAWSOUND")
Начинает проигрывание звукового эффекта убирания оружия:
Синтаксис:
*eventTag(КАДР "DEF_SWAPMESH" "СЛОТ1" "СЛОТ2")
Поменяет местами предметы в слотах;
«СЛОТ1» и «СЛОТ2» - это имена слотов, объекты в которых нужно поменять. Пустые имена не допускаются.
Не рекомендуется использовать «ZS_RIGHTHAND» и «ZS_LEFTHAND» в качестве имени первого или второго слота, т.к. в этом случае движок произведет попытку перевести NPC в один из боевых режимов (аналогично eventTag «DEF_FIGHTMODE»), что иногда может закончиться зависанием игры.
Существует похожий способ переставлять предметы в слотах - это команда
*eventSwapMesh(КАДР "СЛОТ1" "СЛОТ2")
Основные отличия: eventSwapMesh меняет местами только меши предметов в слотах, а eventTag «DEF_SWAPMESH» меняет местами сами эти предметы. Кроме того, eventSwapMesh одинаково работает для любых имен слотов, а eventTag «DEF_SWAPMESH» имеет особое поведение, когда один из слотов является «ZS_LEFTHAND» или «ZS_RIGHTHAND».
Синтаксис:
*eventTag(КАДР "DEF_DRAWTORCH")
Ничего не делает.
Синтаксис:
*eventTag(КАДР "DEF_INV_TORCH")
Если в левой руке NPC нет факела, то ничего не делает.
Если же в левой руке NPC держит факел, то убирает факел в инвентарь до конца текущего набора анимаций, связанных с использованием предмета/MOB'а. Пример: NPC подходит с горящим факелом к кровати, ложится спать. Нужно временно убрать факел из левой руки, иначе NPC может поджечь кровать :)
Синтаксис:
*eventTag(КАДР "DEF_DROP_TORCH")
То же, что и DEF_INV_TORCH, только факел не убирается в инвентарь, а кидается на землю.
Синтаксис:
*eventTag(0 "DEF_HIT_LIMB" "КОНЕЧНОСТЬ1" "КОНЕЧНОСТЬ2" "КОНЕЧНОСТЬ3" "КОНЕЧНОСТЬ4")
Устанавливает, какой частью тела персонаж наносит повреждение другим персонажам. В качестве параметров используются имена костей/слотов. Можно указать до четырех повреждающих конечностей.
Пример:
//для кулачной драки устанавливается *eventTag(0 "DEF_HIT_LIMB" "Bip01 R Hand") //для драки одноручным оружием устанавливается *eventTag(0 "DEF_HIT_LIMB" "ZS_RIGHTHAND") //(в боевом режиме одноручное оружие находится в слоте "ZS_RIGHTHAND") //для кусающегося снеппера устанавливается *eventTag(0 "DEF_HIT_LIMB" "BIP01 HEAD")
Синтаксис:
*eventTag(0 "DEF_HIT_DIR" "НАПРАВЛЕНИЕ")
Устанавливает направление удара - влияет на выбор анимации защиты. Например, если первый NPC бьет другого посредством анимации
ani ("s_2hAttack" ...) { ... *eventTag (0 "DEF_DIR" "U") ... }
а другой, дерущийся одноручным оружием, успевает заблокировать удар, то будет использована анимация «t_1hParade_U» для блока. То есть при определении анимации атаки можно указать, какой анимацией нужно поставить блок. (Понятно, что если атакуемый NPC - сам игрок, то выбор соответствующей анимации для блока выполнит движок, а не человек.)
«НАПРАВЛЕНИЕ» - любая строка текста длиной до 10 символов. Направление по умолчанию - «O» (заглавная английская буква, не ноль). То есть
//отсутствие строчки *eventTag (0 "DEF_DIR" ...) //дает то же, что и присутствие *eventTag (0 "DEF_DIR" "O")
Синтаксис:
*eventTag(0 "DEF_DAM_MULTIPLY" "МНОЖИТЕЛЬ")
Позволяет указать множитель урона для анимации атаки. То есть, например, если для какой-то анимации атаки мы пишем
ani ("s_2hAttack_1" ...) { ... *eventTag (0 "DEF_DAM_MULTIPLIER" "2.0") ... }
то это означает, что эта атака будет наносить урон вдвое больший, чем вообще-то положено при таких соотношениях силы, урона оружия и брони противника. Урон будет умножаться на два независимо от того, критическая атака или нет. Можно написать число, меньшее 1.0, и тогда урон будет уменьшен.
Синтаксис:
*eventTag(0 "DEF_PAR_FRAME" "НАЧ_КАДР КОН_КАДР")
Используется для анимации блокирования. Указывает, начиная с какого кадра и заканчивая каким блок будет давать защиту от урона. Если не указать такой eventTag или указать «0 0» в качестве начального и конечного кадров, то блок будет давать защиту все время проигрывания анимации.
Синтаксис:
*eventTag(0 "DEF_OPT_FRAME" "КАДР1 КАДР2 КАДР3 ... КАДР10")
Используется для анимации атаки. Указываются кадры (числом от 1 до 10), когда нужно проверять на столкновение повреждающей конечности (см. описание «DEF_HIT_LIMB») и жертвы. Несколько кадров указывается, чтобы реализовать комбоудар. Таким образом, комбоудар может состоять из максимум 10 ударов. Обычно eventTag «DEF_OPT_FRAME» применяется вместе с «DEF_HIT_END» и «DEF_WINDOW».
Пример (mds_overlayhuman_2hST2.mds, Г2):
ani ("s_2hAttack" 1 "s_2hAttack" 0.0 0.2 M. "Hum_2hAttackComboT3_M02.asc" F 1 150) { *eventTag (0 "DEF_HIT_LIMB" "ZS_RIGHTHAND") *eventTag (0 "DEF_OPT_FRAME" "5 45 90 138") *eventTag (0 "DEF_HIT_END" "35 75 120 147") *eventTag (0 "DEF_WINDOW" "13 41 53 81 98 126 146 149") ... }
Анимация содержит кадры с 1 по 150. Полный комбоудар будет состоять из 4 ударов - на 5, 45, 90 и 138 кадрах. При этом возможны случаи:
Синтаксис:
*eventTag(0 "DEF_HIT_END" "КАДР1 КАДР2 КАДР3 ... КАДР10")
Указывает кадр, на котором «обрубается» комбоудар, если не нажать во время клавишу «вверх» (Г1) или левую кнопку мыши (Г2). Баг Готик в том, что в этом случае мы услышим все звуковые эффекты, следующие за этим кадром, а анимация заканчивается характерным передёргиванием персонажа.
Число кадров, указанное в этой записи, должно совпадать с числом кадров eventTag'а «DEF_OPT_FRAME».
Синтаксис:
*eventTag(0 "DEF_WINDOW" "НАЧ_КАДР1 КОН_КАДР1 НАЧ_КАДР2 КОН_КАДР2 ... НАЧ_КАДР10 КОН_КАДР10")
позволяет задать «окно» на анимации - интервал кадров, в течение которого нужно нажать клавишу «вверх» (Г1) или левую кнопку мыши (Г2), чтобы продолжить комбоудар. Если не успеть - см. выше, что будет.
Число интервалов должно совпадать с числом кадров eventTag'а «DEF_OPT_FRAME» (см. пример выше).
P.S. Спасибо alex_draven и Ukur'у за ценные замечания.
Автор статьи - Kerrax.
Проект портала World of Gothic RU. © 2005-2009 marazmus, MaGoth и команда World of Gothic RU.
Копирование материалов сайта разрешено только при явном согласии авторов материалов.
При копировании материалов прямая ссылка на сайт обязательна.