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

Редактирование и создание скриптов

Редактирование и создание скриптов на языке LUA

Если у вас появились вопросы по применению скриптов в игре. Задавайте их в этой теме - умные головы,
модосторители и просто разбирающиеся в программировании люди вам ответят.


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


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


"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
ted80Дата: Вс, 31.01.2016, 17:06 | Сообщение # 736
Гражданский
Пользователи
Сообщений: 15
Награды: 0
Репутация: [ 0 ]

sergej5500, Измените функцию

if (s_obj) and (s_obj:section_name()=="personal_rukzak") then
[blink]obj[/blink]=alife():create("personal_rukzak_box",vector():set(db.actor:position().x,db.actor:position().y,db.actor:position().z),db.actor:level_vertex_id(),db.actor:game_vertex_id())
[blink]local obj_id = level.object_by_id(obj)[/blink]
level.map_add_object_spot([blink]obj_id[/blink], "ui_pda2_actor_rukzak_location", "st_ui_pda_actor_rukzak")
end


Сообщение отредактировал ted80 - Вс, 31.01.2016, 17:10
 
sergej5500Дата: Пн, 01.02.2016, 09:40 | Сообщение # 737
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
Награды: 29
Репутация: [ 1355 ]

Добрый день.

Поймал вылет с таким логом.

Зов Припяти\gamedata\scripts\smart_terrain.script:584: attempt to index local 'job_data' (a nil value)

584 строка в скрипте аналогична строке в соответствующем файле из оригинала ЗП. Судя по логу, что то не в порядке с работами НПС в смарте.

Локация Кордон из ЧН. Смарты и работы расставлял в СДК. После заселения каждого смарта спавнил в этом смарте тестовый сквад. Число неписей в тестовом скваде было равно числу работ в проверяемом смарте. Сбоев при проверке не было. Неписи нормально выполняли свои работы. Все точки walk и look находятся на сетке.

В момент вылета в онлайне было 4 смарта.

Главная база - (южный блокпост). В смарте 30 работ для sim_default. Было занято 20. При нахождении игрока внутри блокпоста игра вылетела.
Деревня новичков. В смарте 30 работ для sim_default. Было занято 10.
Два симуляционных смарта. В каждом по 9 работ по sim_default. В момент вылета эти смарты были пустыми.

Я не вижу причин для вылета. Все эти смарты были проверены. До переполнения им далеко.

В чем может быть причина вылета?
 
denis2000Дата: Пн, 01.02.2016, 18:18 | Сообщение # 738
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

sergej5500, Проверьте эксклюзивные работы, возможно ошибка в имени работы.

"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
avn1975Дата: Пт, 05.02.2016, 17:28 | Сообщение # 739
Гражданский
Пользователи
Сообщений: 15
Награды: 0
Репутация: [ 0 ]

создал скрипт для фонарика и пнв как детектор добавить не знаю может кто подскажет благодорю за помощь https://yadi.sk/d/vSt5ckpVoNxBA

Сообщение отредактировал avn1975 - Сб, 06.02.2016, 08:56
 
Игорь_ГоДата: Сб, 06.02.2016, 13:54 | Сообщение # 740
Отмычка
Пользователи
Сообщений: 26
Награды: 0
Репутация: [ 0 ]

Всем привет!
Сделал-переделал локации, теперь пытаюсь разобраться-повозиться со скриптами и прочей программной заумностью, посему возникли два вопроса:
1 напр., сделал дверку с костями, выбрал логику двери и... и что дальше происходит, выбирается определенный файл анимации? Тогда где находится дверная анимация ( в самой модели вроде бы нет), и возможно ли ее заменить своею?
2 есть ли в движке возможность включать лампочки по какому-нибудь событию, напр,, включением рубильника?
 
denis2000Дата: Сб, 06.02.2016, 18:07 | Сообщение # 741
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

Игорь_Го,
1. Двери не имеют анимации (точнее объекты physic_door класса O_DSTR_S), у двери определенная конфигурация и настройки скелета в частности сустава door, который должен быть типа Joint и иметь настроенные углы поворота по оси Y.
Есть объекты с анимацией которые используются как двери, но по определению они physic_object класса O_PHYS_S, как например большие ворота в подземке или мост в Лиманск.
2. Есть метод для такого обекта obj:get_hanging_lamp():turn_on() - включить, obj:get_hanging_lamp():turn_off() - выключить. Использоваение смотри в xr_effects.script.


"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
sergej5500Дата: Вт, 09.02.2016, 19:58 | Сообщение # 742
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
Награды: 29
Репутация: [ 1355 ]

Добрый день. Возник такой вопрос.

1. Имеются два одинаковых бронекостюма. Один из костюмов надет на игрока. В тесте использовал Экзы Рассвета.

2. Один костюм нужно передать неписю в диалоге. Для передачи использую функцию remove_item.
xr_effects.remove_item(actor,npc,{"csky_exo_outfit"})

3. При этом удаляется костюм, надетый на игрока. Можно ли как то проверить костюм и удалить тот, который в рюкзаке?



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

sergej5500, Пробуйте так:
Цитата
function remove_item(actor, npc, p)
if (p and p[1]) == nil then abort("Wrong parameters in function 'remove_item'!!!") end
local item_section = p[1]

local obj = db.actor:object(item_section)

local function search_item(temp, item)
if (item:section() == item_section) and
((db.actor:item_in_slot(2) ~= obj) or (db.actor:item_in_slot(3) ~= obj) or (db.actor:item_in_slot(7) ~= obj) or (db.actor:item_in_slot(12) ~= obj)) then
obj = item
end
end
db.actor:iterate_inventory(search_item, db.actor)

if obj ~= nil then
alife():release(alife():object(obj:id()), true)
else
abort("Actor has no such item!")
end
news_manager.relocate_item(db.actor, "out", item)
end


"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
sergej5500Дата: Вс, 28.02.2016, 18:36 | Сообщение # 744
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
Награды: 29
Репутация: [ 1355 ]

Добрый день.

Делаю сложный квест. Игрок должен, надев любой костюм определённой группировки, передать неписю другой костюм этой же группировки. В квесте 4 костюма. Возможны любые комбинации этих костюмов. В т.ч. оба костюма могут быть одинаковы.

alfa_outfit
alfa_exo_outfit
reduce_alfa_outfit
reduce_alfa_exo_outfit

Прекондишион, открывающий ветку диалога передачи костюма. И связанные функции.

[cut=Функции]function zat_b38_plennic_has_alfa_outfit(actor,npc)
return (db.actor:object("alfa_outfit") and not get_actor_slot_item("alfa_outfit","outfit")) or sgm_functions.have_item_count("alfa_outfit",2)
end

-- 'Проверка по количеству предметов одного типа.
function have_item_count(need_item,num,st_find)
local item_section=need_item
local need_count=tonumber(num)
local has_count=0
local function calc(temp,item)
if (st_find==nil or st_find==false) and item:section()==item_section then
has_count=has_count+1
elseif st_find==true and find_in_string(item:section(),item_section) then
has_count=has_count+1
end
end
db.actor:iterate_inventory(calc,db.actor)
return has_count>=need_count
end

-- 'Проверка наличия определенного предмета в слоте.
function get_actor_slot_item(item_name,item_type)
local pistol_in_slot=db.actor:item_in_slot(2)
local rifle_in_slot=db.actor:item_in_slot(3)
local outfit_in_slot=db.actor:item_in_slot(7)
local helm_in_slot=db.actor:item_in_slot(12)
if item_name~=nil and item_type=="pistol" and pistol_in_slot~=nil and find_in_string(pistol_in_slot:section(),item_name) then
return true
elseif item_name~=nil and item_type=="rifle" and rifle_in_slot~=nil and find_in_string(rifle_in_slot:section(),item_name) then
return true
elseif item_name~=nil and item_type=="outfit" and outfit_in_slot~=nil and find_in_string(outfit_in_slot:section(),item_name) then
return true
elseif item_name~=nil and item_type=="helm" and helm_in_slot~=nil and find_in_string(helm_in_slot:section(),item_name) then
return true
else
return false
end
end
[/cut]
Ветка диалога должна быть активна, если у игрока есть нужный костюм и он не в слоте. Или нужных костюмов две штуки. Прекондишион работает нормально.

Передача костюма неписю.
function zat_b38_plennic_out_alfa_outfit(actor,npc)
xr_effects.remove_item(actor,npc,{"alfa_outfit"})
end

Если костюм на игроке и костюм, передаваемый неписю, одинаковы, то пропадает костюм, надетый на игрока. В этом случае пропадает маскировка игрока.

Правка функции remove_item по предложению denis2000 в посте выше, привела к вылету.

[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 : No such operator defined


stack trace:
[/cut]
 
denis2000Дата: Пн, 29.02.2016, 08:57 | Сообщение # 745
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

Цитата sergej5500 ()
Правка функции remove_item по предложению denis2000 в посте выше, привела к вылету.

Вместо
Код
news_manager.relocate_item(db.actor, "out", item)
надо
Код
news_manager.relocate_item(db.actor, "out", item_section)


"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
sergej5500Дата: Сб, 05.03.2016, 00:09 | Сообщение # 746
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
Награды: 29
Репутация: [ 1355 ]

Добрый вечер.

Хочу вернуться к вопросу о костюмах и слотах. После некоторых тестов пришёл к выводу, что лучше всего подходят для квеста такие функции.

[cut=Проверка наличия костюмов]function zat_b38_plennic_outfit_has_item(first_speaker, second_speaker)
local item_sections = {
[1] = "alfa_outfit",
[2] = "alfa_exo_outfit",
[3] = "reduce_alfa_outfit",
[4] = "reduce_alfa_exo_outfit"
}
local needed = 2
local count = 0
local item_section
local function calc(temp, item)
if item:section() == item_section then
count = count + 1
end
end
for k,v in pairs(item_sections) do
item_section = v
get_story_object("actor"):iterate_inventory(calc, actor)
end
return count >= needed
end[/cut]

[cut=Проверка отсутствия костюмов]function zat_b38_plennic_outfit_not_has_item(first_speaker, second_speaker)
local item_sections = {
[1] = "alfa_outfit",
[2] = "alfa_exo_outfit",
[3] = "reduce_alfa_outfit",
[4] = "reduce_alfa_exo_outfit"
}
local needed = 2
local count = 0
local item_section
local function calc(temp, item)
if item:section() == item_section then
count = count + 1
end
end
for k,v in pairs(item_sections) do
item_section = v
get_story_object("actor"):iterate_inventory(calc, actor)
end
return count < needed
end[/cut]

[cut=Передача костюма]function zat_b38_plennic_outfit_otdat(first_speaker, second_speaker)
local npc = dialogs.who_is_npc(first_speaker, second_speaker)
local actor = dialogs.who_is_actor(first_speaker, second_speaker)
local i = 1
local j = 0
local section
local item_sections = {
[1] = "alfa_outfit",
[2] = "alfa_exo_outfit",
[3] = "reduce_alfa_outfit",
[4] = "reduce_alfa_exo_outfit"
}
local function transfer_object_item(temp, item)
if (item:section() == section and i ~= 0) then
actor:transfer_item(item, npc)
i = i - 1
end
end
for k,v in pairs(item_sections) do
section = v
j = i
actor:iterate_inventory(transfer_object_item, nil)
if ((j - i) ~= 0) then
news_manager.relocate_item(actor, "out", section, j - i)
end
end
end[/cut]

Проверку проводил на одинаковых костюмах. Передал неписю в тесте 20 костюмов. 3 раза передался костюм из слота. 17 костюмов ушло из рюкзака.

Вопросы такие. Как доработать функцию передачи, чтобы проверить, не в слоте ли костюм? И передать тот, который в рюкзаке.

Если переданный костюм - экзоскелет: alfa_exo_outfit или reduce_alfa_exo_outfit, то нужно выдать инфопорцию. Она нужна для выбора визуала непися после "переодевания". Как отследить тип костюма и выдать инфопорцию?
 
denis2000Дата: Вт, 08.03.2016, 14:42 | Сообщение # 747
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

sergej5500, Готовый скрипт не предложу, могу посоветовать алгоритм:
1. Задайте индекс найденных предметов = 0 и пустую таблицу найденных предметов find_items
2. Итерируясь по инвентарю ищите предметы с именами секций из таблицы item_sections и помещаете их в новую таблицу find_items, увеличивая при этом индекс найденных предметов
3. Если индекс найденных предметов равен 1, то предмет только один придется передать его (даже если он в слоте)
4. Если индекс найденных предметов больше 1, то итерируясь по таблице find_items отдайте первый же предмет который не находиться при этом в слоте.


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

Цитата sergej5500 ()
Вопросы такие. Как доработать функцию передачи, чтобы проверить, не в слоте ли костюм? И передать тот, который в рюкзаке.

Если переданный костюм - экзоскелет: alfa_exo_outfit или reduce_alfa_exo_outfit, то нужно выдать инфопорцию. Она нужна для выбора визуала непися после "переодевания". Как отследить тип костюма и выдать инфопорцию?


Вот так попробуй:
[cut noguest]
function zat_b38_plennic_outfit_otdat(first_speaker, second_speaker)
local actor = ( first_speaker and first_speaker:id() == db.actor:id() ) or second_speaker
local npc = ( first_speaker and first_speaker:id() ~= db.actor:id() ) or second_speaker
local actor_outfit_id = actor:item_in_slot( 7 ):id()
local item_sections = {
["alfa_outfit"] = true,
["alfa_exo_outfit"] = true,
["reduce_alfa_outfit"] = true,
["reduce_alfa_exo_outfit"] = true
}
local outfit_tbl = {}
local count = 0
local function calc( temp, item )
if item:id() ~= actor_outfit_id then
local section = item:section()
if item_sections[ section ] == true then
count = count + 1
outfit_tbl[ count ] = item:id()
end
end
end
actor:iterate_inventory( calc, actor )
local need_count = 3 -- Здесь количество необходимых бронекостюмов для передачи
for k,v in pairs( outfit_tbl ) do
if k > need_count then
break
else
local obj = level.object_by_id( v )
local sect = obj:section()
actor:transfer_item( obj, npc )
news_manager.relocate_item( actor, "out", sect, 1 )
if sect == "alfa_exo_outfit" or sect == "reduce_alfa_exo_outfit" then
give_info("exo_outfit_done")
end
end
end

end[/cut]


Терпение......
И все получится!
 
tema796Дата: Вс, 13.03.2016, 00:36 | Сообщение # 749
Гражданский
Пользователи
Сообщений: 20
Награды: 0
Репутация: [ -20 ]

Доброго времени суток. Решил написать функцию на проверку что костер горит но тут случился такой вылет:
Код
[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   : ...r. - Зов Припяти\gamedata\scripts\_tkp_s_data.script:64: attempt to index local 'Alife' (a nil value)

Я не могу понять в чем причина. Вот сама функция, которую я вызываю:
Код

function Turn_On_Koster()
for i =1,65535 do
local Alife = alife():object(i)
local Obj_id = level.object_by_id(Alife.id)
local FireCamp = Obj_id:get_campfire()
           if FireCamp and FireCamp:is_on() and Obj_id:position():distance_to(db.actor:position()) < 5 then
     _tkp_send_tips.Koster_On()
           end
       end
end


Сообщение отредактировал tema796 - Вс, 13.03.2016, 00:37
 
denis2000Дата: Вс, 13.03.2016, 18:02 | Сообщение # 750
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

tema796, Для одного из значений i, переменная Alife = nil, в результате попытка получить Alife.id оборачивается вылетом.

"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
Поиск: