Войти на сайт Регистрация Лента форума Пользователи Правила сайта Поиск по форуму
  • Страница 4 из 5
  • «
  • 1
  • 2
  • 3
  • 4
  • 5
  • »
Модератор форума: denis2000, FantomICW  
Форум » Моды для игр » Модостроение » Курс молодого бойца - КМБ. Уроки для начинающих
Курс молодого бойца - КМБ. Уроки для начинающих
trackerДата: Вт, 02.11.2010, 09:28 | Сообщение # 1
Удаленные



Курс молодого бойца. Уроки для начинающих *


В этой теме на конкретных примерах (Уроках) разбирается весь процесс создания мода.

Правила работы в теме:
Любой пользователь обладающий опытом и знаниями в модостроение, создает урок по определенной теме (отражено в задаче урока), после этого описывает выполнение поставленной задачи в виде отдельного файла и (или) напрямую в своем посте спрятав его под спойлер. В дополнении к уроку желательно выложить содержимое папки gamedata с выполненным уроком, чтобы пользователь скачав его мог проверить правильность выполнения урока самостоятельно.
Обсуждение уроков ведется в теме: "Общие вопросы модостроения". Также в данной теме могут быть размещены дополнительные материалы помогающие пользователю освоить все аспекты модостроения.

Будем пытаться не использовать специфические файлы, поэтому можно работать в чистом ЗП, SGM и т.д. **

Не рекомендуется размещать информацию автором которой вы не являетесь, но если она полезна для пользователей сайта указывайте автора. Не рекомендуется размещать информацию доступную на других ресурсах повещенных модостроению - пользователи и так смогут ее найти. Запрещено размещать непроверенную информацию. В любом случае модераторы раздела оставляют за собой право удалить пост с Уроком или Справочной информацией в случае нарушения автором правил данного форума или правил данной темы.

*В любом уроке, вопросы рассмотренные полно в предыдущем уроке, могут быть описаны весьма сжато, поэтому при возникновении вопросов, прежде всего посмотрите предыдущие.
** Если нет специальных пояснений то урок делался на чистом ЗП 1.6002, в противном случае указан мод и версия для которой урок предназначен.

Скрипт показа координат в реальном времени

[cut=Рекомендации по оформлению]1. Заголовок сообщения из которого понятно назначение поста (Урок, Справочная информация или другое)
2. Если это урок то он должен иметь четко обозначенную задачу и желательно иметь ссылку на файл с выполненным уроком, для того чтобы выполняющие его могли скачать и посмотреть выполнение урока на примере.
3. Придерживайтесь устоявшейся цветовой схемы:
а) Путь к файлу и (или) имя файла - Зеленый
б) Имя параметра, функции и т.п. в файле - Желтый
в) Не рекомендуется использовать оранжевый - это цвет комментариев кураторов раздела и к тому же близок к цвету ссылок.
4. Куски кодов и конфигурационных файлов обязательно помещайте в контейнер
Код
Исходный текст файла
.
5. Выделение текста изменением размера шрифта, его типом на усмотрение автора, главное не перебарщивать.[/cut]

Тема предназначена только для публикации уроков и справочной информации, вопросы в другой теме! Флуд и оффтоп будет наказан без предупреждения, а пост удалён, что бы там не находилось.
 
FantomICWДата: Ср, 03.07.2013, 21:19 | Сообщение # 46
Лидер «Свободы»
Свобода
Сообщений: 4438
Награды: 44
Репутация: [ 1340 ]

Урок 56 (б)
Задача: создание инвентарного комплекса (см. урок 56) в ТЧ и ЧН, способом добавления функции коллбека использования предметов из ЗП



Урок 61
Тема: Текстурирование.Создание золотистой текстуры оружия
Требуемая утилита: Paint.Net



Урок 62
Тема: Создание артефакта в Сталкер Зов Припяти (полный разбор)
Ссылка на урок





Сообщение отредактировал FantomICW - Чт, 04.07.2013, 19:27
 
denis2000Дата: Чт, 25.07.2013, 14:02 | Сообщение # 47
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1916 ]

Урок 63
Задача: Исправление скрипта отвечающего за спавн сквадов на стартовых позициях в начале новой игры


Урок 64
Задача: Перенести в декомпилированную локацию настройки сделанные прямым редактированием all.spawn.


"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
FantomICWДата: Ср, 28.08.2013, 01:19 | Сообщение # 48
Лидер «Свободы»
Свобода
Сообщений: 4438
Награды: 44
Репутация: [ 1340 ]

Урок 65
Тема: Перенос объектов из архивов СДК в игровой формат, жесткая привязка к локации (объект динамический, но никуда не будет улетать от выстрела).
Необходимы утилиты: Milkshape 1.8.4 и выше с плагинами Сталкера, SDK 0.7
Модель объекта (готовая, в OGF)





Сообщение отредактировал FantomICW - Ср, 28.08.2013, 01:20
 
NIVДата: Вс, 15.09.2013, 08:52 | Сообщение # 49
Полевой исследователь
Ученые сталкеры
Сообщений: 167
Награды: 4
Репутация: [ 180 ]

Урок 66 (автор NIV)
Платформа: "Зов Припяти"
Задача: Создание квеста на поиск перехода на другую локацию. Переход будет доступен после активации по сюжету. Установка меток на квестовую область и место перехода. Использование окна подтверждения (GUI) для подтверждения перехода или возврата на текущую локацию (как это было в ТЧ и ЧН).
Сложность: выше средней.
Необходимые навыки и инструменты: разбор all.spawn (ACDC); прописать координаты ГГ на экран в моде "Повелитель Зоны". Представлять, как работает логика рестрикторов.



Ссылка на gamedata с выполненным уроком


Изменяем реальность S.T.A.L.K.E.R. CoP: "Цена Новых Исследований" / "New Investigations' Value"

Сообщение отредактировал NIV - Вс, 15.09.2013, 14:48
 
FantomICWДата: Ср, 18.09.2013, 20:52 | Сообщение # 50
Лидер «Свободы»
Свобода
Сообщений: 4438
Награды: 44
Репутация: [ 1340 ]

Modmaker's Notes™
Тема заметки: Логика НПС, стреляющего в другого персонажа
Требуемая утилита: Notepad ++ (обычный блокнот тоже пойдет, но файл подготавливался именно для синтаксиса Notepad ++)
[cut=Немного пояснений ]Новая серия моих модостроительских работ. Уроками их назвать сложно, тем не менее, они могут оказаться вполне полезными в некоторых случаях. Скриптовые заметки буду выкладывать в файлах с расширением .lua, а конфиговые - в .properties. [/cut]
Ссылка на справочный материал


Modmaker's Notes™
Тема заметки: Скриптовые методы спавна трупа
Требуемая утилита: Notepad ++ (обычный блокнот тоже пойдет, но файл подготавливался именно для синтаксиса Notepad ++)
Ссылка на справочный материал





Сообщение отредактировал FantomICW - Ср, 18.09.2013, 20:52
 
NIVДата: Пн, 14.10.2013, 20:10 | Сообщение # 51
Полевой исследователь
Ученые сталкеры
Сообщений: 167
Награды: 4
Репутация: [ 180 ]

Урок 67 (автор NIV)
Платформа: "Зов Припяти"
Задача: Ограничение времени на выполнение квеста и вывод таймера с остатком времени на экран.
Сложность: не очень сложно.
Необходимые навыки и инструменты: Notepad++



При работе над данным материалом автору помогали ценными мыслями и советами участники форума denis2000 и FantomICW.

Ссылка на gamedata с выполненным уроком


Изменяем реальность S.T.A.L.K.E.R. CoP: "Цена Новых Исследований" / "New Investigations' Value"

Сообщение отредактировал NIV - Пн, 14.10.2013, 20:46
 
FantomICWДата: Вс, 15.12.2013, 13:58 | Сообщение # 52
Лидер «Свободы»
Свобода
Сообщений: 4438
Награды: 44
Репутация: [ 1340 ]

Modmaker's Notes™
Тема заметки: Скрываем метку НПС на карте (как отряд Петрухи в ТЧ)
Требуемая утилита: Notepad ++ для красивой подсветки синтаксиса
Ссылка на справочный материал


Урок 68 (Ретро-серия)
Тема: Текстурирование | Создаем насечки на текстуре оружия
Автор: BigBabay
Ссылка на PDF


Modmaker's Notes™
Тема заметки: Выдаем рандомную награду ГГ
Требуемая утилита: Notepad ++ для красивой подсветки синтаксиса
Ссылка на справочный материал





Сообщение отредактировал FantomICW - Вс, 15.12.2013, 13:59
 
strelok200Дата: Чт, 19.12.2013, 17:11 | Сообщение # 53
Бывалый
Свобода
Сообщений: 126
Награды: 0
Репутация: [ 33 ]

Урок 69 (Автор strelok200)
Тема: GUI

Итак, уважаемые, прежде чем приступить к этому уроку я вам советую прочесть статью от FantomICW, которая поможет вам научиться работать с текстурами GUI, правильно размещать соответствующие элементы
Ну а если вы уже ознакомились, то давайте приступим к созданию окошка с новым элементом:шкала
В игре примерно выглядит вот так.

Сегодня мы разберем как создается такой элемент
Возьмем соответственно две основные текстуры
http://yadi.sk/d/4jwtk_aAEYH3e
Рассматривать размещение элементов, координаты, коллбеки я не буду, перейду сразу к скриптовой части.
Цель следующая: ГГ должен выставить ползунок шкалы в определенном месте и нажать кнопку. В том случае, если ГГ выставил ползунок "верно" и нажал на кнопку, то выдадим ему инфопоршень. Для начала определим, ту зону, в которой мы будем считать, что ползунок выставлен верно и соответственно код будет следующим

Теперь заходим в игру, выставляем ползунок как хотим, нажимаем кнопку. На экран будет выведено значение переменной self.shkala:GetFValue()
Запоминаем это число, затем выставляем ползунок в другом месте, на экране увидим новое значение.
У меня грубо говоря получилось значение 0.4 и 0.5
Теперь сделаем проверку: если значение переменной self.shkala:GetFValue() больше 0.4 и меньше 0.5, то выдадим инфопоршень. Код будет следующим


Содержание файла radist_pribor.xml (подробно рассматривать не буду)


Сообщение отредактировал strelok200 - Чт, 19.12.2013, 17:11
 
FantomICWДата: Чт, 23.01.2014, 19:18 | Сообщение # 54
Лидер «Свободы»
Свобода
Сообщений: 4438
Награды: 44
Репутация: [ 1340 ]

Всех с наступающим! smile
Modmaker's Notes™
Тема заметки: Скриптовое действие на позиции НПС (вычисляем позицию НПС в реальном времени)
Требуемая утилита: Notepad ++ для красивой подсветки синтаксиса
Ссылка на справочный материал

Добавлено (23.01.2014, 19:18)
---------------------------------------------
Урок 70
Тема: GUI | Создания инвентарного Gui-комплекса + основы Gui
Тема-статья на ап-про

Урок 71
Тема: GUI | Создание новой отметки НПС на карте
Тема-статья на ап-про



 
СахарДата: Сб, 13.12.2014, 05:10 | Сообщение # 55
Гражданский
Пользователи
Сообщений: 2
Награды: 4
Репутация: [ 69 ]

Урок №72 (Автор: Я то бишь Сахар)
Тема: 3D моделирование | "Maya: вандализм или проламывание стены."
Требующиеся программы: Autodesk Maya (от 8.5 до 2014) плагин для импорта/экспорта геометрий.
[cut]
[cut=Для новичков]

[/cut]
[cut=«Лофтим» эскиз дыры ]Для начала нам нужно создать кривую для этого нам нужно перейти на полку Curves. На этой полке выбираем инструмент Pencil Curve Tool.

Выбрав данный инструмент курсор изменится со стрелочки на карандаш. После нужно зажать клавишу x (привязка к сетки) нарисовать кривую окружность.

Дальше нам нужно создать копию данной кривой для этого выделяем нашу линию и жмём Ctrl + D (если нечего не произошло, то проверьте раскладку клавиатуры, а так же посмотрите, не включен ли у вас Caps Lock). После чего выделяем одну из кривой и переключаемся на инструмент move

(или клавиша W).
Дальше с помощь появившегося контролера тянем одну из кривых наверх

Теперь переходим к самому интересному, создадим из этих двух кривых полигонную модель. Для этого выделяем обе кривые и жмём F4 (переключаемся на инструменты для работы со сплайтами и кривыми) после выбираем в панели главного меню (там где file, edit и т.д) кнопку Surfaces у нас «выкатится меню» и рядом с надписью Loft жмём на кубик. У нас появится окно под название Loft Options устанавливаем параметры как на скрииншоте который приведён ниже.

И жмём на кнопку "Loft" после чего у нас должно получится что-то вроде этого.
[/cut]
[cut=Само проламывание стены.]Теперь нам надо подогнать и отмасштабировать получившийся эскиз.

Ну и наконец, кульминация создаём отверстие для этого жмём на F3 после выделим нашу модель (в моём случай это забор) после наш эскиз. И применим к ним команду Mesh --> Booleans --> Difference (на название команды, а не на кубик.) В итоге мы получаем красивый пролом в стене, останется только положить на него X-Ray шейдер и затекстурировать.
[/cut]
[/cut]

Добавлено (13.12.2014, 05:10)
---------------------------------------------
Урок №73 (Автор: Сахар)
Тема: 3D моделирование | "Maya: " Эксперименты над людьми или перенос модели из Сталкер Чень Чернобыля в Сталкер Чистое Небо и Сталкер Зов Припять без потери «весов»."
Требующиеся программы: Autodesk Maya (от 8.5 до 2014) плагин для импорта/экспорта геометрий и X-Ray SDK 0.7 или X-Ray SDK 0.6/0.5.
[cut=Часть первая подготовка модели]
Для начала нам нужно импортировать (никоем случи не открыть!) модель которую мы будем переносить. (думаю мне не надо подробно разъяснять как экспортировать модель.) Теперь нам нужно её подготовить для жмём на две кнопки, которые показаны на скриншоте ниже.

Теперь нам нужно удалить старый character для этого нам нужно нажать на главной пенели window --> Outliner или так смотрим скриншот.

Теперь жмём на «синего человечка» (если он у вас не появился, то нужно в окне Outliner – ра нажать Show --> Show All) и нажимаем клавишу Delete. Всем модель подготовлена.
[/cut]

[cut=Создаём новые кости]
Теперь нам надо создать и добавить к скелету две недостающие кости для этого переходим на полку Animation и там выбираем инструмент Joint Tool

Вместо курсора у нас появится прицел теперь зажав клавишу Х (привязка к сетке) жмем на сетку между ног нашей модели примерно так.

Теперь отпускаем клавишу Х и зажимаем V (привязка к вершинам в нашем случай к джоинтам (суставам) поэтому мы и отключили меш в самом начале)

Теперь нам осталось соединить два скелета для этого выделяем кость bip01_pelvis и joint1(выбираем первую кость зажимаем Сtrl и жмём на вторую кость. Именно так если сначала мы выберем joint1 а только потом bip01_pelvis то в СДК у нас будет вылет! ) после чего выполняем команду connect Joint

