Модостроение. Создание и редактирование квестов
|
|
denis2000 | Дата: Пн, 10.10.2011, 21:25 | Сообщение # 1 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| Создание и редактирование квестов Создание новых квестов и редактирование существующих Если у вас появились вопросы по созданию и редактированию квестов, изменению существующих и добавлению новых в игру. Задавайте их в этой теме - умные головы, модосторители и просто разбирающиеся в программировании люди вам ответят.
Много интересного материала здесь (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 за это полезное сообщение: |
|
|
NIV | Дата: Ср, 25.09.2013, 12:59 | Сообщение # 151 |
Полевой исследователь
Ученые сталкеры
Сообщений: 167
| Коллеги, как вы считаете, можно ли в ЗП вернуть в ПДА некоторые функции из ПДА ТЧ, а именно: 1) добавить страничку "проваленные задания" (всего-то нарисовать новый элемент GUI) и 2) вернуть таймер на задания, типа "осталось 16 часов до провала"; 3) и др. - "Энциклопедия" и т.п. ? А может, в каком-то моде это уже реализовано? Добавлено (25.09.2013, 12:59) --------------------------------------------- Volk66, здесь, конечно не очень хороший поиск, тогда юзай "расширенный поиск" Яндекса по этому форуму. И всё найдется, например, сообщения 206 - 207.
Изменяем реальность S.T.A.L.K.E.R. CoP: "Цена Новых Исследований" / "New Investigations' Value"
|
|
|
Эти 0 пользователя(ей) поблагодарили NIV за это полезное сообщение: |
|
|
denis2000 | Дата: Вт, 01.10.2013, 09:13 | Сообщение # 152 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| Цитата (NIV) Коллеги, как вы считаете, можно ли в ЗП вернуть в ПДА некоторые функции из ПДА ТЧ Теоритически это вполне возможно, есть ли мод с такой реализацией в свободном доступе - не знаю, сам поищи.
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
NIV | Дата: Сб, 05.10.2013, 22:29 | Сообщение # 153 |
Полевой исследователь
Ученые сталкеры
Сообщений: 167
| Попробовал вместо таймера в ПДА сделать таймер на экране через sr_timer.script. Но поскольку он управляется из рестриктора, получается забавная вещь: уходишь с локации - таймера нет, возвращаешься - таймер продолжает отсчет. А хотелось бы, чтобы и на другой локации таймер продолжался. Как можно считать остаток времени и передать его в качестве параметра рестриктору на новой локации?
Изменяем реальность S.T.A.L.K.E.R. CoP: "Цена Новых Исследований" / "New Investigations' Value"
|
|
|
Эти 0 пользователя(ей) поблагодарили NIV за это полезное сообщение: |
|
|
FantomICW | Дата: Сб, 05.10.2013, 23:05 | Сообщение # 154 |
Лидер «Свободы»
Свобода
Сообщений: 4438
| NIV, рекомендую глянуть схему работы армейского таймера в SGM. Там все построено на очень простой форме в XML и скриптами, которые вполне реально разобрать. [cut=XML-форма]Код <!-----[Военный таймер]------> <army_timer_form x="69" y="518" width="281" height="229"> <texture>ui_mod_timer_main_wnd</texture> <btn_start x="93" y="81" width="122" height="23"> <texture_e>ui_button_ordinary_e</texture_e> <texture_t>ui_button_ordinary_t</texture_t> <texture_h>ui_button_ordinary_h</texture_h> <text font="letterica16">st_army_timer_start</text> </btn_start> <btn_stop x="93" y="115" width="122" height="23"> <texture_e>ui_button_ordinary_e</texture_e> <texture_t>ui_button_ordinary_t</texture_t> <texture_h>ui_button_ordinary_h</texture_h> <text font="letterica16">st_army_timer_reset</text> </btn_stop> <btn_close x="93" y="168" width="122" height="23"> <texture_e>ui_button_ordinary_e</texture_e> <texture_t>ui_button_ordinary_t</texture_t> <texture_h>ui_button_ordinary_h</texture_h> <text font="letterica16">st_menu_close</text> </btn_close> <timer_value x="115" y="35" width="220" height="16"> <text r="154" g="205" b="50" a="100" align="c" font="letterica16"></text> </timer_value> </army_timer_form> [/cut] [cut=Скриптовая прорисовка ]Код army_timer_value=0 army_timer_deprive=0 army_timer_active=false class "army_timer" (CUIScriptWnd) function army_timer:__init(owner) super() self.owner = owner self:InitControls() self:InitCallBacks() end function army_timer:__finalize() end function army_timer:InitControls() self:SetWndRect(Frect():set(0,0,1024,768)) local xml = CScriptXmlInit() xml:ParseFile("ui_mod_elements.xml") self.army_timer_form=xml:InitStatic("army_timer_form",self) self:Register(xml:Init3tButton("army_timer_form:btn_start",self.army_timer_form),"btn_start") self:Register(xml:Init3tButton("army_timer_form:btn_close",self.army_timer_form),"btn_close") self:Register(xml:Init3tButton("army_timer_form:btn_stop",self.army_timer_form),"btn_stop") self.timer_value=xml:InitStatic("army_timer_form:timer_value",self.army_timer_form) end function army_timer:Update() CUIScriptWnd.Update(self) if not object_alive(db.actor) then self:btn_close() end if army_timer_active==true then army_timer_value=string.format(math.floor(time_global()/1000))-army_timer_deprive else if army_timer_value>0 then army_timer_value=0 end end self.timer_value:TextControl():SetText(army_timer_value) end function army_timer:InitCallBacks() self:AddCallback("btn_start",ui_events.BUTTON_CLICKED,self.btn_start,self) self:AddCallback("btn_stop",ui_events.BUTTON_CLICKED,self.btn_stop,self) self:AddCallback("btn_close",ui_events.BUTTON_CLICKED,self.btn_close,self) end function army_timer:OnKeyboard(dik,keyboard_action) CUIScriptWnd.OnKeyboard(self,dik,keyboard_action) if keyboard_action == ui_events.WINDOW_KEY_PRESSED then if dik == DIK_keys.DIK_ESCAPE then self:btn_close() end end return true end function army_timer:btn_start() army_timer_active=true army_timer_deprive=string.format(math.floor(time_global()/1000)) end function army_timer:btn_stop() army_timer_active=false end function army_timer:btn_close() give_object_to_actor("army_timer") self:HideDialog() end [/cut]
Сообщение отредактировал FantomICW - Сб, 05.10.2013, 23:07 |
|
|
Эти 0 пользователя(ей) поблагодарили FantomICW за это полезное сообщение: |
|
|
NIV | Дата: Пн, 07.10.2013, 20:24 | Сообщение # 155 |
Полевой исследователь
Ученые сталкеры
Сообщений: 167
| FantomICW, сам таймер, может быть и не сложный. Сложно все остальное. Сейчас пытаюсь понять идеологию (sgm_loader.script). Там есть менеджер сохранений, менеджер худа и менеджер таймера. И все их надо переносить. Я ничего не упустил?
Изменяем реальность S.T.A.L.K.E.R. CoP: "Цена Новых Исследований" / "New Investigations' Value"
|
|
|
Эти 0 пользователя(ей) поблагодарили NIV за это полезное сообщение: |
|
|
FantomICW | Дата: Пн, 07.10.2013, 21:21 | Сообщение # 156 |
Лидер «Свободы»
Свобода
Сообщений: 4438
| NIV, да, есть там некий апдейт таймера. Тебя должна интересовать, в таком случае, строчка Код sgm_timers.timers_main() Скажем так, вероятно, чтобы не впихивать в апдейт bind_stalker.script все SGM-скрипты, Николай вынес их в отдельный файл - sgm_loader.script. Строчки из bind_stalker.script: Код --/ SGM in if mod_update() then sgm_loader.sigerous_mod_main() end --/ SGM out А там уже через функцию sigerous_mod_main запускается функция SGM-апдейта. Выходит, вызов апдейта таймера можно вызвать просто через bind_stalker.script. Логично? А теперь к самому таймеру. Итак, вызывается функция timers_main из sgm_timers.script, там уже и timers_update. Если важен только армейский таймер, все сокращается: [cut=Код]Код function timers_main() timers_update() end function timers_update() --//Таймер армейских часов//--> if ui_mod_elements.army_timer_active==true then ui_mod_elements.army_timer_value=string.format(math.floor(time_global()/1000))-ui_mod_elements.army_timer_deprive else if ui_mod_elements.army_timer_value>0 then ui_mod_elements.army_timer_value=0 end end end [/cut] Как-то так. Вроде не сложно?
Сообщение отредактировал FantomICW - Пн, 07.10.2013, 21:22 |
|
|
Эти 0 пользователя(ей) поблагодарили FantomICW за это полезное сообщение: |
|
|
NIV | Дата: Вт, 08.10.2013, 18:10 | Сообщение # 157 |
Полевой исследователь
Ученые сталкеры
Сообщений: 167
| Я почти перенес армейский таймер. Там важно использовать еще и менеджер худа (sgm_huds.scripts)(в нем есть такие строки: [cut]Код function CHudManager:hud_utils()
if timer.army_timer_active==true then local data_timer=timer.army_timer_value add_hud("hud_timer_wnd",data_timer) else -- if check_seconds(2) then release_hud("hud_timer_wnd") --end end (закомментировал уже я)[/cut] Пишу "почти перенес", потому что в SGM многое сделано через флаги , а чтобы перенести их обработку, нужно переносить слишком много функций. Например [cut] в (sgm_huds.scripts) есть переменнаяlocal hud_elements_precond=precond_hud(1). А в _g.script : Код function precond_hud(type) if type==nil or type==1 then return (not db.actor:is_talking()) and object_alive(db.actor) and check_ui_worked(true) and dont_has_alife_info("inventory_wnd_opened") and dont_has_alife_info("sleep_active") and dont_has_alife_info("actor_in_sleep") and dont_has_alife_info("screenshot_mode") - а это проверки на функциях SGM и инфо оттуда же. [/cut] Пришлось в тестовых целях убрать эти проверки.
Самая большая проблема в том, что при переходе на другую локацию таймер закрывается и сбрасывается. Пока я не понял, можно ли запомнить значение отсчитанного времени и на другой локации снова запустить таймер автоматом с этого значения.
P.S. Только что понял - армейский таймер показывает реальное время, а не игровое! Используется time_global(). А мне надо игровое - как перевести?
Изменяем реальность S.T.A.L.K.E.R. CoP: "Цена Новых Исследований" / "New Investigations' Value"
Сообщение отредактировал NIV - Вт, 08.10.2013, 20:42 |
|
|
Эти 0 пользователя(ей) поблагодарили NIV за это полезное сообщение: |
|
|
FantomICW | Дата: Вт, 08.10.2013, 18:52 | Сообщение # 158 |
Лидер «Свободы»
Свобода
Сообщений: 4438
| NIV, попробуй еще это (на АМК нашел): Код local iTimer local last function start_timer_minutes_test(seconds) if last~= nil then iTimer = time_global()+last --/ взводим таймер на остаток времени last else iTimer = time_global() + 7*1000 --/ взводим таймер например 7 сек. end end
function timer_n_minutes_test() --/ вызывается из ':update' сталкер-биндера if iTimer then last=iTimer-time_global() -- присваиваем переменной остаток времени до конца работы таймера if iTimer < time_global() then iTimer = nil --/ выключаем таймер last=nil СКРИПТ.ФУНКЦИЯ--/ выполняем действие end end end
-- выводим значение таймера в обратном отсчете на худ function hud_static() --/ вызывается из ':update' сталкер-биндера local hud = get_hud() local st if iTimer then st = hud:GetCustomStatic("hud_timer") if st==nil then hud:AddCustomStatic("hud_timer", true) st = hud:GetCustomStatic("hud_timer") end if last~=nil then local hours = math.floor(last/3600000) local minutes = math.floor(last/60000 - hours*60) local seconds = math.floor(last/1000 - hours*3600 - minutes*60) local text = string.format("%02d:%02d:%02d",hours,minutes,seconds) -- выводим время в формате 00:00:00 --local text=string.format("%.f",last/1000) st:wnd():SetTextST(text) end else if hud:GetCustomStatic("hud_timer")~=nil then hud:RemoveCustomStatic("hud_timer") end end end
|
|
|
Эти 0 пользователя(ей) поблагодарили FantomICW за это полезное сообщение: |
|
|
NIV | Дата: Сб, 12.10.2013, 15:26 | Сообщение # 159 |
Полевой исследователь
Ученые сталкеры
Сообщений: 167
| Возвращаясь к таймерам: Реализовал убывающий таймер на основе армейского из SGM. Отсчёт времени происходит на основе переменных: Код niv_quest_timer_start_value=string.format(math.floor(time_global()/1000)) и niv_quest_timer_value=niv_quest_timer_limit_timer_value-(string.format(math.floor(time_global()/1000))-niv_quest_timer_start_value)*11 Таймер работает от реального времени. На 11 умножаем для того, чтобы подогнать это время под игровое. При загрузке сейва, использовании спальника или перехода на другую локацию, таймер продолжает отсчёт, здесь всё нормально.
Но потом возникает проблема с перемоткой времени: например, при переходе между локациями, таймер меняется только на то время, которое проходит по часам компьютера*11, а не на 4 часа, как сдвигается игровое время.
Попробовал вместо time_global() использовать game.time(). При этом получается такой эффект: если ничего не трогать, таймер идёт нормально, но при переходе на другую локацию, от таймера отнимается 4 часа (как и нужно), а когда загружается другая локация, таймер показывает отрицательное время, порядка -11 тыс часов. Либо при сохранении и последующей загрузке таймер также показывает такое отрицательное время.
Я полагаю, что в этом случае либо неправильно сохраняются переменные, либо у них неправильный формат? Если пробовать поменять функцию на game.get_game_time() - то сразу вылет (неправильное использование???)
Требуется помощь: либо как ввести перемотку времени при использовании time_global(), либо как правильно использовать game.time() - подскажите, пожалуйста!
Изменяем реальность S.T.A.L.K.E.R. CoP: "Цена Новых Исследований" / "New Investigations' Value"
|
|
|
Эти 0 пользователя(ей) поблагодарили NIV за это полезное сообщение: |
|
|
denis2000 | Дата: Сб, 12.10.2013, 16:35 | Сообщение # 160 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| NIV, Перемотка или установка времени в игре происходит при помощи функций из xr_effects.script (set_game_time и forward_game_time), используйте их для корректировки своего таймера.
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
NIV | Дата: Сб, 12.10.2013, 17:17 | Сообщение # 161 |
Полевой исследователь
Ученые сталкеры
Сообщений: 167
| denis2000, да, forward_game_time используется в рестрикторе левел-чейнджера. Но она меняет только игровое время, а не time_global(). Или я что-то не допонял?
Изменяем реальность S.T.A.L.K.E.R. CoP: "Цена Новых Исследований" / "New Investigations' Value"
Сообщение отредактировал NIV - Сб, 12.10.2013, 17:18 |
|
|
Эти 0 пользователя(ей) поблагодарили NIV за это полезное сообщение: |
|
|
denis2000 | Дата: Сб, 12.10.2013, 18:54 | Сообщение # 162 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| NIV, Если ваш таймер считает реальное время, то не понятно это заявление: Цитата NIV ( ) таймер меняется только на то время, которое проходит по часам компьютера*11, а не на 4 часа, как сдвигается игровое время. Если ваш таймер считает игровое время, то в моем посте написан ответ на ваш вопрос! Компенсируйте значение вашего таймера в соответствии с игровым временем, измененным указанными функциями.
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
NIV | Дата: Сб, 12.10.2013, 19:39 | Сообщение # 163 |
Полевой исследователь
Ученые сталкеры
Сообщений: 167
| denis2000, когда в функции таймера используется time_global(), он считает реальное время (т.е. медленно). Чтобы компенсировать это, умножаем разность времени на 11, тогда время, отсчитываемое таймером, почти совпадает с игровым (то, которое показывают часы). Когда происходит переход на другую локацию, игровое время проматывается на 4 ч вперед функцией forward_game_time в спейс-рестрикторе, а таймер успевает уйти только на время, потраченное на загрузку игры (~15-20 минут игровых, 1-2 мин реальных). Вот эту разницу и надо как-то компенсировать. Если же использовать в таймере функцию game.time() (игровое время), то при смене уровня таймер сначала реагирует на forward_game_time и время переводит, но после загрузки локации показывает сильно отрицательное время. Аналогично и при save/load (см. выше, #159). Так что, по большому счёту, мне не удалось добиться работоспособности таймера на игровом времени.Добавлено (12.10.2013, 19:39) ---------------------------------------------
Цитата denis2000 нужно изменить окончательно и бесповоротно параметр time_global() или на худой конец game.time()? Даже не знаю, не будешь же часы у компьютера переводить? Может, лучше из niv_quest_timer_limit_timer_value вычесть поправку? Идеально было бы заставить работать таймер через game.time() или что-то наподобие. Не пойму, почему там не получается.
Изменяем реальность S.T.A.L.K.E.R. CoP: "Цена Новых Исследований" / "New Investigations' Value"
Сообщение отредактировал NIV - Сб, 12.10.2013, 19:16 |
|
|
Эти 0 пользователя(ей) поблагодарили NIV за это полезное сообщение: |
|
|
denis2000 | Дата: Сб, 12.10.2013, 19:47 | Сообщение # 164 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| Цитата NIV ( ) Может, лучше из niv_quest_timer_limit_timer_value вычесть поправку? Вот это я и хотел от вас услышать! Что-то типа такого: Код niv_quest_timer_limit_timer_value = niv_quest_timer_limit_timer_value - поправка вычисленная из аргументов функции forward_game_time Вот так например рассчитывается разница в секундах реального времени на основе игрового времени: Код local diff_sec = math.ceil(game.get_game_time():diffSec(inited_time)/level.get_time_factor()) где game.get_game_time() - текущее время, inited_time - время начала отсчета, level.get_time_factor() - коэффициент ускорения игрового времени относительно реального (11), :diffSec - функция рассчитывающая разницу времени в секундах, math.ceil - округление до ближайшего большего целого.
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
NIV | Дата: Сб, 12.10.2013, 20:05 | Сообщение # 165 |
Полевой исследователь
Ученые сталкеры
Сообщений: 167
| Ещё уточню - game.get_game_time() возвращает время в виде (Y, M, D, h, m и т.д.)? Может там можно делать арифметику типа time:set (Y, M, D, h + 4, m, s, ms)?
Да именно так - это матрица или массив временных параметров. И можно задать функцией :set(Y, M, D, h + delta, m, s, ms). denis2000
Изменяем реальность S.T.A.L.K.E.R. CoP: "Цена Новых Исследований" / "New Investigations' Value"
Сообщение отредактировал NIV - Сб, 12.10.2013, 20:07 |
|
|
Эти 0 пользователя(ей) поблагодарили NIV за это полезное сообщение: |
|
|
|