Overf1rst 1 541 Опубликовано 1 июля, 2020 Тема посвящена моддингу на платформе Зов Припяти. Правила темы: Здесь задают вопросы и получают на них ответы. Прежде чем задать вопрос, воспользуйтесь поиском, ответ на него, вероятно, уже есть. Если у вас произошёл вылет, проверьте лог и поищите информацию об ошибке в справочнике. Также будет полезно посмотреть справочник ошибок. Если у Вас вылетает какой-то мод, то следует написать в тему этого мода. Грамотно оформляйте свой пост, чётко доносите суть своего вопроса (ответа). Благодарность выражаем в личке или же ставим реакцию. Посты с благодарностями в теме будут удаляться. 19 10 1 1 3 6 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Ayden 286 Опубликовано Понедельник в 11:54 (изменено) Policai У контролёра нету функции стрельбы, я так хотел, перестрелка с ним, тот с РПК, а после того, как добьешь- он прет в бой руками) Прикольно бы смотрелось Изменено Понедельник в 11:54 пользователем Ayden Волк волку- волк, человек человеку- собутыльник. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
denis2000 1 087 Опубликовано Понедельник в 17:02 Ayden Тогда спавните просто зомбированного НПС, добавляете ему ауру при помощи скриптов (как это сделано можно посмотреть в моде Отступник), а для реализации боя руками видимо придется заспавнить вместо НПС, какого то мутанта с визуалом зомбированного, но это будет криво смотреться по многим причинам. 1 Путь во мгле. Связь времен."Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник) Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Бессмертный 2 Опубликовано Понедельник в 17:50 В 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 Опубликовано Вторник в 05:02 Бессмертный возможно ты забыл вызываемый звук прописать, в sr_camp Попробуй _g.script раскоментировать error_log_reason, возможно более подробный даст лог. Дополнено 3 минуты спустя У кого есть модель вот такого нпс? 1 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
AfterGlow 603 Опубликовано Вторник в 05:37 RomaL23 обычный нпс с шейдером фантом. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
RomaL23 6 Опубликовано Вторник в 05:38 AfterGlow это как. Ну точнее, как называется сама модель этого нпс? Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
AfterGlow 603 Опубликовано Вторник в 06:01 RomaL23 сталкер нейтрал новис шото там. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
FacingSlave 160 Опубликовано Вторник в 06:08 RomaL23 Из мода вытащи Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
RomaL23 6 Опубликовано Вторник в 11:18 столкнулся с интересной проблемой, может кто подскажет вот у меня есть два файла по пути 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 286 Опубликовано Вторник в 11:25 (изменено) Как прописать путь залезания по лестнице для нпс? Может вопрос немного глупый, но что то не пойму) Изменено Вторник в 11:25 пользователем Ayden Волк волку- волк, человек человеку- собутыльник. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
denis2000 1 087 Опубликовано Вторник в 11:27 (изменено) 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 и не положили его куда следует. Изменено Вторник в 12:14 пользователем denis2000 Путь во мгле. Связь времен."Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник) Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
RomaL23 6 Опубликовано Вторник в 11:30 denis2000 как это так. у меня all.spawn лежит по пути gamedata\spawns\all.spawn я ума не приложу почему игра просит секции из spawn_old.part. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
denis2000 1 087 Опубликовано Вторник в 11:31 (изменено) Ayden В оригинале НПС не лазят по вертикальным лестницам, из за того, что движком не предусмотрено проигрывание специальных анимаций (хотя они есть в библиотеке). RomaL23 Игра просит секции из all.spawn, только и всего. Есть ли эти секции в каком либо другом файле этой вселенной ей по барабану. Изменено Вторник в 11:34 пользователем denis2000 1 Путь во мгле. Связь времен."Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник) Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
RomaL23 6 Опубликовано Вторник в 11:34 denis2000 p.s. вы мне скидывали локации из путь во мгле, я ещё несколько месяцев назад просил их. вот оттуда я и взял кордон, увы проблемный. rawdata прямо из того архива Дополнено 5 минуты спустя p.s. x2 в spawn.part никаких этих секций нет, которые требует игра. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Ayden 286 Опубликовано Вторник в 11:58 denis2000 Ну в том и дело, что он просто стоя без анимации поднимается) Получается надо делать отдельный участок с анимацией? Волк волку- волк, человек человеку- собутыльник. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
denis2000 1 087 Опубликовано Вторник в 12:09 (изменено) Ayden Это логичное следствие, только, как без движка, синхронизировать перемещение и эти анимации я не представляю. Возможно получиться сделать отдельную схему поведения НПС для такого действия. Короче, в качестве старта, попробуйте найти эти анимации и зацепить из при помощи схемы remark. 46 минут назад, RomaL23 сказал: rawdata прямо из того архива Эти наработки вы используете на свой страх и риск. 46 минут назад, RomaL23 сказал: в spawn.part никаких этих секций нет, которые требует игра. Ок. Еще раз: Игра не знает о манипуляциях в SDK если вы должным образом не пере собрали all.spawn и не положили его куда следует. Эти секции из all.spawn. Изменено Вторник в 12:21 пользователем denis2000 1 Путь во мгле. Связь времен."Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник) Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Ayden 286 Опубликовано Вторник в 12:35 (изменено) denis2000 Спасибо! В принципе там немного, для одной сценки надо, вот думаю, будет ли это выглядеть нормально, там лестница импровизированная Изменено Вторник в 12:36 пользователем Ayden Волк волку- волк, человек человеку- собутыльник. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Бессмертный 2 Опубликовано Вторник в 17:08 Как можно сократить паузы между действиями (анекдот, игра на гитаре\гармошке) сталкеров у костра? Хочется сократить "неловкие" паузы и повысить частоту совершаемых ими действий. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Paradox27kms 17 Опубликовано Вторник в 17:26 (изменено) А как сделать чтобы диалог нельзя было скипнуть? Я в плане того что некоторые диалоги в игре можно по множеству раз "читать" как пример в ЧН когда разговариваешь с Лесником и если нажать клавишу ESC то можно кучу раз активировать диалог и следовательно он будет выдавать ГГ кучу винторезов в награду за основной квест. (p.s я сейчас не про то как исправить данный баг с винторезом) Изменено Вторник в 17:32 пользователем Paradox27kms Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
FacingSlave 160 Опубликовано Вторник в 17:56 Paradox27kms в логику нпс, в секцию meet: allow_break = false 1 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Paradox27kms 17 Опубликовано 4 часа назад При добавлении новых строчек в титрах игры ловлю вылет Спойлер 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 10 Опубликовано 4 часа назад Только начинаю делать моды на ЗП. Совсем не могу понять, как декомпилировать локации. SDK скачал, а локаций нет. P.S. Если если возможность, я буду рад проконсультироваться с кем-то лично, кто шарит в моддинге на ЗП и не откажется помочь. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты