Shambler team

Создание сценариев

Для создания сценариев (aka скриптов) в Half-Life существуют две энтити: scripted_sequence и scripted_sentence. Первая отвечает за движения, выполняемые монстром/персонажем, будь то ходьба, бег, нажатие кнопки, тряска автомата с газировкой или почёсывание подбородка. Вторая служит для того, чтобы персонаж произнес какую-то фразу. При этом его голова повернётся в сторону слушателя, и рот будет открываться в соответствии с амплитудой звука.

Scripted_sequence — проигрывание движения
Эта (точечная) объект-энтитя размещается там, куда пойдёт или побежит объект, на которого она настроена. Её можно подставить вплотную к полу, но следите, чтобы никакие посторонние блоки не пересекали её пускай даже краешком.
Основные параметры настраиваются следующим образом:
  • Name(targetname) — имя, используемое для вызова сценария. Активатором, как и везде, может быть любая энтитя, включая самого монстра.
  • Angle — сторона, куда повернется лицом монстр, когда доберётся до нужной точки.
  • Target — энтитя, которая активируется после завершения этого сценария, т.е. после того, как монстр доберется до точки и проделает необходимую анимацию. Обычно этой энтитей бывает другой scripted_sequence для этого же монстра, или кнопка, на которую он нажал.
  • Delay before trigger(delay) — задержка между завершением анимации и срабатыванием target-энтити.
  • Kill Target — энтитя, которая будет удалена с карты после завершения сценария (часто сюда ставят имя этого же монстра, если нужно сделать так, чтобы тот зашел за угол и исчез)
  • Target Monster(m_iszEntity) — имя того самого монстра, который выполняет сценарий. Это может быть также название класса (например, monster_scientist) — в таком случае scripted_sequence выберет любого монстра этого класса в пределах радиуса, задаваемого в поле Search Radius
  • Action Animation(m_iszPlay) — название анимации, которую монстр проделает, когда доберётся до расположения этого scripted_sequence. Если вам нужно, чтобы монстр просто подошёл куда-то без дополнительной анимации, то оставьте это поле пустым.
  • Idle Animation(m_iszIdle) — название анимации, которую монстр будет выполнять до тех пор, пока не будет вызван scripted_sequence. Например, на карте c1a2b.bsp падение учёного в шахте лифта — пока вы не добрались до верху, он будет дёргаться, а при прохождении игроком триггера, он выполнит анимацию падения (к тому же у scripted_sequence параметр "Move to Position" = Instantaneous и установлены флаги "Leave Corpse" и "No interruptions", о чём сейчас пойдёт речь).
    Или поедающий труп зомби, подскакивающий при виде игрока.
    Если вам нужно, чтобы монстр постоянно выполнял Idlе-анимацию (как сидящий с кружкой кофе учёный в начале игры), то оставьте поле Action animation пустым, а поле Name заполните произвольным названием, правда если оставите Name пустым, то заданное вами движение в Idle Animation проиграется однократно и перейдёт к одному из движений idle. Замечу, что если при компиляции модели в её файле .qc в некотором движении прописана команда LOOP, то движение будет постоянно повторяться заново, переходя от последнего кадра на первый. А если в движении LOOP не было задано, то проигрывание остановится на последнем кадре и так и будет продолжать оставаться.
    Примечание: раньше ошибочно написал, что для повторения движения поле Name будто бы нужно было тоже оставлять пустым, теперь исправил.

  • Search Raduis(m_flRadius) — если в поле Target Monster задан класс монстра, то монстр будет выбираться внутри радиуса, задаваемого в этом поле. Также это применяется для создания учёных и охранников, которых надо подвести к кнопке или сканеру, чтобы они их активировали — поле Name оставляется пустым, в поле Target Monster указывается класс монстра (учёный monster_scientist, Барни — monster_barney или др.), здесь указывается радиус, и устанавливается некое значение поля Repeat Rate ms (например, 10) в миллисекундах до повторной попытки вызвать объект для движения, если он окажется занят.
  • Repeat Rate ms(m_flRepeat) — поиск монстра в радиусе, задаваемом выше, производится с указываемой в этом поле частотой в миллисекундах.
  • Move to position(m_fMoveTo) — определяет способ передвижения монстра на пути к позиции.
    • No — монстр не пойдёт к scripted_sequence, а выполнит анимацию там, где стоит.
    • Walk — подойдёт, и затем выполнит анимацию.
    • Run — подбежит, и выполнит анимацию.
    • Instantaneous — он телепортируется в место scripted_sequence и выполнит анимацию (это хорошая альтернатива monstermaker'у, если монстры должны иметь какие-то настройки типа имени и т.д.).
    • No, Turn to Face — то же, что и No, правда перед анимацией он повернётся в направлении, указываемом в поле Angle.

Теперь флаги у scripted_sequence:

  • 4 = Repeatable — поставьте, если сценарий нужно активировать много раз (например, ходящие учёные между ЭВМ в начале игры),
  • 8 =Leave corpse — если в конце анимации монстр умирает (например при падении), то с этим флагом труп не исчезнет.
  • 32 = No interruptions — если в момент проигрывания сценария игрок попытается повести монстра за собой или выстрелить в него, то сценарий не прервётся.
  • 64 = Override AI — обычно сценарии игнорируются, если монстр в состоянии боя. Но этот флаг заставляет монстра выполнить сценарий независимо от того, чем тот занимается. Если у монстра во время выполнения движения, перехода или перебега здоровье станет отрицательным (это можете увидеть в консоли командой impulse 103), то при этом он останется в живых до конца задачи. А если его управление перейдёт сразу к следующему scripted_sequence тоже с установленным флагом override AI, то и тогда он продолжить выполнять заданное. И шлёпнется от полной потери здоровья, когда закончатся все задачи объектов scripted_sequence с таким флагом.
  • 128 = No script move — после проигрывания движения монстр сместится обратно туда, где он был в её начале.
  • 256 = 9 недокументированный флаг (без названия, № флажка 29-1=256) — заставляет монстра после Idle-анимации непрерывно повторять движение, заданное в Idle_animation — анимацию холостого хода до сброса или следующего вызова другим scripted_sequence (пример на карте c1a0d.bsp из Half-Life под названием "coffeebreak"). Такой же флаг в Half-Life 2 носит название Loop in Post Idle.
Сейчас мы этот флажок задокументируем. Открывайте ваш файл half-life.fgd, ищите scripted_sequence, под ним строчку:
		128 : "No Script Movement" : 0
и допишите под ней
		256 : "Loop in Post Idle" : 0
а т.к. Hammer легко воспроизводит кириллицу из кодировки Win-1251, то можно немного перевести:
		256 : "Цикл после Idle" : 0

Чтобы задать анимацию, вам необходимо знать её название. Для этого модели можно просмотреть с помощью Jed's Half-Life Model Viewer 1.36 от Neil Jedrzejewski или Half-Life Model Viewer 1.25 от Mete Ciragan.

Внимание, некоторые модели, например, учёные или охранники состоят из нескольких mdl-файлов (barney.mdl, barney01.mdl, barneyt.mdl), если вы недоизвлечёте из архива их все, то при открытии просмотрщиком моделей главного файла (который без доп. окончаний) возникнет ошибка.
Раньше нужную вам модель из подпапки Pak-архива pak0.pak/Models нужно было извлекать с помощью редакторов PakScape или PakExplorer, но с определенных пор Model Viewer научился открывать модели прямо из pak-файлов. Ну а если модели у вас и так находятся вне архива, тогда нет никаких вопросов.

Есть одна небольшая хитрость — если есть две scripted_sequence с одинаковыми именами действующие на разных монстров, то поведение монстров будет синхронизировано следующим образом: тот из монстров, кто раньше подошёл к своему объекту scripted_sequence, не будет сразу выполнять анимацию, а подождёт, пока другой тоже не достигнет своей точки, и потом они вместе выполнят свои движения. Пример этого можно увидеть прямо перед реактором, когда учёные одновременно включают сканеры. Если один из монстров прервал выполнение сценария, то и другой прервёт тоже.

Отдельный вопрос, имеющий косвенное отношение к сценариям — сидящие в креслах учёные. Для этого используется энтитя monster_sitting_scientist. Теоретически располагать её можно на любой высоте от сиденья (желательно где-то на высоте около ста единиц), она всё равно опустится до нужного уровня, главное проследите, чтобы под ней и на некотором расстоянии от неё (≈4 единиц) было только седалище, а не твёрдотельные ручки или спинка, иначе игра неправильно определит высоту и учёный окажется либо слишком высоко либо слишком низко.


При передвижении монстра в нужную точку он всегда пытается использовать сетку из объектов info_node, даже если движение вызвано сценарием. Ноды — это своеобразные узловые точки путей, наподобие тех, по которым бегают боты в многопользовательском режиме. Ставить их довольно просто — выбираете энтитю info_node и кидаете.

Высота над полом может быть любая, игра всё равно самостоятельно опустит их до его уровня. Параметров никаких не нужно, игра, опять же, сама просчитает, какой узел из какого виден (появится надпись при самой первой загрузке карты — "Node graph is out of date. Rebuilding...") и сохранит в папочку maps\graphs. Ставьте их в основном на перекрёстках и углах. Не делайте расстояние между ними слишком большими и не наваливайте их в кучу. Около дверей ставьте по два инфо_нода — с одной стороны и с другой (можете добавить параметр hinttype со значением 1). У лестниц тоже нужно вверху и внизу по штуке. Если будет проблема с лестницами, то сделайте ступеньки пониже (8-12 или даже 16 единиц каждая) и подлиннее (чтобы поставить ногу, людям с запасом хватит длины ступени в 32 единицы, можно и немного короче)

оптимальный размер ступеней в Half-Life
Один из наиболее крупных вариантов размеров ступеней 32х16, которые ещё могут преодолеть человекоподобные монстры.

и вдоль одной лестницы на одной-двух средних ступенях поставьте по такому узлу, т.к. монстры могут пройти только по тем info_node, которые они видят, а лестницы бывают слишком высокими. Но для традиционных лестничных маршей длиной перехода 10 – 25 метров достаточно верхнего и нижнего info_node без промежуточных.

Случался ещё один казус, когда карту обновили, расставили новых навигационных узлов info_node, а персонажи ни в какую не хотели ходить именно по новым даже с помощью scripted_sequence и переминались с ноги на ногу в проходах. Оказалось, что виноваты в этом (!) настройки антивируса. Антивирус запрещал игре записывать обновление путей, т.е. в maps\graphs заменять файлы .nod и .nrp при первой загрузке обновлённой карты.



Scripted_sentence — произнесение речи

Местоположение этого объекта не имеет значения. Настраивается схожим образом с предыдущей.

  • Name — имя для активации.
  • Target — имя энтити, которая сработает позже, но не после завершения фразы, а сразу после начала воспроизведения (об этом ещё скажем в конце). Это часто используют для вызова ответной реплики другого персонажа.
  • Sentence Name — название звукового события, т.е., описание звукового файла для фразы. Важно, что в начале надо поставить восклицательный знак и писать имя события заглавными буквами. Например, одна из реплик учёного: !SC_IDLE0.
  • Speaker Type — имя монстра, который произносит фразу
  • Sentence Time(duration) — время звучания, во время которого он не будет прерываться на случайную реплику. После истечения заданного времени у, например, учёных, охранников, солдат и вортигонтов алгоритм способен спонтанно вызвать звучание заготовленных фраз. Также служит показателем того, как долго объект будет смотреть на слушающего.
  • Search Radius — радиус поиска говорящего монстра (по умолчанию =512)
  • Listener Type — имя слушающего монстра, к которому этот, обращаясь с репликой, повернёт голову. Как правило, тот тоже повернётся, слушая реплику. Если фраза обращена к игроку, то напишите здесь player. Если слушатель будет слишком далеко, то реплика не прозвучит.
  • Volume 0-10 — громкость (по умолчанию максимальная =10)
  • Sound Radius — дальность слышимости
    • 0 — Small Radius — малый радиус (по умолчанию),
    • 1 — Medium Radius — средний,
    • 2 — Large Radius — широкий радиус,
    • 3 — Play Everywhere — проигрывается везде, например, когда кто-нибудь в мегафон говорит.

Флаги:
  • Fire Once — запустится однократно,
  • Followers only — воздействовать только на тех персонажей, которые сопровождают игрока,
  • Interrupt Speech — прервать предыдущие разговоры, а текущая фраза не будет прерываться (впрочем не забывайте задать время звучания в поле Sentence Time), а то персонаж мог бы на середине фразы прерваться и начать говорить что-нибудь стандартное соседнему персонажу/игроку или комментировать неожиданно начавшуюся пальбу,
  • Concurrent — если монстр что-то говорил во время запуска scripted_sentence, то речь не прервётся, а будут звучать обе фразы параллельно.

Как и в случае со scripted_sequence, нам надо знать специальное имя звукового события. Это не то же самое, что и название wav-файла. Это, можно сказать, их группа. Опять зайдём в архив pak0.pak и в папке sound находим файл sentences.txt, внутренности которого устроены так:

...
SC_IDLE0 scientist/ipredictedthis
SC_IDLE1 scientist/containfail
SC_IDLE2 scientist/chaostheory
SC_IDLE3 scientist/howinteresting
...

Сначала заглавными буквами идёт название самого звукового события, которое мы подставим в scripted_sentence (например, в поле Sentence Name=!SC_IDLE0), а потом, через пробел, список wav-ок без расширения, которые по очереди проиграются в этом событии. В данном примере их только по одному, но в звуковых событиях десантников вы увидите их массовое использование:

HG_ANSWER1 hgrunt/clik yessir clik

Движок проиграет Sound/hgrunt/clik.wav, затем Sound/hgrunt/yessir.wav и снова первый звук. А если не указать подкаталог, написав

HG_ANSWER1 clik yessir clik

то по умолчанию файлы clik.wav и yessir.wav движок будет искать в каталоге Sound/vox/ .

Для каждого монстра существует своя группа событий — для учёных их названия начинаются на SC_, для охранников (aka Barney) — на BA_, для десантников (aka Human Grunts) — HG_ и так далее. Правда ничто не мешает использовать речь от одного класса для персонажа другого.
Если вы будете добавлять свои речи, не забудьте их также прописать по аналогии в этом файле, который приложите к своему моду. Звуковые .wav файлы должны быть 8 битными, чтобы говорящие персонажи открывали рты. В противном случае, если, например, это солдаты в противогазах, тогда можно использовать и 16-ти битный звуковой файл, и ртами никто шевелить не станет во время произнесения слов.

Примечание: Игра делает все звуки реплик примерно на 5,8% выше тоном. Т.е. для эксперимента вместо высказывания я сделал синусоидальный звук частотой 440 Гц, а в игре он проигрывается с частотой примерно 465,6 Гц (или даже ещё на десятую долю герца выше).

Есть ещё несколько обозначений в файле sentences.txt: запятые, точки и восклицательные знаки между названиями звуковых файлов.
Точка означает короткую паузу. Точнее вызывает проигрыш файла _period.wav. В папках VOX и FVOX это файл _period.wav с тишиной в четверть секунды, в папке у солдат HGRUNT\_period.wav звучит полусекундный щелчок в рации.
Запятая означает ещё чуть менее продолжительную паузу. Точнее проигрывает _comma.wav из заданной папки. В папках VOX, FVOX, ANBIENCE и SCIENTIST это файлы _comma.wav с тишиной в одну четверть секунды, а в папке у солдат HGRUNT\_comma.wav звучит шум в рации в одну пятую секунды.
Если нужно, то вы можете завести в любой другой папке _period.wav и _comma.wav, и тогда сможете пользоваться знаками "," и "." и при задании фразы/звука и с той папкой (например, в GMAN\).
Ещё есть восклицательный знак, который вызывает повышение тона и громкости. Примеры:

HG_TAUNT1 hgrunt/clik roger, hold. position clik

HG_ANSWER0 hgrunt/clik uhh roger that, clik(p120) clik

HG_CHARGE1 hgrunt/clik move!. in! clik

FAR_WAR5 ambience/(v10 p120) jetflyby1

В скобках буква с числом означает преобразование звука. Если используете больше одного эффекта подряд, то разделяйте их пробелами:

P Изменение тона (иначе говоря, смещение или транспонирование — англ. Pitch) — в диапазоне 50–150.
100 без изменения, 50 очень низко (на октаву, т.е. в 2 раза ниже), 150 очень высоко.
Поставил 130, и народ заговорил высокими мультяшными голосами в изменённых фразах.

V Громкость (от Volume) — % от стандартной громкости.
100 без изменения, 50 половина стандартной громкости.

S Старт — начало проигрывания звука в % от начала файла.
0 проигрывает с самого начала wav-файла, 25 пропускает 25%.

E Конец (от End) — Конечное положение проигрывания в % от конца звука.
100 заканчивает проигрывание в самом конце (как обычно). А 80 заканчивает на 80% от wav файла.

T Сжатие (от Time compress) — Временное сжатие звучания в % (без смещения тона).
100 проигрывает без изменений, 50 проигрывает в 2 раза быстрее — проигрывается только каждый 2 байт wav, 30 — проигрывает на 30% короче.
Штука редко пригождается, даже спецназ переозвучивать мешает, хотя в Half-Life у спецназа использовался для имитации потерь звука в рации.

Длина названия фразы не должна превыщать 15 символов. Например, в sentence.txt можете написать:

123456789ABCDEF gman/hg_gman_connection

Предположительно потому 15, что в scripted_sentence название фразы начинается с символа ! и вместе составит максимально 16 символов, а длина записывается в коде половиной байта. Если вам нужно, то скачать эту речь по рации "Внимание, сейчас будет говорить сам джимэн, соединяю" :) можно по ссылке hg_gman_connection.wav .


У sentense передача управления следующему объекту в параметре target идёт не тогда, когда прозвучит фраза целиком или истечёт заданное пользователем время звучания в параметре Sentence Time (он же duration), а практически сразу же.

Если зададите разговор персонажей из последовательных scripted_sentense, то возникнут трудности:
Допустим, есть первое scripted_sentense, где задано, что один персонаж что-то говорит пару-тройку секунд:
"Наше вам с кисточкой, старина!"
У этого объекта мы задали параметр target "greetings2", который быстро передаёт выполнение второму объекту.
И второе scripted_sentense с названием
Name "greetings2",
в котором второй персонаж отвечает, не дослушивая первого:
"И вам того же!"
В нём самом с помощью параметра Delay before trigger или delay создать задержку не удаётся, да у нас в файле настроек .fgd есть такой параметр, но его значения игнорируются.

Так чтобы вторая реплика не звучала почти одновременно с первой, второму scripted_sentense нужно задать задержку или через trigger_relay с его параметром delay (в нашем случае задержка была бы на те самые пару-тройку секунд) или вызывать последовательный разговор в сценарии из multi_manager'а. Но если хотите, то кроме этих простых решений, можно поискать и более заковыристые, чтобы передать вызов с задержкой через другие объекты-энтити.

Вот вроде и всё, удачных и интересных вам сценариев!



опубликовал BUzer в 2004 г.
дополнил ObaGlaza в 2011-21 гг.


Среди объектов, управляющих звуком, смотри также:
ambient_generic используется для проигрывания звуков,
env_sound добавляет эффекты всему звучанию в заданной объёмной области и
speaker — случайно воспроизводимые звуки из набора как по громкоговорящей связи.

2004 Shambler Team
  Counter.CO.KZ -     !
Hosted by uCoz