Кстати кости удобнее выбирать в окне Outliner.
Теперь переименовываем кость joint1 в root_stalker а joint2 в bip01 для этого в окне Outliner – ра дважды жмем на надпись joint1 после вводим нужное название и нажимаем интер (именно интер иначе новое имя не сохранится)
Теперь опять выделяем кость bip01_pelvis (всё в том же Outliner -ре) зажимаем колёсико мыши и тянем на кость bip01 в итоге у нас кость bip01_pelvis должна пропасть а слева от кости bip01 появится +. Все иерархия скелета восстановлена. Всё модель перенесена осталось её толь экспорировать.
[/cut]
[cut=Скрин Дока]

Как видно я тут с бампом накосяцил smile
[/cut]




Сообщение отредактировал Сахар - Вс, 14.12.2014, 05:41
 
makdmДата: Сб, 07.03.2015, 22:31 | Сообщение # 56
Рожденный в СССР
Разработчики
Сообщений: 1294
Награды: 29
Репутация: [ 1909 ]

Урок №74 (Автор: makdm)
Тема: Создание вертолёта через скрипт

[cut=Урок №74]Первое: Создаём "болванку" скрипта в файле xr_effects.script
Пусть функция будет называться create_helicopter
В качестве аргумента передаём секцию пути, указанную в all.spawn,
на которой будет создан вертолёт, эта же секция пути будет
использована в логике вертолёта, как точка, над которой вертолёт будет "висеть"

Пишем:

function create_helicopter( actor, obj, p )
if p and p[ 1 ] then --проверяем, что секция пути в функцию передана
--проверяем, есть ли такая секция в all.spawn
if not level.patrol_path_exists( p[ 1 ] ) then
--если нет, то вылетаем на рабочий стол
abort("Path %s doesnt exist. Function 'create_helicopter'", tostring( p[ 1 ] ) )
end
local ptr = patrol( p[ 1 ] )
local position = ptr:point( 0 ) -- получаем позицию ( вектор ) точки спавна
local lv_id = ptr:level_vertex_id( 0 ) -- получаем левел вертекс точки спавна
local gv_id = ptr:game_vertex_id( 0 ) -- получаем гейм вертекс точки спавна
local section = "helicopter" -- секцию берём из gamedata\configs\creatures\helicopter.ltx
--создаём серверный объект вертолёта
local s_obj = alife():create( section, position, lv_id, gv_id )
end
end


Теперь подготовим логику вертолёта.
Пусть вертолёт будет просто висеть на месте и нос вертолёта всегда
будет направлен в сторону игрока.
Запретим вертолёту стрелять ракетами и стрелять из пулемёта.

local logic_helicopter = "[logic]\n"..
"active = heli_move@idle\n"..
"[heli_move@idle]\n"..
"path_move = "..tostring( p[ 1 ] ).."\n"..
"path_look = actor\n"..
"invulnerable = true\n"..
"max_velocity = 50\n"..
"enemy = nil\n"..
"immortal = true\n"..
"use_rocket = false\n"..
"use_mgun = false\n"..
"upd_vis = 3\n"..
"engine_sound = true\n"


Теперь добавим логику в нашу функцию
Наша функция теперь будет выглядеть так

function create_helicopter( actor, obj, p )
if p and p[ 1 ] then --проверяем, что секция пути в функцию передана
if not level.patrol_path_exists( p[ 1 ] ) then --проверяем есть ли такая секция в all.spawn
--если нет, то вылетаем на рабочий стол
abort("Path %s doesnt exist. Function 'create_helicopter'", tostring( p[ 1 ] ) )
end
local logic_helicopter = "[logic]\n"..
"active = heli_move@idle\n"..
"[heli_move@idle]\n"..
"path_move = "..tostring( p[ 1 ] ).."\n"..
"path_look = actor\n"..
"invulnerable = true\n"..
"max_velocity = 50\n"..
"enemy = nil\n"..
"immortal = true\n"..
"use_rocket = false\n"..
"use_mgun = false\n"..
"upd_vis = 3\n"..
"engine_sound = true\n"
local ptr = patrol( p[ 1 ] )
local position = ptr:point( 0 ) -- получаем позицию ( вектор ) точки спавна
local lv_id = ptr:level_vertex_id( 0 ) -- получаем левел вертекс точки спавна
local gv_id = ptr:game_vertex_id( 0 ) -- получаем гейм вертекс точки спавна
local section = "helicopter" -- секцию берём из gamedata\configs\creatures\helicopter.ltx
local s_obj = alife():create( section, position, lv_id, gv_id ) --создаём серверный объект вертолёта
end
end


Если всё оставить, как есть, то при вызове функции получим вылет на рабочий стол. Это связано с тем, что для
"правильного" спавна вертолёта не хватает исходных данных.

Эти данные необходимо добавить в STATE часть нет-пакета вертолёта.
Для этого сначала мы прочитаем нет-пакет вертолёта.
Делается это так:

local packet = net_packet() --берём пустой нет-пакет
packet:w_begin( 0 ) -- указатель на начало записи
s_obj:STATE_Write( packet ) -- пишем STATE часть нет-пакета вертолёта в наш пустой нет-пакет
packet:r_seek( 2 ) -- начинаем читать наш пакет
local game_vertex_id = packet:r_u16()
local distance = packet:r_float()
local direct_control = packet:r_s32()
local level_vertex_id = packet:r_s32()
local object_flags = packet:r_s32()
local custom_data = packet:r_stringZ()
local story_id = packet:r_s32()
local spawn_story_id = packet:r_s32()
local visual_name = packet:r_stringZ()
local visual_flags = packet:r_u8()
local motion_name = packet:r_stringZ()
local skeleton_name = packet:r_stringZ()
local skeleton_flags = packet:r_u8()
local source_id = packet:r_u16()
local startup_animation = packet:r_stringZ()
local engine_sound = packet:r_stringZ()

Добавим этот код в нашу функцию
Получим

function create_helicopter( actor, obj, p )
if p and p[ 1 ] then --проверяем, что секция пути в функцию передана
if not level.patrol_path_exists( p[ 1 ] ) then --проверяем есть ли такая секция в all.spawn
--если нет, то вылетаем на рабочий стол
abort("Path %s doesnt exist. Function 'create_helicopter'", tostring( p[ 1 ] ) )
end
local logic_helicopter = "[logic]\n"..
"active = heli_move@idle\n"..
"[heli_move@idle]\n"..
"path_move = "..tostring( p[ 1 ] ).."\n"..
"path_look = actor\n"..
"invulnerable = true\n"..
"max_velocity = 50\n"..
"enemy = nil\n"..
"immortal = true\n"..
"use_rocket = false\n"..
"use_mgun = false\n"..
"upd_vis = 3\n"..
"engine_sound = true\n"
local ptr = patrol( p[ 1 ] )
local position = ptr:point( 0 ) -- получаем позицию ( вектор ) точки спавна
local lv_id = ptr:level_vertex_id( 0 ) -- получаем левел вертекс точки спавна
local gv_id = ptr:game_vertex_id( 0 ) -- получаем гейм вертекс точки спавна
local section = "helicopter" -- секцию берём из gamedata\configs\creatures\helicopter.ltx
local s_obj = alife():create( section, position, lv_id, gv_id ) --создаём серверный объект вертолёта
local packet = net_packet() --берём пустой нет-пакет
packet:w_begin( 0 ) -- начинаем запись с нулевого байта
s_obj:STATE_Write( packet ) -- пишем STATE часть нет-пакета вертолёта в наш пустой нет-пакет
packet:r_seek( 2 ) -- начинаем читать наш пакет
local game_vertex_id = packet:r_u16()
local distance = packet:r_float()
local direct_control = packet:r_s32()
local level_vertex_id = packet:r_s32()
local object_flags = packet:r_s32()
local custom_data = packet:r_stringZ()
local story_id = packet:r_s32()
local spawn_story_id = packet:r_s32()
local visual_name = packet:r_stringZ()
local visual_flags = packet:r_u8()
local motion_name = packet:r_stringZ()
local skeleton_name = packet:r_stringZ()
local skeleton_flags = packet:r_u8()
local source_id = packet:r_u16()
local startup_animation = packet:r_stringZ()
local engine_sound = packet:r_stringZ()
end
end


Теперь нам нужно изменить некоторые значения, хранящиеся в нет пакете,
чтобы наш вертолёт "заработал". Добавляем логику, параметры движения и
анимации, звук, визуал вертолёта.

custom_data = logic_helicopter
motion_name = "idle"
skeleton_name = "idle"
startup_animation = "idle"
visual_name = "dynamics\\vehicles\\mi24\\veh_mi24_u_01"
engine_sound = "vehicles\\helicopter\\helicopter"


Мы использовали логику logic_helicopter, которая сразу записана в нашей функции.
Если мы хотим "вынести" нашу логику в отдельный файл, то в нашей функции нужно
прописать путь к файлу, в котором будет записана логика нашего вертолёта.
Например логика находится в файле logic_helicopter.ltx, тогда в функцию
пишем путь до файла.

local logic_helicopter = "[logic]\ncfg = scripts\\zaton\\logic_helicopter.ltx"

Добавим наши изменения в функцию и запишем их в нет-пакет вертолёта

function create_helicopter( actor, obj, p )
if p and p[ 1 ] then --проверяем, что секция пути в функцию передана
if not level.patrol_path_exists( p[ 1 ] ) then --проверяем есть ли такая секция в all.spawn
--если нет, то вылетаем на рабочий стол
abort("Path %s doesnt exist. Function 'create_helicopter'", tostring( p[ 1 ] ) )
end
local logic_helicopter = "[logic]\n"..
"active = heli_move@idle\n"..
"[heli_move@idle]\n"..
"path_move = "..tostring( p[ 1 ] ).."\n"..
"path_look = actor\n"..
"invulnerable = true\n"..
"max_velocity = 50\n"..
"enemy = nil\n"..
"immortal = true\n"..
"use_rocket = false\n"..
"use_mgun = false\n"..
"upd_vis = 3\n"..
"engine_sound = true\n"
local ptr = patrol( p[ 1 ] )
local position = ptr:point( 0 ) -- получаем позицию ( вектор ) точки спавна
local lv_id = ptr:level_vertex_id( 0 ) -- получаем левел вертекс точки спавна
local gv_id = ptr:game_vertex_id( 0 ) -- получаем гейм вертекс точки спавна
local section = "helicopter" -- секцию берём из gamedata\configs\creatures\helicopter.ltx
local s_obj = alife():create( section, position, lv_id, gv_id ) --создаём серверный объект вертолёта
local packet = net_packet() --берём пустой нет-пакет
packet:w_begin( 0 ) -- указатель записи
-- пишем STATE часть нет-пакета вертолёта в наш пустой нет-пакет
s_obj:STATE_Write( packet )
packet:r_seek( 2 )
-- начинаем читать наш пакет
local game_vertex_id = packet:r_u16()
local distance = packet:r_float()
local direct_control = packet:r_s32()
local level_vertex_id = packet:r_s32()
local object_flags = packet:r_s32()
local custom_data = packet:r_stringZ()
local story_id = packet:r_s32()
local spawn_story_id = packet:r_s32()
local visual_name = packet:r_stringZ()
local visual_flags = packet:r_u8()
local motion_name = packet:r_stringZ()
local skeleton_name = packet:r_stringZ()
local skeleton_flags = packet:r_u8()
local source_id = packet:r_u16()
local startup_animation = packet:r_stringZ()
local engine_sound = packet:r_stringZ()
-- меняем параметры, прочитанные из нет-пакета
custom_data = logic_helicopter
motion_name = "idle"
skeleton_name = "idle"
startup_animation = "idle"
visual_name = "dynamics\\vehicles\\mi24\\veh_mi24_u_01"
engine_sound = "vehicles\\helicopter\\helicopter"
-- начинаем писать в наш пакет изменённые параметры
packet:w_begin( 0 )
packet:w_u16( game_vertex_id )
packet:w_float( distance )
packet:w_s32( direct_control )
packet:w_s32( level_vertex_id )
packet:w_s32( object_flags )
packet:w_stringZ( custom_data )
packet:w_s32( story_id )
packet:w_s32( spawn_story_id )
packet:w_stringZ( visual_name )
packet:w_u8( visual_flags )
packet:w_stringZ( motion_name )
packet:w_stringZ( skeleton_name )
packet:w_u8( skeleton_flags )
packet:w_u16( source_id )
packet:w_stringZ( startup_animation )
packet:w_stringZ( engine_sound )
packet:r_seek( 2 )
-- пишем STATE часть из нашего нет-пакета в нет-пакет вертолёта
s_obj:STATE_Read( packet, packet:w_tell() )
end
end


Теперь мы хотим увидеть наш вертолёт в игре. Сделаем это для оригинально ЗП.
Создадим в корневой папке игры папку gamedata
В папке gamedata создадим две папки configs и scripts
В папке configs создадим папку scripts, а в ней папку zaton
Из распакованных ресурсов игры возьмём файл xr_effects.script и поместим его в папку gamedata\scripts
В сам файл в самый его конец запишем нашу функцию.
Теперь возьмём файл gamedata\configs\scripts\zaton\zat_a1_logic.ltx из ресурсов игры и поместим его
в нашу папку. Путь тот же gamedata\configs\scripts\zaton\
Откроем файл zat_a1_logic.ltx и вместо строчки
on_info = sr_idle@timer %+zat_a1_game_start%
напишем
on_info = sr_idle@timer %+zat_a1_game_start =create_helicopter(zat_sim_15_spawn_for_a1)%

Мы добавили выполнение нашей функции в логику рестриктора, которая работает при старте игры.
В качестве точки спавна мы использовали точку спавна сталкеров, которые появляются в самом начале
игры и идут навстречу игроку.
Запускаем ЗП, начинаем новую игру и, если сделали всё правильно, то слышим звук вертолёта, а,
пробежав, метров 100 вперёд уже видим его.[/cut]

Добавлено (07.03.2015, 22:31)
---------------------------------------------
Урок №75 (Автор: makdm)
Тема: Вызов различных функций или визуальных эффектов при
использовании бустеров без использования проверок на секцию ( if_then_elseif ).

Написано для платформы Зов Припяти.

[cut=Урок № 75]Задача: сделать, чтобы при использовании предмета срабатывал колбэк, которой жёстко привязан к этому предмету.
В качестве предметов, к которым привяжем колбэк возьмём три аптечки.
Секции аптечек: [medkit], [medkit_army], [medkit_scientic]

В файл bind_stalker.script в метод function actor_binder:use_inventory_item(obj) пишем

xr_s.use_inventory_item( obj:section() ) -- здесь мы вызываем колбэк

Теперь открываем файл xr_s.script и в таблицу callbacks допишем следующее

local callbacks={
update={},
game_load={},
death={},
npc_death={},
monster_death={},
offline_death={},
net_spawn={},
net_destroy={},
info={},
item_drop={},
item_take={},
item_take_from_box={},
hit={},
monster_hit={},
npc_hit={},
enemy_see_actor={},
actor_see_enemy={},
npc_shot_actor={},
respawn={},
use={},
actor_destroy={},
main_menu_on={},
main_menu_off={},
------------------makdm_start
use_inventory_item = {
medkit = {},
medkit_army = {},
medkit_scientic = {}
}

------------------makdm_end
}

Теперь добавляем две функции регистрирующие колбэк и удаляющие колбэк.

function reg_use_inv_item_callback( name, sect, func, userobj )
callbacks[name][sect][func]={userobj=userobj}
end

function unreg_use_inv_item_callback( name, sect, func )
callbacks[name][sect][func]=nil
end


И сама функция, которая обрабатывает колбэк.

function use_inventory_item( section )
if callbacks.use_inventory_item[section] == nil then return end
for func,o in pairs( callbacks.use_inventory_item[section] ) do
func( section, o.userobj )
end
end

Пусть наши функции-колбэки хранятся в файле use_item_callbacks.script
Добавим наш файл в функцию init()
function init()
init_module_if_exists("use_item_callbacks")
end


Теперь переходим к файлу use_item_callbacks.script
В нём пишем функцию регистации колбэка и саму функцию, которая будет выполнена при вызове

function init()
xr_s.reg_use_inv_item_callback( "use_inventory_item", "medkit", medkit, nil )
xr_s.reg_use_inv_item_callback( "use_inventory_item", "medkit_army", medkit_army, nil )
xr_s.reg_use_inv_item_callback( "use_inventory_item", "medkit_scientic", medkit_scientic, nil )
end


function medkit( section )
-- здесь мы обрабатываем событие - использование аптечки
end
function medkit_army( section )
-- здесь мы обрабатываем событие - использование армейской аптечки
end
function medkit_scientic( section )
-- здесь мы обрабатываем событие - использование научной аптечки
end


В этот файл по аналогии можно впихнуть хоть все бустеры в игре и прописать их по аналогии в xr_s.script
в таблицу callbacks, тогда при использовании каждого бустера будет вызываться
функция , которая жёстко привязана к этому предмету.

Всё тоже можно сделать и для on_drop_item и для on_take_item

Как видите никаких проверок по секциям if_then_elseif не проводится. Секция предмета - это название функции,
которая сразу же вызывается при использовании бустера.[/cut]


Терпение......
И все получится!


Сообщение отредактировал makdm - Сб, 07.03.2015, 22:57
 
LazurДата: Ср, 29.04.2015, 20:43 | Сообщение # 57
Новичок
Пользователи
Сообщений: 82
Награды: 3
Репутация: [ 96 ]

Урок №76
Тема: Создание LOD статических объектов (видеоурок).
[cut=Видео]

[/cut]

Добавлено (29.04.2015, 20:43)
---------------------------------------------
Урок №77
Тема: Создание LOD динамических объектов (видеоурок).
[cut=Видео][/cut]


На пыльных тропинках аномальных полей
Заспавнятся наши следы...
 
_SkIf_Дата: Пт, 28.08.2015, 15:29 | Сообщение # 58
Удаленные



Урок №78 (автор _SkIf_ (!SkIF!))
Тема: создаем новую иконку для квеста.
Что нужно: Paint.net, любой текстовый редактор.
[cut=Что делаем]
1. Откроем в Paint.net файл ui_actor_newsmanager_icons.dds, он лежит по пути gamedata\textures\ui
Там видим все иконки заданий и достижений, которые используются в игре
[cut=скрин][/cut]
Под иконкой "Особого заказа" рисуем свою иконку
[cut=скрин][/cut]
Далее выделяем иконку с помощью "выделить прямоугольную область
[cut=скрин][/cut]
И в самом низу будут координаты и размер иконки. Далее сохраняем файл и идем дальше.
2. В файле ui_actor_newsmanager_icons.xml по пути gamedata\configs\ui\textures_descr в самом низу, под <texture id="ui_inGame2_Osobiy_zakaz" x="332" y="799" width="83" height="47" /> , но выше
</file>
</w>

пишем
<texture id="ui_inGame2_Metall_box" x="332" y="846" width="82" height="49" />
Теперь разберем
ui_inGame2_Metall_box - ваше имя иконки, потом его и нужно будет писать в icon квеста.
x="332" y="846" width="83" height="48" - это координаты, которые я взял в красную рамку в Paint.net
3. В файле tm_локация по пути gamedata\configs\misc в секции любого квеста ставим свою иконку, я взял секцию квест на исследование места падения Ската-2
[zat_b100_heli_2_crash]
icon = ui_inGame2_Metall_box - новая иконка
prior = 104
storyline = true
title = zat_b100_heli_2_crash_name
descr = zat_b100_heli_2_crash_text
target = zat_b100_heli_2
condlist_0 = {+zat_b100_heli_2_searched} complete, {+pri_b305_actor_wondered_done} complete

Запускаем игру и смотрим. Удачи в моддинге!
[/cut]

Повторяю второй раз:вставь изображения в виде превью.И изучи пункты правил 4.10, 4.13.наговицын


Сообщение отредактировал _SkIf_ - Пт, 28.08.2015, 22:24
 
asd123Дата: Вс, 30.08.2015, 23:31 | Сообщение # 59
Mr. «Магма»
Военные сталкеры
Сообщений: 1386
Награды: 10
Репутация: [ 423 ]

В дополнении к уроку №31..
Урок №79
Тема: Диалоги | Создание диалога, в котором персонаж, с которым начинаем диалог, будет говорить уникальную фразу(Вроде Полковника Ковальского, который всегда говорит "Слушаю, майор")

Да кстати, прежде чем тыкать на спойлер, ознакомьтесь с уроком №31. Под спойлером вы не увидите ссылки на требуемые файлы, или расположение изменяемых строк. В 31 уроке всё подробно расписанно.
[cut=Тык]Начнем с того, что у нас есть персонаж без привязанных к нему стартовых диалогов(2 start_dialog в профиле нпс карается движковым вылетом). Мы хотим, чтобы при разговоре с ним, стартовой фразой он говорил что-то уникальное, вместо генерирующихся фраз. Рассмотрим пример от мною созданного персонажа:
Код
<dialog id="capitol_leader_hello">                             
                        <phrase_list>
                            <phrase id="0">
                      <text></text>
                      <next>1</next>                      
                            </phrase>
                            <phrase id="1">
                      <text></text>
                      <next>2</next>
                            </phrase>
                            <phrase id="2">
                     <text>cap_leader_dialog_1</text>
                            </phrase>
                        </phrase_list>
</dialog>

Итак. Как мы видим, первая кость нашего диалога не имеет текста, как и вторая. Почему? Так устроен движок, и мы не в силах изменять его правила построения диалогов. Дальше идёт 3 кость нашего диалога, и уже в ней есть наша реплика. Реплику придумывайте какую хотите, но самое главное, что она будет появляться всегда(если, конечно же, у Вашего персонажа нет actor_dialog, в котором первым говорит нпс). Продолжаем. Мы создали, и сохранили наш диалог. Что же дальше? Этот диалог у нас является стартовым, который нам скажет персонаж, с которым мы будем говорить. Собственно, из-за этого нам придётся в профиле созданного НПС, добавить две строки:
Код
                   <start_dialog>capitol_leader_hello</start_dialog> -- Сам диалог, который мы добавили.
                        <actor_dialog>actor_break_dialog</actor_dialog> -- Блокировка рандомных фраз

Вот и всё. Заходим в игру и проверяем результат. :)

Напоминаю, что данный урок происходит для бездиалогового персонажа! Есть куча персонажей, у которых actor_dialog начинается с разговора не ГГ, а НПС. В этом случае, созданная нами фраза будет игнорироваться движком до тех пор, пока есть actor_dialog(Ну, или его часть. В зависимости от разветвления данного диалога), заставляющий говорить первым НПС.

p.s создал дополнение к уроку, потому как изначально сам не понимал что как работает. Наелся движковых вылетов побольше, чем борща за все 16 лет :D
[/cut]


У мутантов тоже есть группировки. © Движок X-Ray




Сообщение отредактировал asd123 - Ср, 13.07.2016, 21:35
 
sergej5500Дата: Вт, 14.06.2016, 22:26 | Сообщение # 60
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
Награды: 29
Репутация: [ 1355 ]

Урок 80. Создание зарядов взрывчатки в стиле СГМ.

В СГМ имеются дистанционные заряды, которые можно устанавливать в разных местах. Затем подрывать с помощью пульта. У меня возникло желание сделать подобное в чистом Зове Припяти. Полного подобия добиться не удалось. Но результат оказался не хуже.

Необходимо уметь распаковывать ресурсы Зова Припяти.

Будем создавать закладываемый заряд взрывчатки с возможностью установки таймера задержки взрыва от 1 до 10 секунд. С возможностью подрыва 3-х зарядов с одного пульта.

[cut=Конфиги]1. Открываем файл gamedata\configs\gameplay\character_desc_general. Прописываем ГГ в стартовый набор 4 заряда - remote_explosive_charge. После начала новой игры они окажутся в рюкзаке игрока. Добавляем в секции actor (она первая в этом файле) под строкой conserva = 2 \n строку remote_explosive_charge = 4 \n. Сохраняем файл.

2. Откроем файл gamedata\configs\misc\devices. Добавляем в него в конец файла следующие секции.

[remote_explosive_box_1]:inventory_box
$spawn = "devices\remote_explosive_box_1"
visual = dynamics\box\expl_dinamit.ogf
custom_data = scripts\remote_explosive_box_1.ltx
story_id = remote_explosive_box_1

[remote_explosive_box_2]:remote_explosive_box_1
$spawn = "devices\remote_explosive_box_2"
custom_data = scripts\remote_explosive_box_2.ltx
story_id = remote_explosive_box_2

[remote_explosive_box_3]:remote_explosive_box_1
$spawn = "devices\remote_explosive_box_3"
custom_data = scripts\remote_explosive_box_3.ltx
story_id = remote_explosive_box_3

Это основа зарядов. Обьекты класса inventory_box. Почему я взял их за основу? Их можно спавнить в ходе игры. И им можно задать определённую логику.

Так же добавим в файл такие секции.

[remote_explosive_bomb_1]:explosive_grenade
$spawn = "devices\remote_explosive_bomb_1"
story_id = remote_explosive_bomb_1
visual = dynamics\box\expl_dinamit.ogf
explode_particles = explosions\explosion_barrel
blast = 5.0 ; Сила ударной волны
blast_r = 25.0 ; Радиус ударной волны
frags = 30 ; Кол-во осколков
frags_r = 30.0; Радиус разлёта осколков
frag_hit = 1.5; Убойность осколка

[remote_explosive_bomb_2]:remote_explosive_bomb_1
$spawn = "devices\remote_explosive_bomb_2"
story_id = remote_explosive_bomb_2

[remote_explosive_bomb_3]:remote_explosive_bomb_1
$spawn = "devices\remote_explosive_bomb_3"
story_id = remote_explosive_bomb_3

Это сами заряды. То, что будет взрываться.

Сохраняем и закрываем файл.

3. Откроем файл gamedata\configs\misc\items. Добавим в него в конец файла предметы, которыми будет оперировать игрок - бустеры.

; Заряд, покупаемый у торговца.
[remote_explosive_charge]:booster
$spawn = "devices\remote_explosive_charge"
visual = dynamics\box\expl_dinamit.ogf
inv_name = st_remote_explosive_charge
inv_name_short = st_remote_explosive_charge
description = st_remote_explosive_charge_descr
inv_weight = 3.0
inv_grid_width = 2
inv_grid_height = 2
inv_grid_x = 14
inv_grid_y = 23
cost = 20000

; Пульт для подрыва.
[remote_explosive_pda]:booster
$spawn = "devices\remote_explosive_pda"
visual = dynamics\devices\dev_decoder\dev_decoder.ogf
inv_name = st_remote_explosive_pda
inv_name_short = st_remote_explosive_pda
description = st_remote_explosive_pda_descr
inv_weight = 0.3
inv_grid_width = 1
inv_grid_height = 1
inv_grid_x = 15
inv_grid_y = 8
cost = 20
can_trade = false
quest_item = true

Пульт является квестовым предметом. Его нельзя продать или выкинуть из инвентаря.

Не буду останавливаться на прописывании зарядов в торговлю или настройке интерфейсных иконок для заряда и пульта. На эту тему есть другие уроки. В приложенной к уроку геймдате иконки настроены.

Сохраняем файл.

4. Откроем файл gamedata\configs\text\rus\st_items_equipment. Добавим в него текстовые описания бустеров.

<string id="st_remote_explosive_charge">
<text>Заряд РС-15 с блок-детонатором</text>
</string>
<string id="st_remote_explosive_charge_descr">
<text>Подрывной заряд. Идет в комплекте с пультом управления. Для установки заряда его необходимо использовать. После установки заряда необходимо установить таймер взрывателя. Задержку взрыва можно выставить в диапазоне от одной до десяти секунд.</text>
</string>
<string id="st_remote_explosive_pda">
<text>Пульт управления зарядом РС-15</text>
</string>
<string id="st_remote_explosive_pda_descr">
<text>Для детонации установленных зарядов РС-15 пульт необходимо использовать. Для надёжного срабатывания установленных зарядов они должны нахлдиться не далее 150 метров от игрока.</text>
</string>

Сохраняем файл.

5. Откроем файлы gamedata\configs\ui\map_spots и map_spots_16. Находим в них секцию

<treasure hint="st_ui_pda_secret">
<level_map spot="treasure_spot" pointer="quest_pointer"/>
<mini_map spot="treasure_spot_mini"/>
</treasure>
<treasure_spot width="20" height="20" alignment="c" stretch="1">
<texture>ui_inGame2_PDA_icon_secret</texture>
</treasure_spot>
<treasure_spot_mini width="17" height="17" alignment="c" stretch="1">
<texture>ui_inGame2_PDA_icon_secret</texture>
</treasure_spot_mini>

Добавляем под неё в оба файла секцию

<explosive hint="st_ui_pda_explosive">
<level_map spot="explosive_spot" pointer="quest_pointer"/>
<mini_map spot="explosive_spot_mini"/>
</explosive>
<explosive_spot width="20" height="20" alignment="c" stretch="1">
<texture>ui_inGame2_PDA_icon_explosive</texture>
</explosive_spot>
<explosive_spot_mini width="17" height="17" alignment="c" stretch="1">
<texture>ui_inGame2_PDA_icon_explosive</texture>
</explosive_spot_mini>

Эта секция отвечает за иконку заряда на мини карте.

Сохраняем файлы.

6. Откроем файл gamedata\configs\ui\textures_descr\ui_actor_pda_icons. Под строкой

<texture id="ui_inGame2_PDA_icon_secret" x="52" y="563" width="25" height="25" />

добавим строку

<texture id="ui_inGame2_PDA_icon_explosive" x="52" y="563" width="25" height="25" />

Мы зарегистрировали текстуру метки заряда на карте. И задали её вид. Метка заряда аналогична метке тайника. Если вы умеете править dds файлы, то можете открыть файл gamedata\textures\ui\ui_actor_hint_wnd и выбрать другой значок для метки тайника. Или добавить свой собственнцй значок. В приложенной к уроку геймдате это сделано. На редактировании dds файлов я останавливаться не буду.

Сохраняем файл.

7. Откроем файл gamedata\configs\text\rus\ui_st_pda. Добавим в него метку заряда

<string id="st_ui_pda_explosive">
<text>Заряд РС-15</text>
</string>

Сохраняем файл.

8. Откроем файл gamedata\configs\text\rus\ui_st_screen. Добавим в него служебные сообщения, которые будут выдаваться при работе с зарядами.

<string id="st_remote_explosive_no_use">
<text>Один пульт поддерживает только три заряда.</text>
</string>
<string id="st_remote_explosive_install">
<text>Заряд РС-15 успешно установлен. Выставьте таймер взрывателя.</text>
</string>
<string id="st_remote_explosive_detonator">
<text>Таймер взрывателя РС-15 активирован.</text>
</string>
<string id="st_remote_explosive_pda_init">
<text>На заряды РС-15 отправлен сигнал подрыва.</text>
</string>
<string id="st_explosive_remote_code">
<text>Выставить таймер заряда ($$ACTION_USE$$)</text>
</string>

Сохраняем файл.

9. Откроем файл gamedata\configs\ui\game_tutorials. Добавим в него туториал, который будет выдан при попытке заложить четвертый заряд. Секция.

<remote_explosive_no_use>
<global_wnd/>

<item>
<length_sec>9</length_sec>
<pause_state>off</pause_state>
<guard_key/>
<sound>device\pda\pda_news</sound>
<cursor_pos/>
<pda_section/>
<grab_input>0</grab_input>
<main_wnd>
<auto_static start_time="0" length_sec="8000" x="10" y="275" width="400" height="150" alignment="l" stretch="1" light_anim="" la_cyclic="1" la_texture="1" la_alpha="1">
<window_name>w1</window_name>
<text font="graffiti22" r="225" g="225" b="250" a="255">st_remote_explosive_no_use</text>
</auto_static>
</main_wnd>
</item>
</remote_explosive_no_use>

Сохраняем файл.

10. В папке gamedata\configs\scripts создаем три файла с именами remote_explosive_box_1.ltx, remote_explosive_box_2.ltx и remote_explosive_box_3.ltx.

В файл remote_explosive_box_1.ltx прописываем логику заряда.

Логика:

[logic]
active = ph_code

[ph_idle]
nonscript_usable = false

[ph_code]
tips = st_explosive_remote_code
on_info = {+remote_explosive_pda_init} nil %=remote_explosive_box_1_activate%

on_check_code1 = 1 | %+remote_1_1_explosive =send_tip(st_remote_explosive_detonator:got_ammo)%
on_info1 = {+remote_1_1_explosive} ph_idle@1

on_check_code2 = 2 | %+remote_1_2_explosive =send_tip(st_remote_explosive_detonator:got_ammo)%
on_info2 = {+remote_1_2_explosive} ph_idle@2

on_check_code3 = 3 | %+remote_1_3_explosive =send_tip(st_remote_explosive_detonator:got_ammo)%
on_info3 = {+remote_1_3_explosive} ph_idle@3

on_check_code4 = 4 | %+remote_1_4_explosive =send_tip(st_remote_explosive_detonator:got_ammo)%
on_info4 = {+remote_1_4_explosive} ph_idle@4

on_check_code5 = 5 | %+remote_1_5_explosive =send_tip(st_remote_explosive_detonator:got_ammo)%
on_info5 = {+remote_1_5_explosive} ph_idle@5

on_check_code6 = 6 | %+remote_1_6_explosive =send_tip(st_remote_explosive_detonator:got_ammo)%
on_info6 = {+remote_1_6_explosive} ph_idle@6

on_check_code7 = 7 | %+remote_1_7_explosive =send_tip(st_remote_explosive_detonator:got_ammo)%
on_info7 = {+remote_1_7_explosive} ph_idle@7

on_check_code8 = 8 | %+remote_1_8_explosive =send_tip(st_remote_explosive_detonator:got_ammo)%
on_info8 = {+remote_1_8_explosive} ph_idle@8

on_check_code9 = 9 | %+remote_1_9_explosive =send_tip(st_remote_explosive_detonator:got_ammo)%
on_info9 = {+remote_1_9_explosive} ph_idle@9

on_check_code10 = 10 | %+remote_1_10_explosive =send_tip(st_remote_explosive_detonator:got_ammo)%
on_info10 = {+remote_1_10_explosive} ph_idle@10

[ph_idle@1]:ph_idle
on_info = {+remote_explosive_pda_init} ph_idle@1t

[ph_idle@1t]:ph_idle
on_game_timer = 10 | nil %=remote_explosive_box_1_activate%

[ph_idle@2]:ph_idle
on_info = {+remote_explosive_pda_init} ph_idle@2t

[ph_idle@2t]:ph_idle
on_game_timer = 20 | nil %=remote_explosive_box_1_activate%

[ph_idle@3]:ph_idle
on_info = {+remote_explosive_pda_init} ph_idle@3t

[ph_idle@3t]:ph_idle
on_game_timer = 30 | nil %=remote_explosive_box_1_activate%

[ph_idle@4]:ph_idle
on_info = {+remote_explosive_pda_init} ph_idle@4t

[ph_idle@4t]:ph_idle
on_game_timer = 40 | nil %=remote_explosive_box_1_activate%

[ph_idle@5]:ph_idle
on_info = {+remote_explosive_pda_init} ph_idle@5t

[ph_idle@5t]:ph_idle
on_game_timer = 50 | nil %=remote_explosive_box_1_activate%

[ph_idle@6]:ph_idle
on_info = {+remote_explosive_pda_init} ph_idle@6t

[ph_idle@6t]:ph_idle
on_game_timer = 60 | nil %=remote_explosive_box_1_activate%

[ph_idle@7]:ph_idle
on_info = {+remote_explosive_pda_init} ph_idle@7t

[ph_idle@7t]:ph_idle
on_game_timer = 70 | nil %=remote_explosive_box_1_activate%

[ph_idle@8]:ph_idle
on_info = {+remote_explosive_pda_init} ph_idle@8t

[ph_idle@8t]:ph_idle
on_game_timer = 80 | nil %=remote_explosive_box_1_activate%

[ph_idle@9]:ph_idle
on_info = {+remote_explosive_pda_init} ph_idle@9t

[ph_idle@9t]:ph_idle
on_game_timer = 90 | nil %=remote_explosive_box_1_activate%

[ph_idle@10]:ph_idle
on_info = {+remote_explosive_pda_init} ph_idle@10t

[ph_idle@10t]:ph_idle
on_game_timer = 100 | nil %=remote_explosive_box_1_activate%

В секциях

on_check_code1 = 1 | %+remote_1_1_explosive =send_tip(st_remote_explosive_detonator:got_ammo)%
on_info1 = {+remote_1_1_explosive} ph_idle@1

on_check_code2 = 2 | %+remote_1_2_explosive =send_tip(st_remote_explosive_detonator:got_ammo)%
on_info2 = {+remote_1_2_explosive} ph_idle@2

и так далее мы выбираем время задержки подрыва заряда. При попытке юзания заряда появится кодовое окно, в котором мы выберем число от 1 до 10. Время задержки взрыва в секундах. Если таймер не установлен, то взрыв произойдёт немедленно после команды на подрыв.

Секции

[ph_idle@1]:ph_idle
on_info = {+remote_explosive_pda_init} ph_idle@1t

[ph_idle@1t]:ph_idle
on_game_timer = 10 | nil %=remote_explosive_box_1_activate%

и так далее отсчитывают время до подрыва заряда. И производят сам подрыв.

В файлах remote_explosive_box_2.ltx и remote_explosive_box_3.ltx прописываем однотипную логику. Меняем функцию подрыва remote_explosive_box_1_activate на remote_explosive_box_2_activate и remote_explosive_box_3_activate соответственно.

Инфопорции таймеров remote_1_1_explosive, remote_1_2_explosive, remote_1_3_explosive и т.д. меняем на remote_2_1_explosive, remote_2_2_explosive, remote_2_3_explosive и т.д. для файла remote_explosive_box_2.ltx и remote_3_1_explosive, remote_3_2_explosive, remote_3_3_explosive и т.д. для файла remote_explosive_box_3.ltx.

Сохраняем файлы.[/cut]

[cut=Скрипты]1. Открываем файл gamedata\scrips\_g.script. Добавим в него следующие функции.

-- 'Удаление нескольких инфопортаций по возрастающим номерам.
function disable_several_info(l_part,r_part,count_a,count_b)
if count_b==nil then
count_b=count_a
count_a=1
end
for i=count_a,count_b do
disable_info(l_part..i..r_part)
end
end

-- 'Удалить все обьекты с указанной секцией.
function release_objects_by_section(find_string)
for a=1,65534 do
local obj = alife():object(a)
if obj then
if obj:section_name()~=nil and string.find(obj:section_name(),find_string) then
local sect=obj:section_name()
remove_object_by_id(obj.id)
end
end
end
end

-- 'Удалить все обьекты с указанным именем.
function release_objects_by_name(find_string)
for a=1,65534 do
local obj = alife():object(a)
if obj then
if obj:name()~=nil and string.find(obj:name(),find_string) then
local sect=obj:name()
remove_object_by_id(obj.id)
end
end
end
end

-- 'Удаление обьекта по его ID.
function remove_object_by_id(item_id)
if item_id~=nil and alife():object(item_id) then
alife():release(alife():object(item_id),true)
end
end

-- 'Закрыть инвентарь/КПК.
function game_hide_menu(type)
if type==1 then
get_hud():HideActorMenu()
elseif type==2 then
get_hud():HidePdaMenu()
else
get_hud():HideActorMenu()
get_hud():HidePdaMenu()
end
end

-- 'Создание предмета в рюкзаке ГГ.
function give_object_to_actor(section,count)
if count==nil then count=1 end
for i=1, count do
alife():create(section,db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),db.actor:id())
end
end

Сохраняем файл.

2. Открываем файл gamedata\scrips\bind_stalker. Находим функцию

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
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
if(s_obj) and s_obj:section_name()=="remote_explosive_charge" then
addon_callbacks.remote_explosive_charge_init()
end
if(s_obj) and s_obj:section_name()=="remote_explosive_pda" then
addon_callbacks.remote_explosive_pda_init()
end
end
end

Сохраняем файл.

3. Создаем в папке gamedata\scrips пустой файл addon_callbacks.script. Добавим в него наши функции.

function remote_explosive_charge_init()
local actor = db.actor
if has_alife_info("remote_explosive_pda_init") then
release_objects_by_section("remote_explosive_box_")
release_objects_by_section("remote_explosive_bomb_")
if has_alife_info("remote_explosive_1_install") then disable_info("remote_explosive_1_install") end
if has_alife_info("remote_explosive_2_install") then disable_info("remote_explosive_2_install") end
if has_alife_info("remote_explosive_3_install") then disable_info("remote_explosive_3_install") end
disable_info("remote_explosive_pda_init")
end
if db.actor:object("remote_explosive_pda") == nil then
give_object_to_actor("remote_explosive_pda")
end
if not has_alife_info("remote_explosive_1_install") then
disable_several_info("remote_1_","_explosive",1,10)
local sobj=alife():create("remote_explosive_box_1",actor:position(),actor:level_vertex_id(),actor:game_vertex_id())
give_info("remote_explosive_1_install")
level.map_add_object_spot_ser(sobj.id,"explosive","")
xr_effects.send_tip(db.actor,nil,{"st_remote_explosive_install","got_ammo"})
elseif not has_alife_info("remote_explosive_2_install") and has_alife_info("remote_explosive_1_install") then
disable_several_info("remote_2_","_explosive",1,10)
local sobj=alife():create("remote_explosive_box_2",actor:position(),actor:level_vertex_id(),actor:game_vertex_id())
give_info("remote_explosive_2_install")
level.map_add_object_spot_ser(sobj.id,"explosive","")
xr_effects.send_tip(db.actor,nil,{"st_remote_explosive_install","got_ammo"})
elseif not has_alife_info("remote_explosive_3_install") and has_alife_info("remote_explosive_2_install") then
disable_several_info("remote_3_","_explosive",1,10)
local sobj=alife():create("remote_explosive_box_3",actor:position(),actor:level_vertex_id(),actor:game_vertex_id())
give_info("remote_explosive_3_install")
level.map_add_object_spot_ser(sobj.id,"explosive","")
xr_effects.send_tip(db.actor,nil,{"st_remote_explosive_install","got_ammo"})
else
game.start_tutorial("remote_explosive_no_use")
give_object_to_actor("remote_explosive_charge")
end
game_hide_menu()
end

--Данная функция выполняет следующие задачи:

--Проверка наличия инфопорции подрыва - remote_explosive_pda_init. Если инфопорция имеется - (после предыдущего подрыва новых зарядов не ставили) - то локации проверяются на наличии установленных и не сработавших зарядов и бомб. Все несработавшие объекты удаляются. Инфопорции сбрасываются.

--Проверка наличия у игрока пульта для подрыва. Выдача пульта, если его нет.

--Проверка на кол-во установленных зарядов. Установка зарядов в определенном порядке. 1, 2 и 3. Установка меток на карте. Выдача служебных сообщений. Сброс инфопорций таймеров от предыдущих зарядов. Отказ в установке 4 заряда.

function remote_explosive_pda_init()
give_info("remote_explosive_pda_init")
xr_effects.send_tip(db.actor,nil,{"st_remote_explosive_pda_init","got_ammo"})
game_hide_menu()
end

--Эта функция посылает служебное сообщение и выдает инфопорцию на подрыв.

Сохраняем файл.

4. Открываем файл gamedata\scrips\ph_code.

Находим функцию.

function codepad:update(delta)
end

Добавляем в неё возможность перехода на другой тип логики. Это нужно для нормальной работы зарядов. Так.

function codepad:update(delta)
if xr_logic.try_switch_to_another_section(self.object, self.st, db.actor) then
return
end
end

Сохраняем файл.

5. Открываем файл gamedata\scrips\xr_effects. Добавим в неё исполняемые функции.

function remote_explosive_box_1_activate(actor,obj)
alife():create("remote_explosive_bomb_1",vector():set(obj:position()),obj:level_vertex_id(),obj:game_vertex_id())
level.add_call(
function()
if get_story_object("remote_explosive_bomb_1") ~= nil then
return true
end
end,
function()
expl_obj = get_story_object("remote_explosive_bomb_1")
expl_obj:explode(0)
end
)
if xr_conditions.object_exist(nil,nil,{"remote_explosive_box_1"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_box_1"})
end
if xr_conditions.object_exist(nil,nil,{"remote_explosive_bomb_1"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_bomb_1"})
end
end

function remote_explosive_box_2_activate(actor,obj)
alife():create("remote_explosive_bomb_2",vector():set(obj:position()),obj:level_vertex_id(),obj:game_vertex_id())
level.add_call(
function()
if get_story_object("remote_explosive_bomb_2") ~= nil then
return true
end
end,
function()
expl_obj = get_story_object("remote_explosive_bomb_2")
expl_obj:explode(0)
end
)
if xr_conditions.object_exist(nil,nil,{"remote_explosive_box_2"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_box_2"})
end
if xr_conditions.object_exist(nil,nil,{"remote_explosive_bomb_2"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_bomb_2"})
end
end

function remote_explosive_box_3_activate(actor,obj)
alife():create("remote_explosive_bomb_3",vector():set(obj:position()),obj:level_vertex_id(),obj:game_vertex_id())
level.add_call(
function()
if get_story_object("remote_explosive_bomb_3") ~= nil then
return true
end
end,
function()
expl_obj = get_story_object("remote_explosive_bomb_3")
expl_obj:explode(0)
end
)
if xr_conditions.object_exist(nil,nil,{"remote_explosive_box_3"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_box_3"})
end
if xr_conditions.object_exist(nil,nil,{"remote_explosive_bomb_3"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_bomb_3"})
end
end

Эти функции выполняют основную задачу - производят подрыв зарядов.

Сохраняем файл. [/cut]

Начинаем новую игру и опробуем заряды.

Выполненное задание

Хочу выразить огромную благодарность автору SGM Gelorge за идею зарядов и скриптовые функции. Так же хочу поблагодарить denisa2000 и makdm за помощь в составлении скриптов.


Сообщение отредактировал sergej5500 - Вт, 14.06.2016, 22:43
 
Форум » Моды для игр » Модостроение » Курс молодого бойца - КМБ. Уроки для начинающих
  • Страница 4 из 5
  • «
  • 1
  • 2
  • 3
  • 4
  • 5
  • »
Поиск: