Overf1rst 1 544 Опубликовано 1 июля, 2020 Тема посвящена моддингу на платформе Зов Припяти. Правила темы: Здесь задают вопросы и получают на них ответы. Прежде чем задать вопрос, воспользуйтесь поиском, ответ на него, вероятно, уже есть. Если у вас произошёл вылет, проверьте лог и поищите информацию об ошибке в справочнике. Также будет полезно посмотреть справочник ошибок. Если у Вас вылетает какой-то мод, то следует написать в тему этого мода. Грамотно оформляйте свой пост, чётко доносите суть своего вопроса (ответа). Благодарность выражаем в личке или же ставим реакцию. Посты с благодарностями в теме будут удаляться. 19 10 1 1 3 6 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Ayden 313 Опубликовано 7 июля (изменено) Policai У контролёра нету функции стрельбы, я так хотел, перестрелка с ним, тот с РПК, а после того, как добьешь- он прет в бой руками) Прикольно бы смотрелось Изменено 7 июля пользователем Ayden Волк волку- волк, человек человеку- собутыльник. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
denis2000 1 091 Опубликовано 7 июля Ayden Тогда спавните просто зомбированного НПС, добавляете ему ауру при помощи скриптов (как это сделано можно посмотреть в моде Отступник), а для реализации боя руками видимо придется заспавнить вместо НПС, какого то мутанта с визуалом зомбированного, но это будет криво смотреться по многим причинам. 1 Путь во мгле. Связь времен."Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник) Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Бессмертный 4 Опубликовано 7 июля В sr_camp добавлялась новая секция, чтобы НПС проигрывали легенды у костра. Игра запускается нормально, но после некоторого времени в лагере, вылетает с ошибкой: [LUA] Error: [string "sound_theme"]:225: bad argument #1 to 'gsub' (string expected, got nil) В чем может быть проблема? Прикладываю свой sr_camp. Спойлер local npc_role = {noone=0, listener=1, director=2} CAMP_SECTION = "camp" -------------------------------------------------------------------------------- -- Precondition functions -------------------------------------------------------------------------------- function sr_camp_idle_precondition(camp) return true end function sr_camp_harmonica_precondition(camp) --printf("camp harmonica precondition") if(#camp.harmonica_table>0) then local n = 0 for k,v in pairs(camp.npc) do n = n + 1 end if(n>1) then for k,v in pairs(camp.npc) do local scheme = db.storage[k] and db.storage[k].active_scheme and db.storage[k][db.storage[k].active_scheme] local npc = db.storage[k] and db.storage[k].object --printf(" is director %s", tostring(v.harmonica==npc_role.director)) --printf(" base_action %s", tostring(scheme.base_action) ) --printf(" description %s", tostring(scheme.description) ) if(v.harmonica==npc_role.director) and (scheme ~= nil and scheme.base_action == scheme.description) and npc ~= nil and not xr_meet.is_meet(npc) then --if(v.harmonica==npc_role.director) then --printf(" return true [%s]", k) return true end end end end --printf(" return false") return false end function sr_camp_guitar_precondition(camp) --printf("camp guitar precondition") if(#camp.guitar_table>0) then local n = 0 for k,v in pairs(camp.npc) do n = n + 1 end if(n>1) then for k,v in pairs(camp.npc) do local scheme = db.storage[k] and db.storage[k].active_scheme and db.storage[k][db.storage[k].active_scheme] local npc = db.storage[k] and db.storage[k].object --printf(" is director %s", tostring(v.guitar==npc_role.director)) --printf(" base_action %s", tostring(scheme.base_action) ) --printf(" description %s", tostring(scheme.description) ) if(v.guitar==npc_role.director) and (scheme ~= nil and scheme.base_action == scheme.description) and npc ~= nil and not xr_meet.is_meet(npc) then --if(v.guitar==npc_role.director) then --printf(" return true [%s]", k) return true end end end end --printf(" return false") return false end function sr_camp_story_precondition(camp) if(#camp.story_table>0) then local n = 0 for k,v in pairs(camp.npc) do local npc = db.storage[k] and db.storage[k].object if npc ~= nil and not xr_meet.is_meet(npc) then n = n + 1 end end if(n>1) then return true end end return false end function sr_camp_legend_precondition(camp) if(#camp.legend_table>0) then local n = 0 for k,v in pairs(camp.npc) do n = n + 1 end if(n>1) then for k,v in pairs(camp.npc) do local scheme = db.storage[k] and db.storage[k].active_scheme and db.storage[k][db.storage[k].active_scheme] local npc = db.storage[k] and db.storage[k].object if(v.legend==npc_role.director) and (scheme ~= nil and scheme.base_action == scheme.description) and npc ~= nil and not xr_meet.is_meet(npc) then return true end end end end return false end -------------------------------------------------------------------------------- -- Класс CCampManager -------------------------------------------------------------------------------- -- Кемп содержит свои действия в терминах состояния кемпа (рассказ истории, музыка, ожидание), а не в терминах анимаций персонажей -- Кемп возвращает свое состояние, а решение какую именно анимацию играть принимает финальная схема, например xr_animpoint class "CCampManager" function CCampManager:__init(object, ini) self.object = object self.ini = ini local stories = utils.cfg_get_string(ini, CAMP_SECTION, "stories", nil, false, "", "test_story") self.story_table = parse_names(stories) local guitars = utils.cfg_get_string(ini, CAMP_SECTION, "guitar_themes", nil, false, "", "test_guitar") self.guitar_table = parse_names(guitars) local harmonicas = utils.cfg_get_string(ini, CAMP_SECTION, "harmonica_themes", nil, false, "", "test_harmonica") self.harmonica_table = parse_names(harmonicas) local legends = utils.cfg_get_string(ini, CAMP_SECTION, "legends_and_stories", nil, false, "", "legend001") self.legend_table = parse_names(legends) self.npc = {} self.schemes = {} -- Хранилище для режиссера лагеря. Режиссерем является сталкер, затеявший необычное поведение self.director = nil -- Текущее состояние self.active_state = "idle" --' Для теста создаем объект истории self.sound_manager = sound_manager.get_sound_manager(CAMP_SECTION..self.object:id()) self.sound_manager_started = true -- Состояния кемпа self.states = { idle = { director_state = nil, general_state = "idle", min_time = 30000, max_time = 40000, timeout = 0, transitions = {harmonica = 20, guitar = 20, story = 30, legend = 30}, precondition = sr_camp_idle_precondition }, harmonica = { director_state = "play_harmonica", general_state = "listen", min_time = 10000, max_time = 11000, timeout = 3000, transitions = {idle = 100, harmonica = 0, guitar = 0, story = 0, legend = 0}, precondition = sr_camp_harmonica_precondition }, guitar = { director_state = "play_guitar", general_state = "listen", min_time = 10000, max_time = 11000, timeout = 4500, transitions = {idle = 100, harmonica = 0, guitar = 0, story = 0, legend = 0}, precondition = sr_camp_guitar_precondition }, legend = { director_state = "legend", general_state = "listen", min_time = 10000, max_time = 22000, timeout = 0, transitions = {idle = 100, harmonica = 0, guitar = 0, story = 0, legend = 0}, precondition = sr_camp_legend_precondition }, story = { director_state = "tell", general_state = "listen", min_time = 10000, max_time = 11000, timeout = 0, transitions = {idle = 100, harmonica = 0, guitar = 0, story = 0, legend = 0}, precondition = sr_camp_story_precondition }, } self.active_state_time = 0 self.timeout = 0 self.idle_talker = nil end -- Переключает состояния кемпа function CCampManager:update() -- Если саундменеджер говорит какую то историю - ждем окончания. if not self.sound_manager:is_finished() then self.sound_manager:update() return end if self.sound_manager_started == false then return end -- Если кто-то говорит айдловую фразу, ждем пока он договорит. if(self.idle_talker~=nil) then if(xr_sound.sound_table[self.idle_talker]) then return else self.idle_talker = nil end end -- Выбор состояния кемпа. Тут решается что делать дальше. --printf("camp time %s", tostring(self.active_state_time - time_global())) if(self.active_state_time < time_global()) then self:set_next_state() if self:get_director() == false then self.active_state = "idle" for k,v in pairs(self.npc) do v.state = self.active_state end --self:set_next_state() end self.sound_manager_started = false for k,v in pairs(self.npc) do if(db.storage[k]) then xr_logic.issue_event(db.storage[k].object, db.storage[k][db.storage[k].active_scheme], "update") end local meet = db.storage[k] and db.storage[k].meet and db.storage[k].meet.meet_manager if meet then meet.npc_is_camp_director = self.director == k end end end -- Выбираем новую тему для саундменеджера (Для гитары и гармошки нужно будет юзать другой метод, чтобы не начали играть звук до того, как достанут инструмент) if(self.timeout~=0) and (self.timeout<=time_global()) then self:set_story() self.timeout = 0 end -- Болтовня в айдле if(self.active_state=="idle") then local npc_count = 0 local talkers = {} for k,v in pairs(self.npc) do npc_count = npc_count + 1 table.insert(talkers, k) end if(npc_count~=0) then self.idle_talker = talkers[math.random(#talkers)] xr_sound.set_sound_play(self.idle_talker, "state") end end end function CCampManager:set_next_state() --printf("CAMP set_next_state") local transitions = self.states[self.active_state].transitions local rnd = math.random(100) for k,v in pairs(transitions) do --printf("check %s value %s rnd %s", k, v, rnd ) if(rnd<v) then if self.states[k].precondition(self) == true then self.active_state = k --printf("FOUND") break end else rnd = rnd - v end end --printf("active state %s", self.active_state) for k,v in pairs(self.npc) do v.state = self.active_state end self.active_state_time = time_global()+math.random(self.states[self.active_state].min_time, self.states[self.active_state].max_time) self.timeout = time_global()+self.states[self.active_state].timeout end function CCampManager:get_director() if(self.active_state=="idle") then self.director = nil return end local directors = {} local npc_count = 0 for k,v in pairs(self.npc) do npc_count = npc_count + 1 local storage = db.storage[k] if storage ~= nil then local scheme = storage.active_scheme and storage[storage.active_scheme] local npc = storage.object if(v[self.active_state]==npc_role.director) and (scheme ~= nil and scheme.base_action == scheme.description) and not xr_meet.is_meet(npc) then table.insert(directors, k) end end end if(npc_count==0) then self.director = nil return end if(#directors<1) then return false --abort("There is no director for state [%s]. Camp [%s]!!!", self.active_state, self.object:name()) elseif(#directors==1) then self.director = directors[1] else self.director = directors[math.random(#directors)] end --printf("camp director [%s]", self.director) end function CCampManager:set_story() if(self.active_state=="story") then self.sound_manager:set_storyteller(self.director) self.sound_manager:set_story(self.story_table[math.random(#self.story_table)]) self.sound_manager_started = true elseif(self.active_state=="idle") then self.sound_manager_started = true end end -- Возвращает текущее действие кемпа function CCampManager:get_camp_action(npc_id) if(npc_id==nil) then abort("Trying to use destroyed object!") end if(self.npc[npc_id]==nil) then return end return self.npc[npc_id].state, self.director==npc_id end -- Регистрит персонажа в кемп function CCampManager:register_npc(npc_id) -- local npc_id = npc:id() --printf("Register NPC to camp %s", self.object:id()) self.npc[npc_id] = {state = self.active_state} db.storage[npc_id].registred_camp = self.object:id() -- При регистрации персонажа, проверяем какие роли он может выполнять. for k,v in pairs(self.states) do --printf("FIND NPC ROLE %s", npc_id) local role = self:get_npc_role(npc_id, k) if(role==npc_role.noone) then abort("Wrong role for npc[%s] with id[%d] in camp [%s]!!!", npc:name(), npc_id, self.object:name()) end self.npc[npc_id][k] = role end self.sound_manager:register_npc(npc_id) xr_logic.issue_event(db.storage[npc_id].object, db.storage[npc_id][db.storage[npc_id].active_scheme], "update") end -- Убирает персонажа из кемпа function CCampManager:unregister_npc(npc_id) -- local npc_id = npc:id() -- Если удаляется режиссер лагеря if self.director == npc_id then self.sound_manager_started = false self.active_state_time = 0 self.director = nil self.active_state = "idle" for k,v in pairs(self.npc) do v.state = self.active_state end end db.storage[npc_id].registred_camp = nil self.npc[npc_id] = nil self.sound_manager:unregister_npc(npc_id) end function CCampManager:get_npc_role(npc_id, state) local scheme = db.storage[npc_id][db.storage[npc_id].active_scheme] if scheme == nil then return npc_role.noone end local npc_actions = scheme.approved_actions local descr = scheme.description if(state=="harmonica") or (state=="guitar") or (state=="legend") then descr = descr.."_"..state --printf("finding music director [%s]", descr) for i = 1,#npc_actions do --printf("check action [%s]", npc_actions[i].name) if(npc_actions[i].name==descr) then --printf("DIRECTOR FOUND music") return npc_role.director end end return npc_role.listener elseif(state=="story") then for i = 1,#npc_actions do if(npc_actions[i].name==descr) or (npc_actions[i].name==descr.."_weapon") or (npc_actions[i].name==descr.."_s") or (npc_actions[i].name==descr.."_sk") or (npc_actions[i].name==descr.."_sa") or (npc_actions[i].name==descr.."_sr") or (npc_actions[i].name==descr.."_so2") or (npc_actions[i].name==descr.."_so3") then --printf("DIRECTOR FOUND story") return npc_role.director end end return npc_role.listener elseif(state=="idle") then return npc_role.listener end return npc_role.noone end -------------------------------------------------------------------------------- function get_current_camp(position) for k,v in pairs(bind_camp.camps) do if v.object:inside(position) then return v.camp end end return nil end function start_guitar(npc) local camp_id = db.storage[npc:id()].registred_camp if camp_id == nil then return --abort("trying to play guitar without camp [%s]",tostring(npc:name())) end local camp = bind_camp.camps[camp_id].camp camp.sound_manager:set_storyteller(camp.director) camp.sound_manager:set_story(camp.guitar_table[math.random(#camp.guitar_table)]) camp.sound_manager_started = true camp.sound_manager:update() end function start_harmonica(npc) local camp_id = db.storage[npc:id()].registred_camp if camp_id == nil then return --abort("trying to play harmonica without camp") end local camp = bind_camp.camps[camp_id].camp camp.sound_manager:set_storyteller(camp.director) camp.sound_manager:set_story(camp.harmonica_table[math.random(#camp.harmonica_table)]) camp.sound_manager_started = true camp.sound_manager:update() end function start_legend(npc) local camp_id = db.storage[npc:id()].registred_camp if camp_id == nil then return end local camp = bind_camp.camps[camp_id].camp camp.sound_manager:set_storyteller(camp.director) camp.sound_manager:set_story(camp.legend_table[math.random(#camp.legend_table)]) camp.sound_manager_started = true camp.sound_manager:update() end Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
RomaL23 6 Опубликовано 8 июля Бессмертный возможно ты забыл вызываемый звук прописать, в sr_camp Попробуй _g.script раскоментировать error_log_reason, возможно более подробный даст лог. Дополнено 3 минуты спустя У кого есть модель вот такого нпс? 1 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
AfterGlow 605 Опубликовано 8 июля RomaL23 обычный нпс с шейдером фантом. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
RomaL23 6 Опубликовано 8 июля AfterGlow это как. Ну точнее, как называется сама модель этого нпс? Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
AfterGlow 605 Опубликовано 8 июля RomaL23 сталкер нейтрал новис шото там. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
FacingSlave 163 Опубликовано 8 июля RomaL23 Из мода вытащи Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
RomaL23 6 Опубликовано 8 июля столкнулся с интересной проблемой, может кто подскажет вот у меня есть два файла по пути editors\rawdata\levels эти два файла: spawn_old.part и spawn.part я долго ломал голову, почему игра пытается найти файлы которые я не инклудил, и смарты которые я удалил с локации. Оказалось, что в spawn_old.part есть секции, которые как раз таки просит игра с таким вылетом:Description : There is no configuration file [scripts\escape\smart\esc_smart_terrain_3_0.ltx] in smart_terrain [esc_smart_terrain_3_0] эти секции есть в spawn_old.part, вот секция из лога: [object_844] attached_count = 1 clsid = 6 co_flags = 2 name = esc_smart_terrain_3_0 position = -23.051250, -12.322126, -119.508192 rotation = 0.000000, 0.000000, 0.000000 scale = 1.000000, 1.000000, 1.000000 type = 2 version = 23в spawn.part этого всего нет. Вопрос такой, а можно ли редактировать этот spawn_old.part?? убрать оттуда секции которые просит игра, например смарт террейны, файлы с логикой и так далее? если можно то что для этого надо? пересобирать локацию?локация взята из мода, и вот эти секции остались с него именно в этом файле. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Ayden 313 Опубликовано 8 июля (изменено) Как прописать путь залезания по лестнице для нпс? Может вопрос немного глупый, но что то не пойму) Изменено 8 июля пользователем Ayden Волк волку- волк, человек человеку- собутыльник. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
denis2000 1 091 Опубликовано 8 июля (изменено) 55 минут назад, RomaL23 сказал: у меня есть два файла по пути editors\rawdata\levels Видимо все же по пути editors\rawdata\levels\имя_уровня 55 минут назад, RomaL23 сказал: два файла: spawn_old.part и spawn.part Файл spawn.part SDK читает, файл spawn_old.part - нет. 55 минут назад, RomaL23 сказал: почему игра пытается найти файлы которые я не инклудил, и смарты которые я удалил с локации. Игра не знает о манипуляциях в SDK если вы должным образом не пере собрали all.spawn и не положили его куда следует. Изменено 8 июля пользователем denis2000 Путь во мгле. Связь времен."Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник) Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
RomaL23 6 Опубликовано 8 июля denis2000 как это так. у меня all.spawn лежит по пути gamedata\spawns\all.spawn я ума не приложу почему игра просит секции из spawn_old.part. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
denis2000 1 091 Опубликовано 8 июля (изменено) Ayden В оригинале НПС не лазят по вертикальным лестницам, из за того, что движком не предусмотрено проигрывание специальных анимаций (хотя они есть в библиотеке). RomaL23 Игра просит секции из all.spawn, только и всего. Есть ли эти секции в каком либо другом файле этой вселенной ей по барабану. Изменено 8 июля пользователем denis2000 1 Путь во мгле. Связь времен."Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник) Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
RomaL23 6 Опубликовано 8 июля denis2000 p.s. вы мне скидывали локации из путь во мгле, я ещё несколько месяцев назад просил их. вот оттуда я и взял кордон, увы проблемный. rawdata прямо из того архива Дополнено 5 минуты спустя p.s. x2 в spawn.part никаких этих секций нет, которые требует игра. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Ayden 313 Опубликовано 8 июля denis2000 Ну в том и дело, что он просто стоя без анимации поднимается) Получается надо делать отдельный участок с анимацией? Волк волку- волк, человек человеку- собутыльник. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
denis2000 1 091 Опубликовано 8 июля (изменено) Ayden Это логичное следствие, только, как без движка, синхронизировать перемещение и эти анимации я не представляю. Возможно получиться сделать отдельную схему поведения НПС для такого действия. Короче, в качестве старта, попробуйте найти эти анимации и зацепить из при помощи схемы remark. 46 минут назад, RomaL23 сказал: rawdata прямо из того архива Эти наработки вы используете на свой страх и риск. 46 минут назад, RomaL23 сказал: в spawn.part никаких этих секций нет, которые требует игра. Ок. Еще раз: Игра не знает о манипуляциях в SDK если вы должным образом не пере собрали all.spawn и не положили его куда следует. Эти секции из all.spawn. Изменено 8 июля пользователем denis2000 1 Путь во мгле. Связь времен."Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник) Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Ayden 313 Опубликовано 8 июля (изменено) denis2000 Спасибо! В принципе там немного, для одной сценки надо, вот думаю, будет ли это выглядеть нормально, там лестница импровизированная Изменено 8 июля пользователем Ayden Волк волку- волк, человек человеку- собутыльник. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Бессмертный 4 Опубликовано 8 июля Как можно сократить паузы между действиями (анекдот, игра на гитаре\гармошке) сталкеров у костра? Хочется сократить "неловкие" паузы и повысить частоту совершаемых ими действий. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Paradox27kms 17 Опубликовано 8 июля (изменено) А как сделать чтобы диалог нельзя было скипнуть? Я в плане того что некоторые диалоги в игре можно по множеству раз "читать" как пример в ЧН когда разговариваешь с Лесником и если нажать клавишу ESC то можно кучу раз активировать диалог и следовательно он будет выдавать ГГ кучу винторезов в награду за основной квест. (p.s я сейчас не про то как исправить данный баг с винторезом) Изменено 8 июля пользователем Paradox27kms Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
FacingSlave 163 Опубликовано 8 июля Paradox27kms в логику нпс, в секцию meet: allow_break = false 1 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Paradox27kms 17 Опубликовано 10 июля При добавлении новых строчек в титрах игры ловлю вылет Спойлер Expression : false Function : CXml::Load File : E:\priquel\sources\engine\xrXMLParser\xrXMLParser.cpp Line : 87 Description : XML file:ui\game_tutorials.xml value: errDescr:Error reading Attributes. Редактировал ui_credits_base.xml Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Flicker652 20 Опубликовано 10 июля Только начинаю делать моды на ЗП. Совсем не могу понять, как декомпилировать локации. SDK скачал, а локаций нет. P.S. Если если возможность, я буду рад проконсультироваться с кем-то лично, кто шарит в моддинге на ЗП и не откажется помочь. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
denis2000 1 091 Опубликовано 11 июля (изменено) Paradox27kms Косяки с атрибутами в тегах текста? Flicker652 Задавайте конкретный вопрос в соответствующей теме. Изменено 11 июля пользователем denis2000 Путь во мгле. Связь времен."Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник) Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Paradox27kms 17 Опубликовано 11 июля denis2000 спс разобрался самостоятельно. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Иблисианин Миднайт 0 Опубликовано 12 июля Возможно ли сделать диалоговое окно для двух-трёх и т.д. персонажей? Если да, как это можно сделать? Я помню точно, такое было реализовано в одном из модов на ТЧ. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты