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


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


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

denis2000,

Спасибо за помощь. Возник ещё один вопрос. Я сделал закладываемые заряды взрывчатки. Как в СГМ.

[cut=Функция установки зарядов]function remote_explosive_charge_init()
if has_alife_info("remote_explosive_pda_init") then
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_box_2"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_box_2"})
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_box_4"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_box_4"})
end
if xr_conditions.object_exist(nil,nil,{"remote_explosive_box_5"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_box_5"})
end
if xr_conditions.object_exist(nil,nil,{"remote_explosive_1"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_1"})
end
if xr_conditions.object_exist(nil,nil,{"remote_explosive_2"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_2"})
end
if xr_conditions.object_exist(nil,nil,{"remote_explosive_3"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_3"})
end
if xr_conditions.object_exist(nil,nil,{"remote_explosive_4"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_4"})
end
if xr_conditions.object_exist(nil,nil,{"remote_explosive_5"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_5"})
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 xr_conditions.object_exist(nil,nil,{"remote_explosive_box_1"}) then
alife():create("remote_explosive_box_1",vector():set(db.actor:position().x,db.actor:position().y,db.actor:position().z),db.actor:level_vertex_id(),db.actor:game_vertex_id())
elseif
not xr_conditions.object_exist(nil,nil,{"remote_explosive_box_2"}) then
alife():create("remote_explosive_box_2",vector():set(db.actor:position().x,db.actor:position().y,db.actor:position().z),db.actor:level_vertex_id(),db.actor:game_vertex_id())
elseif
not xr_conditions.object_exist(nil,nil,{"remote_explosive_box_3"}) then
alife():create("remote_explosive_box_3",vector():set(db.actor:position().x,db.actor:position().y,db.actor:position().z),db.actor:level_vertex_id(),db.actor:game_vertex_id())
elseif
not xr_conditions.object_exist(nil,nil,{"remote_explosive_box_4"}) then
alife():create("remote_explosive_box_4",vector():set(db.actor:position().x,db.actor:position().y,db.actor:position().z),db.actor:level_vertex_id(),db.actor:game_vertex_id())
elseif
not xr_conditions.object_exist(nil,nil,{"remote_explosive_box_5"}) then
alife():create("remote_explosive_box_5",vector():set(db.actor:position().x,db.actor:position().y,db.actor:position().z),db.actor:level_vertex_id(),db.actor:game_vertex_id())
else
game.start_tutorial("remote_explosive_no_use")
give_object_to_actor("remote_explosive_charge")
end
end
[/cut]

Как видно из функции, проверяется кол-во установленных зарядов. Функция if not xr_conditions.object_exist(nil,nil,{"remote_explosive_box_1"}) then. Функция работает. Но если заложенные заряды оказались далеко, в оффлайне, то функция считает что зарядов нет, дает сбой и позволяет поставить 6, 7 и т.д. заряд.

Используемые функции

function object_exist(actor , npc , p)
return get_story_object(p[1]) ~= nil
end

function get_story_object(story_obj_id)
local obj_id = story_objects.get_story_objects_registry():get(story_obj_id)
if obj_id == nil then return nil end
return (db.storage[obj_id] and db.storage[obj_id].object) or (level ~= nil and level.object_by_id(obj_id))
end

Видимо, функция object_exist правильно работает, только если объект в онлайне. Или она так действует только с объектами класса inventory_box. Это нежелательно.

Нужно, чтобы заложенные заряды проверялись и в оффлайне и даже на других локациях. Как поправить эту функцию или написать новую? Чтобы сбоев с объектами не было.

[cut=Заряды]
[remote_explosive_box_1]:inventory_box
$spawn = "devices\remote_explosive_box_1"
visual = dynamics\devices\dev_rukzak\dev_rukzak.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[/cut]

И еще один вопрос. Функция xr_effects.destroy_object(actor,npc,{"story","remote_explosive_box_1"}) сработает, если объект в оффлайне или на другой локации?


Сообщение отредактировал sergej5500 - Вс, 25.10.2015, 18:58
 
denis2000Дата: Вс, 25.10.2015, 19:06 | Сообщение # 692
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

sergej5500, Ваши заряды в офлайне не взорвутся. Тут придется всю систему пересмотреть или подрывать заряды автоматически при удалении от них на 120 метров например.

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

Цитата denis2000 ()
Ваши заряды в офлайне не взорвутся. Тут придется всю систему пересмотреть или подрывать заряды автоматически при удалении от них на 120 метров например.


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

[cut=Код]if has_alife_info("remote_explosive_pda_init") then
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_box_2"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_box_2"})
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_box_4"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_box_4"})
end
if xr_conditions.object_exist(nil,nil,{"remote_explosive_box_5"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_box_5"})
end
if xr_conditions.object_exist(nil,nil,{"remote_explosive_1"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_1"})
end
if xr_conditions.object_exist(nil,nil,{"remote_explosive_2"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_2"})
end
if xr_conditions.object_exist(nil,nil,{"remote_explosive_3"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_3"})
end
if xr_conditions.object_exist(nil,nil,{"remote_explosive_4"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_4"})
end
if xr_conditions.object_exist(nil,nil,{"remote_explosive_5"}) then
xr_effects.destroy_object(actor,npc,{"story","remote_explosive_5"})
end
disable_info("remote_explosive_pda_init")
end[/cut]

Эта проверка должна удалить все несработавшие объекты. Независимо от их положения. Защита от непредвиденных последствий.
 
denis2000Дата: Вс, 25.10.2015, 19:38 | Сообщение # 694
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

Цитата sergej5500 ()
Защита от непредвиденных последствий.

Есть проблема: будут удалены только заряды в онлайне.


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

Цитата denis2000 ()
Есть проблема: будут удалены только заряды в онлайне.


Печально. Тогда придется добавить счетчик. Для контроля установки зарядов использовать функции ins_counter и counter_equal. А несработавшие заряды удалять проверкой всех объектов в игре.

За помощь спасибо.

Добавлено (25.10.2015, 23:58)
---------------------------------------------
Добрый вечер. Попробовал сделать мину.

[cut=Логика][logic]
active = ph_idle

[ph_idle]
on_info = {=dist_to_actor_ge(35)} ph_idle@expl

[ph_idle@expl]
on_game_timer = 15 | ph_idle@expl %=mine_activate%[/cut]

[cut=Функция подрыва]function mine_activate(actor,obj)
for a=1,65534 do
local object = alife():object(a)
if (object==IsStalker or object==IsMonster) then
if distance_between(object,obj)<=25 then

alife():create("rukzak_explosive",vector():set(obj:position()),obj:level_vertex_id(),obj:game_vertex_id())
level.add_call(
function()
if get_story_object("rukzak_explosive") ~= nil then
return true
end
end,
function()
expl_obj = get_story_object("rukzak_explosive")
expl_obj:explode(0)
end
)
end
end
end
local sobj = alife():object(obj:id())
if sobj then
alife():release( sobj, true )
end

end[/cut]

По замыслу, если ближе 25 метров от заряда окажется монстр (сталкер), то заряд должен взорваться. Логика сработала. Заряд исчез. Вылета не было. Взрыва тоже не было. В каком месте функции допущена ошибка?


Сообщение отредактировал sergej5500 - Вс, 25.10.2015, 23:59
 
denis2000Дата: Пн, 26.10.2015, 18:23 | Сообщение # 696
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

sergej5500, Я вам уже писал по поводу мин. В движке есть объект - скриптовая зона (script_zone), у которой есть биндер xr_zones.script. Так вот у этого объекта есть колбеки на попадание в зону объекта (arena_zone_binder:on_enter) и выход из этой зоны объекта (arena_zone_binder:on_exit). Нет необходимости периодически шерстить все объекты проверяя расстояние от "мины"! Попал НПС, ГГ, Мутант или что либо другое в эту зону, вызвался колбек - в его отработке спавните взрывчатку и взрывайте - все просто!

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

denis2000,

Посмотрел xr_zones.script и возникло несколько вопросов.

arena_zone_binder - это относится к конкретной скриптовой зоне arena_zone или ко всем script_zone? Каждую скриптовую зону нужно биндить индивидуально?

Каким образом спавнятся script_zone? Они делаются в СДК? Или их можно сделать из логики через xr_effects?
 
denis2000Дата: Вт, 27.10.2015, 18:22 | Сообщение # 698
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

Цитата sergej5500 ()
Каждую скриптовую зону нужно биндить индивидуально?

Конечно же все экземпляры класса обрабатываются одним скриптом!
Цитата sergej5500 ()
Каким образом спавнятся script_zone?

SDK, all.spawn или скриптом.


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

denis2000,

В Зове Припяти нет ни одной script_zone. Поэтому не очень понятно, как с ними работать. Несколько вопросов.

1. Спавн script_zone. Есть inventory_box с логикой.

[cut=Логика][logic]
active = ph_idle

[ph_idle]
nonscript_usable = false
on_info = {=dist_to_actor_ge(15)} nil %=destroy_object =create_script_zones%[/cut]

Как будет выглядеть функция create_script_zones? Функция должна заспавнить скриптовую зону радиусом 10 метров в точке, где располагался inventory_box.

Назовем скрипт-зону mine_script_zones.

2. Скрипт-зона должна при попадании в неё сталкера или мутанта заспавнить в своих координатах заряд взрывчатки функцией примерно такого вида. После этого скрипт - зона должна удалиться.

[cut=Функция]
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
)

local sobj = alife():object(obj:id())
if sobj then
alife():release( sobj, true )
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[/cut]

Как нужно править xr_zones?
 
denis2000Дата: Ср, 28.10.2015, 15:14 | Сообщение # 700
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

Цитата sergej5500 ()
В Зове Припяти нет ни одной script_zone

Есть одна единственная на все игры в оригинальном ТЧ.
Цитата sergej5500 ()
Как будет выглядеть функция create_script_zones?

Код
function create_script_zones(actor,obj)
local script_zone = alife():create("script_zones",vector():set(obj:position()),obj:level_vertex_id(),obj:game_vertex_id())
--;;;;;;;;;;;;;;;;;;;;;;;
--Здесь радактированием нетпакета объекта script_zone нужно прикрутить шейп нужной формы и размера
--;;;;;;;;;;;;;;;;;;;;;;;
end

Цитата sergej5500 ()
Как нужно править xr_zones?

Простите у меня нет готовых решений.


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

Добрый вечер. Попробовал сделать в чистом ЗП персональные флешки в стиле СГМ.

В бинд-сталкер дописал код вида.

if (s_obj) and (s_obj:section_name()=="dv_test_case") then
alife():create("dv_test_case_box",vector():set(-152.94622802734,-29.912256240845,-403.56521606445),99393,93)
give_item_to_sid("medkit,bandage","dv_test_case_box")
end

Конфиги

[dv_test_case]:booster
$spawn = "devices\dv_test_case"
visual = dynamics\devices\dev_pda\dev_pda.ogf

[dv_test_case_box]:inventory_box
$spawn = "devices\dv_test_case_box"
custom_data = scripts\addon_test_rukzak_1.ltx
visual = dynamics\devices\dev_rukzak\dev_rukzak.ogf
story_id = dv_test_case_box

Рюкзак заспавнился после активации бустера. С хабаром. С помощью какой функции на этот рюкзак можно поставить метку тайника? Метка должна ставиться после активации бустера. С помощью какой функции метку убрать с рюкзака после его юзания? Как это правильно сделать?
 
denis2000Дата: Вт, 15.12.2015, 12:55 | Сообщение # 702
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

Цитата sergej5500 ()
С помощью какой функции на этот рюкзак можно поставить метку тайника?

level.map_add_object_spot(<ID объекта на который ставить метку>, <Имя метки>, <Имя описания>)
Цитата sergej5500 ()
С помощью какой функции метку убрать с рюкзака после его юзания?

level.map_remove_object_spot(<ID объекта с которого снять метку>, <Имя метки>)


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

Здравствуйте, в ТЧ есть возможность активации артефактов.
После отыгрыша анимации, артефакт выбрасывается, и после пары секунд спавнится аномалия,
такой вопрос - можно ли как-то отловить момент активации и эти пару секунд - когда артефакт выброшен но аномалия еще не появилась?
 
denis2000Дата: Ср, 23.12.2015, 18:57 | Сообщение # 704
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

ted80, Потеря арта, возможно, вызовет колбек on_item_drop. Но как отследить спавн аномалии не совсем понятно.

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

Втом-то и дело, с установленными детекторами артефактов, при дропе арта - происходит замена арта, на невидимый и не подбираемый предмет, а активации аномалии не происходит (((
 
Поиск: