Модостроение. Спавн и логика
|
|
denis2000 | Дата: Пн, 10.10.2011, 21:20 | Сообщение # 1 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| Спавн и логика Создание объектов на локации и логика поведения этих объектов Если у вас появились вопросы по созданию динамических объектов в игре (НПС, монстры, аномалии, и т.п.) и настройке их "поведения". Задавайте их в этой теме - умные головы, модосторители и просто разбирающиеся в программировании люди вам ответят.
Много интересного материала здесь (wiki), Lua_help.script, Help из SDK 0.7
Сборник модостроения ЗП v10.10.11 (автор: XOBAH): *.CHM, *.HTML [cut noguest=Если у вас не открывается файл CHM]Если у вас не открывается файл: 1. Запустите [Пуск]=>[Выполнить] (либо хот-кей [WIN]+[R]) 2. Введите команду (без кавычек) "regsvr32 %windir%\system32\hhctrl.ocx" 3. Если вылезло окно об успешном завершении вы все сделали правильно и можете перезагружать компьютер (а может и не надо) Также: файлы МОГУТ не открываться если в пути к файлу есть: символы кириллицы, "_", "#" Также: есть не стандартные программы-просмоторщики CHM файлов. Например: FBReader[/cut]
[cut=Где найти лог игры после вылета]Что такое LOG ошибки, и как мне его найти? Это система отладки происходивших вылетов, которая подается игрой в форме текста, хотя не всегда. Для того чтоб найти LOG необходимо зайти вот сюда:
В Win хр лог находится:
C:\Documents and Settings\All Users\Документы\S.T.A.L.K.E.R. - Зов Припяти\logs
Затем открываете первый файл в формате TXT, и в нем отбираете с низу 25 строчек. После кидаете эти 25 строчек в сообщение на форум.
В Win7 лог находится C:\Users\Public\Documents\S.T.A.L.K.E.R. - Зов Припяти\logs
Путь к папке с логом можно найти открыв файл fsgame.ltx который находится в корневой директории ЗП, за это отвечает строка: ... $app_data_root$ = true | false| $fs_root$| users\(тут мы указываем что папка пользователя, будет хранится рядом с Fsgame.ltx) ... $logs$ = true| false| $app_data_root$| logs\(а тут мы указываем что в папке пользователя, в подпапке Logs будут храниться наши логи) ... [/cut][cut=Получение более подробной информации о вылете (ХОВАН)] Открываем файл _g.script и ищем такую функцию: function abort(fmt, ...) Там есть заккомментированная строчка "--error_log(reason)", ее и надо расскомментировать, должно получиться вот так: Code function abort(fmt, ...) local reason = string.format(fmt, ...) error_log(reason) end Вот для примера два одинаковых вылета, первый с функцией по умолчанию, второй - с поправленной функцией
Первый: Code Expression : !m_error_code Function : raii_guard::~raii_guard File : D:\prog_repository\sources\trunk\xrServerEntities\script_storage.cpp Line : 748 Description : ....a.l.k.e.r. - Зов Припяти\gamedata\scripts\_g.script:478: bad argument #2 to 'format' (string expected, got nil) Второй: Code Expression : 0 Function : ErrorLog File : D:\prog_repository\sources\trunk\xrServerEntities\script_engine_script.cpp Line : 49 Description : 'Attempt to read a non-existant string field 'path_walk' in section 'walker@mechanic' [/cut]
Перед тем, как задать вопрос в этой теме, прочтите все предыдущие страницы, статьи в wiki по ссылке из шапки и соседнюю тему "Курс молодого бойца", возможно Ваш вопрос уже рассматривался.
Если произошел вылет - выкладываем лог! Вопрос ставим четко, не забываем указывать версию игры, установленные моды их версии, установленные фиксы модов и подробно ваши правки. Помните чем подробнее вопрос, тем точнее ответ.
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
FantomICW | Дата: Вс, 27.10.2013, 20:12 | Сообщение # 676 |
Лидер «Свободы»
Свобода
Сообщений: 4438
| Добрый вечер! Хотел бы задать один вопрос по логике рестриктора. Нужно чтобы во время кат-сцены (схема sr_cutscene) вместо музыки-абмиента играл другой конкретный трек, при этом дополнительные звуки, вызываемые в этом же рестриктором через play_sound должны также работать. Как можно подобную вещь реализовать?
|
|
|
Эти 0 пользователя(ей) поблагодарили FantomICW за это полезное сообщение: |
|
|
denis2000 | Дата: Пн, 28.10.2013, 11:36 | Сообщение # 677 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| FantomICW, Временно убрать амбиентные звуки (или музыку) вроде нельзя, можно только "перекричать", т.е. воспроизвести нужные звуки с гораздо большим уровнем. play_sound и play_sound_looped прекрасно работают, но помни один объект - один звук, нет возможности одному объекту воспроизводить несколько звуков одновременно.
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
makdm | Дата: Пн, 28.10.2013, 11:58 | Сообщение # 678 |
Рожденный в СССР
Разработчики
Сообщений: 1294
| FantomICW, вопрос больше относится к скриптованию. Делаем вот так.
[cut noguest]Открываем файл sr_cutscene.script
1. В фнукцию set_scheme дописываем наш звук, который будет воспроизводиться вместо Ambient
st.sound = utils.cfg_get_string( ini, section, "sound", obj, false, "")
2. Работаем с классом - class "action_cutscene" На методе __init(obj, storage) прописываем флаг проигрыша звука, а также считываем текущий уровень звука амбиента
self.sound = false self.snd_volume = level.get_snd_volume()
3. Переходим на метод update Здесь проверяем нужно ли убрать амбиент и отыграть наш звук, если да, то считываем параметр звука из ltx файла загружаем его в левый и правый канал Выставляем флаг, что звук загружен, а также отключаем Амбиент
if self.st.sound and self.sound == false then local snd_ini = ini_file("misc\\script_sound.ltx") self.path = snd_ini:r_string(self.st.sound,"path") self.sound_obj_right, self.sound_obj_left = sound_object(self.path), sound_object(self.path) local ambient_vol = 0 get_console():execute("snd_volume_music "..ambient_vol) self.sound_obj_left:play_at_pos (db.actor, vector():set(-1, 0, 1), 0, sound_object.s2d) self.sound_obj_right:play_at_pos (db.actor, vector():set( 1, 0, 1), 0, sound_object.s2d) self.sound = true end
4. Так как после сцены нужно восстановить амбиент и отключить звук, то добавляем ещё один метод deactivate(delta)
function action_cutscene:deactivate(delta) if self.sound == true then self.sound_obj_right:stop() self.sound_obj_left:stop() local ambient_vol = self.snd_volume get_console():execute("snd_volume_music "..ambient_vol) end end
5. В логику sr_cutscene вписываем наш звук sound = секция_звука
6. Сам звук прописываем в script_sound.ltx примерно так или по другому но без rnd
[Секция_звука] type = actor actor_stereo = false npc_prefix = false path = characters_voice\scenario\имя_файла_звука shuffle = seq idle = 1,1,100
Причем play_sound будет работать, так как он использует другую схему воспроизведения звука и звуки не перекрывают друг друга.[/cut]
Терпение...... И все получится!
Сообщение отредактировал makdm - Пн, 28.10.2013, 11:59 |
|
|
Эти 0 пользователя(ей) поблагодарили makdm за это полезное сообщение: |
|
|
sergej5500 | Дата: Пт, 08.11.2013, 00:58 | Сообщение # 679 |
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
| Добрый вечер. Можно ли решить такую задачу? Есть несколько несквадовых НПС со стори ид: jup_a9_stalker1, jup_a9_stalker2 и т.д. У каждого свой файл логики. Есть сквады НПС со стори ид: jup_a9_alfa_squad1,jup_a9_alfa_squad2 и т.д. Несквадовые НПС относятся к группировке сталкер алиес, сквады к группировке альфа. Группировки взаимно нейтральны друг к другу. Нужно поссорить их друг с другом после выдачи определенной инфопорции. Сталкеры выступят с одной стороны, альфа с другой. Можно ли это сделать и как? Правку отношений группировок делать нежелательно. Нужно, чтобы конкретные сталкеры поссорились с конкретной альфой. Заранее благодарен за советы.
|
|
|
Эти 0 пользователя(ей) поблагодарили sergej5500 за это полезное сообщение: |
|
|
makdm | Дата: Пт, 08.11.2013, 11:04 | Сообщение # 680 |
Рожденный в СССР
Разработчики
Сообщений: 1294
| sergej5500, в файле xr_effects.script есть готовая функция, которая вызывается из логики НПС и ссорит его с конкретным сквадом.
set_squad_goodwill_to_npc
Срабатывание по поршню выглядит примерно так
on_info = {+поршень_смены_отношений -поршень} %+поршень =set_squad_goodwill_to_npc(jup_a9_alfa_squad1:enemy)%
Терпение...... И все получится!
|
|
|
Эти 0 пользователя(ей) поблагодарили makdm за это полезное сообщение: |
|
|
sergej5500 | Дата: Пт, 08.11.2013, 11:34 | Сообщение # 681 |
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
| makdm, Спасибо за совет. Ещё один вопрос. Можно ли поссорить конкретный сквад с конкретным НПС? По Вашей формуле НПС ссорится со сквадом. Хотелось бы поссорить их взаимно и одновременно.
|
|
|
Эти 0 пользователя(ей) поблагодарили sergej5500 за это полезное сообщение: |
|
|
makdm | Дата: Пт, 08.11.2013, 12:09 | Сообщение # 682 |
Рожденный в СССР
Разработчики
Сообщений: 1294
| sergej5500, эта функция именно это и делает. Ссорит одновременно и НПС со сквадом и всех членов сквада с НПС.
Терпение...... И все получится!
|
|
|
Эти 0 пользователя(ей) поблагодарили makdm за это полезное сообщение: |
|
|
sergej5500 | Дата: Вс, 10.11.2013, 10:49 | Сообщение # 683 |
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
| Добрый День. Интересует такой момент. В теме "Идеи и предложения для СГМ" неоднократно предлагались идеи квестов по "тихому" устранению враждебных НПС на вражеской базе. Поэтому есть вопросы. Есть ли возможность отследить, от какого оружия получен хит? Выделяются ли отдельно хиты от ножа и оружия с глушителем? Можно ли в логике НПС прописать что-то типа: если НПС завалили с ножа, то всё спокойно, если с СВД, то вся база нападёт на ГГ?
|
|
|
Эти 0 пользователя(ей) поблагодарили sergej5500 за это полезное сообщение: |
|
|
denis2000 | Дата: Ср, 13.11.2013, 16:33 | Сообщение # 684 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| sergej5500, Косвенным путем определить оружие из которого завалил НПС ГГ можно: в колбеке на хит НПС определять если хит нанес ГГ, то считать активный слот и соответственно активное оружие - если это слот ножа, то оружие соответственно нож. Тихая миссия с ножа на базе есть в моде "Время Альянса", там реализация очень хорошая (естественно в пределах возможностей движка)
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
makdm | Дата: Ср, 13.11.2013, 17:16 | Сообщение # 685 |
Рожденный в СССР
Разработчики
Сообщений: 1294
| sergej5500, без лишней скромности, дополню ответ Дениса, что схема, когда отслеживается выстрел из оружия с глушителем или без него , также реализована в аддоне "Время Альянса". В случае выстрела без глушака поднимается тревога. Всё можно посмотреть, скачав аддон " Время Альянса". Схема с глушителем в файле xr_conditions.script Функция wpn_has_silencer
Терпение...... И все получится!
Сообщение отредактировал makdm - Ср, 13.11.2013, 17:20 |
|
|
Эти 0 пользователя(ей) поблагодарили makdm за это полезное сообщение: |
|
|
sergej5500 | Дата: Пн, 18.11.2013, 20:14 | Сообщение # 686 |
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
| Добрый вечер. Я сделал квестовый сейф, для открытия которого нужны три ключа. №1, №2 и №3. При тестировании обнаружил следующее. 1. Если ГГ пытается открыть сейф за три попытки, используя каждый раз один ключ, то все нормально. Порядок использования ключей любой. Все работает. 2. Если игрок пытается открыть сейф за две попытки, имея первый раз один ключ, второй раз два оставшихся ключа, то все нормально. Порядок использования ключей любой. Все работает. 3. Если игрок имеет сразу три ключа, то все нормально. 4. Если игрок имеет в первый заход ключи №1 и №2, то процесс зависает. Висит надпись "Использовать ключи", но действия нет. Если у игрока в первый заход ключи №1 и №3, или №2 и №3, то процесс срабатывает. При втором заходе с третьим ключом в этих случаях сейф открывается.
[cut=Логика сейфа][logic] active = ph_idle@zapert
[ph_idle@zapert] nonscript_usable = false tips = rasvet_addon_inventory_box_zapert on_info = {=actor_has_item(way_jup_pripyat_box_key_1)} ph_idle@has_one_key, {=actor_has_item(way_jup_pripyat_box_key_2)} ph_idle@has_one_key, {=actor_has_item(way_jup_pripyat_box_key_3)} ph_idle@has_one_key
[ph_idle@has_one_key] nonscript_usable = false tips = rasvet_addon_inventory_box_key on_use = {=actor_has_item(way_jup_pripyat_box_key_1)} ph_idle@first_key %=remove_item(way_jup_pripyat_box_key_1)%, {=actor_has_item(way_jup_pripyat_box_key_2)} ph_idle@first_key %=remove_item(way_jup_pripyat_box_key_2)%, {=actor_has_item(way_jup_pripyat_box_key_3)} ph_idle@first_key %=remove_item(way_jup_pripyat_box_key_3)% on_info = {=actor_has_item(way_jup_pripyat_box_key_1) =actor_has_item(way_jup_pripyat_box_key_2)} ph_idle@has_two_key, {=actor_has_item(way_jup_pripyat_box_key_1) =actor_has_item(way_jup_pripyat_box_key_3)} ph_idle@has_two_key, {=actor_has_item(way_jup_pripyat_box_key_2) =actor_has_item(way_jup_pripyat_box_key_3)} ph_idle@has_two_key
[ph_idle@has_two_key] nonscript_usable = false tips = rasvet_addon_inventory_box_two_key on_use = {=actor_has_item(way_jup_pripyat_box_key_1) =actor_has_item(way_jup_pripyat_box_key_2)} ph_idle@second_key %=remove_item(way_jup_pripyat_box_key_1) =remove_item(way_jup_pripyat_box_key_2)%, {=actor_has_item(way_jup_pripyat_box_key_1) =actor_has_item(way_jup_pripyat_box_key_3)} ph_idle@second_key %=remove_item(way_jup_pripyat_box_key_1) =remove_item(way_jup_pripyat_box_key_3)%, {=actor_has_item(way_jup_pripyat_box_key_2) =actor_has_item(way_jup_pripyat_box_key_3)} ph_idle@second_key %=remove_item(way_jup_pripyat_box_key_2) =remove_item(way_jup_pripyat_box_key_3)% on_info = {=actor_has_item(way_jup_pripyat_box_key_1) =actor_has_item(way_jup_pripyat_box_key_2) =actor_has_item(way_jup_pripyat_box_key_2)} ph_idle@has_tru_key
[ph_idle@has_tru_key] nonscript_usable = false tips = rasvet_addon_inventory_box_two_key on_use = {=actor_has_item(way_jup_pripyat_box_key_1) =actor_has_item(way_jup_pripyat_box_key_2) =actor_has_item(way_jup_pripyat_box_key_3)} ph_idle@open %=remove_item(way_jup_pripyat_box_key_1) =remove_item(way_jup_pripyat_box_key_2) =remove_item(way_jup_pripyat_box_key_3)%
[ph_idle@first_key] nonscript_usable = false tips = rasvet_addon_inventory_box_zapert on_info = {=actor_has_item(way_jup_pripyat_box_key_1)} ph_idle@first_one_key, {=actor_has_item(way_jup_pripyat_box_key_2)} ph_idle@first_one_key, {=actor_has_item(way_jup_pripyat_box_key_3)} ph_idle@first_one_key
[ph_idle@first_one_key] nonscript_usable = false tips = rasvet_addon_inventory_box_key on_use = {=actor_has_item(way_jup_pripyat_box_key_1)} ph_idle@second_key %=remove_item(way_jup_pripyat_box_key_1)%, {=actor_has_item(way_jup_pripyat_box_key_2)} ph_idle@second_key %=remove_item(way_jup_pripyat_box_key_2)%, {=actor_has_item(way_jup_pripyat_box_key_3)} ph_idle@second_key %=remove_item(way_jup_pripyat_box_key_3)% on_info = {=actor_has_item(way_jup_pripyat_box_key_1) =actor_has_item(way_jup_pripyat_box_key_2)} ph_idle@first_two_key, {=actor_has_item(way_jup_pripyat_box_key_1) =actor_has_item(way_jup_pripyat_box_key_3)} ph_idle@first_two_key, {=actor_has_item(way_jup_pripyat_box_key_2) =actor_has_item(way_jup_pripyat_box_key_3)} ph_idle@first_two_key
[ph_idle@first_two_key] nonscript_usable = false tips = rasvet_addon_inventory_box_two_key on_use = {=actor_has_item(way_jup_pripyat_box_key_1) =actor_has_item(way_jup_pripyat_box_key_2)} ph_idle@open %=remove_item(way_jup_pripyat_box_key_1) =remove_item(way_jup_pripyat_box_key_2)%, {=actor_has_item(way_jup_pripyat_box_key_1) =actor_has_item(way_jup_pripyat_box_key_3)} ph_idle@open %=remove_item(way_jup_pripyat_box_key_1) =remove_item(way_jup_pripyat_box_key_3)%, {=actor_has_item(way_jup_pripyat_box_key_2) =actor_has_item(way_jup_pripyat_box_key_3)} ph_idle@open %=remove_item(way_jup_pripyat_box_key_2) =remove_item(way_jup_pripyat_box_key_3)%
[ph_idle@second_key] nonscript_usable = false tips = rasvet_addon_inventory_box_zapert on_info = {=actor_has_item(way_jup_pripyat_box_key_1)} ph_idle@second_one_key, {=actor_has_item(way_jup_pripyat_box_key_2)} ph_idle@second_one_key, {=actor_has_item(way_jup_pripyat_box_key_3)} ph_idle@second_one_key
[ph_idle@second_one_key] nonscript_usable = false tips = rasvet_addon_inventory_box_key on_use = {=actor_has_item(way_jup_pripyat_box_key_1)} ph_idle@open %=remove_item(way_jup_pripyat_box_key_1)%, {=actor_has_item(way_jup_pripyat_box_key_2)} ph_idle@open %=remove_item(way_jup_pripyat_box_key_2)%, {=actor_has_item(way_jup_pripyat_box_key_3)} ph_idle@open %=remove_item(way_jup_pripyat_box_key_3)%
[ph_idle@open] nonscript_usable = true tips = rasvet_addon_inventory_box_open[/cut]
Проблема, полагаю в секции has_two_key. Но я не вижу тут ошибки. Может, кто-нибудь увидит её "свежим" взглядом. Заранее благодарен за советы.
|
|
|
Эти 0 пользователя(ей) поблагодарили sergej5500 за это полезное сообщение: |
|
|
makdm | Дата: Пн, 18.11.2013, 21:06 | Сообщение # 687 |
Рожденный в СССР
Разработчики
Сообщений: 1294
| sergej5500, секция
[ph_idle@has_two_key]
вот это посмотрите
on_info = {=actor_has_item(way_jup_pripyat_box_key_1) =actor_has_item(way_jup_pripyat_box_key_2) =actor_has_item(way_jup_pripyat_box_key_2)}
Терпение...... И все получится!
Сообщение отредактировал makdm - Пн, 18.11.2013, 21:06 |
|
|
Эти 0 пользователя(ей) поблагодарили makdm за это полезное сообщение: |
|
|
sergej5500 | Дата: Пн, 18.11.2013, 23:09 | Сообщение # 688 |
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
| makdm, Спасибо за совет. Помогло. Я попробовал переделать логику и обобщить её для произвольного числа ключей. Уже для трех ключей логика довольно сложная. В xr_conditions добавил код
[cut=Функция]function way_jup_pripyat_box_key_has_1(actor, npc) local info_table = { [1] = "way_jup_pripyat_box_key_1_naiden", [2] = "way_jup_pripyat_box_key_2_naiden", [3] = "way_jup_pripyat_box_key_3_naiden" } local count = 0 for k,v in pairs (info_table) do if has_alife_info(v) then count = count + 1 end end if count = 1 then return true else return false end end[/cut]
Если найден один ключ (любой), то функция должна вызывать true. Получил
[cut=лог]FATAL ERROR [error]Expression : !m_error_code [error]Function : raii_guard::~raii_guard [error]File : D:\prog_repository\sources\trunk\xrServerEntities\script_storage.cpp [error]Line : 748 [error]Description : ...files 1\Зов Припяти\gamedata\scripts\xr_logic.script:477: attempt to index global 'xr_conditions' (a nil value)
stack trace:[/cut]
Вопрос, как правильно в xr_conditions составить функцию подсчета кол-ва инфопорций?
|
|
|
Эти 0 пользователя(ей) поблагодарили sergej5500 за это полезное сообщение: |
|
|
makdm | Дата: Пн, 18.11.2013, 23:18 | Сообщение # 689 |
Рожденный в СССР
Разработчики
Сообщений: 1294
| sergej5500, лог говорит о том, что у Вас синтаксическая ошибка в файле xr_conditions У Вас не хватает либо end, либо if, либо then и т.д.
Можно написать проще
function way_jup_pripyat_box_key_has_1(actor, npc) local info_table = { [1] = "way_jup_pripyat_box_key_1_naiden", [2] = "way_jup_pripyat_box_key_2_naiden", [3] = "way_jup_pripyat_box_key_3_naiden" }
for k,v in pairs (info_table) do if has_alife_info(v) then return true end end return false end
Что Вы имеете ввиду, когда пишите про подсчета кол-ва инфопорций?
Терпение...... И все получится!
Сообщение отредактировал makdm - Пн, 18.11.2013, 23:50 |
|
|
Эти 0 пользователя(ей) поблагодарили makdm за это полезное сообщение: |
|
|
FantomICW | Дата: Вт, 19.11.2013, 00:03 | Сообщение # 690 |
Лидер «Свободы»
Свобода
Сообщений: 4438
| sergej5500, если не ошибаюсь, то сама ошибка была в следующем: Должно быть: То есть, был не поставлен второй знак =.
Сообщение отредактировал FantomICW - Вт, 19.11.2013, 00:04 |
|
|
Эти 0 пользователя(ей) поблагодарили FantomICW за это полезное сообщение: |
|
|
|