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


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


"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
victor12Дата: Вс, 28.12.2014, 01:35 | Сообщение # 556
Отмычка
Пользователи
Сообщений: 29
Награды: 0
Репутация: [ 0 ]

Всем доброй ночи! Я сейчас играю в Чистое небо (SGM), играю за бандитов, как увеличить количество групп бандитов, куда залезть и что исправить. Раньше знал, но это было давно.

Intel®Core(TM2)CPU 6400 2.13\2.13GHz, ОЗУ-7ГБ(доступно 5.75 Гб), система - 64 разр., ВК - GF440 1 Гб, игра - лицензионная.
 
denis2000Дата: Вс, 28.12.2014, 11:41 | Сообщение # 557
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

victor12, Насколько я помню файл faction_bandit.ltx секции [expansion_*] параметр base_squad_number

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

Добрый день.

В СГМ 2.1 есть функция в _g.scripts.

[cut=Функция]function give_random_treasure(need_level,count)
if count==nil then count=1 end
local selected_treasure
local selected_table
local level_name=level.name()
local its_all=true
for i=1,count do
if need_level==nil then
if level_name=="zaton" then
selected_treasure = get_random_string(treasure_with_zaton)
selected_table = treasure_with_zaton
elseif level_name=="jupiter" then
selected_treasure = get_random_string(treasure_with_jupiter)
selected_table = treasure_with_jupiter
elseif level_name=="pripyat" then
selected_treasure = get_random_string(treasure_with_pripyat)
selected_table = treasure_with_pripyat
elseif level_name=="darkvalley" then
selected_treasure = get_random_string(treasure_with_darkvalley)
selected_table = treasure_with_darkvalley
elseif level_name=="military" then
selected_treasure = get_random_string(treasure_with_military)
selected_table = treasure_with_military
elseif level_name=="agroprom" then
selected_treasure = get_random_string(treasure_with_agroprom)
selected_table = treasure_with_agroprom
elseif level_name=="escape" then
selected_treasure = get_random_string(treasure_with_escape)
selected_table = treasure_with_escape
elseif level_name=="marsh" then
selected_treasure = get_random_string(treasure_with_marsh)
selected_table = treasure_with_marsh
else
return
end
else
if need_level=="zaton" then
selected_treasure = get_random_string(treasure_with_zaton)
selected_table = treasure_with_zaton
elseif need_level=="jupiter" then
selected_treasure = get_random_string(treasure_with_jupiter)
selected_table = treasure_with_jupiter
elseif need_level=="pripyat" then
selected_treasure = get_random_string(treasure_with_pripyat)
selected_table = treasure_with_pripyat
elseif need_level=="darkvalley" then
selected_treasure = get_random_string(treasure_with_darkvalley)
selected_table = treasure_with_darkvalley
elseif need_level=="military" then
selected_treasure = get_random_string(treasure_with_military)
selected_table = treasure_with_military
elseif need_level=="agroprom" then
selected_treasure = get_random_string(treasure_with_agroprom)
selected_table = treasure_with_agroprom
elseif need_level=="escape" then
selected_treasure = get_random_string(treasure_with_escape)
selected_table = treasure_with_escape
elseif need_level=="marsh" then
selected_treasure = get_random_string(treasure_with_marsh)
selected_table = treasure_with_marsh
else
return
end
end
if treasure_manager.get_treasure_manager():check_treasure_given(selected_treasure)~=true then
treasure_manager.get_treasure_manager():give_treasure(selected_treasure)
else
for k,v in pairs(selected_table) do
if v~=nil and treasure_manager.get_treasure_manager():check_treasure_given(v)~=true then
its_all=false
end
end
if its_all==false then
give_random_treasure(need_level,1)
end
end
end
end[/cut]

Функция выдает рандомный тайник.

Вызывается в диалоге. Например, так.

[cut=Выдача награды за квест]function esc_b1_mechanic_task_complete(actor,npc)
give_reward("wpn_saiga")
give_reward("ammo_12x70_buck",3)
give_reward("ammo_12x76_zhekan",3)
dialogs.relocate_money(npc,5000,"in")
give_random_treasure()
give_secret(1)
end[/cut]

Попробовал вызвать функцию через xr_effects.

[cut=xr_effects]function give_random_treasure()
give_random_treasure()
end[/cut]

В строку on_complete в секции квеста прописал вызов функции.

on_complete = %=add_actor_rank(8) =inc_faction_goodwill_to_actor(stalker:200) =give_random_treasure%

После завершения квеста вылез жучок.

[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 : ....r. - Зов Припяти\gamedata\scripts\xr_effects.script:-1: stack overflow

stack trace:
[/cut]

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

Цитата sergej5500 ()
В каком месте я допустил ошибку?

Именно в этом месте:
Код
function give_random_treasure()
give_random_treasure()
end

Вы из функции вызываете ее-же рекурсивно, гарантированное переполнение стека, хорошо что без мертвого зависания винды.


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

Цитата sergej5500 ()
В каком месте я допустил ошибку?


sergej5500, вот в этом

Цитата sergej5500 ()
function give_random_treasure()
give_random_treasure()


Функция начинает вызывать саму себя и происходит переполнение.

Назовите функцию по-другому.


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

Цитата denis2000 ()
Вы из функции вызываете ее-же рекурсивно, гарантированное переполнение стека,


Тогда как её вызвать правильно, без вылета.


Сообщение отредактировал sergej5500 - Вт, 30.12.2014, 19:27
 
makdmДата: Вт, 30.12.2014, 19:35 | Сообщение # 562
Рожденный в СССР
Разработчики
Сообщений: 1294
Награды: 29
Репутация: [ 1909 ]

sergej5500, да как хотите. Например так:

function give_treasure_random()
give_random_treasure()
end


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

Добрый день.

Возникла следующая проблема.

Описание проблемы

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

sergej5500,
talse вместо false:
Код
if r_mod_params("bool","repair_arms_box_parametr",talse) and pistol_in_slot~=nil then

Пропущен and в условии:
Код
if r_mod_params("bool","repair_outfit_box_parametr",false) helm_in_slot and helm_in_slot:condition()<0.01 then


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

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

Функция, отвечающая за отображение СГМ-мин ка карте в СГМ-2.1

[cut=Функция]function submodule_mines_control(object)
if check_seconds(1) and dont_has_alife_info("opt_deactivate_minetrap") and r_mod_params("bool","create_mines_permition",true)==true then
if find_in_string(read_string("minetraps_config","levels","misc\\config_minetraps.ltx"),level.name()) then
for k,v in pairs(sgm_flags.table_mod_mineraps[level.name()]) do
if object~=nil and object:alive() and get_story_object_id(v)~=nil and level.object_by_id(get_story_object_id(v))~=nil
and distance_between(level.object_by_id(get_story_object_id(v)),object)<=r_mod_params("number","mine_traps_radius",4.0) then
if sgm_functions.ReadAvoidMines(object:section())==false then
remove_spot_on_map(get_story_object_id(v),sgm_flags.spot_ground_trap)
detonate_explosive_charge(get_story_object_id(v),false) unregister_story_id(v)
end
end
if db.actor:object("minetrap_detector") or db.actor:object("minetrap_elite_detector") then
if get_story_object_id(v)~=nil then
if db.actor:object("minetrap_elite_detector") then
if level.object_by_id(get_story_object_id(v))~=nil and distance_between(level.object_by_id(get_story_object_id(v)),db.actor)<=75
and level.map_has_object_spot(get_story_object_id(v),sgm_flags.spot_ground_trap)==0 then
play_snd_at_actor([[ambient\special\marsh_beep_1]])
add_spot_on_map(get_story_object_id(v),sgm_flags.spot_ground_trap,"st_minetrap_name")
elseif level.object_by_id(get_story_object_id(v))~=nil and distance_between(level.object_by_id(get_story_object_id(v)),db.actor)>75 then
remove_spot_on_map(get_story_object_id(v),sgm_flags.spot_ground_trap)
end
else
if level.object_by_id(get_story_object_id(v))~=nil and distance_between(level.object_by_id(get_story_object_id(v)),db.actor)<=50
and level.map_has_object_spot(get_story_object_id(v),sgm_flags.spot_ground_trap)==0 then
play_snd_at_actor([[ambient\special\marsh_beep_1]])
add_spot_on_map(get_story_object_id(v),sgm_flags.spot_ground_trap,"st_minetrap_name")
elseif level.object_by_id(get_story_object_id(v))~=nil and distance_between(level.object_by_id(get_story_object_id(v)),db.actor)>50 then
remove_spot_on_map(get_story_object_id(v),sgm_flags.spot_ground_trap)
end
end
end
else
if get_story_object_id(v)~=nil and alife():object(get_story_object_id(v)) then
remove_spot_on_map(get_story_object_id(v),sgm_flags.spot_ground_trap)
end
end
end
end
end
end[/cut]

Если игрок подорвет мину выстрелом или её подорвут собой мутанты или сталкеры, то маркер мины убирается с карты через несколько секунд. Причем закономерность не просматривается. Иногда мина удаляется практически мгновенно, иногда через минуту. Можно ли сделать функцию более стабильной?
 
denis2000Дата: Сб, 03.01.2015, 14:18 | Сообщение # 566
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

sergej5500, Могу предложить только убрать check_seconds(1).

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

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

Известно, что в СГМ альфовцы и прочие противники отлично видят сквозь кусты.

Пришла в головы такая идея. Ставим на локации рестриктор (длин или несколько) с именем esc_no_eye_range_1, esc_no_eye_range_2 и т.д. Рестриктор делаем без логики, со стори-ид и с множеством шейпов. Так, чтобы шейпы накрыли кустарники.

В СГМ я нашел функцию в sgm_modules:

[cut=Функция]function submodule_vision_range(object)
if check_seconds(3) and r_mod_params("bool","night_blindness_range",true)==true and check_range_deterioration_exception(object) then
if present_day() then
if dont_has_alife_info("blackday_is_active") then
if object:range()<=40 then
object:set_range(80)
end
end
else
if dont_has_alife_info("blackday_is_active") then
if object:range()>40 then
object:set_range(20)
end
end
end
if has_alife_info("blackday_is_active") then
if object:range()>40 then
object:set_range(15)
end
end
end
end[/cut]

Если на локации затмение, то обзор неписей падает.

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

Добавлено (05.01.2015, 12:54)
---------------------------------------------
Добрый день.

Возник такой вопрос.

[cut=Функция]function jup_b202_inventory_box_relocate(actor, npc)
local inv_box_out = get_story_object("jup_b202_actor_treasure")
local inv_box_in = get_story_object("jup_b202_snag_treasure")
local items_to_relocate = {}
local function relocate(inv_box_out, item)
table.insert(items_to_relocate, item)
end
inv_box_out:iterate_inventory_box (relocate, inv_box_out)
for k,v in pairs(items_to_relocate) do
inv_box_out:transfer_item(v, inv_box_in)
end
end[/cut]

Можно ли переделать функцию так, чтобы она чистила рюкзак ГГ? Забирала все предметы, кроме квестовых предметов, ножа, фонаря и бинокля. И рандомно перебрасывала их в один из инвентарных ящиков из списка.

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

Цитата sergej5500 ()
Как сделать функцию, отслеживающую попадание НПС в зону такого рестриктора?

Я бы не рекомендовал такое делать - это создаст существенную нагрузку на скрипты...

Цитата sergej5500 ()
И рандомно перебрасывала их в один из инвентарных ящиков из списка.

Можно конечно, берем стандартную функцию переноса предметов инвентаря ГГ в указанный ящик:
Код
function relocate_actor_inventory_to_box(actor, npc, p)
    local function transfer_object_item(item)
     if item:section() ~= "wpn_binoc" and item:section() ~= "wpn_knife" and item:section() ~= "device_torch" then
      db.actor:transfer_item(item, inv_box_1)
     end
    end
    inv_box_1 = get_story_object (p[1])
    actor:inventory_for_each(transfer_object_item)
end

Преобразуется в такую:
Код
function relocate_actor_inventory_to_random_box(actor, npc, p)
    local box_table = {
    [1] = "<ящик 1>",
    [2] = "<ящик 2>",
    [3] = "<ящик 3>"
    }
    local not_relocated_item = {
    ["wpn_binoc"] = true,
    ["wpn_knife"] = true,
    ["device_torch"] = true
    }
    local function transfer_object_item(item)
  if not_relocated_item(item:section())~=true then
   db.actor:transfer_item(item, inv_box_1)
  end
    end
    inv_box_1 = get_story_object(box_table[math.random(1,#box_table)])
    actor:inventory_for_each(transfer_object_item)
end

box_table - таблица стори ид ящиков для рандомного выбора,
not_relocated_item - таблица не перемещаемых объектов
if not_relocated_item(item:section())~=true then - условие не попадания предметов в ящик


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

denis2000,

Попробовал функцию в таком виде.

[cut=xr_effects]function esc_relocate_actor_inventory_to_random_box(actor,npc,p)
local box_table = {
[1] = "esc_inventory_box_13"
}
local not_relocated_item = {
["wpn_binoc"] = true,
["wpn_knife"] = true,
["device_torch"] = true
}
local function transfer_object_item(item)
if not_relocated_item(item:section())~=true then
db.actor:transfer_item(item,inv_box_1)
end
end
inv_box_1 = get_story_object(box_table[math.random(1,#box_table)])
actor:inventory_for_each(transfer_object_item)
end[/cut]

Ящик номер 13 находится неподалеку от точки старта. Вызвал функцию в рестрикторе стартоврго автосейва.

Вылез жук.

[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 : ...shing\Зов Припяти\gamedata\scripts\xr_effects.script:4577: attempt to call upvalue 'not_relocated_item' (a table value)


stack trace:
[/cut]
 
makdmДата: Пн, 05.01.2015, 22:26 | Сообщение # 570
Рожденный в СССР
Разработчики
Сообщений: 1294
Награды: 29
Репутация: [ 1909 ]

sergej5500, чуть-чуть поправил функцию, попробуй так:

function esc_relocate_actor_inventory_to_random_box(actor,npc,p)
local box_table = { "esc_inventory_box_13" }
local not_relocated_item = {
["wpn_binoc"] = true,
["wpn_knife"] = true,
["device_torch"] = true
}
local function transfer_object_item(item)
if not_relocated_item[item:section()] == nil then
db.actor:transfer_item(item,inv_box_1)
end
end
inv_box_1 = get_story_object(box_table[math.random(1,#box_table)])
actor:inventory_for_each(transfer_object_item)
end


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