Архив
Новости
Текущие
Архив
Общение
Форум
Библиотека
Статьи
Стихотворения
Fan-Works
Рисунки
Зарубежные рисунки
Аудио
Видео
Флэш
Игры
Fan-Миссии
Установка FM
Thief 1 FMs
Thief 2 FMs
Thief 3 FMs
TDM FMs
Переводы
Прохождения
Обзоры
Demo
В Разработке
Отмененные
Редакторы
DromEd
T3Ed
DarkRadiant
Сайт
Ссылки
Авторы
О сайте
Просмотр каталога:
Простой | Подробный

На главную » Файловый Архив » Редакторы » DromEd » Tutorials » dromed_notes.pl

DromEd-овские заметки

автор Dront


Данный документ - если можно так выразиться, продолжение к файлам DromEd Tutorial, Mods и ConVict, что поставляются в комплекте с DromEd. Всё это нажито собственным опытом и проверено на деле не раз.
Внимание! Документ написан под DromEd 1.37. Теоретически все нижеописанные приёмы могут работать и в DromEd 2, но это уже не проверялось. Где есть исключение - там оговорено.
При наличии ошибок или неточностей прошу уведомить меня об этом личным сообщением на форуме или по e-mail.

Часть 1. Меню и команды DromEd.

1.1. Меню File.
1.2. Меню Edit.
1.3. Меню View.
1.4. Меню Shapes.
1.5. Меню Tools.
1.6. Меню Editors.
1.7. Меню Game.
1.8. Меню Multibrush.
1.9. Команды load_a_texture и remove_a_texture.
1.10. Команда compress_textures.
1.11. Команда script_drop.
1.12. Изменение небесного фона; команда load_sky.
1.13. Команда texture_change.
1.14. Список команд, вводимых в командную строку DromEd и в консоль в игровом режиме.
1.15. Немного юмора.
1.1. Меню File.

Часть 2. Operation brushes (они же просто brush'и) и всё про них.


2.1. Отличия Fill water и Flood друг от друга; немного полезной информации о воде.
2.2. Ограничение на высоту ступеней лестницы.
2.3. Решение проблемы с выравниваем по сетке.
2.4. Команда max_polys, чем она хороша и плоха. Как понизить число полигонов.
2.5. Проблемы при изменении масштаба текстуры.
2.6. "Переходные" типы заполнения brush'ей.

Часть 3. Простейшие источники света (lights); потоки (flows); участки (areas).


3.1. Точечные источники света "из ниоткуда".
3.2. Создание течения (flow).
3.3. Создание лавы.
3.4. Создание сложной Multibrush при помощи Area Brush.
3.5. Немного информации о воде и потоке на английском.

Часть 4. Объекты: Свойства (Propeties).


4.1. Свойство Engine Features -> Locked.
4.2. Свойство Engine Features -> LOcked: открытие замка.
4.3. Свойство DarkGameSys -> PickSrc. Создание третьей отмычки.
4.4. Свойство AI -> Ability Settings -> Idle. Поворачивающийся AI.
4.5. Свойства в AI -> Attributes: Hearing и Vision.
4.6. Свойства в AI -> Attributes: все остальные.
4.7. Свойство AI -> Ability Settings -> Combat: Non-hostile. Невраждебный AI.
4.8. Свойство AI -> AI Core -> Team. AI, сражающиеся друг с другом.
4.9. Свойство A -> AmbientHacked. Разные способы передачи амбиентных звуков.
4.10. Что такое Frob.
4.11. Изменение яркости освещения.
4.12. Свойство AI -> AI Core -> Alertness cap.
4.13. Убегание (flee). Свойство AI -> Utility -> Flee point.
4.14. Убегание (flee). Свойство AI -> Ability Settings -> Flee: Condition for flee.
4.15. Увеличение количества жизни существа. Свойства Game -> Damage Model: Hit Points и Max Hit Points.
4.16. Неубиваемые враги. Типы поведения AI при смерти. Свойство Game -> Damage Model -> Slay Result.
4.17. Изменение голоса существа. Свойства Speech -> Voice и Voice Index.
4.18. Свойство DarkGameSys -> Loot. Что нужно перед тем, как создать цель типа "goal_special".
4.19. Помещение трупа на уровень. Метасвойство M-PosedCorpse.
4.20. Помещение на уровень трупа, лежащего на спине. Свойство Creature -> Current Pose.
4.21. Свойство Difficulty -> Destroy. Различия между уровнями сложности.
4.22. Room brushes: попытка создания автокарты. Свойство Room -> Automap.
4.23. Room brushes: акустика. Свойство Room -> Acoustics.
4.24. Свойство Shape -> Model Name. Изменение модели объекта.
4.25. Метасвойство M-BaseRamirez. Превращение в Рамиреса одним махом.
4.26. Оптические свойства предмета: Renderer -> Extra Light.
4.27. Оптические свойства предмета: прозрачность, излучение света, прорисовывание.
4.28. Изменение движений AI. Свойство Motions -> ActorTagList.
4.29. Свойства Schema -> Class Tags и Material Tags.
4.30. Свойство Inventory -> Object Name. Создание своего названия объекта в инвентаре.
4.31. Ось открытия двери.
4.32. Свойство Frog-beast: Explode range.
4.33. Метасвойство M-ZombiePossum. Как сделать зомби лежачим одним махом.
4.34. Метасвойство IsLoot, или Как сделать вещь драгоценностью.
4.35. Защита двери от открытия ударом.
4.36. Некоторые основные скрипты, как они действуют.
4.37. Act/React - источники и приёмники. Краткий обзор.
4.38. Как сделать объект источником света.
4.39. Вес предмета. Как сделать, чтобы flash-бомба не падала на пол.
4.40. Скрипт Extinguishable. Как сделать свечу, которую можно потушить и снова зажечь.
4.41. Баловство с оружием ближнего боя.
4.42. Изменение размеров объекта так, чтобы сквозь него нельзя было пройти.
4.43. Свойства AI -> Responses.
4.44. SpotLights.
4.45. Свойство Creature -> Time Warp, что оно даёт.
4.46. Свойство Schema -> Play Params. Какие фразы Гарретт говорит один раз, какие - нет.
4.47. Свойство AI -> AI Core -> Movement: max speed. Летающие противники.
4.48. Свойство AI -> Utility -> Pathable Object.

Часть 5. Объекты: Связи (Links).


5.1. Связь Lock.
5.2. Связь Contains для создания предмета на поясе.
5.3. Связь ControlDevice.
5.4. Связь ParticleAttachement. Привязка к объекту.
5.5. Связь AICurrentPatrol.
5.6. Связи TPath и TPathInit. Создание управляемого лифта.
5.7. Пукающий буррик.
5.8. Связь ParticleAttachement. Привязка к точке тела.
5.9. Связь Corpse.
5.10. DestroyTrap и ControlDevice.
5.11. RequireAnyTrap, RequireAllTrap, Inverter и ControlDevice.
5.12. Связь CreatureAttachment.
5.13. Связь FrobProxy.
5.14. Горячие плиты. HotPlateControllers и ControlDevice.
5.15. Один из примеров использования связи AIWatchObj.

Часть 6. Объекты: Простые комбинации свойств и связей. Нехитрые приёмы.


6.1. Телепортация предмета.
6.2. Телепортация Гарретта.
6.3. Нажимная плита и ловушка: первые шаги.
6.4. Нажимная плита и ловушка: корректировка свойств плиты.
6.5. Нажимная плита и ловушка: корректировка свойств ловушки.
6.6. Спящие AI.
6.7. Говорящий Гарретт.
6.8. Conversation. Основные понятия.
6.9. Conversation: AI, идущий к объекту.
6.10. Conversation: AI, использующий объект.
6.11. Conversation: AI, поворачивающийся к чему-либо.
6.12. Conversation: возможные движения говорящих AI.
6.13. Создание мага из слуги.
6.14. Слуга, бьющийся в рукопашную.
6.15. Слуга с мечом.
6.16. Двойные двери.
6.17. Открытие талисманом ward'а.
6.18. Создание системы сигнализации.
6.19. Управление целями. QuestVarTraps.
6.20. Один из примеров использования Act/React.

Часть 7. Объекты: Сложные комбинации свойств и связей. Изощрённые дромадёрские мысли.


7.1. CamVator. Взгляд на происходящее со стороны.
7.2. Совместное использование скриптов TrigInvFrob и StdButton.
7.3. Создание неба при помощи объектов.
7.4. Создание случайных условий в DromEd.
7.5. Триггер срабатывает только при определённом порядке поворота рычагов - как реализовать?



Часть 1. Меню и команды DromEd.


1.1.1. File -> New/Open - надеюсь, объяснять не надо :) Создание нового файла/открытие ранее созданного. Внимание! Несмотря на то, что при выборе пункта Open можно загрузить файл .gam (gamesys), делать этого не надо! При попытке открыть .gam-файл через это окно DromEd со свистом вылетит. Для загрузки gamesys применяем команду set_gamesys (имя файла без расширения).

1.1.2. File -> Save Cow - сохранение и gamesys'а, и файла миссии в один файл. См. далее для подробностей.

1.1.3. File -> Save Gamesys - сохранение, грубо говоря, иерархии объектов. По умолчанию используется dark.gam, при внесении туда изменений (добавлений новых архетипов в Object Hierarchy) сохраняем gamesys этой командой.

1.1.4. File -> Save Mission - сохранение файла миссии - то есть всего остального: собственно уровня со всей его местностью, объектами и т.д.

1.1.5. File -> Add Texture Family - добавление семейства текстур. Введите название семейства, чтобы загрузить. Об этой команде написано в DromEd Tutorial.

1.1.6. File -> Load Script - загрузка скрипта. Аналогично - вводим название скрипта, и он загружается. И об этом также написано в DromEd Tutorial.

1.1.7. File -> Toggle AI. Правильнее было бы "Toggle AI awareness". То же, что происходит при вводе команды aiawareofplayer, про которую написано в DromEd Tutorial.

1.1.8. File -> Exit. Надеюсь, объяснять не надо. :)

1.2. Меню Edit.

1.2.1. Edit -> Undo. Отмена последнего действия. У меня работает как-то криво - либо объект теряет свойства, либо brush не вырисовывается после отмены... Лично я эту команду не применяю.

1.2.2. Edit -> Clear. Удаление выделенного объекта. То же, что и нажатие клавиши Delete.

1.2.3. Edit -> Clone. Клонирование (копирование) выделенного объекта. То же, что и нажатие клавиши Insert.

1.3. Меню View.

1.3.1. View -> Zoom In/Zoom Out. Увеличение/уменьшение изображение в 2D-окнах (или окне). То же, что и выбор соответствующего пункта в меню, вызываемом правой кнопкой мыши.

1.3.2. View -> 2x2/1 Left, 3 Right/1 Top, 3 Bottom. Расстановка окон вида - либо по умолчанию - 4 окошка одинакового размера (2 на 2), либо 3D-вид слева, 3 2D-вида справа, либо первый сверху, вторые 3 снизу.

Остальные пункты пока не разобраны.

1.4. Меню Shapes.

1.4.1. Shapes -> Cube, Cylinder, Pyramid, Corner-Apex Pyramid, Wedge, Dodecahedron. Создание brush в форме указанной фигуры - соответственно параллелепипед, цилиндр, пирамида, наклонная пирамида, клин (треугольная призма), додекаэдр.

1.4.2. Shapes -> Sides In Base. Количество сторон у цилиндра, пирамиды или наклонной пирамиды (если они выбраны). Говорят, что больше 10 сторон вводить нельзя.

Остальные пункты пока не разобраны.

1.5. Меню Tools.

1.5.1. Tools -> Portalize/Optimize/Compute Pathfinding Database/Build Room Database. Про действия этих команд подробнейшим образом написано в файле DromEd Tutorial. Стоит лишь заметить, что всякий раз, когда внизу у имени файла появляется звёздочка, это значит, что уровень следует портализовать (или оптимизировать).

1.5.2. Tools -> Build AI Room Database. При помощи этой команды улучшается ориентация AI в комнатных brush'ах. Рекомендуется проделывать вместе с Build Room Database и Compute Pathfinding Database.

1.5.3. Tools -> Light. Пересчёт освещения. Вообще, освещение автоматически пересчитывается при портализации, но ради одного пересчёта света портализовать неудобно, особенно если уровень большой. Команду можно применять при изменении яркости источника света, но не при его перемещении - в последнем случае возле имени файла внизу появится звёздочка, говорящая о том, что надо портализовать уровень.

1.5.4. Tools -> Quick Lighting/Raycast Lighting/Objcast Lighting. Про эти пункты написано в DromEd Tutorial: это выбор типа освещения. При создании уровня можно оставить Quick Lighting (если не занимаемся освещением), но в готовом уровне, конечно же, должно быть уделено должное внимание освещению, и уделяться оно должно либо в режиме Raycast Lighting, либо Objcast Lighting. Разница между ними двумя только в одном: в режиме Objcast Lighting неподвижные объекты также отбрасывают тени, в режиме Raycast теней от объектов нет.

1.5.5. Tools -> Link Group. Без понятия.

1.5.6. Tools -> Generate Report. Создание некоего отчёта по уровню. Никогда не пользовался этой командой, но стоит попробовать.

1.5.7. Tools -> List object/Object Histogram. Первый пункт просто покажет вам, какие объекты есть на вашем уровне, второй ещё и скажет, сколько объектов каждого вида. То есть, если у вас на уровне стоит 5 одинаковых стульев (допустим, stool), в первом окне будет написано пять строчек со словом stool, во втором - одна строчка вроде "(005) stool".

1.6. Меню Editors.

1.6.1. Editors -> Object Hierarchy/Texture Palette. Ну, уж об этом все уши прожужжали уже в DromEd Tutorial.

1.6.2. Editors -> Motion Editor. По всей видимости, вызывает встроенный редактор движений. Теоретически в нём можно посмотреть некоторые движения, но и не более того. Для редактирования текущих движений или создания новых необходимо использовать сторонние программы.

1.6.3. Editors -> Mission Parameters/GameSys Parameters/Campaign Parameters. Вызывает параметры миссии или gamesys (см. выше пункты 1.1.3 и 1.1.4), которые можно менять на своё усмотрение. Опять же, поэксперементировать можно, но здесь я ничем помочь не могу пока что.

1.6.4. Editors -> Mission Quest Data/Campaign Quest Data. Про первый пункт всё разжёвано и в рот положено ещё в DromEd Tutorial, а второй пункт становится активным при хотя бы одном входе в режим игры. Там будет показаны результаты пройденного уровня (как будто вы сыграли миссию уже в игре и досрочно завершили её читерской комбинацией Ctrl+Alt+Shift+End).

1.7. Меню Game. При выборе любого пункта (кроме Game Mode Settings) вы автоматически перенесётесь в игровой режим - либо с установленным в настройках игры разрешением, либо с указанным (от 320*200 до 1280*1024). При выборе Game Mode Settings появится окно настроек, где можно установить те же опции, что и в игре, только здесь всё написано более сухим языком.

1.8. Меню Multibrush. Почти полностью не изучено, могу лишь сказать, что при выбранной multibrush можно выбрать Multibrush -> Save Group и сохранить эту группу в файл с расширением .vbr. Теперь эта multibrush может быть в любой момент загружена и вставлена в любую точку уровня.

1.9. Можно загрузить в программу не семейство текстур, а только одну текстуру (например, не всё семейство mine, а только текстуры панели управления лифтом и его пути). Для этого вводим команду load_a_texture mine melevpanel - добавляется текстура панели управления. Вторая, если не ошибаюсь, называется melevtr, также содержится в семействе mine, так что вводим то же самое, изменяем только название текстуры. Ясное дело, что и остальные надо вводить по такому же принципу (load_a_texture (название семейства) (название текстуры)). Удаляется она, если не ошибаюсь, командой remove_a_texture. Контекст тот же (пробел, название семейства, пробел, название текстуры.)

1.10. Команда compress_textures удаляет ненужные в миссии текстуры. Очень помогает - вместо загрузки текстур семейства по одной можно загрузить семью, разукрасить комнаты нужными текстурами, а потом при помощи этой команды удалить "мусор".

1.11. Команда script_drop выбрасывает скрипты с уровня, но каким образом: при вводе её появляется список всех использованных скриптов в миссии. Так, можно увидеть, что, к примеру, миссия Song Of The Caverns в Thief Gold использует только лишь один ConVict. (Справедливости ради, это единственная миссия Thief Gold, использующая только его, остальные либо используют "индивидуальный" скрипт (missxx.osm), либо ConVict в комплекте с другими - как, например, Thieves' Guild - она использует ConVict, Evidence и Gen; evidence, говорят, спрятался внутрь ConVict'а.) Так что с невидимыми целями явно можно работать и без самодельных скриптов! И вот как: (см. пункт 6.19).

1.12. Можно изменить небо миссии, причём достаточно просто. Во-первых, выбираем Editors -> Mission Parameters в меню самого DromEd. В окошке выбираем Sky Rendering Mode и выбираем Textures вместо Stars. И теперь на небе у нас гордо красуется пресловутая Jorge. Чтобы не было Jorge - при помощи команды load_sky грузим текстуру неба. Все их виды есть в архиве fam.crf, вот их перечень:
bsky - Jorge.
dmb - аналогично, тоже Jorge. (Хотя и в архиве это бог весть что.)
dsky - небо с полной луной, ночь. (6 разных текстур соответствуют 6 сторонам параллелепипеда, на который небо может быть наложено.)
nsky - облачное небо, день.
acid - "кислотное" небо - сплошная каша из облаков. День вроде как, но очень странный :)

1.13. Сообщение Elder'а keeper'а на форуме DarkFate от 21.01.05.
"Полезная команда в дромеде. Заменяет текстуру на уровне на другую:
texture_change <№ замещаемой текстуры>, <№ новой текстуры>
Номер текстуры - под ее изображением

Наверное, должно сильно облегчать жизнь, если одна из часто используемых текстур на уровне вам не нравится и нет желания все менять вручную."

1.14. Полезная ссылка по поводу команд, вводимых в консоль в игре (и не только):
http://www.ttlg.com/forums/showthread.php?t=47143&highlight=list+commands
http://www.ttlg.com/forums/showthread.php?t=108684 - а здесь описаны команды, вводимые в само окно DromEd'а.
(Ссылки найдены на форуме DarkFate, за первую спасибо UL'у, за вторую - clearing'у.)

1.15. Немного юмора.
В консоли, что выводится Ctrl+P в игровом режиме, введите команду:
scale_sim_time 2. Это ускорит процесс вдвое. :)
А ещё можно, наоборот, замедлить всё донельзя - например, scale_sim_time 0.5 - или ускорить - scale_sim_time 5.
Числа, естественно, по вкусу. Настроение поднимет точно, особенно если в замедленном режиме зомбей мочить. :)



Часть 2. Operation brushes (они же просто brush'и) и всё про них.




2.1. Два практически одинаковых, на первый взгляд, типа заполнения brush'ей имеют приличные отличия. Это fill water и flood. Fill water заполняет пространство водой, уничтожая собой все твёрдые преграды на своём пути. А flood не уничтожает твёрдые объекты. (Про это написано в части XIV DromEd Tutorial.) Кроме того, лаву можно создать только при помощи flood'а. Хотя... я могу и ошибаться. Как создать лаву - см. пункт 3.3.

2.2. Ещё одна важная деталь: любая ступенька лестницы (наклонной, понятное дело) должна быть максимум 0.75 единиц в высоту при глубине (длине) в 1. Можно также попробовать сделать ступеньку более высокой, но соотношение 0.75:1 желательно сохранить или уменьшить. (Лично я обычно строю ступеньки с соотношением высота:глубина = 0.5:1.) Разумеется, существует и некое предельное значение высоты, после которого по лестнице не могут ни подниматься, ни спускаться AI. (Менее подробно об этом написано в части XIV DromEd Tutorial.)

2.3. При проблемах с выравниванием по сетке и ошибках при оптимизации (которые не случаются при портализации) стоит проверить это самое выравнивание. Полезная команда для этого: hilight_check_snap 1, которая подсвечивает все невыровненные brush'и. Чтобы выровнять их, стоит вначале изменить размер сетки до 11 (чтобы выравнивание было как можно более незаметным; при более мелком размере сетки, возможно, ошибка не исправится) и вводим hilight_do_snap 1. Brush'и подвинутся на небольшое расстояние, выровнятся. Теперь отключаем подсветку командой hilight_clear и оптимизируем. Но сохраниться лучше в отдельный файл, и только после того, как обследуем все "проблемные" места и убедимся, что всё в порядке, уже можно сохраняться в первоначальный файл. Ещё можно заставить DromEd выравнивать multi brush'и по сетке - для этого достаточно ввести строчку vbrush_snap в файл user.cfg. Правда, команда (наверное?) будет работать только при создании нового файла, в старых же работать не будет. (Повторюсь, этот факт не проверен.)

2.4. Максимальное число полигонов, которое можно установить, - 2500 (делается это командой max_polys (целое число) ). Но. Эта команда, судя по всему, работает лишь в DromEd, но не в игре. То есть миссия через редактор может идти, а при запуске Thief произойдёт вылет с ошибкой. Поэтому изменить это число можно только если для того, чтобы избежать возможной ошибки при построении слишком сложной brush'и. Тревожный звонок, предостерегающий о приближении к этому пределу - при взгляде на тот или иной участок происходит "размазывание" вида перед глазами. В этом случае можно попробовать обойти это ограничение: если речь идёт об открытом пространстве, стоит увеличить масштаб текстур, в частности, неба - при стандартном "звёздном" небе масштаб можно установить хоть 24 - всё равно выглядеть будет как при стандартных 16; у труднодоступных (или просто далеко расположенных) brush'ей также стоит увеличить масштаб текстур. Если же это не помогает, нужно каким-либо образом загородить от взгляда игрока "больную" территорию, или же убрать оттуда все могущие быть лишними brush'и, если такие имеются. (Если же выскакивает ошибка "scene complexity too high" при попытке посмотреть на проблемную территорию, путь к исправлению тот же; чтобы сообщение не выскакивало, можно или применить команду max_polys, либо установить в 3D-виде режим "wireframe brushes" - при этом режиме будет такой же вид, как и в 2D-окнах; не будут показываться текстуры и прочее, а значит, и не будет такой ошибки - по крайней мере, в режиме редактора.)

2.5. Ещё один момент, когда может пригодиться режим wireframe brushes - при изменении масштаба текстуры. Если выскакивает ошибка "Yo, homefry.", то можно сделать следующее: проигнорировать ошибку, а затем как можно быстрее портализировать уровень, после чего менять масштаб уже можно будет, но лишь до выхода из DromEd - при последующей попытке поменять масштаб игнорирование не помогает - происходит вылет. Возможно, дело в выравнивании по сетке - про то, как это можно исправить, см. пункт 2.3.

2.6. Немного о "переходных" типах заполнения brush'ей. Честно говоря, плохо понимаю пока что, как они могут пригодиться на практике - разве что если при проблемах с выравниваем по сетке, большом количестве brush'ей или сложных геометрических формах. В оригинальных миссиях эти вещи же любили использовать.
solid -> water: В пределах этой brush'и, любое твёрдое вещество превращается в воду, но только твёрдое. При помощи таких brush'ей можно, к примеру, создавать бассейны.
solid -> air: Превращает твёрдое вещество в воздух (не трогая при этом воду). При помощи этого типа можно создать, к примеру. отдушину от воды сложной формы одним махом, а не 2-3.
air -> solid: превращает воздух в твёрдое вещество, не затрагивая при этом воду. При помощи такой brush'и можно создать, допустим, плавающую на воде конструкцию с её продолжением на берегу.
water -> solid: превращает воду в твёрдое вещество, не трогая при этом воздух. Это может послужить в создании подводных объектов (или объектов одной формы под водой и другой - над ней.)



Часть 3. Простейшие источники света (lights); потоки (flows); участки (areas).




3.1. Про свет. Можно создать источник света "из ниоткуда" двумя путями: или выбираем Light (внизу), затем выбираем тип - Omni или Spot, вводим яркость, или же в объектной иерархии выбираем fnord/HackLight.
Разница между этими двумя подходами следующая. Light brush'и (которые только Omni или Spot) считаются как обычные браши, а не как объекты. Несмотря на то, что можно выбирать между двумя разными типами источника, я не заметил разницы между Omni и Spot - они оба излучают свет из заданной точки во всех направлениях одинаково. Причём радиус, в котором излучается свет, считается равным бесконечности и не может быть изменён - менять можно только яркость.
Второй подход более разнообразен, но тут уже имеем дело с объектами. Тип Omni аналогичен light brush'и - свет из одной точки в пределах шара с заданным радиусом. Стоит заметить, что при большой яркости и малом радиусе освещённость может быть прерывистой, т.е. вокруг источника света будет ярко, а затем - резкий переход к абсолютной темноте. (Это не чревато ошибками, но выглядит неподобающе.)
Тип Spot - световое "пятно". Излучает свет в пределах воображаемого конуса с задаваемыми размерами (см. пункт 4.44).
Тип Anim наиболее сложен. Грубо говоря, это "анимированный" источник света, но анимация эта может быть различной - мигание, плавный переход от менее яркой освещённости к более яркой и т.д. - вспоминаем оригинальную Escape!, где представлены многие варианты анимации. Более того, один из таких видов анимированных источников света - включаемые/выключаемые лампы, именно AnimLight-свойства позволяют им менять яркость на неопределённое время. К тому же, анимацию можно добавлять как источникам типа Omni, так и источникам типа Spot.

3.2. Чтобы Гарретта несло течением в воде, создаём собственно течение (flow). Перед этим - brush и в Op выбираем fill water, flood или "переходной" тип, позволяющий создать воду в желаемом месте. Потом flow следует поместить так, чтобы его координаты в точности совпадали с координатами brush'и. Далее выбираем нумер группы (от 1 до 64) и нажимаем Edit Group. Здесь стоит обратить внимание на: x change/sec, y change/sec, z change/sec, angle change/sec. (angle - угол), а также Texture Name. Сюда вводим gr, если хочется зелёную воду, или bl, чтоб вода была голубой. (Более подробно про это написано в части XIV DromEd Tutorial.)

3.3. Долгое время я пытался создать лаву, не получалось. Путь создания был таков: я создавал течение (flow), затем редактировал группу под неким номером, где в поле "Текстура" указывал l3 или l4 (текстура лавы, которая содержится в архиве fam.crf). Далее я выбирал Object Hierarchy и в раскрывающемся списке наверху выбирал Flow Groups (вместо обычного Archetypes). И там я насильно перетаскивал свежесозданную группу из Water Flow Group в Lava Flow Group. Как заставить программу сразу же сделать её лавовой группой - я тогда не разобрался. (Теперь вроде разобрался: можно оставить группу в Water Flow Group, выбираем Renderer -> Water Flow Color Index, вводим туда 2. Затем Act/React -> Sources. Создаём новый "сигнал", обжигающий Гарретта при попадании. Объект - наша группа потока, стимул - FireStim, propogator - flow, интенсивность - не больше 10, если хотим оставить себе ещё шанс на выживание. По всей видимости, именно стимул FireStim отличает воду от лавы, в остальном это просто перекрашенная вода.)

3.4. Чтобы выделить большое количество brush'ей в одну multibrush, достаточно окружить все необходимые brush'и Area Brush'ью (так, чтобы brush'и немного выпирали из неё - она захватывает в себя и те brush'и, которых касается). Затем выбираем Me Only (чтобы изменилась на Not Me Only), после - mulibrush me. И тащим нашу multi brush куда хотим. Но не стоит забывать, что любая координата любого центра brush'и не может превышать 1000 и быть меньше -1000. Кроме того, после перемещения стоит проверить выравнивание нашей multi brush по сетке - см. пункт 2.3.

3.5. Некоторая могущая оказаться полезной информация о воде и потоке (flow) - по этой ссылке:
http://www.ttlg.com/forums/showthread.php?t=71395&highlight=tutorial



Часть 4. Объекты: Свойства (Properties).




4.1. Чтобы закрыть дверь или сундук на замок, выбираем Engine Features -> Locked и ставим галочку. (При этом в точке (0;0;0) может появиться некоторое количество объектов (Object) (-1). Не знаю, почему это происходит; я их обычно удаляю, после чего вхожу в игру, выхожу обратно в режим редактора, выбираю Tools -> Build Room Database, после чего всё снова приходит в норму.)

4.2. Но чтобы получить от этого удовлетворение, нужно ещё и как-нибудь открыть его... (Менее подробно и по-английски про пункты 1 и 2 можно прочесть в части XIV файла DromEd Tutorial. - Прим. 11/08/07.)
4.2а). Если охота отпереть его отмычками, то выбираем DarkGameSys -> PickCfg. Стоит учесть, что в первые строчки (LockBits) надо вводить или 1, или 10 - это определяет, какой отмычкой будем отпирать. (Хотя, если ввести 11, то будут допущены обе.) Вторая - Pins - количество щелчков, при достижении которых замок будет взломан до следующей стадии. Третья - TimePct - сколько времени будет затрачено на взлом указанной стадии. Видно, что стадий этих не может быть больше трёх. (Чтобы взламывать замок в 1 или 2 захода, достаточно поставить все нули в полях ненужных стадий.)
4.2б). Ключ. Для этого нужно создать ключ и, выбрав его, выбрать Propeties, а затем Engine Features -> KeySrc. Лично я не знаю, что означают эти поля ввода. Лично я в первое ввожу всегда 1, а в нижнее - число от 1 до 9. (Также в верхнее поле можно вводить 10 или другое двоичное число.) Галочку не ставлю. Далее выбираем дверь, Properties, и затем Engine Features -> KeyDst. Для того, чтобы дверь можно было открыть ключом, нужно, чтобы KeySrc ключа и KeyDst двери полностью совпадали. (Если вместо двери будет замок, действия производим те же.)

4.3. Создание третьей отмычки - казалось бы, вещь простая, но есть одна закавыка - номер. Ясно, что отмычка практически ничем не отличается от обычного ключа, ей нужно лишь назначить PickSrc (DarkGameSys -> PickSrc) в виде некоего числа. Какого? Желательно ввести двоичное число, рекомендуется от 10 и выше. 10 у нас - одна из отмычек (не помню точно, какая), а 1 - другая отмычка, так что 11 - их сумму - лучше не применять. Введём 100. А в замке, что эта отмычка может открыть, в графе LockBits теперь можно написать такие числа: 1; 10; 11; 100; 101; 110; 111. Как нетрудно догадаться, при 1, 10 или 100 можно будет открыть только одной отмычкой, при 11, 101 или 110 подойдут две, а при 111 - все три.
Оригинал находится здесь:
http://www.thief-thecircle.com/dromed/displaysubject.asp?titleID=225&title=A%20Quick%20and%20Easy%20Third%20Lockpick&sub=Objects

4.4. Чтобы враг не просто стоял, а поворачивался из стооны в сторону, выбираем AI -> Ability Settings -> Idling: Directions. Первые 2 окна - время (в течение которого враг повернётся, в миллисекундах), далее - угол поворота в градусах относительно первоначального положения и вероятность (целое число, определяет долю из общих вариантов поворота - т.е. при двух вариантах с вероятностями 9 и 5 AI повернётся в первом направлении с вероятностью 9/14).

4.5. Можно ухудшить или улучшить видео- и аудиоспособности твари (или человека). Выбери AI -> Attibutes -> Hearing или AI -> Attributes -> Vision. Правда, если наткнёшься на врага, тебя не спасут ни его нулевое зрение, ни его нулевой слух.

4.6. Кроме зрения (vision) и слышимости (hearing) врага у него в атрибутах также могут быть: агрессивность (aggressive), "тормозность" (sloth), степень "уклоняемости" (dodginess), ловкость (aptitude), степень самозащиты (defensive) и "многословность" (verbosity). Правда, если это всё поставить на самое крупное (а sloth - на 0), всё равно мало что изменится. (Разумеется, на мой взгляд.)

4.7. Чтобы кто-нибудь перешёл на нашу сторону, выберем AI -> Ability Settings -> Combat: Non-hostile и выбираем Always to player (Если выбрать Always, то он будет не враждебен ни к своим кровным врагам - мертвецам, ни к кому другому вообще. Про данное свойство также написано в части XIV файла DromEd Tutorial.)

4.8. Ещё одна классная штука - команда (Team). Выбираем AI -> AI Core -> Team. Good - эти ребята враждебны ко всем, кроме своих и тебя. Neutral - сражаться не сражаются, а только ищут, если совсем уж никак. Да и их никто не бьёт. Bad'ы - это враги. Причём одна интересная деталь: ребята из двух разных команд (например, Bad 1 и Bad 5 - охранники и нежить) всегда враждебны (т.е. могут драться друг с другом). Вот вам и бесплатное зрелище битвы.

4.9. Та "музыка", которая слышна в миссиях, это, не что иное, как т.н. ambience. Чтобы, например, сделать так, чтобы во время старта раздавался характерный звук, выберем Editors -> Object Hierarchy, а затем fnord/ambientSound. Создадим эту штуку так, чтобы её координаты полностью совпадали с координатами StartingPoint'а, а затем выберем ambientSound и нажмём "Properties". Если охота, можно изменить название нашей ambientSound (традиционное - "amb start"). Выбираем A -> AmbientHacked. В верхнее поле введём 5 (объясню, почему), во 2м оставим 0, далее выберем RemoveProp (OneShot), а далее - в Schema Name - введём или m01start, или m02start, или... без разницы, годится число вплоть до 17 (по номерам миссий). Лично я почему-то всегда ввожу m16start. (RemoveProp означает, что данная schema будет "проиграна" лишь один раз - это годится, например, для одного устрашающего звука или "создания напряжения" (см. архив schema.crf/amb_m??, где ?? - номер миссии - там много чего интересного написано).
Для ветра на улицах вместо RemoveProp (OneShot) выберем Environmental - при пересечении такого ambientSound в указанном радиусе звук будет проигрываться до бесконечности до тех пор, пока не пересечёшь другой ambientSound с другим звуком и/или бОльшим радиусом.
Для музыки - ставим флажок Music (например, m05rising или m15bigbeet).
Или же есть другой путь (то ли который не работает, то ли его не позволяет оценить моя звуковая карта) - выберем комнатную brush, жмём Edit, затем выбираем Room -> Ambient. Ну и там всё почти по аналогии. Если оставить ambientSound без свойств (т. б. во Flags оставить None), то звук, издаваемый ей, будет слышен на указанном радиусе (в этом случае - на расстоянии 5 единиц или ближе, при этом сама ambientSound будет источником звука (т. б. при отдалении тебя от него звук будет утихать). Если же выбрать Environmental, то это свойство "источника звука" отключится, и звук будет слышен на любом расстоянии, пока не "перекроется" другой ambientSound - как это уже сказано выше).

4.10. "Использовать" на "сухом языке" - техническом, то бишь - называется Frob. Чтобы сделать, например, дверь неактивной (т. е. чтобы её нельзя было использовать и она бы не "засвечивалась"), выберем Engine Features -> FrobInfo и везде поставим None. (Хотя, строго говоря, достаточно убрать все флажки в первой строчке - WorldAction. Вторые две - InvAction и ToolAction - относятся к объектам, которые можно взять в инвентарь, и отвечают за последствия простого использования объекта в инвентаре и за взаимодействие объекта с другими объектами соответственно.)

4.11. Если же охота сделать лампу или факел менее яркой, то выбираем Renderer -> Light или Renderer -> Anim Light. Там всё довольно просто - нужно просто поменять параметр Brightness. Но в Anim Light в поля под раскрывающимся списком type лучше вводить числа около 1000, а то глазам очень лохо будет - мигать будет очень быстро. (Значения эти указываются в миллисекундах, оттого при маленьких числах и мигает быстро.)

4.12. Можно ещё и выбрать уровень "пугливости" врага. Выбираем AI -> AI Core -> Alertness cap. Там всё довольно просто: 0 означает, что AI абсолютно спокоен, 1 - встревожен (обычно на 1-м уровне AI пребывает от фразы "Кто там?" до фразы "Наверное, крысы", если между двумя этими фразами его не побеспокоить сильнее), 2 - сильно встревожен - ищет, хотя не уверен, что вы здесь есть; как правило, на 2-м уровне AI ищет в течении примерно десятка секунд, после чего возвращается на 1-й уровень. Третий уровень означает максимальную встревоженность - либо AI услышал очень громкий звук, либо только что потерял вас из виду и хочет найти снова, т.е. во всех случаях он уже знает, что вы здесь есть. Пиковый момент, про который упомянуто в третьей строчке, - по всей видимости, момент боя, когда AI видит вас и сражается с вами.
Несмотря на то, что про уровни встревоженности я объяснил на примере боевых AI, у безоружных уровни встревоженности точно такие же, просто они себя ведут по-другому из-за другого типа AI.
(Про этот пункт кратко написано в части XIV DromEd Tutorial. - Прим. 11/08/07.)

4.13. Ещё одна важная вещь - убегание (flee). Как правило, если хорошо ранить охранника (или тебя увидел слуга), он начинает куда-то бежать. Но куда? Вот в чём вопрос. Создаём маркер и выбираем AI -> Utility -> Flee point. В инструкции (файле DromEd Tutorial.doc) сказано, что здесь надо вводить число от 1 до 100 - оно означает вероятность в процентах, что AI побежит именно к данному пункту. Однако, как правило, AI всё равно бегут не к точке с максимальной вероятностью, а просто к ближайшей. (Не стоит также забывать, что, добежав до одной точки, AI может побежать к другой.)

4.14. Немного ещё про flee. Выбираем AI -> Ability Settings -> Flee: Condition for flee. Здесь устанавливается, когда враг будет убегать, а когда сражаться. Интересное замечание отсюда: нежить не убегает никогда, причём это свойство зашито у них в "корне" (см. свойства архетипа Undead). (Про это также написано в части XIV DromEd Tutorial.)

4.15. Охота сделать врага живучее? Лично у меня уже несколько "монстров-боссов". Выбираем Game -> Damage Model -> Max Hit Points, а затем Game -> Damage Model -> Hit Points. Max Hit Points необходимо указывать для того, чтобы проигрывались звуки удара меча/дубины/стрелы о тело AI, если Max HP будет меньше HP, звук проигрываться не будет.
Базовое повреждение от меча и обычной стрелы лежит где-то от 2 до 5, так что если ввести что-нибудь побольше 100, бить его придётся очень долго... (Про это также написано в части XIV DromEd Tutorial, но менее подробно.)

4.16. Чтобы враг стал вообще неубиваемым, выбираем Game -> Damage Model -> Slay Result. И No Effect. (Destroy означает, что враг удалится с уровня, как будто в процессе игры он выделился, и нажалась невидимая клавиша Delete. Разница между Normal и Terminate, возможно, в эффектах после смерти - при Normal они присутствуют, при Terminate отсутствуют. Хотя я пока в этом до конца не разобрался.)

4.17. Можно изменить голос существа (например, чтобы зомби говорил по-человечески, а Трикстер - как каракатица). Выбираем Speech -> Voice и введём. Если не знаем точно, выбираем в иерархии Sound/Voice, там все голоса. Не стоит даже пытаться создать собственный голос на первых порах, это трудно. (Хотя и возможно, и реально, при создании архетипа голоса в иерархии объектов, сохранении gamesys'а под новым именем, создании папки и файла в ней schema\VOICE.sch в папке Thief (по образцу папок в архиве schema.crf), где VOICE - название созданного голоса, расписать там всё по аналогии, как у других, затем создать папку VOICE/english, куда поместить сами звуковые файлы. Но этот приём на практике ещё не проверен. Также, если это не будет работать, вероятно, нужно ввести ещё и индекс голоса. Делается это почти так же: Speech -> Voice Index, вводим то число, которое стоит у нашего голоса в свойствах в иерархии объектов. И здесь ещё одно ограничение - индекс у каждого голоса уникален, и он не должен превышать определённое число. В Thief Gold столько голосов, что на дополнительные, кажется, номеров уже не хватает.)

4.18. Чтобы, например, кошель добавлял не 100 золотых, а, к примеру, 50, выбираем DarkGameSys -> Loot. Вводим 50 вместо 100. А если эту вещь надобно украсть (т. е. нужно создать цель), в Special надо поставить 1, а затем ввести в командную строку: quest_create_mis goal_special_x, 1 (x - нумер цели). Тип цели x должен ОБЯЗАТЕЛЬНО быть 3 (ограбь на ... монет), а не 1 (сопри объект). (Частично про этот пункт также написано в части XIV DromEd Tutorial.)

4.19. Чтобы поместить на уровне труп, надо немного поработать. Вначале создаём живое существо, а далее уж работаем. Для начала выбираем Creature -> Current Pose. Там вводим следующее: в первой строчке оставляем Tags, во вторую - вводим crumple, die; в третью - 1.00, в четвёртую - 0.40. Галочку убираем. Потом Game -> Damage Model -> Slay Result. Выбираем No Effect. Потом Creature -> Is Non-Physical. Ставим галочку. Усё. (А можно не маяться со всей этой кучей свойств и просто добавить метасвойство M-PosedCorpse.)

4.20. Кто сказал, что все трупы должны лежать строго на животе? Можно положить мертвеца на спину: в Creature -> Current Pose (при уже добавленном M-PosedCorpse!) во вторую строчку вводим zombie, crumple. (Нет, от этого он не будет вставать, как зомбак. Возможно, есть и другие варианты поз, но где их можно найти - я на данный момент без понятия.)

4.21. Можно сделать так, чтобы какой-либо предмет появлялся на одной сложности и исчезал на другой. Выбираем Difficulty -> Destroy. И выбираем номера сложностей - 0, 1 или 2. На этих сложностях предмет исчезнет. (Про это написано в части XIV DromEd Tutorial. Также можно попробовать поэксперементировать с пунктом Turn On/Off в отношении ламп, хотя и осторожно - у меня при стоящем на изначально выключенной лампе свойстве TurnOn(Off) лампа постоянно мерцала, как будто всё время находилась в переходном процессе от выключенного состояния к включённому. Можно также проверить и другие свойства в разделе Difficulty, но, похоже, Destroy - едва ли не единственное из них, которое стабильно работает.)

4.22. Можно ещё натворить разные штучки с комнатами. Вообще, я не рекомендую все комнаты уровня оставлять Default Room'ами, а сварганить хоть и небольшую, но иерархию комнат. (Примечание: лично мне для создания работающей иерархии комнат не потребовалось изменять gamesys, хотя иерархия комнат входит в иерархию объектов.)
Чтобы местонахождение игрока в данной комнатную brush показывала автокарта, выбираем Room -> Automap. Там вводим нужные числа (от 000 до плюс бесконечности) и создаём файл с названием типа "pPPPrLLL.pcx", где PPP - нумер, который ввёлся в Page, а LLL - нумер, что ввёлся в Location. На этом, похоже, мучения внутри DromEd по части автокарты закончены, теперь нужно воспользоваться сторонними программами для окончания создания автокарты.

4.23. Ещё можно выбрать акустические свойства комнаты. Например, захотелось сделать лабиринт. И комнаты этого лабиринта должны быть соответствующими. Выбираем комнату, жмём Edit, затем выбираем Add -> Room -> Acoustics. Для лабиринта подходят Dizzy (головокружительные) или Psychotic. Там ещё ку-уча разных других вариантов!

4.24. Чтобы превратить купца (merchant) в Рамиреса (лучше всего это делать именно с купцом, хотя бы потому, что в миссии про убийцы Рамирес был "создан" тоже из купца), для начала создаём собственно купца, а затем Properties, выбираем Add -> MetaPropety -> AIBehaviours -> AI-B_m5 -> M-BaseRamirez. И всё.

4.25. Можно изменить модель персонажа. Например, нужно превратить слугу (servant) в Сutty. Выбираем Shape -> Model Name. Там введём название. Для Cutty оно называется, если не ошибаюсь, expcuty. Названия этих моделей можно посмотреть в архиве mesh.crf, если речь идёт об AI, и в архиве obj.crf, если речь идёт об объекте. Имя необходимого файла будет с расширением .bin.

4.26. Чтобы существо светилось, выбираем у него в Propeties Renderer -> Self Lit и введём, например, 60 - это яркость. Затем Renderer -> Extra Light, но там ничего не изменяй. При этом существо излучать света не будет, просто станет выглядеть ярче.

4.27. Ещё чуть-чуть об оптических свойствах предметов. Свойство Renderer -> Extra Light позволяет регулировать поглощение/отражение света объектом. Если Amount равен -1 - тело абсолютно чёрное, 1 - его антипод, подсвечивается, как будто вы на него сфокусировали взгляд. Renderer -> Transparency (alpha) регулирует прозрачность. При 0 тело полностью прозрачное - то есть, скорее всего, невидимо, при 1 - непрозрачно. (К примеру, у привидения - Apparition - прозрачность 0.75, то есть что-то видно сквозь него, но уже тускло.). Ещё можно сделать объект невидимым: Renderer -> Render Type и выбираем Not Rendered. (Например, это свойство стоит у ApeBeast'а, что "неожиданно прибегает" в логово осаждённых Хаммеров - сколько в окошко ни высовывайся, его не увидишь.)

4.28. Наверное, замечали, что если дать охраннику голос пьяного, он от этого шататься не станет. Чтобы он шатался, выбираем Motions -> ActorTagList. К WithSword0 добавляем следующее: ", Drunk 0" (без кавычек). Кроме того, можно заставить его вести себя (в плане стиля движений. - Прим. 11/08/07.) как другие существа. Попробуйте также: Nothing, BugDemon 0, ApeBeast 0, Crayman 0, NoFall, Doof, IsBox 0, Cutty, Zombie 0, DancerOne, DancerTwo. Особенно забавно всё это выглядит с Crayman 0 - видимо, только с раколюдьми всё так идеально. А вот если поставить это на человека, то его будет из стороны в сторону носить. Так забавно!

4.29. Хочется, чтоб Константин при ходьбе шагал именно так, как Трикстер, а не охранник (т. б. изменился звук шагов)? (По умолчанию звуки шагов Константина такие же, как и у человека.) Выбираем Schema -> Class Tags и вводим CreatureType ConTrick. Вообще, свойство Class Tags (и прочие Tag'и в группе свойств Schema) отвечает за воспроизводимые объектом звуки. Чтобы лучше понять, зачем они нужны, стоит покопаться в .sch-файлах (архив schema.crf), отвечающих за звуки шагов, звуки ударов одного предмета о другой или просто разные звуки, издаваемые предметами. И там будет написано, что для каждого класса объектов звук будет свой. С Material Tags всё примерно аналогично, только речь идёт уже не о классе объекта, а о материале, из которого он сделан.

4.30. Надо, чтобы в инвентаре объект назывался по-другому? Выбираем Inventory -> Object Name. Например, для ключа от кладбища оно такое: Name_cemetarykey. (Можно также создать своё имя объекта, для этого необходимо открыть файл Objnames,str в архиве Strings.crf и ввести там "своё" имя по аналогии - к примеру, такую строчку:
Name_AncientPapyrus: "ДРЕВНИЙ ПАПИРУС"
Затем в поле пункта Object Name вводим Name_AncientPapyrus. И этот папирус теперь будет называться не "ПАПИРУС", как обычно, а "ДРЕВНИЙ ПАПИРУС". В этом случае .str-файл следует включить в папку strings, последнюю положить в пак с миссией. Подробнее про включение файлов в пак с миссией см. часть 8.0.

4.31. Чтобы решётка открывалась не влево-вправо, а вперёд-назад или вверх-вниз, открываем Properties, ищем в окне свойств Door -> Translating, выделяем то, что там. Нажмём Edit. Там, где x-axis, меняем на y-axis, чтоб дверь двигалась вперёд-назад или z-axis для "вверх-вниз".

4.32. Чтобы лягушка создавала чуть ли не термоядерный взрыв, от которого нигде не укроешься, выбираем у неё в Properties AI -> Ability Settings -> Frog-beast: Explode range. Ну и введём там число побольше. (Повреждения при этом взрыве, однако, будут такие же.)

4.33. Чтобы превратить зомбя в лежачего, выбираем MetaPropety, там откопаем M-ZombieBehaviours и там найдём M-ZombiePossum.

4.34. Чтобы объект можно было сделать драгоценным (т. е. чтобы он появлялся в качестве драгоценности, прибавляющей деньги, в инвентаре), мало одной команды DarkGameSys -> Loot. Тут надо ещё кое-что, а именно: в первую очередь ставим скрипт LootSounds (через S -> Scripts). Далее смотрим Engine Features, а именно FrobInfo. Там в первой опции ставим два флажка на Move и Script, остальные оставляем None'ами. Затем - в тех же Engine Features - выбираем Combine Type, вводим туда Loot. Далее выбираем Inventory и смотрим, что там: сначала выбираем пункт Can't Drop This и ставим галочку, а затем - Type и в раскрывающемся списке выбираем Item. Ну а вот уж потом можно и указывать, сколько там ценностей она прибавляет... Правда, есть один небольшой баг - при взятии такой "драгоценности" раздаётся такой же звук, как и при взятии, к примеру, эликсира или мины. Но это бывает только в том случае, если подобранный предмет - первая драгоценность на уровне, попавшая к вам в ручки. Если же не первая - то звук будет традиционным. Так что лучше спрятать их хорошенько на уровне, чтоб баг был незаметен... (Однако можно вместо всего этого добавления свойств просто выбрать Add -> MetaPropety -> IsLoot.)

4.35. Чтобы дверь нельзя было открыть ударом, я лично тупо ставлю двери большое количество Hit Points'ов - ведь, как известно, если дверь открывать ударами, то она откроется, только "умерев". Вот и поставил я, к примеру, дверке ReinfWood4x8 Max Hit Points - 5000, Hit Points - 2000. Если у игрока хватит терпения открыть её ударами - честь ему и хвала...)

4.36. Есть масса скриптов, позволяющих сделать объект подобием рычага или другого объекта. После установки некоторых из этих скриптов на предмет (S -> Scripts) следует проверить FrobInfo нашего объекта. Там должно в графе WorldAction стоять Script, если не стоит, добавьте. Иначе ничего не будет работать. Где именно нужно редактировать FrobInfo - оговорено специально.
TrigRoomPlayer. Один из самых важных скриптов, делающий комнатную brush способной посылать сигналы, передаваемые через ControlDevice. Комнатная brush с таким скриптом будет посылать сигнал на включение на свой ControlDevice всякий раз, когда игрок будет входить в неё. (Будет ли она посылать сигнал на выключение при выходе - точно не помню.)
TrigRoomCreature - аналогично TrigRoomPlayer, только активировать будет уже не только игрок, но и любое другое живое существо.
TrigSlain - при этом скрипте при смерти товарищ активирует то, ControlDevice'ом к чему является.
TrigUnlock - при открытии замка (двери, сундука или просто замка) активируется то, ControlDevice'ом к чему замок является.
TrigDoorOpen - при открытии двери активируется то, ControlDevice'ом к чему дверь является. Правда, при этом сама дверь может исчезнуть. Если такое произойдёт, то это, скорее всего, означает, что новый скрипт конфликтует с "врождёнными". Нужно поставить галочку Don't Inherit в окошке S -> Scripts.
TrigWorldFrob - скрипт с более широкой степенью охвата, чем предыдущий. Объект с таким скриптом посылает сигнал включения при использовании в игре, но при этом только при нахождении вне инвентаря (если его можно туда взять).
TrigInvFrob - аналогичен TrigWorldFrob, только предмет посылает сигнал включения, будучи использованным в инвентаре. (Не очень понятно, будет ли, к примеру, ключ с этим скриптом посылать сигнал, если его применить на двери - по логике, должен быть ещё и скрипт TrigToolFrob (вспоминаем три строчки во FrobInfo, о которых написано в пункте 4.10), но такового не существует. Возможно, здесь InvAction и ToolAction рассматриваются как одно и то же.)
StdElevator - делает объект передвигаемым, как лифт. Хотя, одного этого скрипта недостаточно: чтобы иметь полную аналогию с лифтом, нужно выбрать Physics -> MovingTerrain и поставить галочку. В этом случае объект будет самопроизвольно двигаться от одного TerrPt'а до другого, не останавливаясь. Чтобы он вёл себя как управляемый лифт (который кнопками вызываешь), добавляем ещё 2 скрипта - StopAtWaypoints (нужен для того, чтобы лифт останавливался у каждого пункта) и ElevatorSounds. Затем в Schema -> ClassTags и ввести DeviceType ElevHmr, например. (В этом случае предмет при передвижении будет издавать такие же звуки, как и лифт Хаммеров. Другие типы схем лифтов можно подсмотреть в архиве schema.crf или даже попытаться создать самостоятельно... но об этом не здесь.)
TrapInverter - как здесь видно из названия, он добавляет объекту свойство Inverter'а (обращает приходящий сигнал от ControlDevice'а - вкл. превращает в выкл. и наоборот.)
TrapRequireAll - аналогично остальным Trap'ам. Как, опять же, видно из названия, добавляет объекту свойства RequireAllTrap.
TrapRequireAny - аналогично RequireAllTrap'у, только добавялет свойство RequireAnyTrap.
TrapRelease - добавляет объекту свойство ReleaseTrap - объект при активации освободит от связи ~Contains все ~ControlDevice'ы к нему.
TrapTeleporter - а вот этот скрипт, я считаю, целесообразно применять только на небольших объектах. Ну сами подумайте - что будет, если в центр дерева попадёт драгоценность? Правильно, в наихудшем случае вы не сможете до неё дотянуться. А это не есть хорошо. Как видно из названия, добавляет объекту свойство TeleportTrap'а.
TrapRelay - добавляет объекту свойство RelayTrap'а, просто передающей сигнал ControlDevice'а дальше, на свой ControlDevice.
TrapTweqEmit - тоже, думаю, годится лишь для небольших объектов. Добавляет свойство EmitterTrap'а выплёвывать всякие нехорошие да вредные снаряды. Можно применять в совокупности со скриптом ReloadTweqEmit, чтобы число выстрелов было бесконечным.
TrapConverse - позволяет объекту заведовать ведением беседы AI (conversation). Более подробно об этом написано в пункте 6.8.
EatFood - делает объект съедобным. Здесь небольшая оговорка: во FrobInfo такого предмета, помимо Script, в графе WorldAction должно стоять ещё и Move, чтобы вещь переместилась к вам в инвентарь; а в графе InvAction - Script и UseAmmo. Script - понятно почему (чтоб съелось), а UseAmmo - чтобы учитывалось количество съеденных предметов.
StdScroll - этот скрипт обычно даётся книгам, чтобы их можно было взять в инвентарь и потом прочесть. Для этого, помимо замены скрипта StdBook на наш StdScroll, вписываем во FrobInfo книги следующее: WorldAction - Move; InvAction - Script. И желательно ещё выбрать Inventory -> Object Name, ввести какое-либо имя из strings.crf\objnames.str (или своё придумать), чтобы книга как-то называлась, будучи в инвентаре.
Container - при помощи этого скрипта предмет может содержать собой что-либо, и при его использовании вы получите содержимое (связанное с ним связью ~Contains), как и при использовании обычного сундука.
TrigWorldFocus - по всей видимости, активирует свой ~ControlDevice в тот момент, когда вы глядите на объект (он подсвечивается). У FrobInfo такого объекта в графе WorldAction должно стоять FocusScript, чтобы сработало.
Есть ещё скрипт CollisionStick. Предмет с таким скриптом прикрепляется ("приклеивается") к поверхности. Но, во-первых, я не видел, чтоб этот скрипт работал; а во-вторых, не совсем понимаю, зачем это нужно. Разве что для того, чтобы объект мог держаться, например, на стене и не падать. С другой стороны, почему тогда картины спокойно висят и не падают?.. Вопрос пока открытый.
Ещё скрипты: TrapQVar - добавляет свойства триггера, изменяющего цели.
TrigAIAlert - AI при переходе на максимальный уровень встревоженности активизирует свой ControlDevice. Стоит заметить, что однажды обеспокоенный AI при быстрой смерти (например, от стрелы) успевает перейти на максимальный уровень встревоженности.
SecureDoor - он, видимо, ставится на дверь, и AI, проходя через/мимо неё, при изменении положения двери (открыли и забыли закрыть, к примеру) AI будет сильно нервничать. Насколько сильно, правда, я пока не проверял. К тому же, в Thief 1 этот скрипт, похоже, не работает - только в Thief 2.
(FrobInfo редактировать нужно лишь для указанных случаев, потому что использование предмета и его включение - это совершенно разные вещи, одна на другую никак не влияет. Если мы даём сигнал от ControlDevice'а, то это всегда сигнал на включение или выключение, а не на использование. Поэтому FrobInfo предметов, на которые вы поставили скрипты, начинающиеся на Trig или Trap, точно менять не надо. Если же требуется подать сигнал на использование предмета, для этого больше подойдёт связь FrobProxy, подробнее см. пункт 5.13.)

4.37. Ещё одна вещь - Act/React. Используется в основном для повреждения чего-либо, хотя в некоторых fm'ках и для других целей (причём довольно разнообразных). Но тут я рассматриваю только то, что можно натворить на базовом уровне, без своих скриптов/gamesys и прочих штучек.
Итак, Act/React. В окне Properties у него есть 2 пункта меню: Sources (источники) и Receptrons (приёмники). Как нетрудно догадаться, source - оружие, receptron - то, что получает повреждение (AI, дверь или Гарретт.)
Source. Тут всё довольно просто: какие типы повреждений (шире говоря - сигналов) может наносить (излучать) данный источник. Для обычного меча, например, это SlashStim. Если меч хочется сделать огненным - добавь FireStim (intensity достаточно 2), освящённым - HolyStim, и т.д. Тут всё достаточно просто.
Receptron. Почти так же просто: реакция объекта на внешнее воздействие. Можно сделать так, чтобы на зомби не действовала святая вода (в строчке HolyStim исправить Damage object на Ignore), но зато его можно было бы оглушить (KnockoutStim)... Простор имеется. Более подробные примеры применения Act/React рассматриваются уже при комбинировании различных свойств и связей - как правило, при сложных задачах это наиболее хороший инструмент.
(Примечание: если при открытии окна Receptrons в него не внести ни одного изменения, то DromEd вылетит с ошибкой. Очень желательно вообще сохраняться перед экспериментированием с Act/React, так как удаление ранее поставленных свойств Sources или Receptrons может также грозить багами или вылетом программы.)

4.38. Чтобы объект стал источником света, никаких скриптов к нему приписывать не надо, просто выбираем Renderer -> Light или Renderer -> Anim Light и вводим там нужные параметры. Таким образом можно сделать висящий канделябр светящимся, который по умолчанию почему-то никакого света не излучает.

4.39. Может случится так, что объект по замыслу должен висеть в воздухе, но в игре он просто падает на землю. Чтобы такое не случалось, в свойствах объекта выбираем Physics -> Model -> Attributes (НЕ в меню, а в окошке! Оно там всегда есть для любого физического объекта). И в графе Gravity % ставим нолик.
Есть и другой способ - посмотреть его свойства Physics -> Model -> Control (тоже не в меню, а в окошке) и поставить галочки Location, Rotation. Этот способ лучше применять к стрелам, ключам, бомбам/минам и прочим объектам, которые можно уронить, запустить и т.д. - изменение свойства Gravity % таких объектов может быть чревато.

4.40. Отдельная история про скрипт Extinguishable - при помощи этого скрипта можно будет погасить горящий предмет - например, поставить его на горящую свечу. Однако чтоб её можно было потушить, одного скрипта мало. Во-первых, нужно, чтобы сама свеча излучала свет - для этого выбираем Renderer -> Anim Light и вводим там лучше всего такие же параметры, как и у факела: тип - maximum brightness, время - по 1 миллисекунде на brighten и на dim, max brightness ставим 100, минимум оставляем 0. Дальше ничего не изменяем. Далее, выбираем Act/React -> Receptrons, чтобы указать на то, что если в свечу попасть водяной стрелой, то она потухнет (то есть применится скрипт). Выбираем Add, в окошке с 0 (None) набираем номер нашей свечи, в стимуле выбираем WaterStim. В раскрывающемся списке справа находим пункт Send to Scripts, и в окошках intensity под max ставим галочку. OK. Всё, теперь можно потушить нашу свечу водой. Ещё можно потушить огонь газовой стрелой, хоть это и дурацкая прихоть, но можно и с ней так же поступить: всё выбираем то же самое, только стимул выбираем не WaterStim, а KOGas (KnockOutGas, видимо). Чтобы можно было обратно зажечь (хотя со свечой это, по-моему, уже слишком), абсолютно то же самое проделываем со стимулом FireStim.
Теперь, если войти в игру с такими параметрами предмета и потушить его, то мы увидим нечто странное: на месте нашей свечи образовался потухший факел, а огонь продолжает гореть! Хотя и правда стало темнее. (Как нетрудно догадаться, в момент потушения просто происходит смена модели свечи, и свет прекращает литься именно из-за исчезновения старой модели.) Так что укажем, что на месте нашей свечи должна быть именно свеча, а не факел. И без огня. Выбираем Tweq -> Models и начинаем там копаться: в раскрывающемся списке Halt выбираем Continue, в AnimC - NoLimit; в MiscC - Anchor, Random; в CurveC - JitterHi. Далее в Rate вводим 125 (по крайней мере, так у факела...), а в Model 5 - то, во что превратится наша свеча. (Да, именно в Model 5, а не Model 0, скрипт ориентируется именно на это поле. - Прим. 22/06/09.) В данном случае это candle1 (если вы выбрали candle1). И ещё: в Tweq -> ModelsState в первой графе ставим галочку на On, вторую и дальше не меняем. Да, и последний штрих: чтобы всё выглядело реалистично, создаём огонёк (TorchFlameYellow) и дым (TorchFlameSmoke) и привязываем каждый к свече связью ParticleAttachement. При этом частицы, скорее всего, будут идти не от фитиля свечки, а от центра, что довольно странно. Чтобы исправить это, в свойствах у частиц SFX -> Particle Launch Info нужно поставить значения Box Min = 1 и Box Max = 1. (в полях Z). Это будет означать, что "коробка", в которой будут витать частицы, переместится на 1 единицу вверх (по оси Z), что примерно равно половине высоты свечки candle1 (для более высоких или более низких свечей нужно подкорректировать цифры).

4.41. Можно ещё поиграться с оружием - к примеру, дать Гарретту кинжал или молот. Но делается это очень сложно, поскольку одного изменения свойств объекта, которого хотим сделать в виде оружия, мало. Необходимо ещё сделать модель руки Гарретта с этим оружием и соответствующие новые движения (если таковые присутствуют). Ниже я рассмотрю только изменение свойств объекта, как если бы у нас уже были и готовый меш, и готовые движения. Ещё раз оговорюсь: самостоятельно новое оружие не делал, даю только общие идеи на тему того, в какие стороны нужно двигаться, имея на руках всё готовенькое.
Создаём объект и возимся с ним. Для начала ставим скрипт sword, а затем добавляем следующие свойства. Engine Features -> FrobInfo: World Action: Move; в InvAction и ToolAction всё одинаково - Script, FocusScript. Далее Inventory -> Type, выбираем Weapon. Затем Inventory -> Object Name, дабы дать какое-либо название нашему оружию. Можно придумать новое, можно взять старое (в stings.crf). И последний штрих с Inventory - Long Description, это будет подпись оружия в левом нижнем углу. Для меча это use_sword. Здесь похожая аналогия со свойством Inventory -> Object Name (пункт 4.30), изменения тоже нужно вносить в файл objnames.str.
Теперь займёмся техническими характеристиками - а именно повреждениями. Для начала - Act/React -> Sources. У мечей источник только один - SlashStim, насколько я помню. Intensity введём 2.00, а в раскрывающемся списке в середине выберем Contact. Можно для полноты картины сделать так же, как и у меча - ещё 2 типа с intensity 4.00 и 6.00. Затем Weapon -> BaseDamage, введём туда двоечку - обычное повреждение обычного меча. Можно и побольше, чтоб резал с одного удара. (Разумеется, можно добавить мечу и другие свойства, например FireStim, чтобы он повреждал и огнём, или HolyStim, чтобы он стал освящённым...) Ещё в Schema -> Class Tags можно ввести WeaponType Sword - это означает, что наше оружие будет издавать звуки меча. Да можно много чего ввести, но нет одного из главных свойств - при нажатии кнопки "меч" оружие уже не выбирается. То есть его можно подобрать лишь один раз и использовать до тех пор, пока не уберёшь в инвентарь или не поменяешь оружие, обратно его можно будет выбрать только прокручиванием (кнопки "предыдущее оружие" и "следующее оружие"). А это не есть правильно. Здесь решение пока не найдено.
Итог: очень много заморочек и закавык. Лучше оставить эту идею, или - если уж совсем хочется - добавить одно-два простеньких свойств "декоративного" характера. Как пример можно рассмотреть меч Masamune из миссий Mystery Man и Sepulchre of the Sinistral.

4.42. При изменении размеров объекта в окне DromEd (Depth, Width, Height) не изменяются его реальные размеры! То есть при "растягивании", допустим, дерева в 10 раз вы увидите огромадное дерево, но будете проходить сквозь него. Чтобы устранить это недоразумение, выбираем в окне свойств дерева Physics -> Model -> Dimensions (опять же, такой раздел есть у всех физических объектов) и также увеличиваем там всё в 10 раз. Есть другой способ изменить размеры: Shape -> Scale, куда можно ввести коэффициенты, на которые умножаются размеры объекта. Но лично я им не пользуюсь.

4.43. Очень интересные штуки для AI - распознавания (Responses). В меню AI -> Responses есть 5 видов:
Alert Response - реакция на тревогу, вызванную вашим появлением. То есть что страж будет делать, если вас увидит. Зачастую именно в ходе такой реакции страж бежит включать тревогу (см. пункт 6.18).
Body Response - реакция на нахождение тела, то бишь что страж будет делать, найдя тело - опять же, может побежать включить тревогу.
Sense Combat Response - реакция на, грубо говоря, попытку ударить. Пьяный страж при помощи этой реакции начинает обращать внимание на происходящее. Что, в общем, естественно.
Signal Response - реакция на внешний сигнал, наиболее распространённый - сигнализация (alarm), который и вводим как сигнал.
Threat Response - распознавание опасности. Эту штукенцию обожают использовать вкупе с MetaProperty M-AlertCapZero (при нём AI абсолютно спокоен при любых условиях) для пьяных стражей. Делают обычно так: опьяняют товарища (голос + motions -> actortaglist); затем добавляют metaproperty; а затем редактируют Responses следующим образом: опасность, что распознаёт страж, - вынутое оружие (raised weapon). Первый шаг его реакции - удаление "спокойного" MetaProperty, второй - проигрывание речёвки пьяного стража на наивысшем уровне беспокойства. Всё это происходит, разумеется, если страж видит вас; если проползти в тени с вынутым оружием незамеченным, это наверняка не произойдёт.
Хитрость здесь состоит в заполнении всех этих полей. Существует масса вариантов заполнений в зависимости от того, какой пункт выбран в раскрывающемся списке над полями с тремя аргументами. Сейчас рассмотрим самый простой вариант распознавания - Sense Combat Response у пьяного стража. Изначально у него присутствует метасвойство M-AlertCapZero, которое позволяет ему ни на что не обращать внимания. В ходе данного распознавания эта метасвойство убирается, в результате чего страж и начинает реагировать на происходящее, по-прежнему оставаясь поддатым. Делается это просто: в окошке Sense Combat Response в раскрывающемся списке выбираем Add/Remove Metaproperty. А дальше указываем: аргумент 1 - Remove, аргумент 2 - M-AlertCapZero, аргумент 3 - имя или номер нашего пьяного стража. То есть в данном случае сначала указываем, добавить или удалить, затем - какое именно метасвойство, и, наконец - кому/чему добавить или у кого/чего убрать. Но и здесь есть нюанс: дело в том, что если наш страж не участвует ни в каких связях и не привязан к чему-либо, связанному с Act/React, то его номер может случайно поменяться - а значит, данное изменение свойств работать перестанет. Чтобы этого не происходило, желательно дать нашему стражу уникальное название - допустим, DrunkGuard1. И это название можно вписать вместо номера в поле аргумента 3. Так как имя объект в процессе игры поменять не может, этот способ более надёжен.
Это - самое простое, что может произойти в ходе того или иного распознавания. В целом же можно применить множество комбинаций, о которых можно прочитать здесь (по-английски): http://dromed.whoopdedo.org/dromed/pseudoscript
Наиболее широко данный способ изменения свойств в ходе игры используется в беседах (conversation). Более подробно о них и о заполнениях данных полей см. пункты 6.8 - 6.12.

4.44. Что-то ничего я ещё не писал о таком типе источников освещения, как о световых пятнах (spotlights). У обычного такого "светового пятна" (fnord/HackLight/SpotLightPoint) свойства такие: в Renderer -> Spotlight стоит в поле x 30, в поле y 30, в поле z 0. При этом свойство Renderer -> Light также есть, от нуля там отлична лишь яркость освещения (первое поле). Можно ради интереса попробовать их изменить, но не думаю, что изменение этих цифр окажет какой-либо архикрасивый эффект - цифры в Spotlight отвечают за размер конуса, в пределах которого распространяется свет. Стоит лишь ещё раз отметить, что у Spotlight может быть свойство не Light, а AnimLight, отвечающее за анимированное освещение. Подробнее о типах источников света написано в пункте 3.1.

4.45. Интересный параметр - Time Warp (Creature -> Time Warp), он характеризует "шустрость" существа, если можно так выразиться. Для примера возьмём вора (thief) и ракочеловека (Crayman). У первого Time Warp равен 0.75, у второго 1.25. Вор двигается довольно быстро, скорость ходьбы его несколько больше, чем у обычного стража, да и остальные движения быстрее. Ракочеловек же делает всё довольно медленно, наверное, замечалось: пока он сделает жест "зов на помощь" и начнёт бежать, его можно успеть прибить даже при неторопливом махании мечом. Однако стоит уменьшить Time Warp у Crayman'а, и он начнёт двигаться шустрее. Очень низко опускать не советую - у того же crayman'а опустил время до нуля, и он в спокойном состоянии стоял не шевелясь, а едва заметил кого - как стало так мотать из стороны в сторону, что он вылетел за пределы уровня, в твёрдое вещество, и выдалась ошибка о неверном положении существа. Так что экспериментировать с этим стоит осторожно.

4.46. Некоторые оригинальные фразы Гарретта, не включённые в игру (в основном это файлы garNNN, где NNN - трёхзначное число) по умолчанию проигрываются сколь угодно много раз - так, если установить комнату-ControlDevice к VOTrap'у, связанной SoundDescription'ом с одной из таких схем, то вы будете слышать эту же фразу ещё раз при повторном входе в комнату. Чтобы устранить это, придётся менять gamesys - в свойствах нужного объекта в иерархии объектов жмём Edit, затем Schema -> Play Params и ставим галочку перед PlayOnce. Есть, правда, и более простой выход без изменения gamesys'а - просто сохранить этот же файл под именем того, который проигрывается только один раз. (Какие из них проигрываются один раз, а какие нет, можно узнать из иерархии объектов по свойствам этой схемы - где не прописано свойство PlayOnce, те не проигрываются один раз.)

4.47. Есть параметр AI -> AI Core -> Movement: max speed. Похоже, он годится только для elemental'ов, которые не состоят ни из каких joint'ов (т.е. это просто один шарик, который может перемещаться), для более сложных существ же он, похоже, не годится. У Fire Elemental'а там стоит 1.75, можно попробовать поэкспериментировать и сделать elemental'а-спринтера, догоняющего вас в один миг. Кроме того (раз уж про elemental'ов речь зашла), их z offset равен 5.00. (Это свойство также принадлежит AI Core.) Что означает - шарик парит на высоте 5 единиц над землёй, по-прежнему ходя по ней. (Насколько я помню, elemental не может менять свой z offset, т.е. всегда "летает" на одной и той же высоте.) Свойство подходит для создания летающих соперников (нет, правильнее сказать - высоко летающих.).

4.48. По умолчанию AI не могут ходить по объектам (на них не просчитывается pathfinding database). Однако есть свойство, которое может это исправить: AI -> Utility -> Pathable object. Если поставить галочку, то AI смогут ходить по нему.



Часть 5. Объекты: Связи (Links).




5.1. Есть замки (physical/Locks). Если охота сделать так, чтобы дверь можно было открыть при открытии замка, связываем дверь с замком flavor'ом Lock. При этом с самой дверью больше ничего делать не надо.

5.2. Чтобы какой-нибудь предмет был на поясе охранника (или какого-нибудь другого врага), нужно связать охранника с этим предметом связью Contains. (Автоматически создастся ещё одна связь - CulpableFor. Скорее всего, именно её присутствие позволит кражу предмета считать карманной.) Затем выделим Contains и нажмём Data. В открывшемся окне выбери Belt. Усё!

5.3. Очень полезная связь - ControlDevice, она очень широко применяется в построении миссий. Например, рассмотрим открытие/закрытие неактивных дверей. Создаём рычаг (Gizmo/Switches/Levers) (хотя Control Device'ом может быть всё что угодно - от рычага до комнаты, подробнее об этом написано в пункте 4.36), и связываем его с дверью связью ControlDevice. итог - при повороте рычага дверь, даже будучи неактивной (без FrobInfo), откроется.

5.4. Чтобы, например, создать зомбя с тучей мух на нём (и так, чтобы она перемещалась вместе с ним), создаём саму тучу (SFX/BugFX/BugHalo, насколько я помню), а затем связываем ЕЁ с зомбём связью ParticleAttachement. Это важно - не зомбя с ней, а наоборот (т. е. у зомбя эта связь будет ~ParticleAttachement). В данных (Data) выбираем Object в первом раскрывающемся списке.
Правда, следует учесть несколько нюансов: осторожнее с удалением связанных этой связью объектов. В нашем случае при удалении тучи мух зомбак тоже исчезнет! То же самое будет, если удалить факел - дым и огонь исчезнут автоматически вместе с ним.
К тому же, объекты с ParticleAttachement могут капризничать при клонировании или перемещении мультибраши (если они в ней содержатся).

5.5. Чтобы при патруле охранник пошёл к тому пункту, к которому надо вам, связываем охранника с ним связью AICurrentPatrol. Вообще говоря, эта связь назначается автоматически во время игры, когда AI идёт по установленному маршруту - при достижении одного TrolPt'а ему назначается связь AICurrentPatrol к следующему. Однако можно перестраховаться и назначить эту связь насильно (самостоятельно), чтобы в игре связь не назначилась к другому TrolPt'у. Приём годится, когда рядом с охранником находится много патрульных точек, ведущих в разные маршруты - по умолчанию охранник идёт к тому, что ближе всего к нему.

5.6. Для создания лифта нужен сам лифт (например, ElevPlatform) и два (или больше) объекта под названием TerrPt (fnord/Maker/TerrPt). В координаты центра TerrPt'а будет перемещаться центр лифта. Связываем лифт с одним из них связью TPathInit, а TerrPt'ы - друг с другом связью TPath (то есть у каждого из них должно быть как минимум 2 связи - TPath и ~TPath). Далее выделяем одну из связей и жмём Data. Там, где Speed, вводим что-нибудь от 2 до 5. То же с другой связью. В случае, если лифт вызывается нажатием кнопки, кнопку связываем ControlDevice'ом с тем TerrPt'ом, к которому должен подъехать лифт. (В этом случае лифт, по идее, должен стоять на том TerrPt'е, который связан с ним связью ~TPathInit, но обычно почему-то он начинает ехать к противоположному TerrPt'у и там останавливается. Вообще говоря, это лечится убиранием галочки из свойства Physics -> Misc -> MOving Terrain у лифта, но когда я её убрал, тот вообще отказался двигаться куда-либо. Поэтому, если нормальное решение не поможет, придётся указывать связь TPathInit к TerrPt'у, противоположному тому, с которого должна начинаться эта самая TPath, т. е. чтобы лифт в итоге стоял у того TerrPt'а, который нужен.)

5.7. Чтобы динозавр (буррик) не рыгал, а пукал (как в Катушке ошибок), выбираем Projectile/fart, далее связываем динозавра с этим fart связями Contains и AIProjectile, а где AIProjectile, нажимаем Data, и там, где написано Launch joint - выбираем Butt (задница) или Tail (хвост). Таким же образом можно настроить выпускание снарядов у магов - скажем, не от пальцев правой руки, а, например, со стороны головы.

5.8. Чтобы голова у кого-нибудь горела огнём (и её обладателю при этом ничего не было), выбираем SFX и ищем там FireShadowHead. Затем связываем её с этим "кем-нибудь" связью ParticleAttachement, затем выделяем её, жмём Data, затем, в первом раскрывающемся списке выбираем Joint, а во втором - joint - выбираем Head. Таким же образом можно заставить витать любые другие частицы вокруг любого другого joint'а AI.

5.9. Бывает полезной связь Corpse. Работает она довольно просто: объект при смерти на своём месте создаёт тот, который связан с ним этой связью. По такому принципу устроены некоторые оружия (правда, не работающие).

5.10. Есть ещё, казалось бы, простая вещь под названием DestroyTrap. Судя по названию, она просто должна уничтожать (безвозвратно удалять с уровня) объект, связанный с ней связью ~ControlDevice. Но, к сожалению, в реальности всё не так. DestroyTrap не уничтожает, а убивает объект. То есть если поставить ControlDevice с неё на AI, то при активации последний умрёт. Если на дверь - она откроется. Но если наставить, скажем, на мебель или другой предмет, не имеющий каких-либо мудрёных скриптов, то он просто исчезнет, как будто действительно удалился воображаемой клавишей Delete. Так что использовать её можно, но осторожно.
Разумеется, и саму DestroyTrap тоже должно что-то активировать. Как видно, аналогия с TeleportTrap'ом (пункт 6.1) почти полная.

5.11. Есть штуки под названием RequireAllTrap и RequireAnyTrap. Это - эдакое подобие рычага (т. е. она обычно выступает в роли ControlDevice'а к чему-либо), обычно неактивного. Чтобы активировать его, необходимо создать некоторое количество ControlDevice'ов к ней. Всё это очень хорошо можно понять на примере портала в миссии про Утробу хаоса - портал деактивируется только при уничтожении четырёх символов стихий. Эти 4 символа связаны с RequireAllTrap'ом связью ControlDevice. RequireAllTrap, в свою очередь, связана ControlDevice'ом с штукой под названием Inverter, которая, в свою очередь, связана ControlDevice'ом с порталом (MawPortal). При деактивации всех четырёх ControlDevice'ов (то есть при уничтожении всех четырёх символов) наступает цепная реакция, и в итоге отрубается портал. RequireAnyTrap работает по такому же принципу, с той лишь разницей, что для её активации необходимо задействовать хотя бы один из её ControlDevice'ов, а не все. (Напомню, что Inverter обращает эффект ControlDevice'а. Говоря по-русски, при простой связи ControlDevice между trap'ом и порталом он вначале был бы выключен, а при уничтожении 4 символов бы включился. Чтобы произошло обратное, между ними ещё поместили Inverter.)

5.12. Связь CreatureAttachment - чем она хороша? При её помощи можно дать существу какой-либо предмет, например, в руки. Правда, его прямо из рук можно будет выхватить, чтобы это предотвратить, всю FrobInfo предмета ставим на None. А вот в создании товарища с мечом эта связь хоть и может быть полезной, но есть один недостаток: вещь поворачивается несогласованно с существом. То есть, например, если дать меч в руку слуге, а затем заставить его искать, то слуга будет держать меч уже в середине клинка, что будет выглядеть глупо. Но всё же можно попробовать и это дело разрешить... (Про то, как дать меч безоружному товарищу, см. пункт 6.15.)

5.13. Что делает связь FrobProxy? Она даёт сигнал на использование предмета, номер которого стоит в строчке "To". Как именно это работает - можно проследить на примере: создадим два рычага и одну дверь. Поместим один рычаг в недоступное место, другой - себе под нос. И свяжем первый рычаг со вторым связью FrobProxy, а второй рычаг с дверью - связью ControlDevice. И при нажатии первого рычага пойдёт цепная реакция: активируется второй, открывая этим дверь. (В принципе, такой же фокус можно было проделать и со связью ControlDevice вместо FrobProxy, но у последней более широкие границы применения - допустим, если удалить дверь, а второй рычаг заменить, к примеру, на яблоко, положив его куда-нибудь, скажем, вам под ноги, и связать рычаг с яблоком связью FrobProxy, то при повороте рычага вы возьмёте яблоко, даже его не видя.)

5.14. Чтобы создать горячие плиты, как в башнях магов (Mage Towers), нужно всего две вещи - сама горячая плита (HotPlate) и штука под названием HotPlatePhase0 или HotPlatePhase180 (fnord/HotPlateController). Управляющий fnord должен быть связан с плитой связью ControlDevice, и всё - плита со временем будет становиться то горячей, то холодной. Чтобы не все плиты "горячились" синхронно, можно создать две группы плит; одну связать ~ControlDevice'ом с HotPlatePhase0, а другую - причём не изменяя ничего в свойствах плиты! - с HotPlatePhase180. И в этом случае плиты будут синхронно "горячиться" только в группах; в то время, как плита одной группы будет горячей, плита из другой будет холодной.

5.15. Ещё одна из достаточно широко используемых связей - AIWatchObj. Как правило, она назначается от AI к какому-либо маркеру, и AI проверяет, появится ли в нужном радиусе от указанного маркера либо он сам, либо игрок, после чего предпринимает действия сродни тем, что применяются в распознаваниях (responses - пункт 4.43) и conversation'ах (пп. 6.8 - 6.12). Рассмотрим как пример следующую ситуацию: страж во время патруля подходит к определённой точке и, остановившись, поворачивается к нужному объекту, стоит несколько секунд, после чего продолжает патруль. Чтобы это реализовать, достаточно создать AI, назначить ему патрульный маршрут и связать его с необходимым TrolPt'ом связью AIWatchObj. А затем повозиться с данными самой связи. Выделяем, жмём Data. Откроется большое окно.
В первом раскрывающемся списке указывается, за чем именно будет следить AI. Ставим Self entry - будет следить, пока сам не окажется у патрульного пункта. (Player intrusion - если у пункта окажется игрок.)
Дальше указываются радиус триггера и высота. Высота должна быть хотя бы с половину роста AI, иначе срабатывать не будет. Я обычно ставлю в районе 8. С радиусом также мелочиться не стоит - в случае, если AI будет просто проходить мимо маркера, а не пойдёт строго к нему. В нашем случае можно поставить в районе 4, но если бы AI проходил мимо, лучше ставить больше.
Дальше в раскрывающихся списках - требуемый уровень встревоженности для выполнения действий (оставляем 0), line requirement и minimum alertness оставляем на None. Maximum alertness я ставлю на 2 (Moderate), но можно понизить и до 1.
Link kill option оставляем Don't kill, если хотим, чтобы наш AI останавливался у точки каждый раз. Галочки не ставим.
Поле Reuse delay означает, в течение которого времени (в миллисекундах) можно будет повторить действия. Скажем, если AI проходит через нужную точку раз в 20 секунд, а надо, чтобы он останавливался через раз, то здесь ставим число между 20000 и 40000. Для остановки каждый раз может быть достаточно 10000, если маршрут не слишком короткий. Что означает Reset delay - точно не помню, но её обычно оставляю нулевой.
В оставшихся полях расписываем, что, собственно, наш AI будет делать, когда доберётся до нашей точки. Первый шаг - поворот к объекту: в раскрывающемся списке выбираем Face, и как ВТОРОЙ (важно - не первый, а именно второй, т.е. первый аргумент будет пустым!) аргумент пишем номер или название объекта (лучше название - надёжнее). Второй шаг - ожидание. Выбираем пункт Wait и в первом аргументе пишем, сколько (в миллисекундах). Скажем, 3000. Но если оставить связь так, то AI, повернувшись к точке, будет стоять абсолютно неподвижно, как замороженный, что будет выглядеть странно. Поэтому во второй аргумент ожидания пишем IdleGesture 0 - это движение, которое он будет воспроизводить при ожидании.
Другой пример использования связи AIWatchObj - просыпающийся при приближении игрока AI. Об этом подробнее написано в пункте 6.6.



Часть 6. Объекты: Простые комбинации свойств и связей. Нехитрые приёмы.




6.1. Телепортация есть и в Воре, просто происходит не картинно. Для того чтобы переместить объект куда-нибудь (например, переместить охранника поближе к игроку), создаём TeleportTrap (fnord/TrapTrig/TeleportTrap), затем что-либо, что можно связать с ней flavor'ом ControlDevice (например, взял яблочко - сзади один охраниик, прихватил следом булку - уже два...), а затем связываем TeleportTrap со стражником flavor'ом ControlDevice. (Желательно ставить TeleportTrap повыше, т. к. это то место, куда переместится ЦЕНТР объекта.) (Если действительно есть желание проделать это с булкой и яблоком, то на них следует предварительно установить скрипт, позволяющий им посылать сигналы для ControlDevice; лучше всего для этого подойдёт TrigWorldFrob, и проверить, чтобы во FrobInfo в графе WorldAction стояло Script. Иначе ничего не будет работать.)

6.2. Для телепортации Гарретта всё делаем так же, как и с любым другим объектом, только TeleportTrap (то место, где должен будет появиться Гарретт) соединяем ControlDevice'ом со стартовой точкой (StartingPoint).

6.3. Можно сделать нажимную плиту и сделать ловушку. Нажимная плита - PressPlate, создаём её и помещаем в какое-нибудь углубление. Ловушка - EmitterTrap (fnord/TrapTrig/EmitterTrap). Связываем плиту с ловушкой связью ControlDevice. Далее я всё разобью на 2 части.

6.4. Чтобы текстура плиты совпадала с текстурой пола (т. б. чтоб плита слилась с полом), выбираем Shape -> TxtReplr0. Вводим название текстуры, причём примерно так: fam/concastle/greenmar или fam/core/tanbrck. То есть первое - всегда fam, второе - название семейства, а третье - собственно название текстуры.

6.5. EmitterTrap, жмём Properties. Выбираем S -> Scripts для начала и вводим ReloadTweqEmit (Это делается для того, чтобы ловушка могла стрелять снарядами бесконечное число раз; если скрипт не ввести, выстрел снарядом будет только один.). (Ввести его надо во второе поле, т. к. в первом должно быть TrapTweqEmit.) Затем выбираем Tweq -> EmitterState. Исправляем всё так, чтоб было похоже на следующее:
----------------
None
None
899
0
----------------
Затем Tweq -> Emit. Окно исправляем до такого:
----------------
Stop Tweq
Sim
Grav
(None)
1
1
----------------
Далее - в Emit what - вводим что-нибудь вроде: spear, broadhead, firebolt, MagicMissile. (Полный список снарядов можно найти в physical/Projectile, в принципе, можно ввести любой снаряд, написанный там.) Далее должны быть нули, да даже если там и не нули, исправлять уже ничего не надо.

6.6. Можно поместить на уровне спящего человека. Например, у меня есть комната, где спят 3 охранника. На всю комнату там раздаётся хор храпов... Ну да ладно, расскажу, что сделать, чтоб он проснулся (и как его "усыпить").
Для начала сделаем так, чтобы он дрых не стоя. Выбираем Creature -> Current Pose. Вводим то же, что и для мёртвого, только там, где числа, в обе строки вводим 1.00. (Параметры для мёртвого можно подсмотреть в метасвойстве M-PosedCorpse или в пункте 4.19.) Далее - AI -> Ability Settings -> Idling: Should fidget. Убираем галочку. После - AI -> AI Core -> Standing motion tags. Оставляем там пустое место и жмём OK, чтобы в окне свойств появилось "Standing motion tags:". Если это не выбирать, то он будет дрыхнуть стоя.
И - наконец, самое главное, - выбираем AI -> AI Core -> Broadcast customization. Галочку не ставим; в первом раскрывающемся списке выбираем Alert zero broadcast, во втором - Custom concept. В следующее после него поле вводим Sleeping.
Далее переименовываем охранника (например, из a ConBowman в SleepingBowMan). Создаём маркер и связываем охранника с ним связью AIWatchObj. Выделяем связь и жмём Data. Там изменяем окно до такого вида:
----------------
Player intrusion
5
12
Raycast
(0) None
(0) None
After completion
Add/Remove MetaProperty
Remove
(а сюда введём то, во что переименовался охранник)
----------------
Единственное, что я так и не сумел исправить - спящий враг видит. Правда, смотрит он всегда в одну сторону, независимо от того, как повёрнут - на север. (Строго говоря, это решение неправильное, потому что командой Add/Remove Metaproperty при таком раскладе мы хотим вообще удалить абсолютно все свойства нашего AI.)

Можно поступить и по-другому: пойти через MetaProperty, а именно M-SleepingServant. Если создать какое-нибудь существо (лучше уж человека) и выбрать (в Propeties) Add -> MetaProperty -> AIBehaviours -> AI-BGen -> M-SleepingServant, то он (человек) будет дрыхнуть. А в связи AIWatchObj, где Add/Remove MetaProperty, напишем M-SleepingServant. Только это почему-то не работает. (Здесь под "это почему-то не работает" подразумевается то, что существо не просыпается, если приблизиться к нему. Возможно, следует изменить цифры 5 и 12 в параметрах связи AIWatchObj.)

6.7. Чтобы Гарретт смог наконец заговорить, создадим объект под названием VOTrap (fnord/TrapTrig/VOTrap). Затем сделаем ему какой-нибудь ControlDevice, комнату, например. Причём примите во внимание - на комнате должен быть установлен скрипт TrigRoomPlayer, чтобы это сработало. (Под "это" подразумевается связь ControlDevice; без этого скрипта (или скрипта TrigRoomCreature) комната ControlDevice'ом быть не может.)
Затем выясняем, ЧТО хотим сказать. Например, "Ну, вот и всё" ("Here we go..." в оригинальном варианте). Это - схема под названием garm0209 (если не ошибаюсь) - она отвечает за файл garm0209. Набираем find_obj garm0209 и смотрим на номер в скобках. Затем связываем VOTrap с этим нумером связью SoundDescription. Всё!
(Обычно название схемы для звука и название самого звукового файла совпадают, но в редких случаях они имеют разные названия. Чтобы удостовериться, что необходимая схема отвечает именно за необходимый нам звук, следует найти её описание в файле garrett.sch архива schema.crf.)

6.8. Пожалуй, самая сложная из всех простых комбинаций - беседа охранников (conversation). Это довольно сложная штука, но я всё же попробую растолковать всё, что понял.
В беседе должны быть её участники - Conversation Actors - и собственно сама conversation, которая обычно является простым маркером (marker) с установленным на ней специальным скриптом. Для начала разберёмся с охранниками. У них обоих должны быть определёныые голоса, например, охранник 1 должен говорить с охранником 3, и никак иначе. У одного охранника выбираем Speech -> Voice и вместо guards введём guard1, у другого - то же самое, только guard3. (Какие именно голоса должны использоваться в создаваемой conversation, можно подсмотреть в звуковых папках, отвечающих за файлы с репликами нужной беседы, и в архиве schema.crf, файлы sg_conv.sch и им подобные, с "суффиксом" conv. Если участник не будет ничего говорить, голос ему менять необязательно.) Затем - для обоих - выбираем Add -> MetaProperty и ищем там M-NoBabble. (Метасвойство означает, что до начала разговора оба стража будут молчать, терпеливо ожидая, пока не включится беседа. Если его не добавлять, то они не будут ничего говорить во время беседы.) Можно ради удобства переименовать охранников, например, ConvGuard1 и ConvGuard2. (Если в названии нет ни одного пробела, то его можно вводить вместо номера объекта в любые поля.)
Теперь займёмся маркером. Для начала переименовываем его - например, в SGConversation. Выбираем S -> Scripts и введём TrapConverse.
Теперь - про связи conversation'а. Его должно что-то активировать - как понятно из названия, скрипт TrapConverse заработает, когда на объект, его содержащий, подастся сигнал "вкл." от ~ControlDevice'а. Например, это может быть комната со скриптом TrigRoomPlayer - при входе игрока в неё сигнал "вкл." пошлётся. Связываем её с маркером связью ControlDevice. Затем связываем маркер с охранниками связью AIConversationActor. Затем выделяем каждую из связей и набираем в данных (Data) номер Actor'а (от 1 до 6). Например, guard1 - это номер 1, а guard3 - номер 2. Участников беседы нумеровать обязательно, эти номера потом будут использоваться! Если участник в ходе conversation'а должен будет выполнить то или иное действие, неважно, сказать ли что-либо, пойти куда-либо, повернуться ли - его вписывать обязательно. Участников conversation'а можно ставить до шести, но при шести DromEd 1.37 у меня ругался и вылетал. 5 и меньше использовать можно.
Теперь выбираем маркер, жмём его Properties и начинаем с ним возиться.
Для начала - перед самым главным - выбираем AI -> Conversations -> SaveConversation. Поставим галочку. Она будет отвечать за то, что если сохраниться в течение беседы, а потом загрузиться, то беседа продолжится с того места, на котором произошло сохранение. Правда, в Thief 2, по всей видимости, это свойство не работает, так что во время бесед для последующей загрузки лучше не сохраняться - в лучшем случае беседа просто начнётся заново, в худшем - полезут непоправимые ошибки, из-за которых либо игра вылетит, либо её невозможно будет закончить (так как некоторые действия conversation будут повторяться по второму разу).
Ну а теперь - глубокий вдох и начинаем. Выбираем AI -> Conversations -> Conversation. Далее выбираем 00. OK. Ну и вот это всё нам придётся заполнять... Ибо именно все эти поля отвечают за то, что будет происходить в течение нашей беседы.
Первым делом необходимо удалить связь ControlDevice, чтобы conversation не включалась дважды. В первом шаге выбираем Remove link, затем - аргумент 1 - введём ControlDevice, аргумент 2 - нумер или название conversation'а (то есть то, что как бы должно быть написано в поле To), аргумент 3 - нумер или название комнаты (то есть From).
Затем - в следующем - выбираем Add/Remove MetaProperty, аргумент 1 - Remove, аргумент 2 - M-NoBabble, аргумент 3 - нумер или название охранника (одного).
Третий шаг - то же самое, только с другим. В принципе, можно не тратить отдельный шаг, а просто приписать номер или название второго стража во второй шаг к первому, через запятую. То есть вместо ConvGuard1 в третьем аргументе второго шага будет ConvGuard1, ConvGuard2. Не проверял, работает ли это, но в Dromesday Book пишут, что должно.
И вот только теперь они, собственно, начинают беседовать: выбираем Play sound/motion. В поле аргумента 1 - нумер conversation'а. Указывается он в формате, подобном следующему: sg_c01. Это название можно узнать в файле sg_conv.sch (или ему подобном - к примеру, если разговор не стражей, а Хаммеритов, то файл называется hm_conv.sch), находящемся в архиве schema.crf. Там расписана вся беседа по репликам, каждой реплике соответствувет своя схема и определённый номер строчки (LineNo), а каждой схеме, в свою очередь, свой звуковой файл. Соответственно, в первый аргумент нужно ввести главный идентификатор, который будет говорить, чья именно это беседа и какой у неё порядковый номер (из всех). То есть написано должно быть только название, но без номера реплики (не sg3c0101, а именно sg_c01). За него отвечает второй аргумент, в него и вписываем LineNo 1. В третий аргумент нужно вписать движения, которые будут воспроизводиться при проигрывании данного звука. Их достаточно много, подробнее о них написано в пункте 6.12. Чтобы не морочиться с лишними движениями, можно просто написать Conversation 0. Если хотим сделать в точности такие же движения, как и в оригинальных беседах - можно подсмотреть их в оригинальных conversation'ах, они будут написаны как третий аргумент в шаге Play sound/motion, отвечающем за реплику с нужным номером. Списываем их в точности так же, как написаны там - со всеми нулями и запятыми.
Conversation придётся расписать по репликам, т. е. в окне Conversation шаг 01 будет соответствовать 1й реплике, 02 - 2й, и т. д. Вводим всё по тому же образцу: Play sound/motion, sg_cNN, LineNo a, где NN - нумер conversation'а, a - нумер реплики. И выбираем соответствующего актёра (т. е. если говорит Actor2, то выбираем ActorTwo, а не ActorOne).
Теперь - про актёров. Какого где выбирать? Разумеется, того, кто будет говорить и двигаться - для шага Play sound/motion всё просто и понятно. А для удаления связей, метасвойств? Здесь тоже актёр нужен, как ни странно - хотя и кажется, что его вмешательство здесь не нужно, иначе ничего не будет работать. Желательно ставить того, кто начинает беседу, просто чтобы не путаться. Так что Unused не ставим вообще.
Если после окончания беседы оба охранника (или кто-то один из них) должны приступить к патрулю, то для них (него) нужно заполнить ещё два шага. Их желательно ставить до шагов, отвечающих за собственно разговор (т.е. до шагов Play sound/motion).
Выбираем Add link, аргумент 1 - AICurrentPatrol. 2й - нумер или название TrolPt'а, к которому должен подойти охранник, 3й - нумер или название самого охранника. Эта связь говорит охраннику, к какой точке будет привязан его патруль.
Дальше - выбираем Add/Remove MetaProperty, аргумент 1 - Add, аргумент 2 - M-DoesPatrol, аргумент 3 - нумер или название охранника. Это метасвойство содержит всего одно свойство: AI -> Ability Settings -> Patrol: Does patrol, говорящее о том, что страж должен начать патруль.
Вообще, все "невидимые" шаги, отличные от собственно разговора и движений, желательно прописывать ПЕРЕД разговором.
Ну вот, вроде всё, что я знал про оригинальные conversation'ы, написал. Если хочется создать собственный разговор, то в двух словах, что для этого нужно: собственно звуковые файлы, которым должны соответствовать схемы и голоса участников беседы, которые нужно вписать в gamesys, а также схема самой беседы, которую тоже нужно вписать в *_conv.sch-файл архива schema.crf. Больше всего возни здесь именно с привязкой звуков к схемам, подробнее об этом см. пункт 8.0.7.
Но чтобы не заниматься созданием собственной беседы, можно воспользоваться какой-либо из оригинальных бесед, не включённой в игру - достаточно послушать реплики стражей и Хаммеритов в папках архива snd.crf, чтобы убедиться в этом.

6.9. Если требуется, чтобы во время conversation'а кто-нибудь прошёл куда-либо, выбираем Goto Object, аргумент 1 - нумер того объекта, к которому он должен подойти. Если он должен не подойти, а подбежать, то, где аргумент 2, пишем Very Fast. Actor - тот, кто должен подбежать.
(Примечание: поскольку объект, к которому нужно подойти, может не участвовать ни в каких связях и не быть привязанным ни к чему, связанному с Act/React, его номер может поменяться в течение редактирования миссии. Надёжнее присвоить объекту уникальное имя и указывать его вместо номера.)

6.10. Аналогично с Frob Object, только тут Very Fast не нужен. Стоит обратить внимание на пару вещей. Во-первых, если просто дать стражу команду Frob Object на кнопку, то он не будет к ней идти! Кнопка просто нажмётся сама собой без всяких движений со стороны AI (т.е. со стороны это будет выглядеть, как будто ничего не произошло, а кнопка нажалась какой-то потусторонней силой). Если AI-человек должен нажать кнопку, то его надо сначала подвести к кнопке (Goto object), затем воспроизвести движение (Play sound/motion, в ТРЕТИЙ аргумент - именно в третий! - написать движение, если не ошибаюсь - Foo 0, Bar 0), и только потом - Frob object.
И, разумеется, при подходе к объекту, которого можно использовать, охранник НЕ будет его использовать. То есть если нужно, чтобы он подошёл, допустим, к двери и открыл её, потребуется заполнить 2 шага - Goto object (в аргументе - номер или название двери), а затем Frob Object (в аргументе тоже номер или название двери).
Стоит заметить, что второй аргумент здесь также может использоваться - если AI должен использовать один объект другим, то второй объект нужно вписать как второй аргумент. Например, AI может использовать (отпереть) дверь, воспользовавшись ключом у себя. (Напомню ещё раз про примечание, указанное в предыдущем пункте - вместо номеров надёжнее присваивать объектам уникальные имена и вписывать их - если объект не участвует в связях и не связан ни с чем из Act/React, его номер может поменяться.)

6.11. Если нужно, чтобы во время conversation'а кто-нибудь повернулся мордой к кому-нибудь, выбираем Face, аргумент 1 оставляем пустым (это важно!), а аргумент 2 - то, к чему он должен повернуться. Actor - тот, кто должен повернуться. Если нужно повернуться не к объекту, а на определённый угол, то пишем размер этого угла (в Dromesday Book пишут, что надо в радианах, но у меня работало в градусах; поворот будет относительно текущего положения AI) в первый аргумент. Если AI должен подойти к объекту, а потом повернуться куда-либо, лучше использовать первый вариант, так как остановившись, он может повернуться как угодно. Если нам точно известно первоначальное расположение AI и оно гарантированно не изменится, можно применить второй вариант.
(Примечание: если поставить и угол, и объект, то AI повернётся в направлении "к объекту минус указанный в первом аргументе угол".)

6.12. Ещё одно маленькое пояснение к conversation'у. "Абракадабра" в третьем аргументе шага Play sound/motion - это motion, точнее его название. Примерное назначение (подчёркиваю, примерное - может, и не такими они окажутся, или же нужно применить два параметра вместе - например, возможно, первые два) - ниже.
Foo 0, Bar 0 - страж наклоняется вперёд, сделав небольшой выпад, и возвращается назад. По одиночке, похоже, имеют другой эффект.
Baz 0 - негодует, тряся руками.
Quux 0 - разводит руками, судя по всему. В сочетании с Baz 0 ничего не даёт (?).
Foo 0 - указывает одной рукой, наклоняя голову - мол, "ну это мы ещё посмотрим".
Bar 0 - резко наклоняется назад, мол "какого чёрта?" - как обычно делает при засаде спереди.
Quux 0, Foo 0 - прячет руки за спину.
(Наблюдение основано на conversation'ах в миссии 5 (Assassins), 15 (Thieves' Guild) и речи отшельника в миссии 17 (Song of the Caverns).)
Search 0, Scan 0 - вглядывается в темноту, словно ищет.
Все эти движения должны вписываться как третий аргумент. Не первый, не второй, а именно третий. Иначе никакого эффекта не будет.
Также можно посмотреть эту тему. Указаны типы движения для Thief 2, наверняка многие подойдут и для Thief 1.
http://www.ttlg.com/forums/showthread.php?s=&threadid=50326
Вдобавок у Yandros'а существует даже специальная демо-миссия, в которой продемонстрированы почти все стандартные движения. (Миссия для Thief 2, разумеется.)

6.13. Чтобы слугу превратить в мага (а можно и такое сделать), для начала выбираем AI -> AI Core -> AI. Введём Human with bow. Затем создаём, например, магический снаряд (MagicMissile), если хочется, чтобы слуга пулялся им, и связываем слугу с ним двумя связями: Contains и AIProjectile. (Автоматически может создаться связь CulpableFor, но на неё не обращаем внимания.) Далее выделяем связь AIProjectile. Цифры там лучше не исправлять, лучше покопаться в раскрывающихся списках. Я уже плохо помню, что именно там написано, но разобраться там вполне реально. Вроде бы, на этом всё.

6.14. К сожалению, меч дать кому-либо гораздо труднее. Можно создать этот меч, связать чела с ним связью Weapon, предварительно подкорректировав AI чела - Human with sword. Но вот самого меча у него в руках не появляется. Уж не знаю, что делать, но тут я бессилен. Надеюсь, что ПОКА бессилен. (Меч и не должен появляться, это нормально. А связь Weapon означает, что при прикосновении правой руки персонажа к Гарретту последнему будет нанесено повреждение, равносильное повреждению от меча. То есть меч как бы "врастает" в руку, если можно так выразиться. Можно также связать персонажа с другим оружием связью Weapon - ZombieClaw, например.)

6.15. И всё-таки - как же дать меч безоружному товарищу? Ответ обнаружился на форуме TTLG по наводке Winter Cat'а:
В первую очередь создаём самих товарища и меч. Корректируем AI товарища на Human with sword, связываем его с нашим мечом связью Weapon. А затем выбираем меч и: в первую очередь всю его FrobInfo ставим на None, иначе меч можно будет нагло выхватить у противника из руки. И, наконец, самое главное - как же привязать меч к товарищу. А вот как: при помощи свойства Renderer -> Mesh Attach. Выбираем, смотрим, что и как заполняется: attached obj 1 - вводим номер меча, joint of skeleton - вводим 15 (это правая рука), угол по иксу оставляем 0, по игреку -30000, по зэд - -15000. Offset ставим: по x - +0.3, по y - -1.5, по z - -0.5. И меч теперь будет в руке, при прикосновении его к Гарретту последний получит повреждение. Но единственный минус, который я заметил - меч странно взаимодействует с полом и стенами комнаты (самой brush, естественно, а не room brush), издавая звук удара меча о материал стены/пола. Ладно ещё, если они все травянистые или покрыты ковром, но если деревянные, каменные или металлические - шум поднимется будь здоров, и все AI, включая "нововооружённого", примутся вас искать. (Меч стукается из-за собственной гравитации, чтобы он не бился головой об пол, ищем в окне свойств Physics -> Attributes, жмём Edit, и в окошке в первом поле (Gravity %) ставим 0. Если и это не поможет, тогда можно уменьшить массу меча (графа Mass в том же свойстве). Теперь меч падать не должен.)

6.16. Чтобы 2 двери открывались одновременно (т. б. сделать двойные двери), их для начала надо повернуть как подобает. Затем связываем одну из них с другой (неважно, какую с какой) связью ScriptParams, затем в данных (Data) пишем Double. Но при этом одна из дверей точно будет открываться не так, как надо. Смотрим её Properties, в окошке (НЕ в меню!) находим Door -> Rotating. Жмём Edit и меняем угол поворота Open Position (как правило, с 270 на 90). И - что важно - галочку Clockwise убираем. Иначе открываться она будет как-то уж совсем по-кривому.

6.17. Чтобы ключом можно было открыть особенный замок (вроде статуй с талисманами у собора или замков на башнях магов), и чтобы при этом последний вставился в замок (и исчез у вас из инвентаря, понятное дело), надо также поработать - как над ключом, так и над замком. Для примера возьму статую с талисманом Воздуха, открываемую им же. Создаём EmptyWard и AirTalisman. В первую очередь и на того, и на другого ставим скрипты. У ward'а они должны быть Ward и LockSounds, галочки быть не должно; а у талисмана - Talisman, StdKey, галочка быть ДОЛЖНА. Ну, разумеется, создаём такие KeySrc талисмана и KeyDst статуи, чтоб они совпадали. Возможно, нужно будет дополнительно указать DromEd на то, что талисман будет именно ОДИН (иначе он просто не откроет ward) - выбираем талисман, Propeties, Engine Features -> Stack Count и ставим единичку. Ну и последний штрих с талисманом - выбираем Engine Features -> FrobInfo и ставим там следующие флажки: Move; (None); Script. А теперь выбираем ward и разбираемся с ним. Строго говоря, талисманом уже можно открыть его, но будет небольшой недочёт - этим же талисманом можно будет снова "закрыть" ward, что в принципе может быть, но если хочется полной аналогии с игрой - тогда придётся ещё кое-что изменить. Выбираем для начала Tweq -> ModelsState и ставим там везде None'ы и нули, а затем - Tweq -> Models. Тут делаем следующее: в первом раскрывающемся списке выбираем RemoveProp; далее - где AnimC - ставим Sim, у остальных оставляем None (или убираем все флажки, чтобы осталось None), после - в поле Rate - вводим единичку, а в следующее поле - Model 0 - модель, на которую должна будет смениться модель пустого ward'а. В данном случае им будет ward со вставленным в него Талисманом Воздуха, модель его называется wdair, поэтому вводим в поле это слово. Однако в игре это работает, а при "самообслуживании" - нет. Не знаю, почему...

6.18. (Слито с сайта Darkfate.ru) В этой обучалке вам расскажут как создать базовую систему сигнализации.

Вам нужно пройти 4 этапа для того, чтобы вышла система сигнализации.
1. Кнопка(ки) любого типа. Я использовал кнопку (-448): Gizmo->Switches->Buttons->Button (-448).
2. Лампочка(ки) сигнализации. Используйте RamirezAlarm: Lights->AlarmLights->RamirezAlarm (-1809).
3. RelayTrap: fnord->TrapTrig->RelayTrap (-1704)
4. DestroyTrap: fnord->TrapTrig->DestroyTrap (-2651)
Необязательно: Если вы хотите, чтобы при сигнализации появилось больше охранников, то вам нужно создать TeleportTrap: fnord->TrigTrap->TeleTrap (-2789)

Когда будете размещать кнопку(ки), убедитесь, что они находятся на уровне пояса. Иначе вам прийдется наблюдать веселую картину: стражники будут нажамать в пустоту. Когда будете размещать RamirezAlarm, убедитесь, что он достаточно высоко расположен, в противном случае, AI будут задевать его. RelayTrap и DestroyTrap могут быть расположены в любом месте.

Итак, нам нужно связать кнопку и RelayTrap. Добавьте следующуюю связь кнопке(ам):

Flavour: ControlDevice
From: Номер Кнопки
To: Номер RelayTrap

Если у вас несколько кнопок, то создайте точно такие же связи с вашим RelayTrap для каждой.

Теперь разберемся с RelayTrap:

Flavour: ControlDevice
From: Номер RelayTrap
To: Номер RamirezAlarm

Если у вас более чем одна лампочка сигнализации, то проделайте указанную операцию для них так же.

Также для RelayTrap нужно добавить еще одн связь:

Flavour: ControlDevice
From: Номер RelayTrap
To: Номер DestroyTrap

И последнее, что нужно сделать с RelayTrap: добавьте свойство 'S' -> 'Scripts'. В первое поле (Script 0) введите 'RamirezAlarm' (без кавычек).

И, наконец, Destroy Trap:

Flavour: ControlDevice
From: Номер DestroyTrap
To: Номер RelayTrap

Вот и все!


*НЕОБЯЗАТЕЛЬНО* Если вы хотите, чтобы при охране появилось больше охранников, то сделайте следующее:

Создайте TeleTrap и поместите туда, где хотелось бы, чтобы появился охранник. Свяжите RelayTrap с TeleTrap:

Flavour: ControlDevice
From: Номер RelayTrap
To: Номер TeleTrap

Далее от TeleTrap к телепортируемому AI:

Flavour: ControlDevice
From: Номер TeleTrap
To: Номер Охранника


Создание одного или нескольких AI, которые должны реагировать на сигнализацию.

Теперь нам нужно дать AI соотвествующие свойства для реагирования на сигнализацию. В свойствах добаьте 'MetaProperty' -> 'AI_Behaviors' -> 'AI_B_m5' -> 'RingTheAlarm'.

Если вы сейчас запустите уровень, то увидите что AI при шуме нажимает 'в воздух' и при этом поднимается тревога. Надо сделать так, чтобы он побежал к кнопке.
Отредактируем свойства AI. Учтите, вы должны отредактировать свойство, находящееся по адресу RingTheAlarm -> AI ->Responses -> Alert Response: (это то метасвойство, которое мы только что добавили).

Разберемся в этом большом окошке-свойстве.
Alert Level (уровень тревоги) - так и оставляем по максимуму.
Priority (приоритет). По умолчанию - High. Можете поставить еще выше. Если самое высокое, то AI без промедления побежит поднимать тревогу, если пониже, то он для начала обследует ситуацию.

RESPONSE: STEP 1 (Реакция: шаг 1)
Step 1: Goto Object (идти к объекту)
Argument 1: номер кнопки (или через запятую - кнопок)
Argument 2: Very Fast (очень быстро)

RESPONSE: STEP 2 (Реакция: шаг 2)
Step 2: Face (повернуться к объекту)
Argument 1: номер кнопки (или через запятую - кнопок)

RESPONSE: STEP 3 (Реакция: шаг 3)
Step 3: Play Sound/Motion (проиграть звук/действие)
Argument 3: WorldFrob 0, AtWaist 0 (незнаю почему именно Аргумент 3)

RESPONSE: STEP 4 (Реакция: шаг 4)
Step 4: Frob Object (активировать (неуверен) объект)
Argument 1: номер кнопки (или через запятую - кнопок)

RESPONSE: STEP 5 (Реакция: шаг 5)
Step 5: Add/Remove Meta-Property (добавить/удалить мета-свойство)
Argument 1: Add (добавить метасвойство...)
Argument 2: M-HeardAlarm (...что услышал сигнализацию)

RESPONSE: STEP 6 (Реакция: шаг 6)
Step 6: Add/Remove Meta-Property (добавить/удалить мета-свойство)
Argument 1: Remove (удалить метасвойство...)
Argument 2: RingTheAlarm (...чтобы поднял тревогу - уже поднята.)

Теперь вы можете натренировать целую армию охраны и прислуги :)

Я надеюсь, что это все вам помогло. И если что - загляните в миссию Thief 1: Assassins (Наемные Убийцы).

6.19. Как сделать так, чтобы в начале миссии были видны не все цели, а при прошествии определённого момента появилась надпись "Новые цели", и невидимые ранее цели бы стали доступными? А вот как.
Управляют state'ом и visible'ом целей (за type и target не ручаюсь, да и не думаю, что это шибко нужно) вещь под названием QuestVarTrap (fnord/TrapTrig/QuestVarTrap). Ей нужно дать какой-либо ~ControlDevice - например, комнату: чтобы при входе в неё активируется эта самая QuestVarTrap, делаем как с любым другим предметом - связываем комнату с trap'ом связью ControlDevice, затем смотрим свойства QuestVarTrap'а. И выбираем там Trap -> QuestVar. И вводим там следующее: =x:goal_state(или visible)_y, где x - номер, на который изменится значение (т.е. чтоб цель стала видимой, вместо x пишем 1), y - номер цели, которая должна появиться. Для каждого изменения нужна своя QuestVarTrap, т.е. если появиться должны 4 новых цели, то нужно создать 4 QuestVarTrap'а, если же какая-то из старых должна стать неактивной - тогда ещё один QuestVarTrap, в свойствах пишем =2:goal_state_y, где y - номер цели.

6.20. Выше (в пункте 4.37) я писал про Act/React, но только самые базовые понятия, без всякого применения. Здесь же рассмотрим один из примеров его применения на практике. Эта вещь по сложности чуть-чуть уступает conversation'у, но разобраться в ней очень желательно, если есть желание развивать свою миссию технически.
При помощи Act/React можно сделать, допустим, такую вещь: при применении одного объекта на другом отмечается выполненной цель, и оба объекта при этом становится невозможно использовать повторно (допустим, поставили молот на пьедестал - и оба после этого становятся неактивными). В первую очередь сообразим, как это вообще должно работать. Ясно, что всё должно произойти как реакция пьедестала на стимул, посылаемый молотом. Чтобы наверняка исключить другие взаимодействия, создадим свой стимул. И в результате его взаимодействия должны получить изменение цели - то есть нужно послать сигнал "вкл." на QuestVarTrap - и сделать неактивными и молот, и пьедестал. Можно поставить им обоим метасвойства FrobInert, но с учётом того, что frob и Act/React мало связаны, лучше всего сделать по-другому: создать в "подсобной" комнате (куда игрок не может добраться) дубликаты наших молота и пьедестала, только неактивные - а после того, как молот провзаимодействует с нашим пьедесталом, телепортировать оба неактивных и убрать оба активных.
Для начала создаём сами молот и пьедестал. В иерархии объектов в раскрывающемся списке вверху выбираем Act/React Stimuli вместо Archetypes. Откроется список всех применяемых стимулов. Создадим свой и назовём его, допустим, HammerStim. Создав, сохраняем gamesys и закрепляем её командой set_gamesys (имя файла).
Теперь при помощи этого стимула заставим работать всё вышеперечисленное. В свойствах нашего молота выбираем Act/React -> Sources. Создаём новый (add): в появившемся окошке в первое поле вписываем номер нашего молота, дальше выбираем свежесозданный стимул HammerStim. В раскрывающемся списке propogator выберем Contact, intensity (интенсивность) конкретно для нашего случая можно ввести любую. Я написал 10. (В других случаях в зависимости от интенсивности сигнала реакция на стимул может быть разной.)
Также корректируем свойства нашего молота: так как берём его в инвентарь, то в пункте FrobInfo должно стоять Move в графе WorldAction. В остальном можно ничего больше не добавлять, даже графу ToolAction, отвечающую за взаимодействие с другими объектами, надо оставить пустой. Также указываем, что это предмет в инвентаре (Inventory -> Type: Item).
Теперь разбираемся, что ещё необходимо создать. Кроме QuestVarTrap'а, дубликатов молота и пьедестала (неактивных, которые выйдут на сцену после того, как стимул подействует), необходимо создать также 2 кнопки, которые пошлют сигнал на включение QuestVarTrap'у и на телепортацию молоту, а также TeleportTrap для молота. (Для пьедестала дополнительно ничего назначать не надо, его можно телепортировать силами Act/React.) Кнопки помещаем тоже в "подсобку", а TeleportTrap помещаем на пьедестал так, чтобы молот, будучи телепортированным, оказался поставленным на пьедестале (как будто его и не телепортировали). Кнопкам лучше назначить уникальные имена, чтобы не запутаться с номерами - допустим, QuestVarButton и TeleportButton. Связываем каждую кнопку ControlDevice'ом со своими trap'ами - первую с QuestVar, вторую с Teleport (последнюю - также ControlDevice'ом с молотом).
Ну а теперь открываем свойства пьедестала. Прежде всего также подкорректируем ему FrobInfo, чтобы он подсвечивался для использования: в графе WorldAction ставим Script. А затем выбираем Act/React -> Receptrons. Распишем здесь все реакции пошагово: в поле Object вводим номер нашего пьедестала, стимул - HammerStim, в полях intensity ставим галочки no min и no max (то есть не имеет значения, какова интенсивность пришедшего сигнала - главное, чтобы пришёл). А дальше пишем реакцию. Первый шаг - удаление "активного" молота, выбираем Destroy Object в раскрывающемся списке Effect, а в поле Agent Object ставим переключатель на Source - это означает, что уничтожится тот "источник", что воздейстовал этим стимулом - то бишь наш молот.
Второй шаг - постановка галочки в целях. (QuestVarTrap нужно предварительно сконфигурировать (см. предыдущий пункт), чтобы она позволяла нужной цели быть выполненной.) Эффект ставим Frob Object, объект - QuestVarButton.
Третий шаг - телепортация "неактивного" молота на место. Также ставим эффект Frob Object, объект - TeleportButton.
Четвёртый шаг (можно его поменять местами с третьим) - телепортация неактивного стола. Тут похитрее: ставим эффект Teleport Object, который позволяет телепортировать один объект (target) на место другого (agent) без всяких дополнительных ухищрений. В качестве target object ставим номер или название "неактивного" пьедестала, в качестве agent object - Me (т.е. наш многострадальный "активный" пьедестал).
Ну и, наконец, пятый, последний шаг - чтобы два объекта не накрывались, нужно один из них убрать - а именно наш "активный" пьедестал. Ставим эффект Destroy Object и переключатель на Me.
Итого после всех этих действий в окне ACt/React -> Receptrons должно быть пять строчек: Destroy Object, две строчки Frob Object, Teleport Object и снова Destroy Object. Последовательность эту соблюдать необходимо - иначе, если в первую очередь уничтожить наш "активный" пьедестал, то все дальнейшие шаги потеряют смысл.
Заходим в игру и проверяем: молот можно использовать как ключ, но применяется он только на пьедестал - с только что расписанными эффектами.
Это только один из примеров, но вообще Act/React используется для решения очень широкого круга задач, их всех здесь рассмотреть просто невозможно.



Часть 7. Объекты: Сложные комбинации свойств и связей. Изощрённые дромадёрские мысли.




7.1. При помощи даже DromEd 1 можно посмотреть на себя со стороны или создать небольшую "сцену" на уровне. Делается это следущим образом (авторы - Silentsleep и Saturnine, я лишь перевёл их инструкцию по адресу http://www.thief_age.republika.pl/info/CamVator.txt ).

В первую очередь создаём лифт и 2 (или больше - в зависимости от того, как и где будет перемещаться смотрящая камера) TerrPt'а. Далее проделываем ту же операцию, что и при обычном лифте - соединяем TerrPt'ы связью TPath, ставим скорость, с которой будет перемещаться камера (желательно поставить 3). Другой же TerrPt тоже связываем с первым TerrPt'ом связью TPath, но в графе "speed" в данных ставим 0. Это будет означать, что "камера" (лифт) будет двигаться обратно с нулевой скоростью - то есть будет по-прежнему стоять на месте.
Далее, создаём саму "камеру" - лифт, а точнее, плот (raft). Меняем его размеры на 1;1;1, чтобы он ни с чем не сталкивался при движении, выбираем Physics -> Misc -> Collision Type в свойствах и ставим там None. Если нужно, убираем галочку с пункта Physics -> Moving Terrain, связываем наш плот (лучше переименовать его в CamVator для удобства) связью TPathInit с первым TerrPt'ом. Также желательно сделать так, чтобы наш плот не вырисовывался (потому что игрок сможет смотреть по сторонам в процессе сцены и может увидеть у себя под ногами плот), поэтому при желании выберем Renderer -> Render Type, а в нём - Not Rendered.
Теперь создаём кнопку (или другой ControlDevice), связываем её ControlDevice'ом со вторым TerrPt'ом - чтобы при использовании кнопки лифт начал двигаться ко второму TerrPt'у. Однако же нужно будет совершить и кое-какую манипуляцию с игроком, чтобы он прочно держался на этом лифте и не смог сдвинуться с места - этой манипуляцией называется связь PhysAttach. Однако же, если её применить просто так, то с игроком будет твориться что-то неладное. В DromEd 1 эта проблема решается легче - нужно всего лишь сначала телепортировать игрока в центр объекта. (Как решить в Thief 2 - честно говоря, не знаю; но можно посмотреть решение такой проблемы в FM-ках, к примеру, Broken Triad.) Что мы и сделаем - выбираем CamVator и редактируем скрипты (S -> Scripts): добавляем скрипт TrapTeleporter, после чего связываем кнопку (её лучше переименовать в TeleButton, потому что потом потребуется ещё одна кнопка) с CamVator'ом связью ControlDevice.
Теперь последний штрих - создаём вторую кнопку, которая, собственно, и послужит ControlDevice'ом к conversation'у. Ибо нам нужно будет добавить связь PhysAttach в течение игры, что лучше всего делается именно conversation'ом. Создаём 2 объекта - кнопку (или другой ControlDevice) и маркер. Связываем первую со вторым связью ControlDevice, приписываем маркеру скрипт TrapConverse, в графе AI -> Conversations -> SaveConversation ставим галочку; создаём AI, связываем маркер с ним связью AIConversationActor, ID ставим 1. (Без актёра просто ничего работать не будет.)
И далее делаем следующее: редактируем свойства маркера. AI -> Conversations -> Conversation, шаг 00. Первое, что делаем - можно удалить связь ControlDevice, чтобы "conversation" не включалась дважды; затем - во втором шаге - выбираем Add link, argument 1 - ControlDevice, argument 2 - Player (не StartingPoint!), argument 3 - CamVator. (Добавляем связь для того, чтобы CamVator знал, что в него должно перемещаться, в данном случае это игрок). В третьем же шаге выбираем Frob object, аргумент 1 - TeleButton. Этот шаг телепортирует нас в центр CamVator'а, он начнёт своё движение. И теперь - чтобы игрок не смог никуда двигаться - в следующем шаге пишем: Add link, argument 1 - PhysAttach, argument 2 - CamVator, argument 3 - Player.
А теперь должен возникнуть вопрос: ну и что дальше? Следующим шагом, по идее, должно быть убирание связи PhysAttach (а значит, и окончание "conversation"а), но что из этого выйдет? А ничего не выйдет - игрок нажмёт кнопку, и ничего не произойдёт - точнее произойдёт, но так быстро, что ничего не успеешь заметить. Поэтому, чтобы прошло какое-то время, заставим AI ходить и впишем этот шаг в conversation. Тогда связь PhysAttach удалится только после того, как AI дойдёт до нужной точки - а значит, мы как бы будем наблюдать за этим.
Желательно сделать так: во-первых, железно необходимо понизить уровень тревожности AI до нуля, иначе он вас увидит и будет пытаться атаковать. Либо добавляем метасвойство M-AlertCapZero, либо просто вручную ставим всё в AI -> AI Core -> Alertness Cap на нули. (Второй вариант сгодится, если этот AI действительно не будет враждебным или его просто больше не увидите на уровне, если же потом с ним придётся иметь дело - лучше сделать метасвойство, а потом - когда удалится связь PhysAttach - его убрать. Или наоборот, он может и не успеть вас заметить. (Хотя это я пока не проверял. - Прим. 25/08/08.)
А затем создаём маркер, к которому он должен пойти, и в предпоследнем шаге пишем: Goto object, (номер или название маркера). А затем уже - Add/Remove MetaPropety (Remove; M-AlertCapZero; (номер или название AI)) и Remove link (PhysAttach, CamVator, Player).
Однако и это может оказаться не тем, что надо. При окончании conversation'а игрок просто упадёт на пол сквозь лифт. Если такое положение вещей не устраивает, можно телепортировать его сразу при окончании conversation'а обратно, для этого создаём кнопку и TeleportTrap в том месте, которое хотим переместить, связываем кнопку с Trap'ом связью ControlDevice, trap - ControlDevice'ом с игроком. И в последнем шаге, уже после удаления связи PhysAttach, пишем Frob object, аргумент - номер кнопки. Да, и проделывать абсолютно все эти шаги должен, естественно, ActorOne - тот самый AI, которого мы избрали на пост первого актёра.
Разумеется, в течение "conversation"а может быть не только ходящий AI, но ещё и много чего другого, как в обычной conversation. В любом случае, всё, что будет между шагами "Add link Phys Attach" и "Remove link Phys Attach", и будет той самой сценой, которую мы будем иметь удовольствие наблюдать "со стороны".
Вот такие пироги. И, что подчеркну, всё это - без каких-либо дополнительных ухищрений! Никаких скриптов или дополнительных выкрутасов. Хотя, конечно, с первого раза это понять не очень легко.

7.2. Ещё одна ссылка с необъятного форума TTLG. На сей раз товарищ под ником Fidcal рассказывает, как можно применить скрипт TrigInvFrob вместе со StdButton.
Оригинал здесь: http://www.ttlg.com/forums/showthread.php?t=83128&highlight=tutorial
Мой перевод и комментарии:
Для чего это нужно? Для того, чтобы объект при применении в инвентаре подействовал как рычаг или кнопка, то есть как ControlDevice.
Что делаем сначала: в свойствах объектах меняем FrobInfo на следующее: World Action - Move; InvAction - Script, FocusScript; Tool Action - Script, FocusScript.
В скрипты же добавляем уже указанные выше StdButton и TrigInvFrob.
Далее Fidcal пишет, что лучше связать наш предмет ControlDevice'ом через ещё один ControlDevice - рычаг, например. (Или RelayTrap, или объект со скриптом TrapRelay, хотя стопроцентную верность этого пока не гарантирую. - Прим. 25/08/08.) А рычаг уже связать ControlDevice'ом с нужным нам объектом. Иначе это всё будет работать только один раз. Хотя, вероятно, может быть и одного раза достаточно. Стоит принять во внимание, что такой предмет при использовании будет перемещаться в центр экрана, как ключ или отмычка, а затем уже, при повтором использовании, уже исполнит свой долг.
(Да, связи здесь не участвуют. Но некая эффектность есть.)

7.3. На самом деле, это не совсем комбинация свойств и связей - связей здесь нет, да и не очень это хитрый приём. Но эффектность есть, поэтому записано это здесь, а не в частях 6, 4 или 8.
...И снова TTLG. На сей раз предложение по архитектуре и не только.
http://www.ttlg.com/forums/showthread.php?t=71559&highlight=tutorial
Честно говоря, большая часть из этого либо уже здесь (в моих заметках) так или иначе освещена, либо (по моему скромному мнению) должна быть само собой разумеющейся для дромадёра. Но одно предложение и меня заинтересовало, а именно: создание нового неба при помощи объектов. Человек взял фотографию звёздного неба, "распилил" её на 4 части по 256*256 пикселей каждая с чёрными участками на краях, чтобы текстуры не смешивались друг с другом на краях. Затем создал 4 двери (4*4 secret door), установил на них эти текстуры (Shape -> TxtRepl r0) и поднял под потолок. И получилось то, что можно увидеть на скриншоте в его шестом сообщении - настоящее звёздное небо фотографического, а не рисованного, качества. Аналогично можно сделать и с другими видами background'а - например, если речь идёт о необитаемом острове, то как background можно сделать фотографию вида на море... Хотя и здесь есть минус - небо выглядит не как небо, а как потолок. Другой способ - конечно же, поместить фотографию в папку fam\skyhw, создать 6 видов на разные грани куба (что будем видеть наверху, внизу и по 4-м сторонам), затем в full.pcx передать всю цветовую гамму и с этим всем попытаться загрузить текстуру неба в DromEd (как менять небо, описано в пункте 1.12). Как видно, у каждого метода есть свои плюсы и минусы...

7.4. На сей раз предложение от dSpair'а, как создать случайные условия в DromEd.
http://www.ttlg.com/forums/showthread.php?t=90380&highlight=tutorial
Всё сводится к следующему: у нас есть комната с 6 пьедесталами. На одном из них (это и будет случайное событие) должен будет появиться предмет, в примере - Талисман Воды. Способ создать такую "случайность" - свойство AI патрулировать по случайному маршруту. Чтобы талисман появлялся в случайных местах, нужно задать такое же количество возможных точек, в которые может прийти AI, и связать каждый участок ControlDevice'ом с TeleportTrap'ом. Вот, собственно, костяк идеи, реализуется же она так:
Создаём комнату в форме цилиндра. У нас есть 6 возможных точек перемещения талисмана. Создаём цилиндр из 6 сторон, затем в каждом углу его - по room brush'е, всего их должно быть 6 штук. И в середине - ещё одну room brush, седьмую. И в каждом уголке room brush'а - по TrolPt'у, в центре же dSpair настоятельно рекомендует поставить 2 TrolPt'а, на первом AI будет стоять, ко второму подойдёт, а уже после него начнутся "случайности". (Хотя, по-моему, если связать TrolPt с несколькими TrolPt'ами связью AIPatrol, то даже при обычном, не случайном, патруле AI всё равно следующий пункт выберет случайно, и не нужно параметра Patrol: Random sequence.)
Теперь создадим AI и подкорректируем его свойства: AI -> Ability Settings: Patrol: Does Patrol - ставим галочку, Patrol: Random sequence - тоже ставим галочку. И последний создаваемый объект здесь - DestroyTrap. Она нужна для того, чтобы талисман не перескакивал с одного места на другое - ведь охранник же продолжит патруль (а значит, и входом в следующую комнату изменит положение талисмана), значит, его надо убрать с уровня. Вот такой вот жестокий механизм. :)
Итак, теперь переименовываем наши комнаты так, чтобы в нашей "подсобке" было 7 разных room brush'ей с разными названиями. Тем 6, что по краям, пишем скрипт TrigRoomCreature.
А теперь разбираемся с талисманом. Если его ещё не создали, делаем это; после чего создаём 6 TeleportTrap'ов, каждую помещаем и поворачиваем так, чтобы талисман при перемещении встал как надо. После чего соединяем их всех ControlDevice'ом с талисманом и ~ControlDevice'ом каждую со своей комнатой.
И последний штрих: чтобы AI при входе в комнату (а значит, и активации телепорта, перемещающего талисман) самоликвидировался, добавляем ещё одну связь - каждую из наших 6 room brush'ей связываем ControlDevice'ом с DestroyTrap'ом, а DestroyTrap натравливаем на охранника всё той же жестокой связью ControlDevice.
И в итоге талисман будет появляться случайно на одном из 6 мест. Разумеется, всё это можно размножить (применить для нескольких вещей) или применить для, допустим, случайного добавления метасвойств предметам: например, при том же входе в комнату охранник включает "её" conversation. Одна, допустим, добавит "спокойное" метасвойство одному AI, другая - другому, и т.д. Вариантов может быть очень много, нужна лишь фантазия...

7.5. Может статься, что потребуется реализовать следующее: заставить определённый триггер сработать, только когда рычаги будут повёрнуты в строго определённом порядке. Несмотря на то, что проблема выглядит простой, решить её простыми комбинациями свойств и связей лично мне представилось невозможным. Поэтому здесь предложу свой способ реализации данной идеи. Рассмотрю его на следующем примере: имеется 3 рычага и 3 двери. Необходимо сделать так, чтобы все три двери открылись только при необходимом порядке поворота рычагов (1, 2, 3), а в противном случае хотя бы одна из дверей должна остаться закрытой, не пропуская игрока. Для этого используем следующее: поставим четвёртую дверь, обычно открытую, и при неверном повороте рычага заставим её закрыться. Поскольку управлять ей могут несколько рычагов одновременно, поставим между ними RequireAnyTrap, чтобы при неверном движении, исходящего от любого из "ненужных" рычагов, механизм сработал. Но здесь получается и другой нюанс - после поворота первого рычага, естественно, не связанного с нашей RequireAnyTrap, нужно будет повернуть второй, который по-прежнему будет связан! Значит, придётся эту связь удалить в течение игры, а для этого подходят две вещи: Act/React и conversation. Поскольку в Act/React я разбираюсь не слишком хорошо, то сделаю через conversation. У которой, правда, есть один минус - необходим хотя бы один участник (actor). (Причём conversation'ов будет несколько - их число должно быть равно числу рычагов, но в них во всех может участвовать единственный актёр.) И, наконец, для красоты желательно оповестить игрока звуками, на верном или неверном он пути - для этого нужны ещё два SoundTrap'а.
Для начала создаём участников действа - рычаги и двери. Для удобства назовём их LeverNo1...3 и DoorNo1...4. Связываем каждый рычаг с соответствующей дверью связью ControlDevice, а для четвёртой двери ставим RequireAnyTrap (которую, опять-таки, для удобства можно переименовать в DoorNo4Trap), соединяем 2 рычага (2-й и 3-й) с нашей RequireAnyTrap ControlDevice'ом, а trap - с дверью, также ControlDevice'ом. Затем конфигурируем две наши SoundTrap: одну, которая отвечает за "провал", связываем связью SoundDescription со схемой звука m10fail (по-моему, она так и называется), а активирует её пускай всё та же вредная RequireAnyTrap - ставим ещё один ControlDevice, от неё к SoundTrap'у, отвечающей за провал. SoundTrap, отвечающую за удачную разгадку, пока только связываем SoundDescription'ом со схемой, привязанной к файлу m10succ, а активирующая её связь добавится в течение игры.
Теперь необходимо создать три маркера и одного AI (можно где-нибудь в подсобке и хоть лягушку - лишь бы 100% смогла активировать conversation), пишем каждому маркеру скрипт TrapConverse, для удобства также переименовываем - допустим, в Conv_1lever...Conv_3levers. Каждую из наших conversation'ов связываем с AI связью AIConversationActor, нумеруем как первого актёра. А conversation'ы активироваться будут по порядку. Пока только свяжем первый рычаг с первой conversation, остальные две оставим без связей - они также добавятся в течение игры.
А теперь пишем, что будет делаться в каждой из наших conversation'ов. Во-первых, необходимо убрать возможность неверного шага со следующего рычага - пишем Remove link, ControlDevice, DoorNo4Trap, LeverNo2. Затем нужно добавить ему же возможность включить следующую conversation, которая позволит пройти дальше - Add link, ControlDevice, Conv_2levers, LeverNo2. Наконец, чтобы не было каши, следует убрать возможность запускать нашу conversation снова - убираем связь ControlDevice от первого рычага к нашей conversation. Для особых вредин, желающих совсем запутать игрока, можно добавить связь от первого рычага к "провальной" DoorNo4Trap.
Всё, с первой conversation покончили. Теперь открываем свойства второй и прописываем ей практически всё по аналогии: убираем возможность включить её второй раз (Remove link, ControlDevice, Conv_2levers, LeverNo2), убираем "провальную" связь с третьего рычага (Remove link, ControlDevice, DoorNo4Trap, LeverNo3), добавляем возможность включить третью и последнюю conversation (Add link, ControlDevice, Conv_3levers, LeverNo3), при желании добавляем "провальную" связь нашему второму рычагу. Но теперь, кроме этого, ещё вспомним - третий рычаг поворачивается последним, после него игрок решит загадку! Так что добавляем ещё одну связь - ControlDevice от третьего рычага до SoundTrap, отвечающей за "удачный" звук.
А что вписывать в третью conversation - дело вкуса. Обязательно достаточно только убрать две связи: от третьего рычага к Conv_3levers и от него же к SoundTrap'у, отвечающему за "удачный" звук (иначе потом при повороте рычага он каждый раз может проигрываться). Но, чтобы избежать каши с ошибочными поворотами рычагов уже после открытия всех дверей, лично я убираю все связи к "провальной" DoorNo4Trap - в нашем случае, от первого и второго рычагов, если они были добавлены в ходе предыдущих conversation'ов.
Как мне кажется, задачу можно решить с меньшим количеством лишних объектов, применяя Act/React - Гарретт имеет некий стимул, который, воздействуя с постоянной интенсивностью, заставляет каждый рычаг реагировать на неё по-своему - с теми же эффектами, которые мы прописывали в ходе conversation'ов.
Кроме того, для Thief 2 существует гораздо более простое решение, но годящееся только для четырёх кнопок: необходимо создать объект под названием odometer, который открывает дверь при верном вводе кодового замка (4 числа). Соответственно, если каждую из кнопок привязать к определённому числу - скажем, от 1 до 4, - а одометр настроить на открытие при вводе кода 1234, то нажатие кнопок строго в необходимой последовательности позволит двери открыться. Но если число кнопок не кратно 4, этот способ не годится. И если используются не кнопки, а рычаги или триггеры, то это тоже, по всей видимости, не годится.

Продолжение здесь.
Описание
Прохождение
FAQ - игровой
FAQ - технический
Скриншоты
Зарисовки
Обои
Видео
Аудио
Патчи
Переводы
Описание
Прохождение
FAQ - игровой
FAQ - технический
Скриншоты
Зарисовки
Обои
Патчи
Переводы
Описание
Прохождение
FAQ - игровой
FAQ - технический
Скриншоты
Зарисовки
Обои
Патчи
Переводы
Описание
Прохождение
FAQ - игровой
FAQ - технический
Скриншоты
Зарисовки
Обои
Патчи
Переводы
New Dark
The Dark Mod
Thief 2 Gold
Прочие

Night Blade
Thievery
Страница сгенерирована за 0.313 секунд.
© 2001-2024 - Thief: the Dark Fate
Использование материалов сайта разрешается только при согласии их авторов и администрации Dark Fate,
при этом ссылка на Dark Fate обязательна.