Войти на сайт Регистрация Лента форума Пользователи Правила сайта Поиск по форуму
Модератор форума: denis2000, FantomICW  
Модостроение. Спавн и логика
denis2000Дата: Пн, 10.10.2011, 21:20 | Сообщение # 1
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

Спавн и логика

Создание объектов на локации и логика поведения этих объектов

Если у вас появились вопросы по созданию динамических объектов в игре (НПС, монстры, аномалии, и т.п.) и настройке их "поведения". Задавайте их в этой теме - умные головы,
модосторители и просто разбирающиеся в программировании люди вам ответят.


Много интересного материала здесь (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 по ссылке из шапки и соседнюю тему "Курс молодого бойца",
возможно Ваш вопрос уже рассматривался.


Если произошел вылет - выкладываем лог! Вопрос ставим четко, не забываем указывать версию игры, установленные моды их версии, установленные фиксы модов и подробно ваши правки.
Помните чем подробнее вопрос, тем точнее ответ.


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

Добрый вечер!
Хотел бы задать один вопрос по логике рестриктора.
Нужно чтобы во время кат-сцены (схема sr_cutscene) вместо музыки-абмиента играл другой конкретный трек, при этом дополнительные звуки, вызываемые в этом же рестриктором через play_sound должны также работать. Как можно подобную вещь реализовать?



 
denis2000Дата: Пн, 28.10.2013, 11:36 | Сообщение # 677
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

FantomICW, Временно убрать амбиентные звуки (или музыку) вроде нельзя, можно только "перекричать", т.е. воспроизвести нужные звуки с гораздо большим уровнем. play_sound и play_sound_looped прекрасно работают, но помни один объект - один звук, нет возможности одному объекту воспроизводить несколько звуков одновременно.

"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
makdmДата: Пн, 28.10.2013, 11:58 | Сообщение # 678
Рожденный в СССР
Разработчики
Сообщений: 1294
Награды: 29
Репутация: [ 1909 ]

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
 
sergej5500Дата: Пт, 08.11.2013, 00:58 | Сообщение # 679
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
Награды: 29
Репутация: [ 1355 ]

Добрый вечер. Можно ли решить такую задачу?
Есть несколько несквадовых НПС со стори ид: jup_a9_stalker1, jup_a9_stalker2 и т.д. У каждого свой файл логики. Есть сквады НПС со стори ид: jup_a9_alfa_squad1,jup_a9_alfa_squad2 и т.д. Несквадовые НПС относятся к группировке сталкер алиес, сквады к группировке альфа. Группировки взаимно нейтральны друг к другу. Нужно поссорить их друг с другом после выдачи определенной инфопорции. Сталкеры выступят с одной стороны, альфа с другой. Можно ли это сделать и как? Правку отношений группировок делать нежелательно. Нужно, чтобы конкретные сталкеры поссорились с конкретной альфой.
Заранее благодарен за советы.
 
makdmДата: Пт, 08.11.2013, 11:04 | Сообщение # 680
Рожденный в СССР
Разработчики
Сообщений: 1294
Награды: 29
Репутация: [ 1909 ]

sergej5500, в файле xr_effects.script есть готовая функция, которая вызывается из логики НПС и ссорит его с конкретным сквадом.

set_squad_goodwill_to_npc

Срабатывание по поршню выглядит примерно так

on_info = {+поршень_смены_отношений -поршень} %+поршень =set_squad_goodwill_to_npc(jup_a9_alfa_squad1:enemy)%


Терпение......
И все получится!
 
sergej5500Дата: Пт, 08.11.2013, 11:34 | Сообщение # 681
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
Награды: 29
Репутация: [ 1355 ]

makdm,
Спасибо за совет. Ещё один вопрос. Можно ли поссорить конкретный сквад с конкретным НПС? По Вашей формуле НПС ссорится со сквадом. Хотелось бы поссорить их взаимно и одновременно.
 
makdmДата: Пт, 08.11.2013, 12:09 | Сообщение # 682
Рожденный в СССР
Разработчики
Сообщений: 1294
Награды: 29
Репутация: [ 1909 ]

sergej5500, эта функция именно это и делает.
Ссорит одновременно и НПС со сквадом и всех членов сквада с НПС.


Терпение......
И все получится!
 
sergej5500Дата: Вс, 10.11.2013, 10:49 | Сообщение # 683
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
Награды: 29
Репутация: [ 1355 ]

Добрый День. Интересует такой момент. В теме "Идеи и предложения для СГМ" неоднократно предлагались идеи квестов по "тихому" устранению враждебных НПС на вражеской базе. Поэтому есть вопросы. Есть ли возможность отследить, от какого оружия получен хит? Выделяются ли отдельно хиты от ножа и оружия с глушителем? Можно ли в логике НПС прописать что-то типа: если НПС завалили с ножа, то всё спокойно, если с СВД, то вся база нападёт на ГГ?
 
denis2000Дата: Ср, 13.11.2013, 16:33 | Сообщение # 684
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

sergej5500, Косвенным путем определить оружие из которого завалил НПС ГГ можно: в колбеке на хит НПС определять если хит нанес ГГ, то считать активный слот и соответственно активное оружие - если это слот ножа, то оружие соответственно нож. Тихая миссия с ножа на базе есть в моде "Время Альянса", там реализация очень хорошая (естественно в пределах возможностей движка)

"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
makdmДата: Ср, 13.11.2013, 17:16 | Сообщение # 685
Рожденный в СССР
Разработчики
Сообщений: 1294
Награды: 29
Репутация: [ 1909 ]

sergej5500, без лишней скромности, дополню ответ Дениса, что схема, когда отслеживается выстрел из оружия с глушителем или без него , также реализована в аддоне "Время Альянса". В случае выстрела без глушака поднимается тревога.
Всё можно посмотреть, скачав аддон " Время Альянса". Схема с глушителем в файле xr_conditions.script
Функция wpn_has_silencer


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


Сообщение отредактировал makdm - Ср, 13.11.2013, 17:20
 
sergej5500Дата: Пн, 18.11.2013, 20:14 | Сообщение # 686
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
Награды: 29
Репутация: [ 1355 ]

Добрый вечер. Я сделал квестовый сейф, для открытия которого нужны три ключа. №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. Но я не вижу тут ошибки. Может, кто-нибудь увидит её "свежим" взглядом. Заранее благодарен за советы.
 
makdmДата: Пн, 18.11.2013, 21:06 | Сообщение # 687
Рожденный в СССР
Разработчики
Сообщений: 1294
Награды: 29
Репутация: [ 1909 ]

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
 
sergej5500Дата: Пн, 18.11.2013, 23:09 | Сообщение # 688
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
Награды: 29
Репутация: [ 1355 ]

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 составить функцию подсчета кол-ва инфопорций?
 
makdmДата: Пн, 18.11.2013, 23:18 | Сообщение # 689
Рожденный в СССР
Разработчики
Сообщений: 1294
Награды: 29
Репутация: [ 1909 ]

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
 
FantomICWДата: Вт, 19.11.2013, 00:03 | Сообщение # 690
Лидер «Свободы»
Свобода
Сообщений: 4438
Награды: 44
Репутация: [ 1340 ]

sergej5500, если не ошибаюсь, то сама ошибка была в следующем:
Код
if count = 1 then

Должно быть:
Код
if count == 1 then

То есть, был не поставлен второй знак =.





Сообщение отредактировал FantomICW - Вт, 19.11.2013, 00:04
 
Поиск: