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


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


"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
strelok200Дата: Вс, 24.08.2014, 15:14 | Сообщение # 526
Бывалый
Свобода
Сообщений: 126
Награды: 0
Репутация: [ 33 ]

FantomICW, Спасибо, конечно, но я воспользуюсь немного другим вариантом
local npc_state = state_mgr.get_state( npc )
if state_lib.states[ npc_state ].animation == "probe_stand" then
 
makdmДата: Вс, 24.08.2014, 17:48 | Сообщение # 527
Рожденный в СССР
Разработчики
Сообщений: 1294
Награды: 29
Репутация: [ 1909 ]

Цитата sergej5500 ()
, чтобы не вылетало?

sergej5500, вместо box прописать npc


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

makdm,

Дмитрий, добрый день. Переделал код так:

[cut=xr_effects]function jup_rasvet_spez_taynik_1_binder(actor,npc)
if find_in_string(npc:section(),"jup_rasvet_spez_taynik_1") and not has_alife_info("jup_rasvet_spez_taynik_1_zalogen") then
if get_item_section_f_inventory_box(box,"detector_elite") and get_item_section_f_inventory_box(box,"medkit")
and get_item_section_f_inventory_box(box,"bandage") and (get_item_section_f_inventory_box(box,"antirad") or get_item_section_f_inventory_box(box,"psy_complex"))
and get_item_section_f_inventory_box(box,"cs_heavy_outfit") and ((get_item_section_f_inventory_box(box,"wpn_abakan")
and get_item_section_f_inventory_box(box,"ammo_5.45x")) or (get_item_section_f_inventory_box(box,"wpn_l85")
and get_item_section_f_inventory_box(box,"ammo_5.56x")) or (get_item_section_f_inventory_box(box,"wpn_wincheaster1300")
and get_item_section_f_inventory_box(box,"ammo_12x"))) then game_hide_menu() give_info("jup_rasvet_spez_taynik_1_zalogen")
end
end
end[/cut]

При подходе к тайнику получил лог.

[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 : ...ogram files 1\Зов Припяти\gamedata\scripts\_g.script:2552: attempt to index local 'obj_box' (a nil value)


stack trace:[/cut]

[cut=_g]-- 'Проверка наличия предметов с указанной частью секции, в инвентарном обьекте.
function get_item_section_f_inventory_box(obj_box,target_item)
local result=false
local function check_items(temp,item)
if item~=nil and find_in_string(item:section(),target_item) then
result=true
return true
end
end
obj_box:iterate_inventory_box(check_items,obj_box)
return result
end[/cut]

2552 строка obj_box:iterate_inventory_box(check_items,obj_box)
 
makdmДата: Вс, 24.08.2014, 18:44 | Сообщение # 529
Рожденный в СССР
Разработчики
Сообщений: 1294
Награды: 29
Репутация: [ 1909 ]

sergej5500, в функцию get_item_section_f_inventory_box передаётся ссылка на клиентский объект
Поэтому в вызове функции везде нужно исправить box на npc

get_item_section_f_inventory_box(npc,"ammo_12x") и т.д.


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


Сообщение отредактировал makdm - Вс, 24.08.2014, 18:45
 
AliceДата: Пн, 25.08.2014, 17:40 | Сообщение # 530
Гражданский
Пользователи
Сообщений: 12
Награды: 0
Репутация: [ 0 ]

Подскажите, пожалуйста, где в ЗП рассчитываются цены на ремонт брони и оружия. Плиззз. sad
 
denis2000Дата: Пн, 25.08.2014, 17:55 | Сообщение # 531
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

Alice, В файле inventory_upgrades.script в функции how_much_repair в строке 190:
Код
return math.floor(cost*(1-item_condition)*cof * cur_price_percent)


"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
AliceДата: Пн, 25.08.2014, 18:23 | Сообщение # 532
Гражданский
Пользователи
Сообщений: 12
Награды: 0
Репутация: [ 0 ]

denis2000, огромное спасибо. А то ремонт в несколько раз превышает стоимость шмотки. Как то не правильно это.

Не подскажите еще , как на разрешение 19:6 (1920 х 1080) оптические прицелы поправить. Они у меня все овальные. Вроде в файле scopes_16.xml нужно что-то сделать , но вот что я не знаю. И гугл выдает только готовые моды.
 
denis2000Дата: Пн, 25.08.2014, 20:01 | Сообщение # 533
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

Alice, Да править нужно файл scopes_16.xml, покажу на примере тега wpn_crosshair:
Код
<wpn_crosshair x="0" y="0" width="1024" height="768">
       <auto_static x="85" y="0" width="854" height="768" stretch="1">
         <texture>wpn_crosshair</texture>
       </auto_static>
       <auto_static x="0" y="0" width="86" height="768" stretch="1">
         <texture>wpn_crosshair_add_l</texture>
       </auto_static>
       <auto_static x="939" y="0" width="85" height="768" stretch="1">
         <texture>wpn_crosshair_add_r</texture>
       </auto_static>
     </wpn_crosshair>

Текст вверху на русском означает, что есть текстура wpn_crosshair с координатами левоговерхнего угла (x, y) 0,0 и размером (width, height) 1024 на 768. Эта текстура составная и состоит из трех: wpn_crosshair, wpn_crosshair_add_l, wpn_crosshair_add_r. Которые размещены на базовой текстуре следующим образом: Текстура wpn_crosshair левый верхний угол в координатах x="85" y="0", размер width="854" height="768", остальные две текстуры призваны закрыть участки не закрытые первой текстурой тоесть x="0" y="0" width="86" height="768" и x="939" y="0" width="85" height="768".
Для того, чтобы расширить по горизонтали нужно увеличивать размер текстуры <texture>wpn_crosshair</texture> параметры x (уменьшать вплоть до 0) и width (увеличивать вплоть до 1024) в теге auto_static (изменять параметры нужно на одну и ту же величину иначе центр текстуры сместиться и прицел перестанет показывать в реальную точку прицеливания), соответственно увеличению центральной текстуры нужно уменьшать боковые текстуры-заглушки.


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

подскажите как правильно совмещать скрипты например вот этот
[cut noguest=скрипт 1]function generic_physics_binder:use_callback(obj,who)
sgm_utilizator.utilizator_reward(self.object)
sgm_callbacks.on_use_box(self.object)
if obj:clsid()==clsid.inventory_box then
local box_name = obj:name()
end
if self.st.active_section then
xr_logic.issue_event(self.object, self.st[self.st.active_scheme], "use_callback", obj, who)
end
if sgm_functions.read_obj_variable(obj,"inv_used")==nil or sgm_functions.read_obj_variable(obj,"inv_used")=="nil" then
sgm_functions.write_obj_variable(obj,"inv_used","searched")
if find_out_string(self.object:section(),"sgm_secret_") and find_out_string(self.object:section(),"dv_") then
sgm_callbacks.on_first_use_box(obj)
end
end
if find_in_string(self.object:section(),"sgm_secret_") then
sgm_callbacks.on_search_secret(self.object)
elseif find_in_string(self.object:section(),"dv_") and find_in_string(self.object:section(),"_unpack") then
sgm_callbacks.on_search_deserve(self.object)
end
end
[/cut]

[cut noguest=скрипт 2]function generic_physics_binder:use_callback(obj, who)
if obj:clsid() == clsid.inventory_box then
local box_name = obj:name()
end
if self.st.active_section then
xr_logic.issue_event(self.object, self.st[self.st.active_scheme], "use_callback", obj, who)
end
-- ARS MOD --------------------------
ars.on_physics_use(obj,who)
-- ARS MOD --------------------------
end
[/cut]

Я совместил так
[cut noguest=скрипт 3]function generic_physics_binder:use_callback(obj,who)
sgm_utilizator.utilizator_reward(self.object)
sgm_callbacks.on_use_box(self.object)
if obj:clsid()==clsid.inventory_box then
local box_name = obj:name()
end
if self.st.active_section then
xr_logic.issue_event(self.object, self.st[self.st.active_scheme], "use_callback", obj, who)
end
if sgm_functions.read_obj_variable(obj,"inv_used")==nil or sgm_functions.read_obj_variable(obj,"inv_used")=="nil" then
sgm_functions.write_obj_variable(obj,"inv_used","searched")
if find_out_string(self.object:section(),"sgm_secret_") and find_out_string(self.object:section(),"dv_") then
sgm_callbacks.on_first_use_box(obj)
end
end
if find_in_string(self.object:section(),"sgm_secret_") then
sgm_callbacks.on_search_secret(self.object)
elseif find_in_string(self.object:section(),"dv_") and find_in_string(self.object:section(),"_unpack") then
sgm_callbacks.on_search_deserve(self.object)
end
if obj:clsid() == clsid.inventory_box then
local box_name = obj:name()
end
if self.st.active_section then
xr_logic.issue_event(self.object, self.st[self.st.active_scheme], "use_callback", obj, who)
end
-- ARS MOD --------------------------
ars.on_physics_use(obj,who)
-- ARS MOD --------------------------
end
end[/cut]
 
denis2000Дата: Ср, 27.08.2014, 08:32 | Сообщение # 535
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

gamer, В первый скрипт добавляем ars.on_physics_use(obj,who). Все скрипты совмещены!
Итого:
Код
function generic_physics_binder:use_callback(obj,who)   
   sgm_utilizator.utilizator_reward(self.object)   
   sgm_callbacks.on_use_box(self.object)   
   if obj:clsid()==clsid.inventory_box then   
    local box_name = obj:name()   
   end   
   if self.st.active_section then   
    xr_logic.issue_event(self.object, self.st[self.st.active_scheme], "use_callback", obj, who)   
   end   
   if sgm_functions.read_obj_variable(obj,"inv_used")==nil or sgm_functions.read_obj_variable(obj,"inv_used")=="nil" then   
    sgm_functions.write_obj_variable(obj,"inv_used","searched")   
    if find_out_string(self.object:section(),"sgm_secret_") and find_out_string(self.object:section(),"dv_") then   
     sgm_callbacks.on_first_use_box(obj)   
    end   
   end   
   if find_in_string(self.object:section(),"sgm_secret_") then   
    sgm_callbacks.on_search_secret(self.object)   
   elseif find_in_string(self.object:section(),"dv_") and find_in_string(self.object:section(),"_unpack") then   
    sgm_callbacks.on_search_deserve(self.object)   
   end
   -- ARS MOD --------------------------   
   ars.on_physics_use(obj,who)   
   -- ARS MOD --------------------------   
end

Более того конструкция:
Код
if obj:clsid()==clsid.inventory_box then   
    local box_name = obj:name()   
   end

Вообше никому не нужна, поскольку переменная box_name далее нигде не используется, а у вас этот код дважды замонстрячен. И эвент дважды выдается на использование объекта.


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

Подскажите где ошибка

[cut noguest=скрипт]function motivator_binder:net_destroy()
if rx_ai then rx_ai.npc_net_destroy(self.object) end
xrs_dyn_music.npc_table[self.object:id()] = nil
xr_combat_ignore.fighting_with_actor_npcs[self.object:id()] = nil
xr_sound.stop_sounds_by_id(self.object:id())
local st = db.storage[self.object:id()]
if st.active_scheme then
xr_logic.issue_event(self.object, st[st.active_scheme], "net_destroy", self.object)
end
if self.st.reach_task then
xr_logic.issue_event(self.object, self.st.reach_task, "net_destroy", self.object)
end
local on_offline_condlist = db.storage[self.object:id()] and db.storage[self.object:id()].overrides and db.storage[self.object:id()].overrides.on_offline_condlist
if on_offline_condlist ~= nil then
xr_logic.pick_section_from_condlist(db.actor, self.object, on_offline_condlist)
end
if db.offline_objects[self.object:id()] then
db.offline_objects[self.object:id()].level_vertex_id = self.object:level_vertex_id()
db.offline_objects[self.object:id()].active_section = db.storage[self.object:id()].active_section
end
db.del_obj(self.object)
db.storage[self.object:id()] = nil
self:clear_callbacks()
if self.e_index ~= nil then
db.delete_enemy( self.e_index )
end
object_binder.net_destroy(self)
end[/cut]

[cut noguest=Лог]* Game vicsi - quicksave.scop is successfully saved to file 'profiles\savedgames\vicsi - quicksave.scop'
* [win32]: free[2317444 K], reserved[233460 K], committed[1643336 K]
* [ D3D ]: textures[538098 K]
* [x-ray]: crt heap[440690 K], process heap[12924 K], game lua[45899 K], render[1886 K]
* [x-ray]: economy: strings[53234 K], smem[16530 K]
* Saving spawns...
* Saving objects...
* 13892 objects are successfully saved
* Game vicsi - quicksave.scop is successfully saved to file 'profiles\savedgames\vicsi - quicksave.scop'

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 : ...talker sigerous\gamedata\scripts\xr_motivator.script:121: attempt to call field 'npc_net_destroy' (a nil value)


stack trace:
[/cut]
 
sergej5500Дата: Вт, 09.09.2014, 23:43 | Сообщение # 537
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
Награды: 29
Репутация: [ 1355 ]

Добрый вечер. Интересует такой момент.

1. Функция спавна мертвого сталкера.
xr_effects.spawn_corpse(actor, nil, {"sim_default_monolith_4","pri_ecolog_briefing_spawn"})

2. Допустим, что у нас есть список спавн-пойнтов. zat_dead_spawn_1, zat_dead_spawn_2, zat_dead_spawn_3, zat_dead_spawn_4, zat_dead_spawn_5, ... и т.д. Всего 20. Или 30.

3. Допустим, что имеется список мертвых сталкеров. sim_default_duty_0, sim_default_duty_1, sim_default_duty_2, ... и т.д.
Всего 30. Или 40.

Можно ли написать функцию, которая на каждом из входящих в список спавн-пойнте рандомно заспавнит одного сталкера из входящих в список мертвых сталкеров? Как такая функция будет выглядеть?
 
makdmДата: Ср, 10.09.2014, 09:24 | Сообщение # 538
Рожденный в СССР
Разработчики
Сообщений: 1294
Награды: 29
Репутация: [ 1909 ]

sergej5500, попробуй так ( в таблицы можно добавлять сколько угодно секций и точек спавна ), сделано для трёх точек и трёх секций сталкеров
[cut noguest]
function spawn_corpse_random()
local section_table = {"sim_default_duty_0","sim_default_duty_1","sim_default_duty_2"}
local point_table = {"zat_dead_spawn_1","zat_dead_spawn_2","zat_dead_spawn_3"}
for i = 1, #point_table do
xr_effects.spawn_corpse(actor, nil, {section_table[math.random(#section_table)],point_table[i]})
end
end
[/cut]
Добавлено (10.09.2014, 09:08)
---------------------------------------------
Есть и второй вариант. Если точно известно количество точек спавна и они называются одинаково, а меняется только цифра на конце, а также известно точное количество секций сталкеров и они также одинаковы в названии и меняется также только цифра на конце, то чтобы не заниматься писаниной больших таблиц, скрипт можно переделать.

Например секции сталкеров: sim_default_duty_1 ... sim_default_duty_40
Имена точек: zat_dead_spawn_1 ... zat_dead_spawn_30

Тогда функция будет такой
[cut noguest]
function spawn_corpse_random()
for i = 1, 30 do
local section_index = math.random(1,40)
local section = "sim_default_duty_"..section_index
local point = "zat_dead_spawn_"..i
xr_effects.spawn_corpse(actor, nil, {section,point})
end
end[/cut]

Добавлено (10.09.2014, 09:24)
---------------------------------------------
gamer, в файле gamedata\scripts\rx_ai.script не найдена функция npc_net_destroy


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


Сообщение отредактировал makdm - Ср, 10.09.2014, 09:25
 
gamerДата: Ср, 10.09.2014, 15:19 | Сообщение # 539
Новичок
Пользователи
Сообщений: 82
Награды: 0
Репутация: [ 0 ]

Правильно понимаю,shader font2 не находит ?

[cut noguest=log]* Game lederlager - начало игры.scop is successfully saved to file 'profiles\savedgames\lederlager - начало игры.scop'
compiling shader font2

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 : d:\stalker sigerous\gamedata\scripts\_g.script:846: bad argument #3 to 'format' (string expected, got nil)


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

gamer, после вылета в папке gamedata открой файл mod_crash_log.txt и посмотри там причину вылета

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