Перейти к содержанию

BarmaGlot

Сталкеры
  • Публикаций

    623
  • Зарегистрирован

  • Посещение

  • Победитель дней

    1

Весь контент BarmaGlot

  1. Как отправить NPC в пешее эротическое путешествие? Как скриптово активировать alife-режим у неписей? Есть ли какой-нибудь "магический" флаг где-нибудь в недрах db.storage или метод/property в свойствах se_object или game_object? Или какой-никакой протокол без необходимости чистить motivation_action_manager от заевших Action? (в последнем случае за каким-то боком AI action_planner продолжает форсить акцию, у которой все эвалуторы предусловий дают false и наоборот – все эвалуаторы эффекта положительны) Пример: у непися не прописаны, прописаны неправильно или принудительно отключены "скриптовые схемы поведения". По идее, он бы должен идти на вольные хлеба. Но он стоит тупо на точке и другим мешает.
  2. crystal Я, недолго думая, уже сегодня поправил это дело в своей реализации. Понадобилось всего 5 строк. В принципе, должно встать на стандартный xr_animpoint.script без проблем.
  3. Давно замечал, что разные NPC могут одновременно занимать один и тот же анимпойнт. Смотрится комично и ничем кроме улыбки не чревато. Однако! Это было в давних версиях и сейчас может быть уже исправлено. Исправлено?
  4. Вопрос: как можно принудить непися ползти/идти/бежать на определённые координаты? Мне известны способы: 1) npc:set_dest_level_vertex_id(vid). Работает 99.9%, но иногда неписи впадают в ступор и отказываются подчиняться. Плюс он с точностью до плюс-минус метра около ноды/вертекса, а надо бы точнее. 2) заранее скомпилированные в SDK patrol пути и npc:set_patrol_path(...) – работает, но это должно быть жёстко определено заранее. А как подобное сварганить "на лету"? Пробовал класс move – безуспешно, ноль реакции. Сейчас решаю с помощью чудовищного костыля, заставляя непися перемещаться примерно в нужную точку при помощи анимации типа zat_b38_stalker_alert, которая в своей части худо-бедно имитирует усреднённую поступь, но есть не у всех моделей. А также чревата факапами типа прохода сквозь стены или по воздуху. 3) любопытный метод npc:set_desired_position(vector) кажется нерабочим... P.S. платформа Anomaly, но для CoC актуально, полагаю, как и для CoP. Поэтому пишу в теме CoP как наиболее посещаемой.
  5. FalkineIsaku Создать Lua-функцию, где пропарсить логику схемы и вписать что угодно в любое схемное правило. Пример для схемы xr_walker и события on_game_timer (а там много ещё разного другого барахла можно перебрать): for k,v in pairs(db.storage[nid].walker.logic) do if v.name == "on_game_timer" then db.storage[nid].walker.logic[k].v1 = math.random(100500) end end
  6. baraholschik По порядку: 1. Как правило, на квест вешаются рестрикторы/функторы. Как в LTX-файлах описаний скриптов, так и в Lua-скриптах (в последних обычно живут т.н. функторы – регулярно по таймеру вызываемые функции). Любой из этих кусков кода проверяет что-то заданное. И видимо, если квест проваливается, то условия проверки не соблюдены. Вывод: надо смотреть логику/скрипты конкретных квестов. 2. Я бы сделал через стандартный для CoC скриптовый callback npc_on_before_hit(obj, hit, ...). Предварительно также однократно кэшировал по событию загрузки или первоначального апдейта т.н. blacklist/whitelist из txt или ltx-файла настроек с указанием секций бессмертных, либо трудноубиваемых неписей. В самом коллбэке смотреть, не входит ли непись в особый список, и модифицировать передаваемый мутабельный объект hit в сторону смягчения (вплоть до полной отмены) либо, наоборот, ужесточения ущерба. В зависимости, в том числе, и от того, кто наносит ущерб (это указано в одном из свойств hit). 3. Если сделать пункт 2, то пункт 3 будет уже сделан на 99%. Надо будет только выделить желаемых бессмертных неписей в отдельный список.
  7. Emmis стандартно, преобразованием координат. Простейший случай: local new_cam_pos = vector():set(cam_pos):add(vector():set(device().cam_dir):mul(x)) где x будет расстоянием. Константой, например 1 – один метр от cam_pos, либо какой-то функцией.
  8. Desi Нет почти всего из названного. Есть только SetColor(GetARGB) и SetHeading Рискну предположить, что есть. Например, есть стандартный байнд на кнопку "Скрыть хад/показать хад".
  9. Flatu Вот тема под модификацию "Аномалия", там скорее ответят. https://ap-pro.ru/forums/topic/402-anomaly-152 И более подробно там осветите свою проблему: есть ли моды, строк 20 из конца файла лога, при каких обстоятельствах возникает, откуда скачана сама Аномалия.
  10. liner Есть несколько способов, в зависимости от того, какой звук как играется. Лично я сделал так: self.so_masked[nid] = sound_object(snd, 0x00004000) -- v366 who the heck cutting native sounds? self.so_masked[nid]:play_at_pos(nil, npc:bone_position("bip01_head"), self.delay_sound+0.06, sound_object.s3d) self.so_masked[nid].volume = 0.23 -- masked till all the previous sounds fail to be played till its proper end self.so_masked[nid].frequency = timbre self.so_masked[nid].min_distance = 3 self.so_masked[nid].max_distance = 16 -- v330 to cancel the sound from static position if npc is in moving state ttt_lib.NseqCreate("chain_check_npc_sound_pos_"..nid..self.section, 0, "sound_theme", nid, self.section) И сразу после создания sound_object я вызываю самописную FIFO-очередь запланированных игровых событий, которая не гробит общие ресурсы типа методов апдейта, а персонифицированно проверяет с заданным интервалом какое-то одно конкретное событие. В частности, необходимость актуализации координат в методе sound_object:play_at_pos В вашем случае можно в первом приближении навесить такую актуализацию в стандартный апдейт, npc или актёра или xr_motivator'а->update->xr_sound:update
  11. А есть вообще для CoP Lua-скриптов хоть какой-нибудь базовый дебаг-функционал? Типа, printf()? Если есть, то можете прилепить упомянутый gamedata\scripts\death_manager.script в аттач, чтоб я глянул. Ну или сами там пропишите перед проблемной строкой распечатку переменных, свойств объекта и/или таблицы, которые превратились в nil.
  12. CoolBasik Там надо пообщаться со Швом, будет квест на добычу медицинского шмота. Так же надо пообщаться с Бродягой – он пошлёт завалить псевдогиганта, который путается под ногами. Вроде бы больше никаких инфопоршней не требуется для активации следующего сюжетного диалога. Такого рода ситуации, типа "ничего не происходит", элементарно решаются поиском через текстовые и XML-файлы в пути gamedata\configs. Аналогично можно было отследить причину поломки диалога из вашего первого вопроса, но предполагаю, что вы воспользовались поиском по теме или погуглили (и правильно сделали). Коллега crystal буквально на секунду опередил с правильным ответом.
  13. GameCube Именно, как бы "сами", как бы "подумав". Это, действительно, со стороны должно казаться "думанием, искусственным интеллектом" (и, по факту, его натуральный зачаток). В противовес (или, скорее в дополнение) той "логике", что там в ltx-скриптах "наглухо" прописана мод-мейкером, как вот Neptun говорит: Беда в том, что эта ltx-логика может и часто бывает не прописана вовсе или прописана неграмотно, ну и всякие разные ситуации "недефолтные". А в парадигме "думания" NPC натурально будет "думать" так же как и человек, расставляя приоритеты для широкого спектра своих действий и/или "инстинктов".
  14. GameCube По хорошему NPC должны "сами" решать, как реагировать на выброс. А именно куда и как прятаться и прятаться ли. А не руководствоваться прописанными ltx-костылями-скриптами. Которые для большинства NPC как раз отсутствуют. Если, конечно, они не какие-то особенные квестовые товарищи со специфичным уникальным поведением именно в выброс. Эта задача решается добавлением поведенческой схемы с околовысшим приоритетом. На птичьем языке это выглядит так: class "eva_surgeon" (property_evaluator) -- v460 npc should react to surge if he is got no exclusive/dynamic surge job already function eva_surgeon:__init(storage, eva_name) super(nil, eva_name) self.st = storage self.engaged = false end function eva_surgeon:evaluate() if doin(self.cooldown) then return self.engaged end local npc = alive_stalker(self.object) -- v456 assert, zombied not allowed if not npc then self.cooldown = ttt_time() + 88888888 -- permanent ban; this doubles ban established at set_scheme (for tst -- v444) self.engaged = false state_mgr.beh_set(self.object and self.object:id(), "npc_wanna_hide_from_surge", false) -- v416 script behaviour processing return false end self.cooldown = ttt_time() + math.random(24000, 36000) -- update animpoint eva just once per 5 seconds (+- crowd disperse), unless action is triggered local nid = npc:id() if xr_conditions.surge_started() and not npc:critically_wounded() -- oopse -- or state_mgr_movement.stucked[nid] -- v469 tst centralized antistuck protocol then -- v461 off glitching dynamic walker action -- local st = db.storage[nid] -- local as = st and st.active_section -- -- debug23(nid, 3, "%s %s eva_surgeon:eva as %s", nid, self.object:name(), as) -- if type(as) ~= "string" -- or not as:find("surge") -- npc already should be reacting -- then -- debug23(nid, 3, "%s %s npc_wanna_hide_from_surge true", nid, self.object:name()) state_mgr.beh_set(nid, "npc_wanna_hide_from_surge", true) self.engaged = true return true -- end end -- debug23(npc:id(), 3, "%s eva_reflex false", npc:id()) state_mgr.beh_set(nid, "npc_wanna_hide_from_surge", false) -- v416 script behaviour processing self.engaged = false return false end class "act_surgeon" (action_base) function act_surgeon:__init (npc, action_name, storage) super(nil, action_name) self.st = storage end vars.surge_covers = {} function act_surgeon:initialize() action_base.initialize(self) -- npc should choose the nearest level/online cover; level covers are preselected at load local nearest_dist = 88888888 local nearest_vert local npc = self.object local npc_pos = npc:position() for vert, pos in pairs(vars.surge_covers) do local dist = npc_pos:distance_to_sqr(pos) if dist < nearest_dist then nearest_dist = dist nearest_vert = vert end end self.vertex = nearest_vert if self.vertex then if vars.surge_cover_vertexes[self.vertex] then local vertexes = vars.surge_cover_vertexes[self.vertex] local vert local n = {} for k,_ in pairs(vertexes) do n[#n + 1] = k end local num = #n for i=1, num do -- CPU hung/lock preventor local v = n[math.random(num)] if not db.used_level_vertex_ids[v] and npc:accessible(v) then vert = v break end end if vert then self.vertex = vert end end self.pos = level.vertex_position(self.vertex) debug32(3, "%s act_surgeon:ini %s %s", npc:id(), npc:name(), self.vertex) end end function act_surgeon:execute() action_base.execute(self) if doin(self.cooldown or 1) then return end self.cooldown = ttt_time() + math.random(12000, 18000) local npc = alive_stalker(self.object) -- zombied not allowed: they are immune to any surges if not self.vertex or not npc then return end local nid = npc:id() move_mgr.mm_disable(nid) local state local dist = npc:position():distance_to_sqr(self.pos) if dist < 4 then state = random_choice( "guard", -- "guard_chasovoy", "guard_na", -- "threat", -- "threat_danger", -- "threat_heli", -- "threat_na", "hide", "hide_na", "caution", "ward", "fold_arms", "search", "sit", "psy_pain", "smoking_stand", "ispug", "drunk_stand", "probe_stand", "probe_crouch", "animpoint_stay_ohrana", "drink_vodka_stand" ) local timing = vars.anim_special_timings[state] if timing then self.cooldown = ttt_time() + timing else self.cooldown = self.cooldown + math.random(23000, 69000) end ttt_lib.send_to_vertex(nid, npc:level_vertex_id(), "act_surgeon@ttt@3488", state) elseif dist < 64 then state = random_choice("sneak_run_no_wpn", "walk", "walk", "run") ttt_lib.send_to_vertex(nid, self.vertex, "act_surgeon@ttt@3491", state) elseif dist < 1024 then state = random_choice("walk", "run", "run", "sprint") ttt_lib.send_to_vertex(nid, self.vertex, "act_surgeon@ttt@3491", state) else state = random_choice("run", "sprint", "sprint") ttt_lib.send_to_vertex(nid, self.vertex, "act_surgeon@ttt@3491", state) end state_mgr.set_state(npc, state, nil, nil, {look_mod = look.path_dir}) debug23(nid, 3, "%s act_surgeon:exe %s %s %s->%s(%s)", nid, npc:name(), state, npc:level_vertex_id(), self.vertex, round(npc:position():distance_to(level.vertex_position(self.vertex)))) end function act_surgeon:finalize() action_base.finalize(self) end После чего эта пара evaluator/action должна быть грамотно прописана среди прочих схем. Язык назван "птичьим", потому что это из самописной скриптовой реализации, где вся сердцевина скриптового "ИИ" полностью переписана (это под Аномалию). Привожу как пример и общий принцип. Конкретно в моей реализации NPC побежит до ближайшего укрытия, где не будет кучковаться в одну точку, а рассредоточится по помещению и будет реагировать разнообразно. Также у меня из-за наивысшего приоритета прекращается стрельба. Но это по вкусу. Как-то так...
  15. 23 сезон "Битвы экстрасенсов" плавно подходил к концу. Ничего не предвещало ничего, но тут из зрительного зала раздался вопрос: "Должно ли было что то произойти после этого?" Ведущий отделался состоянием офигения средней тяжести, а вот паре-тройке участников шоу пришлось временно сойти с дистанции. Однако, стопроцентно верный ответ существует: да! Должно было что-то произойти. И произошло. И будет происходить. Что-то...
  16. TheEastonGame Рекомендуется принять последствия своего выбора и как-то изловчиться из этой ситуации, например, переодевшись в костюм наёмника с несодранной нашивкой и выполнив циклические задания у других наймов, прокачать репутацию с враждебной группировкой. А вообще, если вбить в поиск по данной теме "отношени*" (именно по данной теме, без кавычек, звёздочка в конце – не ошибка), то получите три страницы ответов на подобные ситуации, в том числе и рецепты принудительного изменения отношений посредством читов ака консольных команд.
  17. А можно ваши гитарные анимации пощупать? omf-файл и сопутствующий код. Я в своём моде-долгострое испытываю большой затык, не связанный с гитарами. Но и гитарная тема есть, очень модифицированная. И нечто новое могло бы дать стимул к пробитию/воздвижению новых стен. А так апатия... Конкретно про гитары мечтал полностью прописывать значимые композиции по характерным ладам/паузам, понятно, что это нереализуемо почти наверняка. Но помечтать невредно, да и энтузиазм иногда способен горы своротить. Мод для "Аномалии", надеюсь, не критично в плане совместимости.
  18. Сделайте апгрейд до 1.5.2. Если вылет останется, именно стабильный, то сэйвгейм в студию. При условии, разумеется, что у вас нет никаких аддонов/модов.
  19. dasistfakt У вас мод стоит, Redux. Так что не по адресу вопрос. Впрочем, минутный поиск в яндексе даёт ответ: https://vk.com/wall-78827612_23033 Дополнено 2 минуты спустя Garage Head Имхо, не стоит качать. Вся визуальная красота похерится. А принципиально нового ничего тут нет.
  20. А можно поподробнее про это пожелание? Чем так плох системный диск в данном случае? За себя скажу сразу: по возможности ставлю строго на системный, как наиболее быстрый и объёмистый.
  21. кокието мызли вслух осень, да. а у нас зима уже, писос
  22. Petrunko Если вбить в поиск по данной теме "отношени*", то можно найти рецепт: принудительное изменение отношений с группировкой (в любую сторону)
  23. ian98 Самый надёжный и правильный, но затратный способ: создать свою поведенческую схему, Evaluator+Action, зарегистрировать их в npc:motivation_action_manager() и придать наивысший приоритет путём грамотной прописки по отношению к куче сторонних поведенческих схем. Тогда в action:execute() непись будет чётко исполнять требуемые команды, типа state_mgr.set_state(npc, "run") Но раз непись приговорён к скорой смерти, то, возможно проще будет отвязать его от motivation_action_manager, примерно как npc:motivation_action_manager():setup(nil) после чего он также будет реагировать как на оболочечные команды типа state_mgr.set_state(npc, "run"), так и на более фундаментальные типа npc:set_movement_type(move.run) Примеры есть в скриптах...
  24. VirusAlex И можно, и нужно, действительно. За SoC не впишусь, но в Аномалии, к примеру, делаю так: в sound_theme.script в начале создаём local cooldown = {} -- filter for repeating phrases Далее в методе function npc_sound:play(nid, faction, point, force, no_actor_copy) примерно перед самим воспроизведением вставляю -- lets filter sounds that are repeated too often near actor/observer -- f.e. poorly scripted bar_zone_general in Dolg hungar endlessly says the same hello phrase "idi svoey dorogoy, stalker" -- actor also would not listen to the same joke twice in a minute, etc local dist = npc:position():distance_to_sqr(device().cam_pos) if dist < 1234 -- ~36.6 meters and doin(cooldown[snd]) then -- debug23(nid, 3, "%s sound_theme.npc_sound:play %s has been filtered for played recently", nid, snd) return 0 end if snd:sub(1, 4) == "char" then -- only speakable sounds from characters_voice path cooldown[snd] = ttt_time() + math.random(120000, 180000) -- cooldown will take 2~3 minutes end Здесь фунуция doin - это моя самописная по проверке истекшего либо действующего таймера, да и время ttt_time() у меня по своему вычисляется, так что это делаете какими-то другими методами. Суть та же. Snd - сигнатура звука/истории/шутки/юмора
  25. "На карте костры под небом жёлтые, синие в помещениях". Вопрос: имеются ли какие-либо Lua-адрессабельные свойства/функции у объектов/аномалий "костёр", позволяющие как раз отличить "жёлтые" костры от "синих", либо это кропотливая ручная работа по сведению таких геоданных в самопальную таблицу? В своём моде хочу чтобы дождь заливал костры (равно как и взрывающиеся рядом гранаты их гасят, что сделано), но пока это дело двадцатой важности... Если "уличные" костры уже гасятся дождём автоматически, то туплю ))) Дополнено 8 минуты спустя 1917 К вам вопрос был, но может всезнающий народ поможет.