В этой теме на конкретных примерах (Уроках) разбирается весь процесс создания мода.
Правила работы в теме: Любой пользователь обладающий опытом и знаниями в модостроение, создает урок по определенной теме (отражено в задаче урока), после этого описывает выполнение поставленной задачи в виде отдельного файла и (или) напрямую в своем посте спрятав его под спойлер. В дополнении к уроку желательно выложить содержимое папки gamedata с выполненным уроком, чтобы пользователь скачав его мог проверить правильность выполнения урока самостоятельно. Обсуждение уроков ведется в теме: "Общие вопросы модостроения". Также в данной теме могут быть размещены дополнительные материалы помогающие пользователю освоить все аспекты модостроения.
Будем пытаться не использовать специфические файлы, поэтому можно работать в чистом ЗП, SGM и т.д. **
Не рекомендуется размещать информацию автором которой вы не являетесь, но если она полезна для пользователей сайта указывайте автора. Не рекомендуется размещать информацию доступную на других ресурсах повещенных модостроению - пользователи и так смогут ее найти. Запрещено размещать непроверенную информацию. В любом случае модераторы раздела оставляют за собой право удалить пост с Уроком или Справочной информацией в случае нарушения автором правил данного форума или правил данной темы.
*В любом уроке, вопросы рассмотренные полно в предыдущем уроке, могут быть описаны весьма сжато, поэтому при возникновении вопросов, прежде всего посмотрите предыдущие. ** Если нет специальных пояснений то урок делался на чистом ЗП 1.6002, в противном случае указан мод и версия для которой урок предназначен.
[cut=Рекомендации по оформлению]1. Заголовок сообщения из которого понятно назначение поста (Урок, Справочная информация или другое) 2. Если это урок то он должен иметь четко обозначенную задачу и желательно иметь ссылку на файл с выполненным уроком, для того чтобы выполняющие его могли скачать и посмотреть выполнение урока на примере. 3. Придерживайтесь устоявшейся цветовой схемы: а) Путь к файлу и (или) имя файла - Зеленый б) Имя параметра, функции и т.п. в файле - Желтый в) Не рекомендуется использовать оранжевый - это цвет комментариев кураторов раздела и к тому же близок к цвету ссылок. 4. Куски кодов и конфигурационных файлов обязательно помещайте в контейнер
Код
Исходный текст файла
. 5. Выделение текста изменением размера шрифта, его типом на усмотрение автора, главное не перебарщивать.[/cut]
Тема предназначена только для публикации уроков и справочной информации, вопросы в другой теме! Флуд и оффтоп будет наказан без предупреждения, а пост удалён, что бы там не находилось.
Эти 0 пользователя(ей) поблагодарили tracker за это полезное сообщение:
Урок 39.(Автор - GEONEZIS) Задача: Создание многоэтапного квеста на последовательный поиск предметов. Реализация на X-Ray 1.6.00
Поставленная задача состоит в обучения принципам построения сложных многоходовых заданий на чистой игре Сталкер Зов Припяти. Будет показан процесс построения сложного диалога с ветвлением, последовательный спавн квестовых предметов через скрипт и собственно структура многоуровнего квеста. Задание следующее. Новиков просит ГГ принести для него разбросанные по локации сканеры аномалий. Квест будет построен таким образом что необходим исключительно поэтапный вариант его прохождения, то есть от одной точки к другой, без каких-либо вариантов. Получить один предмет раньше другого не будет предоставляться возможным. Необходимые для редактирования файлы: 1. конфигурационные в (gamedata\configs\gameplay\) -character_desc_jupiter.xml -dialogs_jupiter.xml -info_jupiter.xml 2. конфигурационные в (gamedata\configs\misc\) - tm_jupiter.ltx - quest_items.ltx - death_generic.ltx 3. конфигурационные в (gamedata\configs\text\rus\) - st_dialogs_jupiter.xml - st_quests_jupiter.xml - st_items_quest.xml 4. конфигурационные в (gamedata\configs\misc\trade\) - trade_generic.ltx 5. скриптовый в (gamedata\scripts\) - dialogs_jupiter.script - ui_si.script - bind_stalker.script - new_tasks.script Рассмотрим структуру квестовых диалогов. Для этого откроем dialogs_jupiter.xml и в самом низу добавим два диалога. Один активный при старте задания. Второй на завершение. В принципе можно было объединить их в один, но рассмотрим более легкий вариант. Однока при этом внесем разнообразие в процесс выдачи задания предоставив несколько вариантов его получения внутри диалога. Этот несколько освежит стандартные методы диалогостроения, когда все они делаются последовательными, без каких-либо вариантов.
Сразу же пропишем русскую транскрипцию в st_dialogs_jupiter.xml для того чтобы понимать о чем в диалоге идет речь :
Code
<string id="jup_b6_scientist_tech_quest_anomalies_scaner_0"> <text>Приветствую, хотел бы оказал вам максимально возможное содействие. Какого рода помощь тебе необходима?</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_1"> <text>В принципе есть одно небольшое дело, главное это твое желание работать.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_2"> <text>Я готов.Что нужно делать?</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_3"> <text>Прекрасно. Правда придется немного побегать. Мне необходимо получить кое-какие данные.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_4"> <text>Замеры? Необходимо будет устанавливать какие-нибудь сканеры?</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_41"> <text>Нет, устанавливать не придется. Их уже установили. Тебе же наоборот придется их собрать и доставить сюда, чтобы я смог получить с них результаты замеров.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_401"> <text>Что за сканеры-то? Аномальная активность?</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_4011"> <text>Обыкновенные сканеры аномалий. Их показатели результатов замеров будут мне необходимы для проведения настройки моего оборудования.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_4012"> <text>Все ясно. Придется взять научный комбез. Передавай координаты.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_4013"> <text>Уже загрузил. Комбез это хорошая тема. Обязательно возьми. И смотри не сварись в аномалиях.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_402"> <text>Кто их устанавливал и куда мне придется отправиться?</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_4021"> <text>Тебе то не все-равно, кто их размещал. Пару дней назад, сталкеры из Свободы - сойдет такой ответ? Не о том думаешь. Твоя задача отправиться на Затон, пробежаться по точкам и вернуться назад живым вместе со сканерами. Все ясно?</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_4022"> <text>Все. Передавай координаты.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_4023"> <text>Уже загрузил. Комбез научный только одень. И смотри не сварись в аномалиях.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_5"> <text>А может еще что нужно?</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_51"> <text>Нет, хотя может быть потом я подберу для тебя работку. Но сначала ты должен будешь добыть результаты измерений с установленных на Затоне сканеров аномалий.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_52"> <text>Искать сканеры в аномалиях. Ха, веселая преспектива. Без специального научного костюма мне там долго не пролазить...</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_53"> <text>Намек понял. Вот держи ССП-99. Неплохой костюм, хотя и поношенный. Координаты сканеров я тебе загрузил.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_531"> <text>Хотя бы кровь с костюма отмыли? По-любому с трупака какого-нибудь своего ботанического дружка сняли...</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_5311"> <text>Ой, ну давай мне не заливай..Тоже мне брезгливый нашелся. У самого-то, чай не первой свежести костюмчик..</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_5312"> <text>Проехали Кулибин. Все, я отправляюсь за замерами...</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_5313"> <text>Поосторожнее там...</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_532"> <text>Все понял, отправляюсь.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_5321"> <text>Поосторожнее там...</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_6"> <text>Хорошо, я сделаю то что нужно. Говори с чего начинать.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_61"> <text>Вот это деловой разговор, делового человека. Вообщем план таков. Сначала ты находишь на Затоне сканеры аномалий, установленные там нашими сподручными сталкерами. Координаты я тебе уже сбросил. Потом, я может быть посмотрю еще что для тебя..</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_611"> <text>Все ясно, Кулибин. Жди, я за твоими сканерами.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_6111"> <text>Поосторожнее там. В аномалиях не сгинь...</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_end_0"> <text>Вот все твои сканеры.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_end_1"> <text>Отличная работа. Немедленно начинаю работу над обработкой результатов замеров. Новую работу получишь позже. А пока гуляй.</text> </string>
Теперь разберем структуру представленных диалогов:
- Во втором диалоге нет ничего сложного: активен при наличие инфопоршня jup_novikov_quest_zaton_scanner_have_6, исчезает после выдачи jup_novikov_quest_zaton_scanner_end, имеет прекондишн actot_have_all_zaton_scaner когда в инвенторе ГГ наличие всех квестовых предметов. содержит один акшион actot_to_novikov_give_zaton_scaner на передачу предметов заказчику. - первый диалог сложнее. основная особенность это вложенная тройная разветвленность, когда можно выбрав одну из трех веток получить один и тот же результат. - внутри каждой из веток также имеет место дополнительные ответвления. - старт задания происходит по выдачи акшиона give_novikov_zaton_scaner_quest сопровождается также выдачей инфопоршня jup_novikov_quest_zaton_scanner_start - создание первого квестового предмета происходит также внутри диалога- акшион jup_b6_create_first_scaner - чисто для атмосферности происходит выдача ГГ костюма для выполнения задания при выборе одной из трех веток. это акшион jup_b6_to_actor_give_spez_outfit
Объявим используемые инфопоршни в info_jupiter.xml. Добавим в конце файла код:
Добавим наши диалоги НПС (В данном случае Новикову) для этого в файл character_desc_jupiter.xml в его профиль <specific_character id="jup_b6_scientist_tech" team_default="1"> добавим строки диалогов
С диалогами и инфопоршнями разобрались теперь добавим необходимые для выполнения квеста предметы.
В файл quest_items.ltx пропишем семь секций предметов zat_spec_anomaly_scanner_№. Все предметы являются квестовыми- невозможна их продажа и выкладывание из инвентаря ГГ.
В файл st_items_quest.xml пропишем дескрипцию предметов.
Code
<string id="zat_spec_anomaly_scanner_1_name"> <text>«Сканер грави-химического симбионта»</text> </string> <string id="zat_spec_anomaly_scanner_1_descr"> <text>«Специализированный сканер аномальной активности из серии 32.1351. Используется учеными для изучения процессов происходящих в грави-химическом симбионте»</text> </string> <string id="zat_spec_anomaly_scanner_2_name"> <text>«Сканер химической аномалии»</text> </string> <string id="zat_spec_anomaly_scanner_2_descr"> <text>«Специализированный сканер аномальной активности из серии 27.7724. Используется учеными для изучения процессов происходящих в химической аномалии»</text> </string> <string id="zat_spec_anomaly_scanner_3_name"> <text>«Сканер гравитационной аномалии»</text> </string> <string id="zat_spec_anomaly_scanner_3_descr"> <text>«Специализированный сканер аномальной активности из серии 78.9835. Используется учеными для изучения процессов происходящих в гравитационной аномалии»</text> </string> <string id="zat_spec_anomaly_scanner_4_name"> <text>«Сканер термальной аномалии»</text> </string> <string id="zat_spec_anomaly_scanner_4_descr"> <text>«Специализированный сканер аномальной активности из серии 47.3246. Используется учеными для изучения процессов происходящих в термальной аномалии»</text> </string> <string id="zat_spec_anomaly_scanner_5_name"> <text>«Сканер пси-статической аномалии»</text> </string> <string id="zat_spec_anomaly_scanner_5_descr"> <text>«Специализированный сканер аномальной активности из серии 06.8912. Используется учеными для изучения процессов происходящих в пси-статической аномалии»</text> </string> <string id="zat_spec_anomaly_scanner_6_name"> <text>«Сканер термального симбионта»</text> </string> <string id="zat_spec_anomaly_scanner_6_descr"> <text>«Специализированный сканер аномальной активности из серии 35.0205. Используется учеными для изучения процессов происходящих в термальном симбионте»</text> </string> <string id="zat_spec_anomaly_scanner_7_name"> <text>«Сканер электро-статической аномалии»</text> </string> <string id="zat_spec_anomaly_scanner_7_descr"> <text>«Специализированный сканер аномальной активности из серии 03.1392. Используется учеными для изучения процессов происходящих в электро-статической аномалии»</text> </string>
В файле trade_generic.ltx пропишем торговлю. также нужно добавлять индивидуально во все остальные файлы конфигов торговли. (но не обязательно)
С квестовыми предметами также разобрались, теперь необходимо разобраться со скриптами квеста. Собственно теперь мы и подходим к основной сути нашего урока, в этом этапе заключен его основной смысл.
В файле dialogs_jupiter.scriptдобавим следующие функции:
Code
function jup_b6_create_first_scaner(first_speaker, second_speaker) alife():create("zat_spec_anomaly_scanner_1",vector():set(-436.574,-6.527,170.169),116113,16) end
function jup_b6_to_actor_give_spez_outfit(first_speaker, second_speaker) dialogs.relocate_item_section_to_actor(first_speaker, second_speaker, "scientific_outfit") end
function give_novikov_zaton_scaner_quest() task_manager.get_task_manager():give_task("geonezis_jup_spec_scaner") end
function actot_to_novikov_give_zaton_scaner(first_speaker, second_speaker) local items_table = {"zat_spec_anomaly_scanner_1","zat_spec_anomaly_scanner_2","zat_spec_anomaly_scanner_3","zat_spec_anomaly_scanner_4","zat_spec_anomaly_scann er_5","zat_spec_anomaly_scanner_6","zat_spec_anomaly_scanner_7"} for k,v in pairs(items_table) do if db.actor:object(v) ~= nil then dialogs.relocate_item_section_from_actor(first_speaker, second_speaker, v) end end end
function actot_have_all_zaton_scaner(first_speaker, second_speaker) return db.actor:object("zat_spec_anomaly_scanner_1")~=nil and db.actor:object("zat_spec_anomaly_scanner_2")~=nil and db.actor:object("zat_spec_anomaly_scanner_3")~=nil and db.actor:object("zat_spec_anomaly_scanner_4")~=nil and db.actor:object("zat_spec_anomaly_scanner_5")~=nil and db.actor:object("zat_spec_anomaly_scanner_6")~=nil and db.actor:object("zat_spec_anomaly_scanner_7")~=nil end
коротко их поясним: - спавн первого квестового предмета - передача бронекостюма ГГ - выдача задания - передача всех квестовых предметов НПС - скрипт проверки наличия в инвенторе ГГ всех необходимых предметов
Теперь создадим файл new_tasks.script и добавим в него следующий код одной основной функции task_spec():
Смерти Вопреки Spectrum Project AP_Prodaction
Сообщение отредактировал GEONEZIS - Вс, 08.04.2012, 08:40
Эти 0 пользователя(ей) поблагодарили Geonezis за это полезное сообщение:
Урок 39a.(Автор - GEONEZIS) Завершение урока по созданию многоэтапного квеста.
Завершающий этап урока. Скрипт созданный нами в файле можно посмотреть в скачанном архиве с отработанным примером. Основная его особенность это последовательный спавн квестовых предметов. Последующий будет создаваться только после того как был найден предыдущий. Также происходит выдача инфопоршней используемых в структуре самого квеста. Еще одна особенность это установка дополнительной проверки в зависимости от локации.
Созданный нами скрипт необходимо обьявить в функции апдейта актора actor_binder:update(delta) в файле bind_stalker.script
Код
..... new_tasks.task_spec() .....
Теперь собственно перейдем к созданию самого задания. Код секции квеста ([geonezis_jup_spec_scaner]) можно просмотреть в файле tm_jupiter.ltx в архиве с отработанным примером. Основные особенности это наличие двух кондишинов один на завершение задания, второй на его провал (в случае если сквад ученых бункера станет врагами по отношению к ГГ). По завершению задания будет повышена репутация у группировки экологов, а также выдана награда. Структура квеста последовательная. Одна секция тайтлов, дескрипшинов и меток заменаяет другую при получении соответсвующих им инфопоршней. Всего 7 таких этапов. Инфопоршни используемые в задании выдаются также последовательно. Определяемыми являются те которые обновляются при спавне (jup_novikov_quest_zaton_scanner_create_№), а не при взятии предмета. На этом урок завершен. Файл с отработанным заданием можно скачать здесь
Смерти Вопреки Spectrum Project AP_Prodaction
Эти 0 пользователя(ей) поблагодарили Geonezis за это полезное сообщение:
Урок 40.Спавн декораций.(Автор- Niafa) В уроке описаны два способа спавна объектов декора на локацию. Принципы, описанные в уроке, подходят для Зова Припяти, однако статья написана для Теней.
[cut=Урок 40] Предположим, Вам нужно добавить на локацию декорации- автомобили, мусор, баррикады_ ящики, катающиеся консервные банки и прочие статичные и динамичные объекты. Самый простой способ - использовать СДК. Но есть два альтернативных способа.
Спавн декораций через скрипт.
Для спавна нам понадобится секция объекта. В моём случае- вышки. Создаём файл тхт, и переименовываем его, меняя расширение на ltx. В моём случае это будет папка config\creatures и файл n_test.ltx. Регистрируем его в файле system.ltx вот так #include "creatures\n_test.ltx" Заметьте, что путь указывается относительно папки config.
В сам файл пишем следующее:
[test_obj]:identity_immunities--test_obj – имя нащей СЕКЦИИ. Не модели, что спавним. $spawn = "physics\object" class = O_INVBOX– класс. Чуть ниже об этом. remove_time = 60000 visual = physics\vishka_high.ogf– путь к модели относительно папки meshes description = "Тестовый объект"
От класса зависит многое. Дальше речь идёт о ТЧ: Так, O_INVBOX спавнит недвижимый объект. Но! Он проницаем. Вне зависимости от настроек шейпов модели. O_PHYS_S спавнит неприбитый объект, но с шейпами. Впрочем, если отредактировать кости модели и поставить им вес по 10 000 , то на ровной площадке модель будет сложно сдвинуть. Этот класс оптимален для спавна люков, моделек оружия, ящиков, прочего физически обсчитываемого мусора, который будет разлетаться от взрывов , аки в Crysis`е. SCRPTCARиспользуется для спавна авто, на которых можно ездить.
Если есть секция, то можно писать функцию. В моём случае: function n_spawn() –имя функции local obj local a = vector()-- Задаем тип переменной local dir = db.actor:direction() a.x = 241.230957-- координата X a.y = 23.297560-- высота Y a.z = 124.653923-- координата Z obj = alife():create("test_obj", a, 525991,145)–собственно спавн. Имя секции в кавычках. end
О том, как снимать координаты, так же информации много. Функцию можно вставить в диалог или забить на выполнение при получении определённого инфопоршня.
Скорее всего в Зове Припяти классы и их параметры изменены. Помогут эксперименты и знание английского. Смотрим, например, файл dynamic_objects.ltx, где прописаны стандартные классы, секции спавна дверей, взрывающихся баллонов и прочего.
Спавн через all.spawn.
Об этом файле и работе с ним много уже написано. Приведу лишь секцию, которая намертво пришивает объект к точке.
[881123513249] ;–номер секции. Должен быть уникальным ; cse_abstract properties section_name = physic_object name = esc_test_object_3;уникальное имя position = -18.547161,-1.374819,-27.618841; координаты direction = 0, 0, 0 id = 65535 version = 118 script_version = 6 ; cse_alife_object properties game_vertex_id = 83;гейм вертекс level_vertex_id = 258824; левел вертекс object_flags = 0xffffff7a custom_data = <<END
[collide] ignore_static END ; cse_visual properties visual_name = physics\vishka_high.ogf; путь к нашей модельке. ; cse_ph_skeleton properties skeleton_name = ; cse_alife_object_physic properties physic_type = 0x3 mass = 10;масса модели fixed_bones = link-- самое интересное и важное.
Fixed_bones- параметр, отвечающий за «пришитую» к локации кость. Link—имя рутовой кости, которая есть во всех РОДНЫХ моделях декораций от GSC(не нпс, авто,мутанты и пр.). Если модель не родная, то пробуем, например bone01 (Максовский формат) или же просто конвертируем модель в формат object c помощью конвертера товарища bardac, а затем смотрим имя кости в actor editor.
Спасибо Sea_Cat за подробную информацию по классам и секциям all.spawn.
[/cut]
Сообщение отредактировал Niafa - Вс, 08.04.2012, 16:25
Эти 0 пользователя(ей) поблагодарили Niafa за это полезное сообщение:
Урок 41 (автор denis2000) Задача: Создание новой модели сталкера/мутанта используя готовый скелет с анимациями и трехмерную модель (жесткая привязка к скелету) Файл с заданием Результат работы "Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение:
Урок 42(Автор - GEONEZIS) Задача: Создание квеста с добавлением дополнительных внутриэтапных заданий. Особенности- отсутствие диалогов, использование рестрикторов. Реализация на X-Ray 1.6.01
Поставленная задача в данном уроке будет заключаться в обучении основным принципам создания среднего по сложности квеста в игре Сталкер Зов Припяти без использования каких-либо диалогов. Выдача задания будет осуществляться автоматически, в данном случае зададим ее при старте игры. Также будет показан прием добавления во внутреннею структуру основного задания нескольких дополнительных подквестов и объяснение применение рестриторов на всех поставленных этапах. Само задание следующее: При старте ГГ на ПДА придет сообщение о необходимости установки схронов. Осущесвляется выдача квеста. Необходимо забрать утерянные рюкзаки и заложить их в трех указанных точках. После этого задание автоматически завершается. Выдача награды не предусмотрена. Необходимые для редактирования файлы:
1. конфигурационные в (gamedata\configs\gameplay\) -character_desc_jupiter.xml -info_zaton.xml 2. конфигурационные в (gamedata\configs\misc\) - tm_jupiter.ltx - quest_items.ltx - devices.ltx - death_generic.ltx 3. конфигурационные в (gamedata\configs\text\rus\) - st_quests_zaton.xml - st_items_quest.xml - ui_st_screen.xml 4. конфигурационные в (gamedata\configs\misc\trade\) - trade_generic.ltx 5. конфигурационные в (gamedata\configs\ui\) - game_tutorials.xml 6. конфигурационные в (gamedata\configs\scripts\zaton\) - файлы логик рестрикторов 7. скриптовый в (gamedata\scripts\) - ui_si.script - bind_stalker.script - new_tasks.script - xr_effects.script 8. all.spawn. (gamedata\spawns\) - alife_zaton.ltx На первоначальном этапе определимся с квестовыми предметами. Всего их шесть. Три будут отвечать за айтем рюкзака до его закладки. Они будут являться потомками основного родительского класса device_pda. Другие три будут определены другим классом, им будет соответствовать установленная логикаи они отвечают за рюкзаки после установки схрона. Пропишем секции их конфигов в файле quest_items.ltx (Здесь и далее буду приводить конфиг только одной секции, остальные задаются аналогично только с изменением числовых значений в имени).
Первый конфиг не содержит в себе прикрепленного файла в дополнительной секции и определяется как простой квестовый предмет, второй же содержит прикрепленный конфиг с логикой его zat_example_taynik_1.ltx Для определении секции zat_example_taynik_1 необходимо определить родительский класс default_inventory_box в файле devices.ltx
В этой секции указываются основные параметры такие как основной класс, форма, визуал. Кроме того определим его основную логику в конфигурационном файле zat_example_taynik_1.ltx
Здесь указывается активная секция это ph_idle@nothing, а также ее содержание. Тайник после установки можно использовать, т.е. возможно его наполнение различными предметами, также при наведении на него будет активна надпись из секции st_taynik_check_descr
Зарегистрируем конфиги первой секции предмета тайник zat_example_taynik_..._item. В файле death_generic.ltx пропишем код
Отметим особенности: Активная секция sr_idle@start переход на вторую происходит по достижению трех условий - наличие инфопоршня активности второго этапа основного задания (zat_test_quest_rest_main_come) - актор находиться в зоне действия рестриктора - наличие в его инвентаре zat_example_taynik_1_item При выполнении всех этих условий выполняется работа рестриктора определяемая в туториале zat_test_quest_1_tutor При получении инфопоршня zat_test_quest_restr_1 происходит переход в третью нулевую секцию логики рестриктора sr_idle@nil При выхода актора из зоны рестриктора его работа прекращается и логика переключается во второе состояние sr_idle@tutorial из которого она может снова перейти в первое или в третье.
Объявим в файле game_tutorials.xml туторы выполняемые в работе рестрикторов
Основные параметры это функция скрипта обработчика действия xr_effects.zat_test_quest_1 и активная надпись из секции zat_test_quest_tips В файле xr_effects.scripts определим функции
Код
function zat_test_quest_1(actor, npc) if xr_conditions.actor_in_zone(actor, npc, {"zat_test_quest_restrictor_1"}) then remove_item(actor, npc, {"zat_example_taynik_1_item"}) alife():create("zat_example_taynik_1",vector():set(210.996811,15.980440,480.381104),1323235,6) db.actor:give_info_portion("zat_test_quest_restr_1") end end
Опишем ее: - если выполнено условие нахождение актора в зоне рестриктора zat_test_quest_restrictor_1 то происходит удаление из инвентаря ГГ айтема первого конфига тайника zat_example_taynik_1_item, создается по заданным координатам второй zat_example_taynik_1 и выдается инфопоршень zat_test_quest_restr_1 Выдача задания будет происходит при старте ГГ одновременно с квестами основного сюжета. Для этого добавим инфопоршень выдачи и сам квест в секцию логики [sr_idle] оригинального рестриктор zat_b101_logic.ltx
Выдача подквестов будет осуществлять в логике другого рестриктора zat_restr_logic_main.ltx Его секция прописывается в all.spawn по аналогии с предыдущими. Сама логика имеет следующий вид:
В активной секции при попадании актора в зону рестриктора происходит выдача внутренних подквестов и переход логики в нулевое состояние. Определим сам квест с подзаданиями:
Особенности: - При старте задания необходимо посетить зону основного рестриктора, устанавливается тагет на zat_restr_main_id. В момент посещения активируются подквесты, выдается инфопоршень zat_test_quest_rest_main_come, задание обновляется, его тагет уходит в nill. после взятия всех квестовых айтемов- необходимо завершение всех трех подквестов для получения инфопоршня zat_test_quest_complete
Скриптовая функция которая отвечает за создание трех основных квестовых предметов и выдачу завершающего основное задание инфопоршня прописывается в файл new_tasks.script, и объявляется в апдейте актора файла bind_stalker.script
Код
new_tasks.task_spec()
сама функция
Код
--/Квест Example function task_spec() local level_name=level.name() if level_name=="zaton" then if has_alife_info("zat_test_quest_begin") and not has_alife_info("zat_test_quest_spawn_items") then alife():create("zat_example_taynik_1_item",vector():set(248.498016,14.915686,484.567932),1391296,6) alife():create("zat_example_taynik_2_item",vector():set(247.778076,14.872326,484.085999),1390040,6) alife():create("zat_example_taynik_3_item",vector():set(247.055069,14.796996,483.116058),1388814,6) news_manager.send_tip(db.actor, "Чтобы выполнить тестовое задание необходимо установить все тайники. Подбери рюкзаки оставленные сталкерами", nil, nil, 14000) db.actor:give_info_portion("zat_test_quest_spawn_items") end if has_alife_info("zat_test_quest_restr_1") and has_alife_info("zat_test_quest_restr_2") and has_alife_info("zat_test_quest_restr_3") and not has_alife_info("zat_test_quest_complete") then db.actor:give_info_portion("zat_test_quest_complete") end end end
Описание: При нахождении ГГ на локации Затон и наличии инфопоршня zat_test_quest_begin создаются квестовые айтемы и отправляется мессадж на пда ГГ. При завершении всех трех подквестов выдается инфопоршень zat_test_quest_complete завершения основного. Все инфопоршни необходимые нам пропишем в файле info_zaton.xml
Урок 43 (Автор - GEONEZIS) Задача: Создание примитивного квеста на поиск двух различных предметов, с выдачей ачивмента. Особенности- пысовский способ его написания, добавление по завершении простого достижения (ачивмента). Реализация на X-Ray 1.6.01
Поставленная в данном уроке задача схожа с той что была в уроке 33 данной темы. Основным отличием от него будет являться способ реализации заданий такого типа. Если ранее основным обработчиком на обновление этапов квеста служило использование функций actor_has_item(...), то сейчас последовательное обновление будет осуществляться через выдачу соответствующих инфопорций. Будет подробно рассмотрена структура диалога в котором будет происходить их выдача. Также среди особенностей отметим добавление по завершении задания специального достижения.
Необходимые для редактирования файлы:
1. конфигурационные в (gamedata\configs\gameplay\) -character_desc_zaton.xml -dialogs_zaton.xml -info_zaton.xml -character_desc_general.xml (необязательно) 2. конфигурационные в (gamedata\configs\misc\) - tm_zaton.ltx - achievements.ltx 3. конфигурационные в (gamedata\configs\text\rus\) - st_dialogs_zaton.xml - st_quests_zaton.xml - st_achievement.xml - ui_st_screen.xml 4. скриптовые в (gamedata\scripts\) - dialogs_zaton.script - xr_statistic.script Начнем с разбора процесса создания ачивмента, выдаваемого по завершении задания. Остальные этапы по написанию квеста будут сокращаны, ибо по большей части они уже были рассмотрены в уроке № 33.
В файле achievements.ltx в самом низу добавим следующую секцию:
Код
[sich_helper] icon = ui_inGame2_Iskatel hint = st_sp_achievement_22_hint name = st_sp_achievement_22_name desc = st_sp_achievement_22_descr functor = xr_statistic.sich_helper_functor
-[sich_helper]- уникальное имя секции ачивмента. его же необходимо зарегистрировать в начале файла в списке всех достижений. -icon- имя секции иконки достижения. берется из файла ui_actor_achivments.xml (\configs\ui\textures_descr\) в свою очередь сама иконка прописывается в ui_actor_achivments.dds (\textures\ui\) В данном случае возьмем стандартную иконку из другого достижения. - hint- описание в ПДА при наведении на ачивку. - name- название (имя) достижения. - desc- описание самого достижения. - functor- имя функции из xr_statistic.script отвечающей за срабатывания условий на получение достижения и собственно его выдача.
Описание русской транскрипции добавим в файл st_achievement.xml
Код
<string id="st_sp_achievement_22_name"> <text>Помошник торговца</text> </string> <string id="st_sp_achievement_22_hint"> <text>Бандиты стали лучше к Вам относится.</text> </string> <string id="st_sp_achievement_22_descr"> <text>Вы нашли и принесли артефакты скряге Сычу. Тем самым Вы заслужили уважение бандитов.</text> </string>
В xr_statistic.script добавляем исполняемую функцию:
Код
function sich_helper_functor() if not has_alife_info("sich_helper_achievement_gained") then if has_alife_info("zat_geonezis_example_quest_complete") then news_manager.send_tip(db.actor, "st_ach_sich_helper", nil, "seeker", nil, nil) xr_effects.inc_faction_goodwill_to_actor(db.actor, nil, {"bandit", 100}) db.actor:give_info_portion("sich_helper_achievement_gained") end end return has_alife_info("sich_helper_achievement_gained") end
более подробно разберем работу данной функции: - происходит проверка, а не было ли уже получено данное достижение (отсутствие инфопоршня sich_helper_achievement_gained) - срабатывание условия выдачи достижения в данном случае условие только одно- это получение инфопоршня zat_geonezis_example_quest_complete (который будет выдаваться по завершению квеста) - далее происходит отправка на пда ГГ сообщения с текстом что достижение было получено. - вызывается обработчик функций на выполнение "бонуса" или "антибонуса" достижения. (в данном случае это только увеличение репутации у сталкеров) - выдается инфопоршень получения достижения (в рассматриваемом примере это sich_helper_achievement_gained) Так, теперь приступим к процессу формирования задания.
Опишем подробно только второй диалог, который будет активен после взятия задания. Первый, на получения квеста можно будет посмотреть в файле dialogs_zaton.xml имя диалога- jup_azot_sborkiquest_init_dialog Соответственно русскую транскрипцию диалогов и квестов также не будем приводить. Ее можно будет увидеть в файлах st_quests_zaton.xml и st_dialogs_zaton.xml
начнем по-порядку разбирать особенности этого диалога:
- обязательными условиями его активации будет наличие инфопоршня выдачи задания jup_azot_quest_sborki_give, а также функции прекондишина actor_has_first_or_second_grenader_item - будет происходить выбор четырех последующих фраз для генерации в зависимости от наличия у ГГ квестовых предметов. - четвертая, имеющая нулевое значение отрицания- будет активна при любых условиях. - первая и вторая- когда у ГГ есть один из двух необходимых предметов активны при наличии выполнения соответствующих прекондишинов if_actor_has_zat_grenader_stalker_flash и if_actor_has_zat_grenader_stalker_gran_instrument. при этом проиходит передача этого предмета НПС функции (transfer_....),получении от НПС награды на каждом этапе и выдача инфопорции на обновление задания. первый и второй этапы- взаимоисключающие. одновременно они не могут быть активны. - третья- когда у ГГ есть оба необходимых предмета. происходит их передача и завершение квеста.
добавим все скриптовые функции в файл dialogs_zaton.script
Код
function jup_azot_quest_sborki_give() task_manager.get_task_manager():give_task("geonezis_azot_quest_sborki_give") end
function zat_b33_relocate_money_to_azot(first_speaker, second_speaker) dialogs.relocate_money_from_actor(first_speaker, second_speaker, 500) end
function actor_has_first_or_second_grenader_item(first_speaker, second_speaker) return first_speaker <img src="/.s/sm/2/surprised.gif" border="0" align="absmiddle" alt="surprised" /> bject("af_baloon") ~= nil or first_speaker <img src="/.s/sm/2/surprised.gif" border="0" align="absmiddle" alt="surprised" /> bject("af_gold_fish") ~= nil end
function actor_has_first_and_second_grenader_item(first_speaker, second_speaker) return first_speaker <img src="/.s/sm/2/surprised.gif" border="0" align="absmiddle" alt="surprised" /> bject("af_baloon") ~= nil and first_speaker <img src="/.s/sm/2/surprised.gif" border="0" align="absmiddle" alt="surprised" /> bject("af_gold_fish") ~= nil end
function if_actor_has_zat_grenader_stalker_flash(first_speaker, second_speaker) return first_speaker <img src="/.s/sm/2/surprised.gif" border="0" align="absmiddle" alt="surprised" /> bject("af_baloon") ~= nil and first_speaker <img src="/.s/sm/2/surprised.gif" border="0" align="absmiddle" alt="surprised" /> bject("af_gold_fish") == nil end
function if_actor_has_zat_grenader_stalker_gran_instrument(first_speaker, second_speaker) return first_speaker <img src="/.s/sm/2/surprised.gif" border="0" align="absmiddle" alt="surprised" /> bject("af_gold_fish") ~= nil and first_speaker <img src="/.s/sm/2/surprised.gif" border="0" align="absmiddle" alt="surprised" /> bject("af_baloon") == nil end
function transfer_zat_grenader_stalker_flash(first_speaker, second_speaker) dialogs.relocate_item_section_from_actor(first_speaker, second_speaker, "af_baloon") end
function transfer_zat_grenader_stalker_gran_instrument(first_speaker, second_speaker) dialogs.relocate_item_section_from_actor(first_speaker, second_speaker, "af_gold_fish") end
Описывать их нет смысла- они все элементарные. Аналогично не будем расписывать процесс добавления диалогов нпс и регистрацию инфопоршней. Все это приведено в уроке № 33. Отметим особенности квеста.
Тайтлы и дескрипшины задания будут обновляться после второго разговора с НПС, при получении соответствующих инфопоршней. То есть основное отличие от задания из урока № 33 это его обновление после передачи предметов, а не при их получении и наличии в инвентаре ГГ. По завершении задания будет выдаваться инфопоршень zat_geonezis_example_quest_complete необходимый для выдачи ачивмента, который в свою очередь будет теперь необходим для разблокировки следующего смыслового диалога zat_b30_owl_stalker_trader_buy_info На этом урок завершен. Скачать пример можно тут
Смерти Вопреки Spectrum Project AP_Prodaction
Сообщение отредактировал GEONEZIS - Ср, 13.06.2012, 19:48
Эти 0 пользователя(ей) поблагодарили Geonezis за это полезное сообщение:
Урок 44 (Автор - GEONEZIS) Задача: Создание квеста с добавлением дополнительных внутриэтапных заданий. Особенности- отсутствие диалогов, использование физических объектов класса physic_destroyable_object в качестве квестовых предметов. Реализация на X-Ray 1.6.01
В данном уроке речь пойдет о реализации задания подобного тому что было рассмотрено в уроке № 42. В отличие от него теперь добавление внутриэтапных заданий будет завязано не на применение рестрикторов, а на использование физических объектов специального класса. Задание этих объектов будет осуществлено как в моде SGM (автор GeJorge) Также особенностью будет добавление класса метки объекта (также по аналогии с SGM) что позволит отказаться от применения рестрикторов в определенных моментах. Выдача задания осуществляется при старте игры. Диалогов нет. Само задание: ГГ на ПДА приходит сообщение о необходимости обыска трех точек с установленными там объектами. Необходимо выяснить что это за объекты и вернуться в стартовую точку. После этого задание автоматически завершается. Выдача награды не предусмотрена. Необходимые для редактирования файлы:
1. конфигурационные в (gamedata\configs\gameplay\) -info_zaton.xml 2. конфигурационные в (gamedata\configs\misc\) - tm_zaton.ltx - quest_items.ltx 3. конфигурационные в (gamedata\configs\text\rus\) - st_quests_zaton.xml - ui_st_screen.xml 4. конфигурационные в (gamedata\configs\models\) - dynamic_objects.ltx 5. конфигурационные в (gamedata\configs\scripts\zaton\) - файлы логик рестрикторов и объектов 6. скриптовый в (gamedata\scripts\) - bind_stalker.script - new_tasks.script 7. all.spawn. (gamedata\spawns\) - alife_zaton.ltx 8. физическая модель в (gamedata\meshes\dynamics\box\) - konteyner.ogf Некоторые этапы добавления изменений будут приведены с сокращением, ввиду их схожести с аналогичными в других уроках. Акцент будет сделан на впервые вносимые изменения и аспекты. Изначально создадим новые классы квестовых предметов.
Класс родительского предмета метка будет соответствовать стандартному квестовому device_pda, но будет иметь визуал нулевого значения. поэтому при написания квестов и установки тагета в них можно будет воспользоваться именно этим приемом, а не добавлением цели на айдишнике отдельного рестриктора. пропишем в quest_items.ltx секцию
сами добавленные метки имеют следующие секции. как видим они являются потомками родительского класса quest_spot. также указывается айди метки по которому будет прописываться таргет story_id.
Новый физический объект используемый нами в квесте объявим в файле dynamic_objects.ltx . Он будет иметь свой уникальный класс наследуемый от основного physic_destroyable_object Секции конфигов будут следующими:
- активная секция логики ph_idle@retranslator_take - первоначальная активная надпись считывается из секции st_take_the_quest_item - при юзании предмета произойдет выдача инфопорции zat_test_quest_item_1_used и переход во вторую секцию логики ph_idle@retranslator_heavy - при этом изменяется активная надпись на st_quest_item_is_used - при получении инфопорции zat_test_quest_complete логика обнуляется. Теперь необходимо создать основной рестриктор на обход которого будет завязана основа квеста. Сам рестриктор создаем в all.spawn по аналоги с предыдущими уроками. Логика рестриктора из файла zat_restr_logic_main.ltx имеет следующий вид:
- имеет три секции первая активная, во вторую переходит по совокупности полученных условий при обновлении квеста. - при этом происходит выдача трех подзаданий. - для перехода в нулевую секцию необходимо завершение задания. Выдача задания будет происходит при старте ГГ одновременно с квестами основного сюжета. Для этого добавим инфопоршень выдачи и сам квест в секцию логики [sr_idle] оригинального рестриктор zat_b101_logic.ltx
Особенности: - При старте задания необходимо посетить зону основного рестриктора, устанавливается тагет на zat_restr_main_id. В момент посещения активируются подквесты, выдается инфопоршень zat_test_quest_rest_main_come, задание обновляется, его тагет уходит в nil. после юзания всех квестовых айтемов созданных в начале объектов проиходит завершение всех трех подквестов, основной квест обновляется снова. чтобы завершить его необходимо снова посетить точку основного рестриктора.
Скриптовая функция которая отвечает за создание трех основных квестовых предметов и выдачу завершающего основное задание инфопоршня прописывается в файл new_tasks.script, и объявляется в апдейте актора файла bind_stalker.script
Код
new_tasks.task_spec()
сама функция
Код
--/Квест Example function task_spec() local level_name=level.name() if level_name=="zaton" then if has_alife_info("zat_test_quest_begin") and not has_alife_info("zat_test_quest_spawn_items") then alife():create("zat_test_stalker_container_1_spot",vector():set(210.996811,15.980440,480.381104),1323235,6) alife():create("zat_test_stalker_container_2_spot",vector():set(267.914307,17.374102,483.001709),1424536,6) alife():create("zat_test_stalker_container_3_spot",vector():set(305.260254,18.979174,532.515625),1484018,287) news_manager.send_tip(db.actor, "Для начала займи указанную точку", nil, nil, 14000) db.actor:give_info_portion("zat_test_quest_spawn_items") end if has_alife_info("zat_test_quest_rest_main_come") and not has_alife_info("zat_test_quest_spawn_items_2") then alife():create("zat_test_stalker_container_1",vector():set(210.996811,15.980440,480.381104),1323235,6) alife():create("zat_test_stalker_container_2",vector():set(267.914307,17.374102,483.001709),1424536,6) alife():create("zat_test_stalker_container_3",vector():set(305.260254,18.979174,532.515625),1484018,287) news_manager.send_tip(db.actor, "Чтобы выполнить тестовое задание необходимо исследовать все контейнеры.", nil, nil, 14000) db.actor:give_info_portion("zat_test_quest_spawn_items_2") end if has_alife_info("zat_test_quest_item_1_used") and has_alife_info("zat_test_quest_item_2_used") and has_alife_info("zat_test_quest_item_3_used") and not has_alife_info("zat_test_quest_all_item_used") then db.actor:give_info_portion("zat_test_quest_all_item_used") end end end
описание: - первоначально по выдаче задания происходит создания меток дополнительных подквестов. - при выдачи самих подквестов происходит создание самих предметов необходимых для их выполнения. - при наличии трех инфопорций полученных от юзания всех предметов выдается общий инфопоршень на обновление основного задания. Все инфопоршни необходимые нам пропишем в файле info_zaton.xml Всю текстовую транскрипцию определим в xml-файлах. На этом урок завершен. Файл с отработанным задание можно скачать тут
Урок 45 (Автор - GEONEZIS) Задача: Создание квеста с добавлением дополнительных внутриэтапных заданий. Особенности- отсутствие диалогов, добавление тайников в качестве квестовых предметов. Реализация на X-Ray 1.6.01
Данный урок практически полностью аналогичен тому что был изложен ранее (урок 44). Его основной отличительной особенностью от предыдущего является только то что выполнение внутренних подквестов будет завязано на исследовании тайников (взятие квестовых предметов из них). Будет показан принцип добавление в игру тайников определенных отдельным классом и их заполнение различными предметами. Поэтому урок будет приведен по максимуму сокращенно, с указанием только основных особенностей и списком всех используемых файлов. Полностью просмотреть вносимые изменения вы сможете скачав пример с отработанным заданием или же изучив материал из урока 44. 1. конфигурационные в (gamedata\configs\gameplay\) -info_zaton.xml 2. конфигурационные в (gamedata\configs\misc\) - tm_zaton.ltx - quest_items.ltx 3. конфигурационные в (gamedata\configs\text\rus\) - st_quests_zaton.xml
4. конфигурационные в (gamedata\configs\scripts\zaton\) - файлы логик рестрикторов и объектов 6. скриптовый в (gamedata\scripts\) - bind_stalker.script - new_tasks.script 7. all.spawn. (gamedata\spawns\) - alife_zaton.ltx Определим в файле quest_items.ltx две родительские секции для создания предмета нового класса "квестовый рюкзак".
В дальнейшем нами будет использоваться переопределенный класс quest_rukzak с определенным визуалом dynamics\devices\dev_rukzak\dev_rukzak.ogf. В классе default_inventory_box определяются другие основные параметры. Вся остальная структура добавляемых изменений аналогично указанным ранее. По другом задается только основной квестовый скрипт в файле new_tasks.script
Код
--/Квест Example function task_spec() local level_name=level.name() if level_name=="zaton" then if has_alife_info("zat_test_quest_begin") and not has_alife_info("zat_test_quest_spawn_items") then alife():create("zat_test_stalker_container_1_spot",vector():set(210.996811,15.980440,480.381104),1323235,6) alife():create("zat_test_stalker_container_2_spot",vector():set(267.914307,17.374102,483.001709),1424536,6) alife():create("zat_test_stalker_container_3_spot",vector():set(305.260254,18.979174,532.515625),1484018,287) news_manager.send_tip(db.actor, "Для начала займи указанную точку", nil, nil, 14000) db.actor:give_info_portion("zat_test_quest_spawn_items") end if has_alife_info("zat_test_quest_rest_main_come") and not has_alife_info("zat_test_quest_spawn_items_2") then local x1_cell=alife():create("quest_rukzak",vector():set(210.996811,15.980440,480.381104),1323235,6) parse_table=utils.parse_spawns("zat_test_quest_item_info_1,af_medusa,wpn_ak74,stalker_outfit,wpn_pm") for k,v in pairs(parse_table) do for i=1,v.prob do alife():create(v.section,vector(),0,0,x1_cell.id) end end local x2_cell=alife():create("quest_rukzak",vector():set(267.914307,17.374102,483.001709),1424536,6) parse_table=utils.parse_spawns("zat_test_quest_item_info_2,af_ice,wpn_abakan,dolg_outfit,wpn_pm") for k,v in pairs(parse_table) do for i=1,v.prob do alife():create(v.section,vector(),0,0,x2_cell.id) end end local x3_cell=alife():create("quest_rukzak",vector():set(305.260254,18.979174,532.515625),1484018,287) parse_table=utils.parse_spawns("zat_test_quest_item_info_3,af_fire,wpn_lr300,svoboda_light_outfit,wpn_pm") for k,v in pairs(parse_table) do for i=1,v.prob do alife():create(v.section,vector(),0,0,x3_cell.id) end end news_manager.send_tip(db.actor, "Чтобы выполнить тестовое задание необходимо исследовать все тайники.", nil, nil, 14000) db.actor:give_info_portion("zat_test_quest_spawn_items_2") end if (not has_alife_info("zat_test_quest_item_1_used")) and has_alife_info("zat_test_quest_spawn_items_2") and db.actor:object("zat_test_quest_item_info_1") then db.actor:give_info_portion("zat_test_quest_item_1_used") end if (not has_alife_info("zat_test_quest_item_2_used")) and has_alife_info("zat_test_quest_spawn_items_2") and db.actor:object("zat_test_quest_item_info_2") then db.actor:give_info_portion("zat_test_quest_item_2_used") end if (not has_alife_info("zat_test_quest_item_3_used")) and has_alife_info("zat_test_quest_spawn_items_2") and db.actor:object("zat_test_quest_item_info_3") then db.actor:give_info_portion("zat_test_quest_item_3_used") end if has_alife_info("zat_test_quest_item_1_used") and has_alife_info("zat_test_quest_item_2_used") and has_alife_info("zat_test_quest_item_3_used") and not has_alife_info("zat_test_quest_all_item_used") then db.actor:give_info_portion("zat_test_quest_all_item_used") end end end
Особенности: - при старте задания создаются квестовые метки - при достижении позиции актора внутри основного рестриктора происходит создание трех квестовых тайников quest_rukzak по заданным координатам и их заполнение различными предметами. - при обыски тайника и взятии ГГ квестового предмета из него происходит выдача инфопоршеней на завершение внутренних подзаданий. - после обыска всех трех тайников выдается основной инфопоршень на обновление основного задания.
Урок 46 (Автор - GEONEZIS) Задача: Создание квеста с использованием объекта класса inventory_box. Особенности- отсутствие диалогов, использование рестрикторов, выдача тайника в качестве награды. Реализация на X-Ray 1.6.01
Поставленная задача в данном уроке будет заключаться в обучении основным принципам создания сложного квеста в игре Сталкер Зов Припяти с добавление объекта класса inventory_box. Выдача задания будет осуществляться автоматически, в данном случае зададим ее при старте игры. Также будет показан пример задания сложной логики добавленного объекта и ее возможная привязка в процессе реализации квестов. Само задание будет следующим. При старте ГГ будет получено сообщение о необходимости поиска схрона на территории Земснаряда. Чтобы открыть этот схрон необходимо использоваться два специальных ключа. Нужно будет найти эти отмычки и использовать их для получения доступа к содержимому объекта. После этого квест автоматически завершается. Вместо получения денежной награды происходит выдача координат тайника, также дополнительно добавленного нами. Необходимые для редактирования файлы:
1. конфигурационные в (gamedata\configs\gameplay\) -info_zaton.xml 2. конфигурационные в (gamedata\configs\misc\) - tm_zaton.ltx - quest_items.ltx - secret_zaton.ltx 3. конфигурационные в (gamedata\configs\text\rus\) - st_quests_zaton.xml - st_items_quest.xml - ui_st_screen.xml 4. конфигурационные в (gamedata\configs\scripts\zaton\) - файлы логик рестрикторов 5. скриптовый в (gamedata\scripts\) - bind_stalker.script - new_tasks.script 6. all.spawn. (gamedata\spawns\) - alife_zaton.ltx Полный процесс регистрации квестовых предметов во всех файлах и некоторые повторяющиеся моменты не будет описаны, они аналогичны предыдущим урокам. Также текстовая транскрипция будет приведена только в файле с отработанным заданием.
Первоначально создадим новый тайник который будет выдан нам в качестве награды по завершению квеста.
- в файле secret_zaton.ltx добавим тайник в общий список zat_hiding_place_56 и объявим его секцию
Код
[zat_hiding_place_56] wpn_vintorez = 1, 1
в нем будет находиться один предмет- винторез.
- создадим секцию рестриктора тайника и сам предмет через all.spawn
; cse_alife_inventory_box properties tip = inventory_box_use
указывается: - класс объекта - уникальное имя секции - координаты точки спавна - прикрепленный файл логики - идентификатор для установления метки таргета - визуал модели объекта - тип объекта
зададим логику нашего объекта в файле zat_test_conteiner.ltx следующим образом:
Теперь более подробно ее разберем. имеющийся у нас схрон (предмет с данной логикой) будет иметь 6 секций возможного состояния. Нам необходимо открыть его используя два ключа. Поэтому возможны следующие варианты: - ящик закрыт. ph_idle@full_locked - использован один из ключей ph_idle@locked - у актора есть один из ключей ph_idle@has_one_key - у актора есть второй ключ при условии что был уже использован любой из первых. ph_idle@locked_has_second_key - у актора сразу есть два ключаph_idle@has_two_key - ящик вскрыт.ph_idle@open
Общая конструкция секций логики: - состоянии запрета использования обработчика nonscript_usable будет true только в одном случае когда ящик открыт. - строка с используемой секции надписи указывается в tips сама транскрипция задается в ui_st_screen.xml - вызываемое действие определяется в on_use- происходит переход в одно из последующих состояний и удаление предметов. - активное состояние определяется из условий on_info
Теперь по порядку разберем каждую из секций. В принципе сложного в построении такой логике ничего нет, решается обыкновенная комбинаторная задача сочетания двух объектов, когда первый ключ есть, второго нет: наоборот второй есть, первого нет; обо есть; ни одного нет.
- активное состояние ph_idle@full_locked- ящик закрыт. изначально необходимо его использовать чтобы произошло обновление квеста (выдача инфопорции +zat_test_quest_find_to_open) и спавн внутрь него необходимого нам предмета (=spawn_object_in(zat_test_container_item:zat_test_cont_id)). это действие возможно только когда ключей у актора нет (!actor_has_item(zat_test_key_2) !actor_has_item(zat_test_key_1)). если мы сразу нашли оба ключа (=actor_has_item(zat_test_key_1) =actor_has_item(zat_test_key_2)) то происходит переход в секцию ph_idle@has_two_key если у гг есть один ключ, но нет другого (не важно какого) то активируется секция ph_idle@has_one_key вторые условия on_info2 следующие: при получении инфопорции zat_test_conteiner_open происходит переход в ph_idle@open, соответственно при получении zat_test_one_lock_open становиться активной ph_idle@locked
- у актора есть один из ключей ph_idle@has_one_key вне зависимости от того какой из ключей был найден при юзании ящика происходит вскрытие одного замка, переход в секцию ph_idle@locked и выполняются следующие действия %=remove_item(zat_test_key_....) =play_sound(power_switch) +zat_test_one_lock_open% удаляется один из ключей из инвентаря ГГ, проигрывается звук вскрытия замка, выдается соответствующий инфопоршень вскрытия.
- один из ключей уже использован, второй нет. ph_idle@locked это переходная секция юзание ящика при этом невозможно. вне зависимости от того какой ключ есть у ГГ (=actor_has_item(zat_test_key_1) !actor_has_item(zat_test_key_2)) или (=actor_has_item(zat_test_key_2) !actor_has_item(zat_test_key_1)) будет осуществлен переход в секцию ph_idle@locked_has_second_key дополнительное условие наличие инфопорции zat_test_conteiner_open переход в ph_idle@open
- один из ключей использован, второй в наличии. ph_idle@locked_has_second_key при наличии одного из двух ключей =actor_has_item(zat_test_key_...) !actor_has_item(zat_test_key_...) во время юзания происходит переход в секцию ph_idle@open,удаляется один из ключей, проигрывается звук вскрытия, выдается соответствующий инфопоршень. основное условие нет ни одного ключа- !actor_has_item(zat_test_key_2) !actor_has_item(zat_test_key_1)происходит переход в состояние ожидания ph_idle@locked дополнительное условие аналогично.
- есть оба ключа. ph_idle@has_two_key при наличии обоих ключей =actor_has_item(zat_test_key_1) =actor_has_item(zat_test_key_2) оба они удаляются. происходит переход в ph_idle@open условия при этом- возвращения в необходимые секции когда либо ключей нет, либо есть по одному.
- ключи заюзаны. ph_idle@open ящик вскрыт- можно забирать инвентарное содержимое. Квестовые предметы- ключи (zat_test_key_1, zat_test_key_2) и необходимый для получения из схрона предмет zat_test_container_item добавим в quest_items.ltx
В принципе он элементарный. До первого юзания ящика активна первая секция, после активна секция на поиск ключей. Квест завершается при наличии у ГГ необходимого и взятого из ящика предмета =actor_has_item(zat_test_container_item) Скрипт на спавн ключей будет иметь следующий вид:
Код
--/Квест Example function task_spec() local level_name=level.name() if level_name=="zaton" then if has_alife_info("zat_test_quest_find_to_open") and not has_alife_info("zat_test_quest_spawn_items") then local rnd_quest_items_1=math.random(1,2) if rnd_quest_items_1==1 then alife():create("zat_test_key_1",vector():set(369.470,-5.291,281.921),1579200,67) alife():create("zat_test_key_2",vector():set(368.114,-5.228,281.887),1577301,67) news_manager.send_tip(db.actor, "Чтобы выполнить тестовое задание необходимо вскрыть заблокированный модуль. Для этого необходимо найти два ключа оставленные в тайниках сталкерами.", nil, nil, 14000) db.actor:give_info_portion("zat_test_quest_spawn_items") elseif rnd_quest_items_1==2 then alife():create("zat_test_key_1",vector():set(366.925,-5.202,281.718),1575412,67) alife():create("zat_test_key_2",vector():set(365.569,-5.450,281.175),1573410,67) news_manager.send_tip(db.actor, "Чтобы выполнить тестовое задание необходимо вскрыть заблокированный модуль. Для этого необходимо найти два ключа оставленные в тайниках сталкерами.", nil, nil, 14000) db.actor:give_info_portion("zat_test_quest_spawn_items") end end if has_alife_info("zat_test_quest_complete") and not has_alife_info("zat_test_quest_tainik_give") then treasure_manager.get_treasure_manager():give_treasure("zat_hiding_place_56") db.actor:give_info_portion("zat_test_quest_tainik_give") end end end
ключи спавняться рандомно в двух точках, после первого юзания ящика (получении инфопоршня zat_test_quest_find_to_open) Выдача тайника происходит по завершении квеста. Может быть сделано это двумя способами или внутри скрипта, или внутри задания. Включение квестового скрипта в обработку аналогично как и в других уроках. Выдача самого квеста на старте игры также по аналогии. Скачать файл с уроком
Смерти Вопреки Spectrum Project AP_Prodaction
Сообщение отредактировал GEONEZIS - Пн, 25.06.2012, 00:02
Эти 0 пользователя(ей) поблагодарили Geonezis за это полезное сообщение:
Урок 47 (Автор-lychagin0) Задача: Возвращение боеспособности БТР. Так как данное сообщение всё таки не является уроком а скорее алгоритм действий я прошу прощения у модераторов за возможное не правильное оформление,это не от не желания,а от не умения.
Для возвращения БТР способности атаковать противника и выполнить другие задачи в игре потребуются распакованные Тени Чернобыля.ИЗ gamedata ТЧ из папки scripts копируем файлы : ph_car.script и se_car.script в одноимённую папку ЗП.Теперь необходимо зарегистрировать файлыph_car.script и ph_minigun.script (этот файл есть в ЗП,его копировать не нужно) в modules.script, добавив после :
Всё на этом со скриптами закончили.Дальнейшие действия описаны для родной модели ЗП : попути: gamedata\meshes\physics\vehicles\btrположить скопированную из ТЧ папку part.Если этого не сделать при уничтожении вылет. Теперь необходимо правильно заспавнить будем спавнить через алспавн(можно через скрипт,но это для отдельного урока) секция для спавна:
Код
[1251] ; cse_abstract properties section_name = m_car name = esc_attack_btr position = -145.99313354492,-14.00541137695,-182.73930358887 direction = 0,3.3020263,0 version = 128 script_version = 12
Здесь координаты Кордон SGM-2.2.И обратите внимание если Вы используете родную модель то путь к визуалу нужно указать так:dynamics\vehicles\btr\veh_btr_script_u_01.ogf
Вот описание возможной логики с Вики: Настройка управления наземным транспортом.
Код
[ph_car] usable = {+info -info =func !func ~number} - условия для юзабелености объекта. show_tips = true/false - отображать ли подсказку. По умолчанию - true. tip_use = <имя_текса> - строка с id текста зарегистрированного в папке gamedata\config\text. Подсказка, в случае, если условия для usable выполнились. По умолчанию - tip_car_use. tip_locked = <имя_текса> - строка с id текста зарегистрированного в папке gamedata\config\text. Подсказка, в случае, если условия для usable не выполнились. По умолчанию - tip_car_locked. В случае, если параметр usable не установлен, то возможна настройка самостоятельного поведения транспорта, а именно БТР. path_walk = <имя_пути> - путь движения транспорта. path_fire = <имя_пути> - вероятно, точки пути по которым возможна стрельба. auto_fire = true/false - разрешить стрелять на ходу. По умолчанию - false. fire_time = <number> - время непрерывной стрельбы в миллисекундах. По умолчанию - 0. fire_rep = inf/<number> - вероятно, время через которое возможна повторная стрельба. inf = -1. fire_range = <number> - сектор стрельбы. По умолчанию - 50 градусов. target = <параметр> - цель для стрельбы. Возможны следующие параметры: points - стрелять в первую точку патрульного пути. Если путь не указан - вылет. Стоит по умолчанию; actor - без комментариев; story_id - персонаж с указанным story_id. track_target = true/false - Некое подобие предупредительной стрельбы, не по цели, а чуть выше. По умолчанию - false. on_target_vis = <параметр>|{+info -info =func !func ~number} %+info -info =func% <название_схемы> - что произойдёт, если цель будет в прямой видимости. В качестве параметра возможны два значения: actor, story_id персонажа. on_target_nvis = <параметр>|{+info -info =func !func ~number} %+info -info =func% <название_схемы> - что произойдёт, если цель пропадёт из области прямой видимости. В качестве параметра возможны два значения: actor, story_id персонажа. invulnerable = true/false - неуязвимость. Если true, транспорт игнорирует все хиты. По умолчанию false. headlights = on/off - вкл./выкл. свет от фар. on_death_info = {+info -info =func !func ~number} %+info -info =func% - что произойдёт при уничтожении транспорта. Поддерживается сигнал arrived.
Вот вроде и всё удачи. Действующую модель можно будет посмотреть завтра в моём допонении к SGM-2.2
Добавлено (27.06.2012, 23:41) --------------------------------------------- Прошу прощёния,но совершенно забыл добавить ложку дёгтя к уроку 47.При спавне не через SDK, 90% вероятность,что ездить по патрульному пути не будет.Дело в том что требуется идеально ровное направление на точку патрульного пути относительно первоначального положения объекта, отклонение в несколько градусов приводит к остановке.В отличие от НПС не может доворачивать на требующееся направление.
Справочный материал Тема: Функции некоторых скриптов и их применение. [cut noguest=Описание скриптов]ФУНКЦИИ, КОТОРЫЕ РАЗРЕШЕНО ВЫЗЫВАТЬ ИЗ ДРУГИХ СКРИПТОВ Активация схем производится с помощью функций:
function gulag_activate(npc, ini, section, gulag_name, death, combat, actor_dialogs, trade, hit) Предназначение: активирует заданную схему, используется схемой гулаг. Тип скрипта определяется автоматически по имени секции. Здесь: npc - персонаж, для которого будет активирована схема ini - его customdata section - имя секции, которая должна быть активирована gulag_name - имя гулага, которое будет добавлено спереди к именам путей death, combat, actor_dialogs, trade, hit - имена секций, задающих поведение при смерти и в бою
function assign_storage_and_bind(npc, ini, scheme, section) Предназначение: Вызывает функцию add_to_binder схемы, а также создает (если его еще нет) и возвращает ссылку на storage для схемы. Примечание: в storage при этом могут оставаться старые данные, схема должна очистить его самостоятельно.
function subscribe_action_for_events(npc, storage, new_action) Предназначение: Регистрирует класс для получения нотификаций о таких событиях как сброс схемы, сохранение и т.д. Класс реализует соответствующие функции (reset_scheme() и т.д.), которые будут вызываться из xr_logic в нужные моменты.
function pick_section_from_condlist(actor, npc, condlist) Предназначение: Проверяет условия condlist, и если они успешны - ставит указанные infoportions и возвращает текст. Если условия не выполняются - возвращает nil.
function try_switch_to_another_section(npc, st, actor) Предназчанение: Используя настройки xr_logic из storage персонажа, пытается переключить его на другую схему, если хоть одно из условий переключения сработало. Обычно вызывается из метода update класса персонажа.
function is_active(npc, st) Предназначение: Вызывается из evaluator-а (или в самом начале update у предметов и монстров) для проверки, что данная схема сейчас активна (схема определяется по данным в storage).
function cfg_get_switch_conditions(ini, section, npc) Предназначение: Считывает все возможные условия переключения схем.
function parse_condlist(npc, section, field, src) Предназначение: Распарсивает условия вида: {+infop1} section1 %-infop2%, {+infop3 -infop4} section2 ... в таблицу. Параметры section и field используются только в сообщениях об ошибках. Если строка src считана не из файла, а передается в эту функцию гулагом, то нужно задать следующие параметры: --]] -- section = "[[[gulag_tasks.script]]]" -- field = "[[[gulag_name=имя_гулага]]]" --[[
-- ПРИВАТНЫЕ ФУНКЦИИ ----------------------------------------------------------------------------------------------------
function activate_by_section(npc, ini, section, loading) Предназначение: Активирует указанную секцию. Если в данный момент какая-либо секция уже активирована, сообщает об ошибке.
function switch_to_section(npc, st, section) Предназначение: Выполняет переключение с одной секции на другую, если новая секция не nil. Если же она nil, остается активной старая секция.
function abort_syntax_error_in_cond(npc, section, field) Предназначение: Сообщает о синтаксической ошибке в условиях переключения схем секции section и поля field, и останавливает игру.
function parse_infop(rslt, str) Предназначение: Распарсивает условия вида " +infop1 =func -infop2 " и т.д. (все не перечислены) в таблицу.
function cfg_get_number_and_condlist(ini, section, field, npc) function cfg_get_string_and_condlist(ini, section, field, npc) function cfg_get_condlist(ini, section, field, npc) Предназначение: Считывает из customdata различные условия переключения схем.
function add_condition(lst, at, cond) Предназначение: Добавляет условие в список условий переключения схем.
function cfg_get_overrides(ini, section, npc) Предназначение: Считывает настройки для схем общего поведения.
function generic_scheme_overrides(npc) Предназначение: Возвращает ссылку на настройки схем общего поведения, актуальные для работающей в данный момент схемы, либо nil, если ни одна из секций не активна, либо настройки не заданы.
--]]
--[[ -- Предназначение: -- вызывается при включении набора скриптов через секцию logic у персонажа. Если в секции logic присутствует только -- поле cfg, использует конфигурационный файл, заданный в этом поле, и возвращает новый ini file. -- Здесь: -- npc - персонаж, для которого будет активирована схема -- ini - его customdata -- stype - тип скрипта. Поскольку имя секции все еще неизвестно, его нужно задавать явно. Допустимые значения -- перечислены в файле modules.script. -- section - имя секции logic -- gulag_name - имя гулага, если скрипт включается гулагом, а не биндером --]][/cut] Кончно это далеко не всё, буду дополнять по мере разбора.
Справочный материал Тема: описание анимаций используемых в сталкере. Автор(собрал воедино lychagin0) [cut noguest=Анимации]wait - стоит ни чего не делает wait_na - то же самое что и wait, стоит ни чего не делает guard - стоит, держит ствол в руках, медленно смотрит по сторонам.Короче анимка охраника guard_chasovoy - анимка часового, делает много чего.разминается, чешит задницу,ствол на плечо руку ко лбу и смотрит по сторонам и еще что то было. guard_na - тоже самое что и guard guard_fire - прикольная анимка, стоит ствол на плече, но время от времени отстрелевает всех подрят. Я эту анимку сталкеру на скадовске поставил. Пока дошел до скадовска этот ублюдок на базе уже троих положил. threat - стоит прицелевшись threat_danger - немного пригнувшись быстро смотрит по сторонам, потом прицеливается и анимка проигровается сначала. give_orders - стоит прицелевшись, но после того как к нему подойдет ГГ начинает проигрывать анимку wait threat_heli - тоже самое что и threat hide - на одном колене прицеливается, смотрит по сторонам, опускет оружие, опять смотрит по сторонам и потом все сначала. press - стоит и по направлению своего взгляда показывает пальцем ward - Стоит, руки за спину, медленно смотрит по сторонам fold_arms - стоит сложа руки search - присел что-то посмотрел, привстал чуть нагнулся и что-то высматривает stoop_no_weap - чуть наклонившись, руки ставит на ноги чуть выше коленок что то высматривает в низу salut - стоит по стоике смирно, потом отдает честь и опять в стоику salut_free - просто расслабившись стоит, отдает честь и опять стоит prisoner - анимка заложника. hide_no_wpn - присел на одно колено, облокотился на руки, и что-то высматривает типо следопыта(наверное это анимка глухоря) hello - стоит мохает рукой hello_wpn - ствол на плече, мохает рукой refuse - стоит пожимает плечами,мохает головой claim - стоит прицелевшись, потом мохает рукой, типо иди сюда backoff - стоит и показует что бы гг убрал ствол punch - анимка удара кулаком в голову binocular - стоит смотрит в биноколь
Очень полезная информация для создателей модов: Предоставляю вам список анимаций, которые использовались ПЫСами в анимпоинтах: zat_b14_give_artefact_idle - стоя рулим( Я так понял что этот анимпоинт связан с баржей на затоне) zat_b14_give_artefact_act - стоя поворачиваем руль zat_b38_stalker_break_lock - чиним замок zat_b38_stalker_turn_on_lift - открываем лифт и спускаемся вниз по лестнице zat_b38_stalker_jump_tonnel - прыгаем в люк zat_b38_stalker_alert - идет как бандит, а потом оглядывается и вскидывает оружие zat_b20_noah_jump - отходим и прыгаем с разбега pri_a17_ice_climb - вверх по лестнице pri_a17_fall_down - попали в человека и он упал pri_a17_pray_in - идет на тебя и по моему посылает pri_a17_pray- идет на тебя и по моему посылает (много раз) zat_b22_medic_turn_idle - чистит стол. Хотя не особо понятно что он делает (видимо эту анимацию исполняет медик на Скадовске) zat_b22_medic_turn_out - отворачиваемся от стола zat_b22_medic_suicide - суицид zat_b3_tech_drunk - спит (Кардан) zat_b3_tech_drink - выпиваем водочки (Кардан) zat_b3_tech_idle - сидим на стуле (Кардан) zat_b3_tech_surprise - заснул сидя (Кардан) give_orders - тоже самое что и анимка give_orders - оглядываемся по сторонам и посылаем на два стороны чуваков bloodsucker_search - оглядываемся по сторонам bloodsucker_panic - от бедра стреляем jup_b10_drunk_ravings - спим сидя pas_b400_vano_probe - тыкаем в детекторе что то pri_a28_kirillov_sit_high_radio - сидим высоко и ковыряемся в радио pri_a18_inspert_monolit_actor - идем и оглядываем все вокруг pri_a20_colonel_radio - стоим оперевшись об стол и смотря в комп/радио pri_a21_sentry_madness - стоим и отстреливаемся по кругу pri_a21_sentry_madness_suicide - отстреливаемся и потом суицид pri_a28_army_trance_out - Совсем не понятно zat_b106_wounded_idle - лежит на кровати (Краб) zat_b38_cop_dead - Прикидываемся трупом jup_b15_zulus_sit_drink - сидим в позе Зулуса и пьем водку jup_b15_zulus_sit_idle - сидим в позе Зулуса jup_b15_zulus_sit_out - слазим со стола jup_b219_actor_one - оружие на плечо и смотрим jup_b219_azot_all - стоим бьем кулаком по столу, указываем в стол zat_b100_heli_2_serch - сидим и тыкаем в ПДА пальцем jup_b217_guide_stand - оглядываемся потихоньку и идем к точке jup_b217_nitro_stand - стоим у стены боком jup_b41_novikov_stand - руки в кармане и стоим pri_b305_actor - идем прямо потом крадемся вправо наставляем ногу на ящик и пушкой смотрим туда jup_a9_cam2_actor - чуть чуть наклонились и рассматриваем что то pri_a25_psy_medic_idle - пси раненый pri_a25_psy_medic_out - выход из пси ранения
Для того чтобы НПС занял анимпоинт и принялся проигрывать нужную анимацию, ему нужно задать логику: [logic@bar_stalker_sleep] active = animpoint@animpoint_stalker_sleep
Урок 48 (Автор lychagin0) Задача: Создание новой модели сталкера/мутанта используя готовый скелет с анимациями и трехмерную модель с использованием программы Rig-O-Matic (Необходимо изучить урок 41).
Программа Rig-O-Matic считывает привязку модели к скелету исходной модели и переносит её на создаваемую модель. Для получения наилучшего результата необходимо подбирать исходную модель наиболее приближенную к создаваемой. После того как вы проделали шаги частей 1 и 2 из урока 41 сохраняем получившуюся модель в формате smd, модель которую вы хотите использовать в качестве исходной модели тоже сохраняем в формате smd. При экспорте в формат smd в окошке галочки ставим вот так : Теперь запускаем Rig-O-Matic , в появившемся окошке в верхней строке указываем путь к файлу исходной модели, во второй строке к вашей модели третья строка результат. Запускаем и ожидаем результат. Обратите внимание,что в пути к файлам не должно быть русских символов. Теперь остаётся пофиксить криво приклеившиеся кости (чаще всего голова, плечи и бёдра. Этот процесс уже как подчёркивал уважаемый denis2000 творческий и делается в ручную). Rig-O-Matic
Урок 49 (Автор lychagin0) Тема: Первые шаги в Maya
Трехмерная графика и анимация, открывающие двери в захватывающий мир виртуальной реальности, занимают особое место среди компьютерных технологий, а пакет Maya справедливо считается одним из лучших (и, увы, одним из самых сложных в изучении) в области трехмерного моделирования, анимации и рендеринга. Он обладает всеми необходимыми средствами для создания игровых миров и анимационных роликов и потому используется рядом разработчиков компьютерных игр и незаменим в компьютерной мультипликации и художественной анимации. Более того, Maya позволяет внедрять фотореалистичные элементы в обычные фильмы, открывая дорогу применению разнообразных спецэффектов, которые невозможно, слишком дорого или чересчур опасно воспроизвести в действительности. Созданная в среде Maya трехмерная анимация часто используется при разработке демонстрируемых по телевидению рекламных роликов, телевизионных заставок и клипов. Дизайнерам данный пакет предоставляет средства фотореалистической визуализации для анализа разрабатываемого проекта, проведения презентаций и создания маркетинговых материалов. Maya также может использоваться в судебной медицине, когда возникает необходимость продемонстрировать воссозданную последовательность происходивших событий, что актуально, например, в отношении автомобильных аварий. Также Maya находит применение в архитектуре и промышленности для визуального представления самых разных моделей, начиная от обычных флаконов и заканчивая автомобилями и самолетами. Пакет Maya достаточно сложен в освоении и имеет огромное число настроек, инструментов и меню — их значительно больше, чем в любом из конкурирующих пакетов, например в 3D Studio MAX. Даже простое перечисление инструментария займет немало времени и вместе с тем не даст ни малейшего представления о нюансах работы. Поэтому знакомиться с возможностями пакета мы будем последовательно и на конкретных примерах, а на первом уроке просто попытаемся немного освоиться с интерфейсом программы, экспериментируя с простыми геометрическими объектами. Теоретические аспекты работы
Для работы в программе предназначена стандартное для Windows-программ главное командное меню и целая серия панелей инструментов, которые располагаются со всех четырех сторон рабочего окна и занимающие большую часть рабочего пространства (рис. 1). С помощью панелей инструментов обеспечивается быстрый доступ к любому элементу интерфейса, к инструментам панелей, а также к любым командам главного меню. Рис. 1. Фрагмент окна Maya при первом запуске
Командное меню расположено в верхней части окна программы и является динамическим, так как часть входящих в него команд изменяются при смене режима работы — первые 6 пунктов меню: File (Файл), Edit (Редактирование), Modify (Изменение), Create (Создание), Display (Отображение) и Window (Окно) одинаковы для всех режимов. Всего предусмотрено 4 режима работы: Animation (Анимация), Modeling (Моделирование), Dynamics (Динамика) и Rendering (Рендеринг). Нужный режим выбирается из раскрывающегося списка, расположенного в левой верхней части окна программы (рис. 2) — сегодня все эксперименты мы будем проводить в режиме Rendering. Переключать режимы можно и с помощью функциональных клавиш F2, F3, F4 и F5. При необходимости некоторые из пунктов меню могут быть превращены в плавающие панели, что позволяет иметь под рукой наиболее часто используемые наборы инструментов. Пункты меню, для которых данное преобразование возможно, отмечены в верхней части двойной линией — для превращения пункта меню в панель достаточно щелкнуть на этой двойной линии (рис. 3). Рис. 2. Установка режима работы Рис. 3. Пример пункта меню, которое может быть превращено в плавающую панель (слева), и соответствующая ему панель (справа)
Наиболее часто используемые панели и палитры загружаются при начальном запуске программы — они отмечены на рис. 4. Прямо под командным меню находится строка состояния (Status Line), в самом начале которой как раз и располагается выше рассмотренный список смены режима. В ней размещаются большинство переключателей и кнопок, необходимых для управления объектами и запуска часто применяемых функций. Ниже расположена панель Shelf (Полка) с самыми разнообразными вкладками — на ней находятся инструменты для создания объектов и их деформации, команды управления анимацией и рендерингом и т.д. Слева расположена панель Tool Box, где преимущественно объединены команды для выполнения операций перемещения, вращения и масштабирования объектов, а также кнопки вариантов отображения окон проекций. В нижней части программного окна расположены палитры Time Slider и Range Slider, позволяющие управлять анимацией. А существенная по размерам область экрана в правой части окна содержит редактор атрибутов Attribute Editor, предназначенный для редактирования объектов. Любую из панелей можно скрыть, щелкнув на треугольнике в ее левом верхнем углу. За открытие/скрытие названных панелей (их называют универсальными) отвечает строка меню UI Elements (Универсальные элементы) из меню Display (Отображение — рис. 5). Кроме того, в правом верхнем углу программного окна имеются кнопки для быстрого открытия/закрытия панелей Attribute Editor, Tool Settings и Channel Box/Layer Editor (рис. 6). Рис. 4. Загружаемый по умолчанию набор панелей Рис. 5. Открытие/скрытие универсальных панелей Рис. 6. Кнопки быстрого открытия/закрытия панелей
Вызывать любые команды можно, не прибегая к командному меню, панели Shelf и пр., а через так называемое меню оперативного доступа, что зачастую оказывается быстрее. Вызов сокращенного варианта данного меню осуществляется при нажатии и удерживании в течение некоторого промежутка времени клавиши Пробел, а вызов полного варианта — в результате последующего щелчка на кнопке Hotbox Controls (Элементы управления меню оперативного доступа) (рис. 7). Рис. 7. Сокращенный вариант меню быстрого доступа
Все создаваемые в программе элементы называют объектами, и к объектам относятся не только любые геометрические тела, но и формы, камеры и источники света и др. Объектами можно управлять, модифицируя их произвольным образом, объединяя в группы, связывая друг с другом и пр., и добиваясь в конечном счете создания нужной сцены. Процесс создания объектов называется моделированием. Моделирование осуществляется в окнах просмотра проекций, которые и занимают основную часть экрана и позволяют рассмотреть объекты с разных позиций и в различных проекциях. По умолчанию на экране отображается одно прямоугольное окно, соответствующее проекции Perspective (Перспектива). Для одновременного появления четырех окон проекции — Тор (Сверху), Side (Сбоку), Front (Спереди) и Perspective (Перспектива) можно нажать клавишу Пробел или щелкнуть на кнопке Four View палитры Tool Box. Повторное нажатие клавиши Пробел (при предварительной активизации нужного окна проекции) позволяет развернуть на весь экран любую другую проекцию. В Maya существует достаточно большее число вариантов компоновок проекций, для выбора которых предназначена команда Panels=>Layouts (Панели=>Компоновка) из меню окна проекций (рис. 8). По умолчанию при открытии программы устанавливается режим работы с одним окном проекции Perspective. При желании можно изменить режим загрузки режима по умолчанию, выбрав нужный вариант компоновки из списка команды Panels=>Saved Layouts (Панели=>Сохранение компоновки) — рис. 9. Рис. 8. Выбор варианта компоновки проекций Рис. 9. Сохранение варианта компоновки проекций в качестве варианта, загружаемого по умолчанию
Любое окно проекции может быть сохранено, что в ряде случаев поможет сэкономить время — например гораздо быстрее по окончании настройки положения объектов (но перед редактированием других характеристик, что может потребовать, в частности, изменения угла обзора) сохранить нужные проекции, чтобы затем иметь возможность их быстро . Для сохранения конкретной проекции активизируйте окно данной проекции и выберите из меню окна проекции команду View=>Bookmarks=>Edit Bookmarks (Вид=>Закладки=>Редактирование закладок — рис. 10) и введите имя закладки. Объекты отображаются в окнах проекций либо в виде каркасов, либо с раскрашенной поверхностью (рис. 11) — изменение режима отображения объектов осуществляется через меню Shading (Затенение) окна конкретной проекции. За установку режима каркасного отображения отвечает команда Wireframe (Каркас) — ей соответствует горячая клавиша 4, а режима тонированной раскраски — Smooth Shade All (Сглаживать все, горячая клавиша 5). Кроме того, предусмотрена возможность изменения размеров окон проекции, реализуемая обычным для окон образом. Рис. 10. Сохранение проекции Все объекты делятся на категории, выбор которых осуществляется из панели Shelf (Полка) с помощью соответствующих кнопок или через командное меню Create (Создание — рис. 12), в котором находится список всех базовых визуализируемых объектов. К числу таких объектов можно отнести сплайны, полигоны, источники света, камеры, кривые и пр. В каждой категории существует целый список разнообразных объектов, например в категории NURBS Primitives (NURBS-примитивы) и Polygon Primitives (Полигональные примитивы) входят Sphere (Сфера), Cube (Куб), Cylinder (Цилиндр), Cone (Конус), Plane (Плоскость) и Torus (Topус). Рис. 12. Выбор объекта из группы через командное меню.
Сообщение отредактировал lychagin0 - Пт, 22.02.2013, 09:24
Эти 0 пользователя(ей) поблагодарили lychagin0 за это полезное сообщение:
Урок 50 (Автор - FantomICW) Тема: Редактируем текстуры оружия (делаем зимний камуфляж для Абакана) Что нам потребуется (найти ранее): Adobe Photoshop + DDS Plugins, файл текстур Абакана, файл текстур камуфляжа Файл с отработанным примером
Приступим. 1. Запускаем Photoshop, открываем wpn_abakan.dds и камуфляж. 2. Переходим на вкладку с камуфляжем. Там выбираем: Выделение---->Все. Дальше: Редактирование---->Определить узор. 3.Теперь переходим на текстуру Абакана. Выбираем:Инструменты---->Узорный штамп. Сверху в параметрах выбираем нужный нам размер штампа и в параметре "Непрозрачность" ставим, примерно, на 26%. 4.Закрашиваем текстуру. 5.Заходим в игру и смотрим наше творение.
Урок 51 (Автор - FantomICW) Тема: Создаем текстуру детектора "Серафим" Пояснение: Сегодня будем редактировать файлы textures/item/item_detector_2 и item_detector_2_segment. "Серафим" использует текстуру детектора "Медведь", получается, если мы изменим item_detector_2, то изменится визуал обоих. Вообще, лучше создать отдельную модель для "Серафима", но сегодня нам это не принципиально.
Лично меня чуток раздражает несоответствие цвета иконки и текстуры самого детектора "Серафим". Ну, и сам ржавый цвет "Медведя" поднадоел. Так-что, будем опираться на иконку. [cut=Иконка][/cut] 1.Открываем item_detector_2 и item_detector_2_segment каким-нибудь .dds редактором (сегодня я использую Paint.net). 2. Редактируем item_detector_2. Выбираем в параметрах "Коррекция"---->"Оттенок и насыщенность". Если мы опираемся на иконку, то делаем цвет синего или голубого оттенка. Табло смотрится не очень. Обводим его с помощью "лассо" и меняем его оттенок на бирюзовый. У меня получилось так: 3.Приступим к item_detector_2_segment. Проделываем тоже самое, только меняем цвета на розово-красные. Пример: 4.Сохраняем все это и смотрим результат:
Урок 52 (Автор FantomICW) Тема: Простейшая настройка модели нпс из Сталкера ЗП/ЧН в SDK Actor Editor Потребуется: SDK Actor Editor с плагинами для ЗП, модель нпс в формате .object, файл настроек костей для моделей ЗП/ЧН (обязательно скачать, ссылка ниже) Файл настроек костей
Итак, мы что-то делали с моделью сталкера, например, в Milshape 3d, и теперь нам надо ее настроить. Сегодня осваиваем самый легкий стандартный способ. 1. Для начала, копируем текстуры модели в аналогичную папку в gamedata СДК. 2. Открываем модель. Должно выглядеть как-то так 3. Открываем вкладку Bones и нажимаем Load. Далее указываем путь к ранее скачанным настройкам костей. 4. В Motions нажимаем на Motion Reference. Выбираем параметры stalker_animation, stalker_scenario_animation, stalker_scripts_animation и stalker_smart_cover_animation 5. В Object внизу есть поле User Data. Там указываем путь к файлу модели в configs/models. В моем случае, это выглядит так #include "models\capture\stalker_freedom_2.ltx" 6. Все! Экспортируем в OGF.
[cut=Небольшое дополнение к Уроку 52] 1. Файл настроек костей для моделей, на самом деле содержит настройки предельных углов поворота костей, шейпы (физические поверхности) костей и их положение, а также группировку костей в скелете и развесовку костей (физическую массу частей скелета). Все эти настройки конечно можно сделать вручную, но проще подгрузить из готового файла *.bones, который можно получить из уже готовой 3D модели в формате *.ogf, при помощи конвертора от бардака:
Цитата
[Преобразование скелета из .ogf в .bones] Команда: converter [-ogf] -bones <оригинал> [-out <результат>]
2. Параметр User Data обычно содержит дополнительные настройки модели, которые могут быть как прямым текстом, так и ссылкой на файл с данными настройками. В моделях НПС эти настройки показывают степень урона при попадании по различным областям модели, общий имунитет к воздействиям и т.д. и т.п. Аналогично в моделях монстров, разрушаемых объектов и техники. Например настройки модели вертолета включают в себя: назначение специфических костей вертолета (где пушки, ракеты, пропеллеры); распределение урона по областям (бонешейпам); путь к файлам моделей осколков вертолета при взрыве; фактор времени уборки частей вертолета после взрыва; параметры взрыва вертолета и некоторые физические параметры модели.[/cut]
Урок 53 (Автор FantomICW) Тема: Пришиваем голову персонажа к модели экзоскелета (самый простой способ) Потребуется: Milkshape 1.8.4 с плагинами, модель зомбака в экзоскелете (или любая другая модель с уже готовым лицом),модель нужного нам персонажа Отработанный пример (модель формата object)
Для начала хотел бы сказать, что это далеко не единственный способ, но он является самым легким. В нашем случае - это то, что надо. Хорошо. 1. Открываем милку и загружаем модель нужного нам перса (у меня это Лебедев) 2. Видим, что у него две группы - лицо и тело. Удаляем группу тела и ее материал. Голову и скелет оставляем) 3. Экспортируем это в Half-life SMD. Выбираем верхнее и нежнее значение. 4. Теперь открываем модель зомби в экзе. Удаляем группу и материал головы. 5. Импортируем ранее сохраненный SMD (выбираем все три значения). И смотрим, как оно стало. Если что-то не так стало, правим (например, иногда не в ту сторону голова развернута) 6. Теперь мы можем настроить текстуры: Выделяем материал--->Внизу кнопка Emissive--->Выбираем белый цвет--->Дальше справа есть название текстуры, нажимаем и выбираем то, что мы хотим У меня вышло так 7. Все! Экспорт и настройка в СДК!
Сообщение отредактировал FantomICW - Сб, 22.12.2012, 11:29
Эти 0 пользователя(ей) поблагодарили FantomICW за это полезное сообщение:
Урок 54 (Автор denis2000, попробую разложить все по полочкам). Задача: Создание спального места в S.T.A.L.K.E.R. Чистое Небо. Причина создания: В ЧН плохой ПНВ, ночью играть очень неудобно.
Чтобы приступить к заданию надо уметь распаковывать all.spawn и снимать координаты в игре.
<!--Добавлены элементы текстовых сообщений--> <string id="sleep_warning_all_pleasures_text"> <text>Я не могу спать! У меня опасное кровотечение и высокий уровень облучённости организма. Используй медикаменты.</text> </string> <string id="sleep_warning_bleeding_text"> <text>Я не могу спать! У меня опасное кровотечение. Используй медикаменты.</text> </string> <string id="sleep_warning_radiation_text"> <text>Я не могу спать! У меня высокий уровень облучённости организма. Используй медикаменты.</text> </string> <string id="sleep_zone_tip"> <text>Спать ($$ACTION_USE$$)</text> </string> <string id="about_actor_no_sleep_text"> <text>Я не устал чтобы спать, укладывай с 18.00 вечера до 6.00 утра).</text> </string>
3)configs\scripts\sr_sleep.ltx создать такой файл, внутри вставить
[cut noguest][logic] ;Активная логика рестриктора sr_idle@wait active = sr_idle@wait
[sr_idle@wait] ;Если ГГ внутри рестриктора перейти в секцию sr_idle@run и вывести подсказку on_actor_inside = sr_idle@run %=run_tutorial(tutorial_sleep)%
[sr_idle@run] ;Если ГГ вышел из рестриктора перейти в секцию r_idle@wait и убрать подсказку on_actor_outside = sr_idle@wait %=stop_tutorial% ;Если у ГГ нет активных подсказок и режим сна не активирован перейти в секцию sr_idle@wait on_info = {!has_active_tutorial -sleep_active} sr_idle@wait [/cut]
5)gamedata\scripts\ui_sleep_dialog.script создать такой файл, внутри вставить
[cut noguest]--Параметр sleep_zones глобальная таблица с именами зон для сна sleep_zones = {"mar_sleep_zone"}
function sleep() callback_for_sleep() end
--Функция обработки события "активация зоны сна" function callback_for_sleep() local blood_level = level.object_by_id(db.actor:id()):get_bleeding() local radiation_level = db.actor.radiation --Если имеется кровотечение или радиационное заражение выводим сообщение о невозможности сна if (blood_level>0.05 or radiation_level>0) then if (blood_level>0.05 and radiation_level>0) then game.start_tutorial("sleep_warning_all_pleasures") elseif blood_level>0.05 then game.start_tutorial("sleep_warning_bleeding") else game.start_tutorial("sleep_warning_radiation") end else --Если время для сна подходящее включаем сон иначе вывод сообщения о неподходящем для сна времени if (level.get_time_hours()>=18 and level.get_time_hours()<=23) or level.get_time_hours()<6 then level.disable_input() use_power_mode(0.98,1.00) level.add_pp_effector("mar_fade.ppe",76424,false) level.set_time_factor(1700) level.hide_indicators_safe() local hud = get_hud() hud:HideActorMenu() hud:HidePdaMenu() db.actor:give_info_portion("actor_is_sleep") else game.start_tutorial("about_actor_no_sleep") local hud = get_hud() hud:HideActorMenu() db.actor:disable_info_portion("sleep_active") end end end
--Обновление событий связанных со сном и с зонами сна function update_for_sleep() --Если в радиусе 150 метров от ГГ есть зоны сна установить на них метку "green_location" иначе убрать с них метку for k,v in pairs(sleep_zones) do local zone = db.zone_by_name[v] if zone then if db.actor:position():distance_to_sqr(zone:position()) < 150*150 then if level.map_has_object_spot(zone:id(), "green_location") == 0 then level.map_add_object_spot(zone:id(), "green_location", "Место сна") end else if level.map_has_object_spot(zone:id(), "green_location") ~= 0 then level.map_remove_object_spot(zone:id(), "green_location") end end end end --Если ГГ спит и пришло время проснуться выполнить необходимые действия для пробуждения if (db.actor:has_info("sleep_active") and db.actor:has_info("actor_is_sleep")) then if level.get_time_hours()>10 then level.remove_pp_effector(76470) level.set_time_factor(8) level.enable_input() level.add_cam_effector("camera_effects\\fusker.anm",76431,false,"") level.add_pp_effector("actor_hit.ppe",76425,false) level.add_pp_effector("shock_hit.ppe",76426,false) db.actor.psy_health=0.25 level.show_indicators()
db.actor:disable_info_portion("sleep_active") db.actor:disable_info_portion("actor_is_sleep") else level.add_pp_effector("black.ppe",76470,true) end end end
--Восстановление сил пред сном function use_power_mode(val_first,val_second) if db.actor.power<val_first then db.actor.power=val_second end end[/cut]
ui_sleep_dialog.script - очень важный скрипт, подробней о нем распишу ниже
6) найти gamedata\scripts\bind_stalker.script в нем [cut noguest]Найти строку: guiders.action_teleport_to_point()
вставить после строк: guiders.action_teleport_to_point() end
7) найти gamedata\scripts\xr_conditions.script в нем
[cut noguest]В конце файла добавить код:
--Проверка что ГГ уже имеет активную подсказку на экране function has_active_tutorial() return game.has_active_tutorial() end [/cut]
8) найти gamedata\scripts\xr_effects.script в нем [cut noguest]В конце файла добавить код:
function stop_tutorial() --Вывод пустой подсказки на 1 сек для отмены других подсказок. game.start_tutorial("about_no_tutorial") end
--Функция вызова сна если ГГ в одной из указанных зон сна function sleep(actor, npc) for k,v in pairs(ui_sleep_dialog.sleep_zones) do if utils.npc_in_zone(db.actor, db.zone_by_name[v]) then ui_sleep_dialog.sleep() db.actor:give_info_portion("sleep_active") end end
end [/cut]
9) Распаковываем all.spawn Для примера берем alife_l01_marsh.ltx то есть уровень Болота, листаем в самый конец видим у нас секция под номером [1416], ниже её создадим под номером [1417]
[cut noguest][1417] ; cse_abstract properties section_name = space_restrictor name = mar_sleep_zone position = -175.399993896484,4.80000019073486,-279.100006103516 direction = 0,0,0
Все сохраняем изменения и запаковываем all.spawn, запускаем новую игру у нас получилось спальное место на болоте - база Чистого неба, на втором этаже (над Лебедевым) возле кровати, лечь спать можно с 18 до 6 утра и сон до 10 часов следующего утра. Сон восстанавливает силы, но нельзя лечь спать с кровотечением или радиационным заражением. Метка на мини-карте показывает, где находится спальное место.
[cut=Дополнение к уроку 54]Теперь немного разберем скрипт ui_sleep_dialog.script строчка sleep_zones = {"mar_sleep_zone"} в ней прописано наше спальное место на базе ЧН "mar_sleep_zone", оно же указано в секции [1417] alife_l01_marsh.ltx из all.spawn я решил добавить ещё одно спальное место, отредактировал sleep_zones получилось, sleep_zones = {"mar_sleep_zone","mar_sleep_zone1"}, добавил секцию [1418] в файл alife_l01_marsh.ltx, с другими координатами и name = mar_sleep_zone1 В итоге получилось два спальных места, также можно добавить и на другие уровни(кордон,свалку...)
Также в этом скрипте можно поменять время, в течении которого гг, сможет лечь и поспать я выставил с 18 вечера до 6 утра(просто поменять цифры на свои)
В этом скрипте присутствует метка green_location которая указывает местоположение спального места на мини-карте, описание её находится в файле map_spots.xml, дело в том что стандартный её размер 32 <green_spot x="0" y="0" width="32" height="32" stretch="1" получился слишком большим, и метка перекрывала две другие метки на мини-карте, поэтому я поменял на <green_spot x="0" y="0" width="12" height="12" stretch="1" получились в итоге симпатичные метки нормального размера, которые соседние не перекрывают. Метка green_location - это стандартная метка из оригинальной игры, желательно сделать свою. denis2000[/cut]
Урок 54а (Автор tromm). Задача: Добавление вида метки спального места из ЗП в ЧН.
Чтобы приступить к заданию нужно уметь пользоваться утилитой Stalker Icon Editor(SIE).
denis2000 прав по поводу того, что стандартная метка green_location не годится для спального места, разработчики сделали очень хорошую в ЗП, вот и выдернем её оттуда. [cut noguest] Нам понадобятся файлы из ЗП ui_actor_hint_wnd.dds, ui_actor_pda_icons.xml, map_spots.xml, map_spots_16.xml; из ЧН нужны ui_common.dds, map_spots.xml, ui_common.xml, и созданный в предыдущем уроке ui_sleep_dialog.script
1) Открываем SIE и добавляем в него файлы ui_actor_hint_wnd.dds, ui_common.dds в файле map_spots.xml ЗП видим упоминание о метке для спального места: ui_pda2_actor_sleep_location и о текстуре которая этой метке соответствует: ui_inGame2_PDA_icon_Place_to_rest; ширина,высота и координаты этой текстуры указаны в файле ui_actor_pda_icons.xml(width="19" и height="19" ширина и высота равны 19 это значение нужно запомнить)
2) Копируем в SIE область с иконкой спального места с файла ui_actor_hint_wnd.dds в свободное место файла ui_common.dds у меня получилось так http://uploads.ru/pBY0A.jpg
3)Открываем файл map_spots.xml ЧН, ближе к концу файла видим упоминание о метках торговца, боармена, механика... Так как на миникарте в игре эти метки синего цвета, то и попробуем чтобы наша метка(спального места) не сильно отличалась от упомянутых. У торговца метка обозначена как ui_pda2_trader_location, скопируем полное упоминание о метке торговца ниже и только вместо trader подставим sleep должно получится:
В этом коде обозначен цвет нашей метки r="11" g="178" b="248"(то есть синий цвет как у выше перечисленных меток)
4) Теперь наша задача зарегистрировать текстуру ui_pda2_sleep в файле ui_common.xml, открываем его находим строчку <texture id="ui_pda2_trader" x="807" y="761" width="13" height="13" /> , копируем эту строку ниже и измеряем координаты нашей метки в файле ui_common.dds ширину и высоту берем 19, так как в ui_actor_pda_icons.xml для текстуры ui_inGame2_PDA_icon_Place_to_rest см.пункт 1) и слово trader меняем на sleep, у меня получилось так <texture id="ui_pda2_sleep" x="903" y="848" width="19" height="19" /> , сохраняем файл
5) Открываем ui_sleep_dialog.script и меняем все значения green_location на ui_pda2_sleep_location сохраняем файл
В запущенной игре метка отобразилась немного неровно,в ui_common.xml увеличил значение с 19 до 21 получилось <texture id="ui_pda2_sleep" x="903" y="848" width="21" height="21" /> в map_spots.xml ЧН в строке <ui_pda2_sleep_location_spot x="0" y="0" width="13" height="13" stretch="1" alignment="c" location_level="-1"> , 13 заменил на 15 получилось <ui_pda2_sleep_location_spot x="0" y="0" width="15" height="15" stretch="1" alignment="c" location_level="-1">[/cut]
Урок 55 (Автор tromm). Задача: Добавление новых проводников в ЧН.
Чтобы приступить к заданию нужно уметь работать с All.spawn и снимать координаты в игре.
Для начала нужно четко представлять, где мы хотим, чтобы у нас появился новый проводник, в файле st_smart_terrain_names.xml, указаны названия всех смарттеррейнов встречающихся в ЧН. Добавим нового проводника на Болота на смарт "Насосная станция" или mar_smart_terrain_5_8. Для работы нам понадобятся файлы guiders_table.script, из распакованного all.spawn - way_l01_marsh.ltx 1) Открываем guiders_table.script ищем строчку teleport_points = { ,ниже идет строка --------- MARSH -------- и идут перечисления смартов на которые проводники могут доставлять гг, как видно их немного, добавим выше строки ----------- ESCAPE -------------- упоминание о Насосной станции, должно получится
2) Вычисляем координаты нашего проводника на Насосной станции(мне понравилось место на вышке) и того места, куда проводники будут доставлять нас на Насосную станцию. Открываем файл way_l01_marsh.ltx, в этом файле указаны координаты мест проводников на болоте, и мест куда они будут нас вести. Для примера возьмем mar_smart_terrain_5_12 (Рыбацкий хутор), попробую разложить все по полочкам. Вот записи, которые соответствуют проводникам для mar_smart_terrain_5_12:
Скопируем эти записи в самый конец файла, записи типа conductor_look соответствуют нашему проводнику,а записи teleport_look соответствуют тому месту, куда нас проводники доставлять и отредактируем их, у меня получилось
Дополнение к уроку 55 [cut noguest]После того как гг покидает болота, то его исключают из группировки Чистое небо, и репутация меняется, из друзей Чновцы становятся нейтралами, желтые кружки на миникарте, до того как гг покинул болота проводники не брали оплату с гг за доставку в определенное место, после того как гг исключили из ЧН, проводники стали брать оплату за свои услуги. Смысл в том, что когда гг потом уже вступал к сталкерам, долговцам, свободовцам, бандюкам то проводники все равно берут оплату за провод в нужное место, какую бы неоценимую пользу гг не принес данной группировке. Попробуем исправить этот неприятный момент, открываем файл guiders.script находим строку if actor_in_faction() == npc:character_community() then ниже строка cost = math.floor(cost/2) меняем её на cost = 0 в итоге получилось
if actor_in_faction() == npc:character_community() then cost = 0
сохраняем изменения в файле, все запускаем игру и видим, что если гг состоит в группировках сталкеры, свобода, долг, бандиты - проводники не берут денег за провод гг до нужного места, то есть все по честному. В следующих постах попробую разобраться как сделать, чтобы когда гг состоит в группировке, то и механики не брали денег за ремонт оружия и шмоток, а брали только за апгрейды. [/cut]
Всё что мы есть - это результат наших мыслей
Сообщение отредактировал tromm - Пт, 28.12.2012, 17:16
Эти 0 пользователя(ей) поблагодарили tromm за это полезное сообщение:
Мы получим турельный пулемёт где cfg = scripts\SGM\red_forest\red_minigun1.ltx файл логики пулемёта. Логика такая же как у БТР кроме путей. секцияvisual_name = dynamics\weapons\wpn_mounted\wpn_mounted_pkm_cover и задаёт визуал спавнящегося объекта. Не пытайтесь этим способом заспавнить треногу. Это отдельный способ. Не прописывайте путь : ВЫЛЕТ.
Сообщение отредактировал lychagin0 - Пт, 22.02.2013, 09:28
Эти 0 пользователя(ей) поблагодарили lychagin0 за это полезное сообщение:
Справочный материал (автор Бабай) Тема: Работа со смарт-террейнами. [cut=Описание]Карты с указанием мест расположения смарт-террейнов СГМ 2.2. Пригодится при создании модов на основе СГМ 2.2 или редактировании заселенности локаций. Скачать Правильно заданный вопрос - половина правильного ответа!
Сообщение отредактировал Бабай - Пн, 22.01.2018, 08:10
Эти 0 пользователя(ей) поблагодарили Бабай за это полезное сообщение:
Перед тем, как начать урок, я хочу сказать, что скриптовой частью я обязан товарищу Ховану и Николаю Болтову. Именно благодаря их скриптам я нашел способ сделать подобную вещь! Огромное им спасибо! А теперь перейдем к уроку. Файлы, которые нам потребуются: - configs/misc/items.ltx - configs/text/rus/st_items_equipment.ltx - scripts/_g.script - scripts/bind_stalker.script - scripts/my_callbacks.script Возможно, вы когда-нибудь задумывались над вопросом создания предмета, из при использовании которого в инвентарь будут выпадать сразу несколько других, как, например, универсальный медкомплект. Долго думая, я понял, что такого эффекта можно достичь используя коллбеки на использовании предметов. Что такое "коллбек"? Если коротко, - это что-то в роде скрипта инфопорции. Однако, коллбек может работать как единожды, так и постоянно: при подборе предметов, при их использовании, при выстреле, при попадению по нпс и так далее. Нас интересует коллбек использования предмета, который будет работать постоянно. 1. Откроем items.ltx и скопируем секцию какого-нибудь бустера. Вставим новую секцию где-нибудь в это-же файле. 2. Настроим его так, как нам этого захочется.
Долго здесь зацикливаться не будем. Все элементарно. Могу только сказать, что при использовании будет проигрываться звук аптечки, а модель взяли армейской аптечки. 3. В st_items_equipment.ltx создаем описание и название предмета
Код
<string id="st_medkit_complex"> <text>Универсальный медкомплект</text> </string> <string id="st_medkit_complex_desc"> <text>Специальный медкомплект, разработанный для спецслужб в Зоне. Включает в себя все основные медикаменты.</text> </string>
На этом с конфигами все. 4. Руководствуясь материалом, взятым из сборника модостроения от Хована, мы создаем файл my_callbacks.script в папке scripts. 5. Наполняем его следующим образом
Код
function on_use_item(sect) --Переменные local actor=db.actor local item_name=sect:section() local actor_pos=db.actor:position() local active_slot=db.actor:active_slot() local active_item=db.actor:active_item() local pistol_in_slot=db.actor:item_in_slot(2) local rifle_in_slot=db.actor:item_in_slot(3) local outfit_in_slot=db.actor:item_in_slot(7) local helm_in_slot=db.actor:item_in_slot(12) --Коллбеки if item_name=="medkit_complex" then give_object_to_actor("drug_anabiotic") give_object_to_actor("antirad") give_object_to_actor("bandage") give_object_to_actor("drug_radioprotector") give_object_to_actor("drug_antidot") give_object_to_actor("drug_psy_blockade") give_object_to_actor("drug_coagulant") give_object_to_actor("drug_booster") end end
give_object_to_actor - как-раз и есть скрипт выдачи ГГ предмета, опираясь на коллбек. В скобках название предмета. Вообщем, продолжаем так-же, и добавляем, что хотим. Надеюсь, принцип ясен. 6. Зарегистрируем наш файл в bind_stalker.script. Там находим функцию function actor_binder:use_inventory_item(obj) и под вторым end прописываем
Код
if obj~=nil then my_callbacks.on_use_item(obj) end
В целом выглядит так:
Код
function actor_binder:use_inventory_item(obj) if(obj) then local s_obj = alife():object(obj:id()) if(s_obj) and (s_obj:section_name()=="drug_anabiotic") then xr_effects.disable_ui_only(db.actor, nil) level.add_cam_effector("camera_effects\\surge_02.anm", 10, false, "bind_stalker.anabiotic_callback") level.add_pp_effector("surge_fade.ppe", 11, false) give_info("anabiotic_in_process") _G.mus_vol = get_console():get_float("snd_volume_music") _G.amb_vol = get_console():get_float("snd_volume_eff") get_console():execute("snd_volume_music 0") get_console():execute("snd_volume_eff 0") end end if obj~=nil then my_callbacks.on_use_item(obj) end end
7. Осталось добавить глобальную функцию give_object_to_actor в _g.script. Внизу пишем:
Код
-- 'Создание предмета в рюкзаке ГГ. function give_object_to_actor(obj,count) if count==nil then count=1 end for i=1, count do alife():create(obj,db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),db.actor:id()) end end
На этом урок заканчивается. Осталось только прописать пак ГГ и протестировать! Пример того, как такого рода предмет работает, в этом видео. [cut=Пример][/cut]
Урок был взят с Ap-pro форума, но авторские права принадлежат мне
Добавлено (19.05.2013, 22:36) --------------------------------------------- Урок 57 Тема: Регистрация новых звуков эксклюзивно для новой локации
Допустим, мы подключили к нашему моду локацию Болота из ЧН и мы хотим провести заселение. Наверняка, мы захотим добавить некоторые звуки новым квестовым НПС. А квестовым НПС у нас на сей урок станет восстановленный нами бармен "Чистого Неба", Холод. В первую очередь ему нужны фразы приветствия и прощания, а остальные пока подождут. 1. Нам надо зарегистрировать нашу локацию в configs/misc/script_sound.ltx. Открываем, и прописываем сверху
Код
#include "script_sound_marsh.ltx"
Ниже в секции
Код
[list]
добавим в конце list_script_sound_marsh 2. Далее в configs/misc создаем файл script_sound_marsh.ltx. 3. Начинаем его заполнять. Создаем список всех звуков, то есть секцию [list_script_sound_marsh]. В ней прописываем все секции звуковых файлов локации. В этот раз мы возьмем фразы Холода. Секция тогда будет выглядеть так:
Обратите внимание, что в параметре path название звука оборвано. А в параметре shuffle стоит рандом. Выходит звук приветствия/прощания не один, и будет рандомный выбор. Название у звуков отличается только после нижнего подчеркивания. 5. Добавим нужный звуковые файлы. Можно скопировать в ЗП полностью всю ЧНовскую папку sounds/character_voice/scenario/marsh, или выбрать оттуда только нужные звуки: mar_csky_barman_meet_bye_1 mar_csky_barman_meet_bye_2 mar_csky_barman_meet_bye_3 mar_csky_barman_meet_greet_1 mar_csky_barman_meet_greet_2 mar_csky_barman_meet_greet_3 6. Теперь можем прописать Холоду в логику:
Урок 58 (Автор denis2000) Задача: Создание аномалии нового типа, на примере хроноаномалии. Файл с выполненным заданием
Сразу определимся, что аномалия - это некий участок игрового пространства при попадании в который ГГ начинают проявляться внешние воздействия: 1. Визуальный эффект аномалии, как на экране у игрока (постпроцесс), так и на локации (партиклы) 2. Звук сработавшей аномалии (может быть а может отсутствовать если аномалия безшумная) 3. Воздействие на параметры ГГ и на окружающее пространство, тут выбор воздействия достаточно широк от не смертельных воздействий до прямой угрозе жизни все на ваш выбор. Создаем спейс-рестриктор в all.spawn:
Код
[20000] ; cse_abstract properties section_name = space_restrictor name = zat_time_anomaly_test position = 245.037811,16.290030,504.355347 direction = 0,0,0
Все стандартно, тип рестриктора 3, координаты, рестриктор сферической формы радиусом, например, пять метров. Создаем точку пути (в ней будем проигрывать партиклы для визуальных эффектов аномалии):
В логике первая активная секция [sr_idle@wait] - ожидание попадания ГГ внутрь рестриктора, как только он попался переключаемся на одну из секций воздействия sr_idle@inside_0 и перед этим запускаем эффекты: 1. run_postprocess(_actor_death_effector:9999:true) - это постпроцесс _actor_death_effector (раскачивание камеры и эффект зернения на экране), можно использовать существующие или создавать свои. 2. play_particle_on_path(anomaly2\a_test:zat_time_anomaly_test_way) - это проигрывание партикла anomaly2\a_test в точке at_time_anomaly_test_way, визуализация аномалии, партиклы можно использовать существующие в particles.xr или сделать свои. В секциях воздействия [sr_idle@inside_0] и [sr_idle@inside_1] есть прежде всего строка ожидающая выхода ГГ из зоны действия аномалии on_actor_outside, при этом аномалия возвращается в исходное состояние. Также в этих секциях обозначено воздействие аномалии on_timer = 1000. Тоесть каждые 1000 мс происходит перемотка игрового времени на 5 минут forward_game_time(0:5) и проигрвание звука play_sound(pda_alarm), звук pda_alarm взят для примера, нужно добавить свой. Секции [sr_idle@inside_0] и [sr_idle@inside_1] образуют некий автогенератор с двумя состояниями, рестриктор попеременно переключается то в оду секцию то в другую - это сделано для того чтобы точнее дозировать воздействие аномалии.
В данном уроке я рассмотрю возможность создания работающего лифта на локации. Он работает только для ГГ и не будет работать для НПС по причине ограничений самого движка. Прежде всего хочу сказать, что реализация лифта основана на динамическом объекте door_lab_x8. Итак начинаем с создания объекта лифт. I. Создаем в 3D редакторе обект. Я сделал тестовый объект в виде прямоугольной платформы, назначил материал, текстуру, создал скелет из двух суставов link и platform. Импортировал в object. II. Создаем анимацю движения. Я сделал простую, короткую анимацию в 30 кадров (ее можно растянуть в SDK поэтому делать ее полноценной длительности смысла нет). III. Настройка объекта лифт в SDK. В SDK нужно настроить шейдеры и материал объекта если необходимо (по умолчанию все и так работает), затем подгрузить созданную анимацию lift_up.skl, затем настроить сустав platform, а именно создать бонешейп, выбрать тип сустава Joint и самое главное настроить Game Material = objects\metal_box. В подключенной анимации уменьшил скорость воспроизведения Speed = 0.1 и поставил флаг Stop at end. Полученный объект импортируем в ogf. IV. Вставляем анимационные и интерактивные объекты на локацию. В all.spawn создаются секции подвижной анимированной платформы:
Код
[20000] ; cse_abstract properties section_name = door_lab_x8 name = zat_lift_test position = 245.037811,16.290030,504.355347 direction = 0,0,0
Тут все понятно: start_snd - звук в начале анимации, stop_snd - звук после окончания анимации. Если анимация достаточно длинная то может понадобиться повторяющийся звук проигрываемый между начальным и конечным idle_snd = device\airtight_gates_idle и idle_delay = 6500 Нижняя кнопка:
При "нажатии" на кнопку лифт проигрывает анимацию в обратном направлении (едет вниз) anim_obj_backward(zat_lift_test) VI. Некое допиливание скрипта bind_door_labx8.script, для того чтобы отключать звук после окончания отыгрывания анимации в обратном порядке. В функции function door_binder_labx8:animation_end_callback(is_end) закоментировать условие if is_end then, таким образом:
Код
function door_binder_labx8:animation_end_callback(is_end) --if is_end then if self.stop_snd then self.stop_snd:play_at_pos(self.object, self.object:position(), 0, sound_object.s3d) end self.is_idle = true self.anim_time = self.object:get_physics_object():anim_time_get() xr_logic.pick_section_from_condlist(get_story_object("actor"), obj, self.on_stop) --end end
[cut=Видео №1][/cut] [cut=Видео №2][/cut]
Урок 60 (Автор denis2000) Задача: Перенос анимпоинтов из Чистого неба или создание новых. Файл с выполненным заданием
Перенос анимпоинта /animpoint/ (в Чистом Небе их называют смарт-кавер /smart cover/) cover_loophole_lead_sit_sleep_mechanic из ЧН в ЗП или создание нового.
В ЧН нам понадобятся файлы: smart_covers_cover_loophole_lead_sit_sleep_mechanic.script smart_covers_loophole_lead_sit_sleep_mechanic.script
Файлы переименуем так: smart_covers_cover_loophole_lead_sit_sleep_mechanic.script в smart_covers_animpoint_lead_sit_sleep_mechanic.script smart_covers_loophole_lead_sit_sleep_mechanic.script в smart_covers_loophole_animpoint_lead_sit_sleep_mechanic.script
В ЗП нам понадобятся файлы: smart_covers.script state_lib_animpoint.script state_mgr_animation_list_animpoint.script state_mgr_animstate_list_animpoint.script xr_animpoint_predicates.script
Правим файл smart_covers_loophole_animpoint_lead_sit_sleep_mechanic.script: Переименуем функцию в function get_loophole(id, position, fov_direction, enter_direction) В выходную таблицу функции добавим параметры:
Код
danger_fov_direction = vector():set(-1,0,0),
Код
danger_fov = 45.0,
Правим файл smart_covers_animpoint_lead_sit_sleep_mechanic.script: Переименуем функцию function get_smart_cover_cover_loophole_lead_sit_sleep_mechanic() в функцию function get_smart_cover() Функцию function exit_random(p) можно просто удалить. В выходную таблицу добавим: