Модостроение. Редактирование и создание скриптов
|
|
denis2000 | Дата: Пн, 10.10.2011, 21:17 | Сообщение # 1 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| Редактирование и создание скриптов Редактирование и создание скриптов на языке 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 по ссылке из шапки и соседнюю тему "Курс молодого бойца", возможно Ваш вопрос уже рассматривался.
Если произошел вылет - выкладываем лог! Вопрос ставим четко, не забываем указывать версию игры, установленные моды их версии, установленные фиксы модов и подробно ваши правки. Помните чем подробнее вопрос, тем точнее ответ.
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
denis2000 | Дата: Чт, 09.06.2016, 08:21 | Сообщение # 796 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| Цитата sergej5500 ( ) Как отследить, сколько игрок проспал в постели? В функции sleep_callback() параметр rnd = math.random(6,12) В скрипте ui_sleep_dialog.script в функции dream_callback() параметр hours = sleep_control.time_track:GetIValue()
Цитата sergej5500 ( ) вызвать пошатывание игрока и расплывание предметов перед глазами...Какие скрипты подойдут? level.add_complex_effector(Имя_эффекта, ИД_эффекта) конечно. Или по отдельности level.add_pp_effector и level.add_cam_effector
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
sergej5500 | Дата: Чт, 09.06.2016, 09:33 | Сообщение # 797 |
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
| denis2000,
За помощь спасибо.
Цитата denis2000 ( ) В функции sleep_callback() параметр rnd = math.random(6,12)
Функция sleep_callback() обеспечивает принудительное засыпание игрока после суток активности. Я спрашивал про сон в постели. Спальное место на Скадовске или Янове.
|
|
|
Эти 0 пользователя(ей) поблагодарили sergej5500 за это полезное сообщение: |
|
|
denis2000 | Дата: Чт, 09.06.2016, 10:02 | Сообщение # 798 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| Цитата sergej5500 ( ) Я спрашивал про сон в постели. Спальное место на Скадовске или Янове. Я таки написал оба варианта.
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
sergej5500 | Дата: Пт, 10.06.2016, 00:23 | Сообщение # 799 |
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
| denis2000,
Попробовал применить параметр hours.
Мои правки.
[cut=bind_stalker] function actor_binder:check_sleep_control() if self.check_sleep_control_time == nil then self.check_sleep_control_time = game.get_game_time() end if game.get_game_time():diffSec(self.check_sleep_control_time) > 86400 then xr_effects.disable_ui(db.actor, nil) level.add_cam_effector("camera_effects\\sleep.anm", 10, false, "bind_stalker.dream_callback") level.add_pp_effector("sleep_fade.ppe", 11, false) db.actor:give_info_portion("actor_is_sleeping") _G.mus_vol = get_console():get_float("snd_volume_music") _G.amb_vol = get_console():get_float("snd_volume_eff") get_console():execute("snd_volume_music 0") get_console():execute("snd_volume_eff 0") surge_manager.resurrect_skip_message() self.check_sleep_control_time = game.get_game_time() end end
function dream_callback() level.add_cam_effector("camera_effects\\sleep.anm", 10, false, "bind_stalker.dream_callback2") local hours = math.random(6,9) level.change_game_time(0,hours/3600,0) level_weathers.get_weather_manager():forced_weather_change() surge_manager.get_surge_manager().time_forwarded = true if(surge_manager.is_started() and level_weathers.get_weather_manager().weather_fx) then level.stop_weather_fx() -- level_weathers.get_weather_manager():select_weather(true) level_weathers.get_weather_manager():forced_weather_change() end db.actor.power = 1 printf("dream_callback: time forwarded on [%d]", hours) end
function dream_callback2() xr_effects.enable_ui(db.actor, nil) get_console():execute("snd_volume_music "..tostring(_G.mus_vol)) get_console():execute("snd_volume_eff "..tostring(_G.amb_vol)) _G.amb_vol = 0 _G.mus_vol = 0 end[/cut]
Этот код работает. Игрок засыпает принудительно.
[cut=ui_sleep_dialog] function dream_callback() level.add_cam_effector("camera_effects\\sleep.anm", 10, false, "ui_sleep_dialog.dream_callback2") local hours = sleep_control.time_track:GetIValue() level.change_game_time(0,hours,0) level_weathers.get_weather_manager():forced_weather_change() surge_manager.get_surge_manager().time_forwarded = true if(surge_manager.is_started() and level_weathers.get_weather_manager().weather_fx) then level.stop_weather_fx() -- level_weathers.get_weather_manager():select_weather(true) level_weathers.get_weather_manager():forced_weather_change() end db.actor.power = 1 printf("dream_callback: time forwarded on [%d]", hours) if hours >= 7 then game.get_game_time():diffSec(self.check_sleep_control_time)==60 else game.get_game_time():diffSec(self.check_sleep_control_time) == game.get_game_time():diffSec(self.check_sleep_control_time) - hours*3600 end end
function dream_callback2() xr_effects.enable_ui(db.actor, nil) get_console():execute("snd_volume_music "..tostring(_G.mus_vol)) get_console():execute("snd_volume_eff "..tostring(_G.amb_vol)) _G.amb_vol = 0 _G.mus_vol = 0 db.actor:give_info_portion("tutorial_sleep") disable_info("actor_is_sleeping") disable_info("sleep_active") 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 : ...shing\Зов Припяти\gamedata\scripts\xr_effects.script:2850: attempt to index global 'ui_sleep_dialog' (a nil value)
stack trace: [/cut]
Ошибка где то в коде
if hours >= 7 then game.get_game_time():diffSec(self.check_sleep_control_time)==60 else game.get_game_time():diffSec(self.check_sleep_control_time) == game.get_game_time():diffSec(self.check_sleep_control_time) - hours*3600 end
Но я её не вижу.
|
|
|
Эти 0 пользователя(ей) поблагодарили sergej5500 за это полезное сообщение: |
|
|
denis2000 | Дата: Пт, 10.06.2016, 08:35 | Сообщение # 800 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| Цитата sergej5500 ( ) Но я её не вижу. Вот ошибка:
Код game.get_game_time():diffSec(self.check_sleep_control_time)==60 И вот ошибка:
Код game.get_game_time():diffSec(self.check_sleep_control_time) == game.get_game_time():diffSec(self.check_sleep_control_time) - hours*3600 Бинарная переменная не может быть оператором!
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
sergej5500 | Дата: Пт, 10.06.2016, 09:30 | Сообщение # 801 |
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
| Цитата denis2000 ( ) Бинарная переменная не может быть оператором!
Как тогда ей поменять значение?
|
|
|
Эти 0 пользователя(ей) поблагодарили sergej5500 за это полезное сообщение: |
|
|
denis2000 | Дата: Пт, 10.06.2016, 12:00 | Сообщение # 802 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| sergej5500, Кому ей? Объясните, что вам требуется.
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
sergej5500 | Дата: Пт, 10.06.2016, 12:12 | Сообщение # 803 |
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
| Цитата denis2000 ( ) Объясните, что вам требуется.
Я добавил в игру таймер check_sleep_control_time. После суточной активности (без сна) он принудительно усыпит игрока на 6-9 часов.
Если игрок спал в кровать 7 и более часов, то таймеру нужно присвоить значение 0. Игрок выспался.
Если игрок спал меньше 7 часов, то значение таймера нужно уменьшить на кол-во часов, которые проспал игрок.
Реально ли это сделать?
|
|
|
Эти 0 пользователя(ей) поблагодарили sergej5500 за это полезное сообщение: |
|
|
denis2000 | Дата: Пт, 10.06.2016, 14:25 | Сообщение # 804 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| sergej5500, Я понимаю что вы хотите сделать глобально! Я не понимаю что вы конкретно хотели добиться вот этими строками:
Код if hours >= 7 then game.get_game_time():diffSec(self.check_sleep_control_time)==60 else game.get_game_time():diffSec(self.check_sleep_control_time) == game.get_game_time():diffSec(self.check_sleep_control_time) - hours*3600 end
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
sergej5500 | Дата: Пт, 10.06.2016, 14:51 | Сообщение # 805 |
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
| Цитата denis2000 ( ) Я не понимаю что вы конкретно хотели добиться вот этими строками:
Хотел поменять значение таймера.
|
|
|
Эти 0 пользователя(ей) поблагодарили sergej5500 за это полезное сообщение: |
|
|
denis2000 | Дата: Пт, 10.06.2016, 22:35 | Сообщение # 806 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| sergej5500, Таймер у вас вот:
Цитата if game.get_game_time():diffSec(self.check_sleep_control_time) > 86400 then self.check_sleep_control_time - это дата/время последнего сна ГГ. Причем self.check_sleep_control_time в скрипте ui_sleep_dialog.script и self.check_sleep_control_time в скрипте bind_stalker.script это РАЗНЫЕ переменные!
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
sergej5500 | Дата: Сб, 18.06.2016, 17:10 | Сообщение # 807 |
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
| Добрый день.
Имеется объект inventory_box с логикой. При удалении игрока на определённую дистанцию объект должен удалить своё содержимое. Написал функцию. Функция вызывается из логики этого бокса.
on_info2 = {=dist_to_actor_ge(10)} %=utilizators_clean%
[cut=Функция] function utilizators_clean(box,victim) local function calc(box,item) if item~=nil then if alife():object(item:id()) then alife():release(alife():object(item:id()),true) end end end box:iterate_inventory_box(calc,box) end [/cut]
Функция не работает. Или чистит инвентарь игрока. Как её поправить, чтобы заработала?
|
|
|
Эти 0 пользователя(ей) поблагодарили sergej5500 за это полезное сообщение: |
|
|
makdm | Дата: Сб, 18.06.2016, 17:26 | Сообщение # 808 |
Рожденный в СССР
Разработчики
Сообщений: 1294
| sergej5500, вместо
function utilizators_clean(box,victim)
должно быть
function utilizators_clean(actor, box)
Терпение...... И все получится!
|
|
|
Эти 0 пользователя(ей) поблагодарили makdm за это полезное сообщение: |
|
|
sergej5500 | Дата: Вс, 19.06.2016, 16:40 | Сообщение # 809 |
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
| Добрый день. Хочу вернуться к вопросу, который задавал несколькими постами выше. О принудительном засыпании игрока. Частично решил задачу.
[cut=_g.script] -- 'Прибавить к pstor-счетчику цифру. function IncCounter(counter_name,add_value) if ReadVariable(counter_name)==nil then WriteVariable(counter_name,0) end if add_value==nil then add_value=1 end if ReadVariable(counter_name)~=nil then local counter=ReadVariable(counter_name) WriteVariable(counter_name,counter+add_value) end end
-- 'Отнять от pstor-счетчика цифру. function DecCounter(counter_name,add_value) if ReadVariable(counter_name)==nil then WriteVariable(counter_name,0) end if add_value==nil then add_value=1 end if ReadVariable(counter_name)~=nil then local counter=ReadVariable(counter_name) WriteVariable(counter_name,counter-add_value) end end
-- 'Запись pstor переменной. function WriteVariable(params_name,value) if value==nil then ClearVariable(params_name) else local opt=ReloadParams(params_name) PstorStore(db.actor,opt,value) end end
-- 'Чтение pstor переменной. function ReadVariable(params_name) local opt=ReloadParams(params_name) return PstorRetrieve(db.actor,opt) end
-- 'Удаление pstor переменной. function ClearVariable(params_name) local opt=ReloadParams(params_name) if db.storage[db.actor:id()].pstor[opt] then db.storage[db.actor:id()].pstor[opt]=nil end end
function PstorStore(obj,varname,val) if obj==nil then return nil end local sub_id=obj:id() if db.storage[sub_id].pstor==nil then db.storage[sub_id].pstor={} end db.storage[sub_id].pstor[varname]=val end
function PstorRetrieve(obj,varname) if obj==nil then return nil end local sub_id=obj:id() if db.storage[sub_id].pstor~=nil then local val=db.storage[sub_id].pstor[varname] if val~=nil then return val end end return nil end
function ReloadParams(params) return params end [/cut]
[cut=bind_stalker]function actor_binder:actor_universal_binder() if self.actor_universal_time == nil then self.actor_universal_time = game.get_game_time() end if game.get_game_time():diffSec(self.actor_universal_time) > 60 then addon_binder.actor_update() self.actor_universal_time = game.get_game_time() end end [/cut]
Таймер запускает скрипт контроля один раз в минуту.
[cut=addon_binder]function actor_update() actor_sleep_control() end
function actor_sleep_control() if ReadVariable("universal_sleep_factot") == nil then WriteVariable("universal_sleep_factot",1) else IncCounter("universal_sleep_factot") end addon_binder.universal_sleep_control() end
function universal_sleep_control() if ReadVariable("universal_sleep_factot") >= 1440 then xr_effects.disable_ui(db.actor, nil) level.add_cam_effector("camera_effects\\sleep.anm", 10, false, "addon_binder.dream_callback") level.add_pp_effector("sleep_fade.ppe", 11, false) db.actor:give_info_portion("actor_is_sleeping") _G.mus_vol = get_console():get_float("snd_volume_music") _G.amb_vol = get_console():get_float("snd_volume_eff") get_console():execute("snd_volume_music 0") get_console():execute("snd_volume_eff 0") surge_manager.resurrect_skip_message() end end
function dream_callback() level.add_cam_effector("camera_effects\\sleep.anm", 10, false, "addon_binder.dream_callback2") local hours = math.random(6,10) level.change_game_time(0,hours,0) level_weathers.get_weather_manager():forced_weather_change() surge_manager.get_surge_manager().time_forwarded = true if (surge_manager.is_started() and level_weathers.get_weather_manager().weather_fx) then level.stop_weather_fx() -- level_weathers.get_weather_manager():select_weather(true) level_weathers.get_weather_manager():forced_weather_change() end db.actor.power = 1 printf("dream_callback: time forwarded on [%d]", hours) WriteVariable("universal_sleep_factot",1) end
function dream_callback2() xr_effects.enable_ui(db.actor, nil) get_console():execute("snd_volume_music "..tostring(_G.mus_vol)) get_console():execute("snd_volume_eff "..tostring(_G.amb_vol)) _G.amb_vol = 0 _G.mus_vol = 0 db.actor:give_info_portion("tutorial_sleep") disable_info("actor_is_sleeping") disable_info("sleep_active") end
[/cut]
[cut=ui_sleep_dialog]function dream_callback() level.add_cam_effector("camera_effects\\sleep.anm", 10, false, "ui_sleep_dialog.dream_callback2") local hours = sleep_control.time_track:GetIValue() level.change_game_time(0,hours,0) level_weathers.get_weather_manager():forced_weather_change() surge_manager.get_surge_manager().time_forwarded = true if(surge_manager.is_started() and level_weathers.get_weather_manager().weather_fx) then level.stop_weather_fx() -- level_weathers.get_weather_manager():select_weather(true) level_weathers.get_weather_manager():forced_weather_change() end db.actor.power = 1 printf("dream_callback: time forwarded on [%d]", hours) if ReadVariable("universal_sleep_factot") == nil then WriteVariable("universal_sleep_factot",1) end if hours >= 6 then WriteVariable("universal_sleep_factot",1) else DecCounter("universal_sleep_factot",hours*60) end --if not ReadVariable("universal_sleep_factot") > 1 then --WriteVariable("universal_sleep_factot",1) --end end[/cut]
В игре фигурирует счетчик universal_sleep_factot. Она возрастает один раз в минуту на единицу. Когда она увеличится до 1440, игрок уснет принудительно. Это всё работает. При сне в постели значение счетчика уменьшается. За это отвечает скрипт
if ReadVariable("universal_sleep_factot") == nil then WriteVariable("universal_sleep_factot",1) end if hours >= 6 then WriteVariable("universal_sleep_factot",1) else DecCounter("universal_sleep_factot",hours*60) end --if not ReadVariable("universal_sleep_factot") > 1 then --WriteVariable("universal_sleep_factot",1) --end
Возникает вопрос, что будет, если счётчик примет отрицательное значение. Я написал проверку. Но игра этот код
if not ReadVariable("universal_sleep_factot") > 1 then WriteVariable("universal_sleep_factot",1) end
не принимает. Вылет с логом
[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 : ...\Зов Припяти\gamedata\scripts\ui_sleep_dialog.script:153: attempt to compare number with boolean
stack trace:[/cut]
153 строка --if not ReadVariable("universal_sleep_factot") > 1 then
Без этой проверки всё работает.
Как правильно проверить, не принял ли счётчик отрицательное значение?
|
|
|
Эти 0 пользователя(ей) поблагодарили sergej5500 за это полезное сообщение: |
|
|
denis2000 | Дата: Вс, 19.06.2016, 19:22 | Сообщение # 810 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| Цитата sergej5500 ( ) attempt to compare number with boolean ReadVariable("universal_sleep_factot") возвращает бинарную переменную, а вы ее сравниваете с числом, что не возможно в данной версии Матрицы.
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
|