-
Число публикаций
1 172 -
Регистрация
-
Последнее посещение
-
Дней в топе
23 -
AMKoin
7,228 [Подарить AMKoin]
Закладки
-
[SoC] Ковыряемся в файлах
[SoC] Ковыряемся в файлах3 часа назад, ASSASIN64 сказал:окошко закрывалось само
Пример без всяких таймеров (bind_stalker.script):
function actor_binder:take_item_from_box(box, item) -- здесь переделываем исходную функцию так, чтобы не выходить из неё, если нет story_id (иначе на "обычных" ящиках не сработает) local story_id = box:story_id() if story_id ~= nil then treasure_manager.take_item_from_box(box, story_id) end -- проверяем, что контейнер, из которого брали предметы, стал пустым if box:is_inv_box_empty() then -- получаем активное окно и закрываем его local inv = level.main_input_receiver() if inv ~= nil then level.start_stop_menu(inv) end end end
Нюанс в том, что контейнер закроется не только по кнопке "взять всё", но и если мы вручную переместили из него последний предмет.
Доработать под кнопку и/или другие нужды не сложно.
-
Правки игры и билды модификаций
Правки игры и билды модификацийЗов Припяти 2 - Билд + SDK 0.7
«Зов Припяти 2» - с таким названием представлена глобальная модификация с новым сюжетом, разработанная на платформе игры Сталкер Зов Припяти. Модификация Зов Припяти 2 по сути является сюжетным продолжением игры, которая была представлена игрокам в оригинальной версии. Главным героем мода является по прежнему майор Дегтярёв от лица которого Вам предстоит пройти новый сюжет, побывать на совершенно новых локациях, на которых присутствуют новые группировки и квестовые персонажи.
Атмосфера игры кардинально изменена благодаря использованию скрытых возможностей движка игры, введением в игру новых аномальных явлений, погодных условий и обновленной графики, мир зоны отчуждения стал еще более таинственным и загадочным. Идея о создании проекта возникла сразу после внезапного сообщения о распаде компании компания-разработчик (признана нежелательной).
Скрытый текстО сюжете:
Сюжет игры Вам предстоит проходить от лица Дегтярёва, который по прежнему является главным героем игры. По завершении спец. операции Фарватер полученные данные были тщательным образом проанализированы и отправлены для дальнейшего анализа в лабораторию по изучению Зоны, главным консультантом в которой был назначен Стрелок. В своем последнем походе к центру Зоны, Стрелку удается разыскать информацию о секретной лаборатории. На базе Диггеров, Стрелку удается раздобыть один из уникальных образцов аномального происхождения под названием Тектонит. Из разговора Диггеров становиться очевидно, что данный образец должен отправиться в одну из секретных лабораторий Монолита, в которой проходят разработки нового оружия. Поиски лаборатории заводят его в тупик и он вынужден обратиться за помощью к военным.
Становиться очевидным что последние изменения в Зоне Отчуждения напрямую связаны с секретной лабораторией и найденной новой аномальной породой. Стрелок уверен что ему все-таки не удалось уничтожить полностью О-Сознание и в поиске разгадки придется все-таки попасть в эту лаборатория. Из разведданных СБУ становиться известно, что некая группа наемников начала поиски этой лабаратории. Цепочка динамично разворачивающихся событий все-таки приведет главного героя в лабораторию управления Ноосферой, поставив его перед выбором - уничтожить Пророка (Он же младший профессор Кайманов) или во фриплее помочь Монолиту установить всеобщий контроль над Зоной.
Локации:
В модификации добавлены новые локации, некоторые модели из которых были взяты из билдов.
Добавленные локации:
Лаборатория X-Z 01
Капёр
Лабиринт База Диггеров
Рабочий Посёлок
Колхоз Путь Ильича
Дикий Лес
Мёртвая Река
Команда разработчиков:
Alex Moroz (США) - продюсер, веб-пиар, главный художник, 3D видеомонтаж.
Олег Якубовский (Crazy_Stalker) - автор сюжета, конфиги, веб-пиар.
Андрей Непряхин (Genior) - автор сюжета, главный художник, автор новых решений.
Михаил Калуга (Михась) - автор сюжета, консультант по оружию.
Иван Рудских (Shredder) - логика, скрипты.
Иван Евгеньевич (optivankiev) - текстуры.
Бложко Олег (Дезертир) (Brom) - моделлер.
Снеговский Анатолий (Carrion-Crow) - левел-дизайн, текстурщик и моделлер.Скрытый текстЗагрузить «Зов Припяти 2 - Тестовый билд» с ФО: торрент [6.58 ГБ]
Тестовый билд для ознакомления. Переходы на все локации в одном месте для удобства. Выйти из лаборатории Стрелка и повернуть налево.
Загрузить «Зов Припяти 2 - SDK 0.7» с ФО: торрент [26.3 ГБ]
Важно! СДК 0.7, полная версия! Для свободного использования в своих разработках! Не забывайте упоминать компанию компания-разработчик (признана нежелательной) как правообладателя данного контента.
Stalker Call of Pripyat Lab XZ-01 custom made location
За оформление, благодарности @Hardmuth.
-
Правки игры и билды модификаций
Правки игры и билды модификацийФИКС ТЯНУЩИХСЯ ТЕНЕЙ ПО БОКАМ (автор оригинальной статьи товарищ ZHUKMAR)
Когда вы двигаетесь вы наверняка сталкивались с проблемой тянущихся по бокам теней. Такая проблема на широкоформатных мониторах 16:9, но на мониторах 5:4 такой проблемы нет. В общем, чтобы исправить данную проблему и на широкоформатных мониторах нужно изменить параметр r2_sun_near_border на значение 1, так как по дефолту стоит 0.75.
-
Скриптование
СкриптованиеВсё. Вопрос таки решил. Месяц бился... Надо было менять в init, в update и в use_callback. В init добавил условие которое предложил @RayTwitty а именно:
... or item:clsid() == clsid.inventory_box then ... --' кстати, работает также и : .. or item:section() == "inventory_box" then ... --' вопрос только в том, что быстрее отрабатывает?...дальше, путём метода народного втыка и постоянного вывода в лог чтобы понять что и куда и когда, выяснил, что в update надо добавить условие для ящиков без логики и в этом условии ещё раз вызывать use_callback, а именно добавил:
--' для всех inventory_box у которых нет логики вызываем callback отдельно ... else if item:clsid() == clsid.inventory_box then item:set_callback( callback.use_object, generic_physics_binder.use_callback, self ) end ...
и, наконец, в use_callback заработало то, что мне было надо, а именно, если ГГ открыл ящик, то получаем object ящика:
--' проверка нужна, т.к. use_callback возвращает и двери... if item:clsid() == clsid.inventory_box then my_global_var.GVObj(item) log("* [bind_physic_object](use_callback) obj: "..item:id()..", "..item:section()..", "..item:name() ) else log("! (1)[bind_physic_object](use_callback) obj: "..item:id()..", "..item:section()..", "..item:name() ) log("! (2)[bind_physic_object](use_callback) obj: " .. item:id() .. " - это не ящик") end
Для чего было надо? Сделал кнопки при открытии ящика: Выложить еду, арты, части мутантов, патроны. Для меня очень удобно, вместо того чтобы клацать мышкой 50 раз, просто один раз на кнопочке - выложить в ящик, и все патроны, например, перекладываются. Также сделал кнопку в инвентаре, сбросить всё в рюкзак, если есть рюкзак, кроме того что в слотах.
Всех кто участвовал - благодарю.
-
[CoP] Ковыряемся в файлах
[CoP] Ковыряемся в файлах@dsh, у меня тоже поначалу перестало работать, но потом заметил, что не работает только "use_object".
В результате "раскопок" выяснил, что этот callback снимается в "xr_logic.reset_generic_schemes_on_scheme_switch()" при переключении схемы. Для чего это было сделано, не понятно, ведь ни одна схема callback'и не устанавливает.
Решил, что это все-таки ошибка и убрал, после чего все callback'и в "bind_physic_object" нормально заработали. Пока что полет нормальный.
В итоге получил следующий код:Скрытый текстfunction generic_physics_binder:net_spawn(data) ... local c = self.object:clsid() if not ((c ~= clsid.inventory_box) and (c ~= clsid.inventory_box_s)) then self.object:set_callback(callback.hit, generic_physics_binder.hit_callback, self) self.object:set_callback(callback.death, generic_physics_binder.death_callback, self) end self.object:set_callback(callback.use_object, generic_physics_binder.use_callback, self) db.add_obj(self.object) return true end function generic_physics_binder:update(delta) ... if self.st.active_scheme ~= nil then xr_logic.issue_event(self.object, self.st[self.st.active_scheme], "update", delta) end xr_sound.update(self.object:id()) end
-
"косые сталкеры"
[SoC] Ковыряемся в файлах08.10.2024 в 20:02, Капрал Хикс сказал:[error]File : E:\stalker\sources\trunk\xrCore\xrDebugNew.cpp
[error]Line : 804 - тут скорее всего 815 должно быть, у меня движок правленый X-ray extensions.После включения префетча звуков такой вылет был, пока не заменил скобки [[ на ", в sound_theme.script (во всех ph_snd_themes).
08.10.2024 в 16:25, Balavnik сказал:Можно ли выносить секцию [spawn] в ltx-файл?
Можно выносить кастомдату любых объектов. Работает во частях трилогии.
10 часов назад, DarkSnowder сказал:где прописаны показатели повышения ранга НПС в момент их привязки к смарту?
smart_terrain.script, se_smart_terrain:update_obj_rank и game_relations.ltx, [smart_terrain_rank_change]
10.10.2024 в 17:57, Sikorskyi сказал:В чистом ТЧ 1.0006 есть такой баг, как "косые сталкеры", когда нпс целятся в бок, угрожая гг.
В state_mgr.script, function state_manager:set_state
Находишь ориг. блок кода: if state_lib.states[self.target_state].movement ~= move.stand and state_lib.states[state_name].movement == move.stand then self.npc:movement_enabled(false) end и меняешь его на: if state_lib.states[self.target_state].movement ~= move.stand and state_lib.states[self.target_state].animation ~= nil and --'исправление анимации нпс при наведении оружия на игрока state_lib.states[state_name].movement == move.stand then self.npc:movement_enabled(false) end
-
[SoC] Ковыряемся в файлах
[SoC] Ковыряемся в файлах22 часа назад, Капрал Хикс сказал:микрозависания при подходе к Бару
Где-то встречал, что нужно заранее грузить все звуки для нпс (characters_voice). Для движка правок не встречал, но оригинале есть функции для итерации звуков и их префетча, реализация в sound_prefetch.script. Работает не пойми как, вроде чуть лучше стало.
https://drive.google.com/file/d/1jC_4xSqnypxmG_qoEPPIhM6O0gD75MVf/view?usp=sharing
Для чистой игры, чтобы сразу в баре + правленые скрипты, т.к. изначально sound_prefetch отключен.
-
[SoC] Ковыряемся в файлах
[SoC] Ковыряемся в файлахВ который раз подниму тему про микрозависания при подходе к Бару... Вроде говорилось по то, что там сразу четыре гулага в онлайн выходят... Оттого и фриз. Как это вообще разрулить по уму? Фиксил кто конкретно этот момент у себя? P. S. Движок OGSR не предлагать:).
-
Скриптование
Скриптование@Balavnik, перебор всех предметов в инвентаре и подсчёт количества каждого типа предмета с возвратом таблицы вида { секция1 = кол-во1, секция2 = кол-во2...}:
Скрытый текстfunction enumerate_items() local counts = {} db.actor:iterate_inventory(function(dummy, item) local sect = item:section() if counts[sect] then counts[sect] = counts[sect] + 1 else counts[sect] = 1 end end, nil) return counts end -- использование local item_counts = enumerate_items() -- получаем таблицу секций предметов в инвентаре и их количества for section, count in pairs(item_counts) do -- здесь что-то делаем с каждой секцией и количеством end
Имхо, это всё вопросы для Скриптования, а не Ковырялки.
-
[SoC] Ковыряемся в файлах
[SoC] Ковыряемся в файлах2 часа назад, UriZzz сказал:функции позволяющие их скриптово закрыть?
function close_current_inv_window() local engine_inv = level.main_input_receiver() if engine_inv ~= nil then engine_inv:GetHolder():start_stop_menu(engine_inv,true) engine_inv = nil end end
В "СЗ" оно долгие годы было частью скриптового инвентаря.
-
[CoP] Ковыряемся в файлах
[CoP] Ковыряемся в файлах1 час назад, SWEAW сказал:В общем, сделал по совету, это
Не правильно. Нужно было ИЛИ раскоментировать стандартный код ИЛИ изменить его, как посоветовал @Kirgudu.
Посмотри внимательно, как написано в его посте.
В функции "trade_manager.update" в условиях для переменных "tt.update_time" и "tt.resuply_time" нужно поменять знак сравнения на "больше" - ">".
При использовании "game.time()" значения времени 60000 и 120000 чрезвычайно малы.
-
[CoP] Ковыряемся в файлах
[CoP] Ковыряемся в файлах2 часа назад, WinCap сказал:И, может быть, его активация вызовет ещё какие-нибудь ошибки.
Чтобы обезопасить себя от теоретически возможных ошибок, но при этом сохранить значения таймаутов хотя бы для находящихся в онлайне торговцев, можно записать переинициализацию таблицы примерно так:
--' if trade_manager[npc:id()] == nil then -- trade_manager[npc:id()] = {} -- вместо этой строки пишем нижеследующую trade_manager[npc:id()] = trade_manager[npc:id()] and { update_time = trade_manager[npc:id()].update_time, resuply_time = trade_manager[npc:id()].resuply_time } or {} --' end
-
[CoP] Ковыряемся в файлах
[CoP] Ковыряемся в файлах30.05.2024 в 12:02, SWEAW сказал:Подскажите, пожалуйста, как изменить trade_manager.script, чтобы торговцы обновляли ассортимент не раз в реальные сутки, а раз в несколько игровых, и, не менее важно, чтобы обновление ассортимента не вызывалось сейв-лоадом (потому что это по сути своей абуз).
Как уже и ответили выше, обновление ассортимента торговцев происходит при вызове функции "npc:buy_supplies(tt.config, str)".
Именно в этот момент в движке происходит наполнение ассортимента в соответствии с конфигами и вызывается она именно из "trade_manager.script".
В этом скрипте присутствуют две переменных для отсчёта времени "tt.update_time" и "tt.resuply_time" и они даже сохраняются и загружаются, но есть один "косяк". Эти переменные загружаются в таблицу в функции "trade_manager.load", а в функции "trade_manager.trade_init" эта таблица "затирается" новой и переменные становятся "nil":
--' if trade_manager[npc:id()] == nil then trade_manager[npc:id()] = {} --' end
И, как следствие, на первом же апдейте, происходит обновление ассортимента торговцев.
Можно раскомментировать условие и тогда обновления ассортимента после save/load’а не будет, но только для тех торговцев кто online. Если отойти подальше и сделать save/load, то он обновится. Поскольку "xr_motivator.script", откуда вызывается сохранение и загрузка trade_manager’а, работает только для тех, кто online.
З.Ы. Дополнительно отмечу, что причина, по которой ПЫСы закомментировали этот код, неизвестна. И, может быть, его активация вызовет ещё какие-нибудь ошибки.
-
[CS] Ковыряемся в файлах
[CS] Ковыряемся в файлахОстановка выдачи заданий категории recover_item (поиск уникальных предметов) после перехода на новую локацию – проблема древняя, однако найти исправление отдельно от глобальных модов и с описанием не удалось. Выкладываю здесь, может кому пригодится…
Проблема кроется в механизме обработки заданий: сначала они все сохраняются в список [task_manager.script] self.inited_tasks в статусе normal (готово к выдаче), потом переводятся в статус selected / completed (начато / выполнено) и удаляются по мере выполнения, при этом задание, которое было только просмотрено (даже в виде заголовка), но не начато, остается в списке навечно.
Ввиду того, что все задания recover_item используют общий заголовок, задание со старой локации занимает собой единственное место в очереди, но не выдается, так как не может пройти проверку actor_on_level(…).
Дополнительная сложность: перед выдачей в диалог все задания также сохраняются в память отряда под номером категории (для recover_item это номер [3], который почему-то не совпадает с номером [7] в менеджере заданий), а все дефолтные проверки сделаны без учета варианта "есть порядковый номер задания entity_id в памяти отряда squad.random_tasks[?], но нет самого задания в inited_tasks".
Правка сводится к удалению "висящих" заданий из памяти и изменению проверок, связанных с перебором squad.random_tasks целиком или только категории recover_item. Ну и, раз уж есть очистка памяти, можно сделать случайный выбор задания при входе в диалог, чтобы не все отряды NPC на локации искали один и тот же предмет.
Начинать новую игру не требуется.
Spoiler-- очистка памяти (возможно, задание с другой локации) и апдейт отряда [sim_squad_generic.script] function sim_squad_generic:init_squad_task() … local task = tm:select_task("recover_item", self.squad_id, player.player_name) (+) выше if tm.inited_tasks.recover_item ~= nil then if tm.inited_tasks.recover_item.status == "normal" then tm.inited_tasks.recover_item = nil end end … function sim_stay_point:update() … local task_entity_id = squad.random_tasks[3] … if task.status == "selected" then (/) if task and task.status == "selected" then -- проверки в диалогах [task_dialogs.script] function squad_has_tasks(npc, actor, p1, p2) function squad_hasnt_tasks(npc, actor, p1, p2) (–) if(task_manager.get_task_manager():get_task_by_entity_id(v).status~="selected") then (+) local rt = task_manager.get_task_manager():get_task_by_entity_id(v) if rt and rt.status ~= "selected" then … function show_tasks(npc, actor, dialog, phrase) function show_description(npc, dialog_name, phrase_id) … if(tsk.status~="selected") then (/) if tsk and tsk.status ~= "selected" then … function give_squad_capture_task(npc, actor, p1, p2) function squad_hasnt_capture_tasks(actor, npc, p1, p2, p3) … if task.status ~= "selected" then (/) if task and task.status ~= "selected" then … function is_recover_item_task(actor, npc) … if task.target == npc_id then (/) if task and task.target == npc_id then -- случайный выбор [task_manager.script] function CRandomTask:select_task(type, obj, faction) … (–) for k,v in pairs(task_table) do if v:check_target(obj, faction) then if v.prior > max_prior then max_prior = v.prior selected_task = v end end end (+) local rec = {} for k,v in pairs(task_table) do if v:check_target(obj, faction) then if type ~= "recover_item" then if v.prior > max_prior then max_prior = v.prior selected_task = v end else rec[#rec +1] = v end end end if next(rec) then selected_task = rec[ math.random(#rec) ] end
-
[SoC] Ковыряемся в файлах
[SoC] Ковыряемся в файлах03.02.2024 в 16:39, Balavnik сказал:Например npc:id() прокатит? Или это метод клиента и не прокатит?
Прокатит-непрокатит, покатит-непокатит... вам не надоело в асфальтовый каток играться?
Можно же изначально писать функции устойчивые к нештатным ситуациям/готовые распознать что угодно в рамках разумно-ожидаемого.
function get_id(obj) if obj ~= nil then if type(obj.id) == 'function' then return obj:id() end -- Если получен клиентский объект, возвращаем его ID if type(obj.id) == 'number' then return obj.id end -- Если получен серверный объект, возвращаем его ID end return nil -- Если объект не получен, или не имеет поля id в ожидаемом формате. Значит это не клиентский и не серверный объект, и возвращать нечего. end
-
Prosectors Project
Prosectors ProjectДополню по подключению.
У нас в используется система событий, она позволяет легко и удобно подключать и отключать различные скриптовые модули без необходимости правки оригинальных файлов.
1. Файл скрипта должен начинаться на 'm_' (пр. m_sos.script), в этом случае он будет автоматически проинициализирован.2. создать функцию init()
function init() end
Она будет вызвана автоматически при инициализации скрипта. Это происходит на этапе создания сервера, ещё до загрузки уровня, поэтому игровые объекты, худ и многое другое тут ещё не доступны.3. Регистрация функций на вызов при определённом событии
function init() event("actor_update"):register(update) endгде "actor_update" - это название события, update - функцияВ данном случае update будет вызываться на каждом апдейте актора. Для того, чтобы функция вызывалась реже, пишем так
event("actor_update"):register(update, {__period = 500})Вызов будет происходить по прошествии указанного времени (в мс) с прошлого, в данном случае 2 раза в секунду.4. Перейдём к самой функции
function update(args) if actor.health > 0.5 then actor.health = (0.5 - actor.health) / args.delta end end
Список аргументов в функцию передаётся в виде таблицы args. В данном случаеargs.time - текущее время (time_global)
args.delta - время, прошедшее с прошлого апдейта
args.binder - биндер актора
5. События и аргументы можно посмотреть в коде поиском по слову 'trigger'
actor_bind
actor_finalize
actor_spawn
actor_destroy
actor_stor
info_received
item_take
item_drop
item_ruck
item_slot
item_use
actor_enter
actor_exit
key_press
key_release
start_dialog
stop_dialog
actor_hit
item_group
item_take_from_box
trade_action
article_received
task_received
update_1st
actor_update
storage_save
storage_load
actor_save
actor_load
trade_perform
trade_terminate
=====
heli_spawn
heli_destroy
heli_death
=====
box_spawn
box_destroy
box_used
box_take
box_drop
box_open
box_close
obj_spawn
obj_used
obj_hit
obj_death
=====
mob_alive_use
mob_corpse_use
mob_living_update
mob_corpse_update
mob_update
mob_death
mob_hit
corpse_spawn
mob_spawn
mob_destroy
mob_save
mob_load
npc_spawn
npc_destroy
npc_hit
npc_death
npc_death_st
npc_living_used
npc_corpse_used
npc_used
npc_1st_update
npc_corpse_update
npc_living_update
npc_update
npc_save
npc_load
trader_used
trader_spawn
trader_destroy
trader_update
trader_save
trader_load
activate_by_section
6. Событие presets. Вызывается при спавне актора и используется для инициализации после загрузки уровня - например поиск графов, создание элементов худа и т.д.
function init() event("presets"):register(presets) end function presets() endНа этом пока всё, возможности системы раскрыл не полностью, но в основном. Примеров использования в скриптах предостаточно.Кроме того присутствуют другие замечательные системы - хранилище, таймеры, а также много другого функционала, полезного для разработчиков. Но об этом в другой раз.
При адаптации скриптов нужно иметь ввиду, что некоторые файлы/функции переименованы и вносить соответствующие корректировки (например ranks -> m_ranks; vector_rotate_y -> vector.rotate_y). И это касается конечно не только скриптов.
-
Prosectors Project
Prosectors ProjectЕдем дальше.
@ted.80, рассмотрел твои мини-моды, написал тутор по подключению. Автопауза и автосейв у нас по моему есть в дебаге, их, возможно, мы просто выведем во внутриигровое меню.
to ALL: Тутор по подключению опциональных модулей на примере actor_talk.script предложенный @ted.80.
Созданием файла:
1. В папке scripts создаем папку optional.
2. В папке optional создаем m_actor_talk.script.
Подключение модуля:
1. Берем текст из скрипта по ссылке и вставляем его в наш созданный файл (m_actor_talk.script), исходный вариант:
local radTbl = { [[characters_voice\human_01\dolg\states\radiation\radiation_1]], [[characters_voice\human_01\dolg\states\radiation\radiation_2]], [[characters_voice\human_01\dolg\states\radiation\radiation_3]], [[characters_voice\human_01\dolg\states\radiation\radiation_4]] } local hpTbl = { [[characters_voice\human_01\ecolog\states\health\health_1]], [[characters_voice\human_01\newbie\states\idle\idle_19]], [[characters_voice\human_01\stalker\states\idle\idle_26]], [[characters_voice\human_01\killer\states\idle\idle_19]] } local hlTbl = { [[characters_voice\human_01\killer\help\wounded_heavy\help_3]], [[characters_voice\human_01\killer\help\wounded_heavy\help_4]], [[characters_voice\human_01\killer\help\wounded_heavy\help_5]], [[characters_voice\human_01\killer\help\wounded_heavy\help_6]] } local victimSTbl = { [[characters_voice\human_01\stalker\fight\enemy_down\enemy_down_1]], [[characters_voice\human_01\stalker\fight\enemy_down\enemy_down_2]], [[characters_voice\human_01\stalker\fight\enemy_down\enemy_down_3]], [[characters_voice\human_01\stalker\fight\enemy_down\enemy_down_4]], [[characters_voice\human_01\stalker\fight\enemy_down\enemy_down_5]], [[characters_voice\human_01\stalker\fight\enemy_down\enemy_down_6]], [[characters_voice\human_01\stalker\fight\enemy_down\enemy_down_7]], [[characters_voice\human_01\stalker\fight\enemy_hit\enemy_hit_1]], [[characters_voice\human_01\stalker\fight\enemy_hit\enemy_hit_2]], [[characters_voice\human_01\stalker\fight\enemy_hit\enemy_hit_3]], [[characters_voice\human_01\stalker\fight\enemy_hit\enemy_hit_4]], [[characters_voice\human_01\stalker\fight\enemy_hit\enemy_hit_5]], [[characters_voice\human_01\stalker\fight\enemy_hit\enemy_hit_6]] } local victimMTbl ={ [[characters_voice\human_01\stalker\fight\fire\fire_1]], [[characters_voice\human_01\stalker\fight\fire\fire_2]], [[characters_voice\human_01\stalker\fight\fire\fire_3]], [[characters_voice\human_01\stalker\fight\fire\fire_4]], [[characters_voice\human_01\stalker\fight\fire\fire_5]], [[characters_voice\human_01\stalker\fight\fire\fire_6]], [[characters_voice\human_01\dolg\reactions\dead_mutant\dead_mutant_1]], [[characters_voice\human_01\dolg\reactions\dead_mutant\dead_mutant_2]], [[characters_voice\human_01\dolg\reactions\dead_mutant\dead_mutant_3]] } local Ptimer1, Ntimer1 = 0, 0 function start_talk() vol = 0.7 if db.actor.health < 0.33 then rand_music = hlTbl[math.random(#hlTbl)] this.playsnd(rand_music,vol) end if db.actor.health < 0.66 then rand_music = hpTbl[math.random(#hpTbl)] this.playsnd(rand_music,vol) end if db.actor.radiation > 0.1 and db.actor.health > 0.66 then rand_music = radTbl[math.random(#radTbl)] this.playsnd(rand_music,vol) end end function kill_mob(victim) vol = 0.5 local Ntimer2 = time_global() if Ntimer1 < Ntimer2 then Ntimer1 = Ntimer2 + 8000 if victim and IsStalker(victim) then rand_music = victimSTbl[math.random(#victimSTbl)] end if victim and IsMonster(victim) then rand_music = victimMTbl[math.random(#victimMTbl)] end this.playsnd(rand_music,vol) end end function playsnd(rand_music,vol) local Ptimer2 = time_global() if Ptimer1 < Ptimer2 then Ptimer1 = Ptimer2 + 10000 playsnd_obj = xr_sound.get_safe_sound_object(rand_music) playsnd_obj:play_no_feedback(db.actor, sound_object.s2d, 1, vector(), vol) end end2. Во всем скрипте заменяем db.actor на actor
3. Заменяем xr_sound на m_sound (82 строка)
4. В конец(!) скрипта добавляем такую конструкцию:
function init() event("actor_update"):register(start_talk) event("mob_death"):register(kill_mob) event("npc_death"):register(kill_mob) end5. Аргумент в функции kill_mob меняем на e, и следующей строкой пишем local victim = e.victim
6. В базе звуков меняем строчки:
[[characters_voice\human_01\dolg\reactions\dead_mutant\dead_mutant_1]], [[characters_voice\human_01\dolg\reactions\dead_mutant\dead_mutant_2]], [[characters_voice\human_01\dolg\reactions\dead_mutant\dead_mutant_3]]
на:
[[characters_voice\_deleted\reactions\dead_mutant\dead_mutant_1]], [[characters_voice\_deleted\reactions\dead_mutant\dead_mutant_2]], [[characters_voice\_deleted\reactions\dead_mutant\dead_mutant_3]]
7. Конечный вариант скрипта должен получится таким:
local radTbl = { [[characters_voice\human_01\dolg\states\radiation\radiation_1]], [[characters_voice\human_01\dolg\states\radiation\radiation_2]], [[characters_voice\human_01\dolg\states\radiation\radiation_3]], [[characters_voice\human_01\dolg\states\radiation\radiation_4]] } local hpTbl = { [[characters_voice\human_01\ecolog\states\health\health_1]], [[characters_voice\human_01\newbie\states\idle\idle_19]], [[characters_voice\human_01\stalker\states\idle\idle_26]], [[characters_voice\human_01\killer\states\idle\idle_19]] } local hlTbl = { [[characters_voice\human_01\killer\help\wounded_heavy\help_3]], [[characters_voice\human_01\killer\help\wounded_heavy\help_4]], [[characters_voice\human_01\killer\help\wounded_heavy\help_5]], [[characters_voice\human_01\killer\help\wounded_heavy\help_6]] } local victimSTbl = { [[characters_voice\human_01\stalker\fight\enemy_down\enemy_down_1]], [[characters_voice\human_01\stalker\fight\enemy_down\enemy_down_2]], [[characters_voice\human_01\stalker\fight\enemy_down\enemy_down_3]], [[characters_voice\human_01\stalker\fight\enemy_down\enemy_down_4]], [[characters_voice\human_01\stalker\fight\enemy_down\enemy_down_5]], [[characters_voice\human_01\stalker\fight\enemy_down\enemy_down_6]], [[characters_voice\human_01\stalker\fight\enemy_down\enemy_down_7]], [[characters_voice\human_01\stalker\fight\enemy_hit\enemy_hit_1]], [[characters_voice\human_01\stalker\fight\enemy_hit\enemy_hit_2]], [[characters_voice\human_01\stalker\fight\enemy_hit\enemy_hit_3]], [[characters_voice\human_01\stalker\fight\enemy_hit\enemy_hit_4]], [[characters_voice\human_01\stalker\fight\enemy_hit\enemy_hit_5]], [[characters_voice\human_01\stalker\fight\enemy_hit\enemy_hit_6]] } local victimMTbl ={ [[characters_voice\human_01\stalker\fight\fire\fire_1]], [[characters_voice\human_01\stalker\fight\fire\fire_2]], [[characters_voice\human_01\stalker\fight\fire\fire_3]], [[characters_voice\human_01\stalker\fight\fire\fire_4]], [[characters_voice\human_01\stalker\fight\fire\fire_5]], [[characters_voice\human_01\stalker\fight\fire\fire_6]], [[characters_voice\_deleted\reactions\dead_mutant\dead_mutant_1]], [[characters_voice\_deleted\reactions\dead_mutant\dead_mutant_2]], [[characters_voice\_deleted\reactions\dead_mutant\dead_mutant_3]] } local Ptimer1, Ntimer1 = 0, 0 function start_talk() vol = 0.7 if actor.health < 0.33 then rand_music = hlTbl[math.random(#hlTbl)] this.playsnd(rand_music,vol) end if actor.health < 0.66 then rand_music = hpTbl[math.random(#hpTbl)] this.playsnd(rand_music,vol) end if actor.radiation > 0.1 and actor.health > 0.66 then rand_music = radTbl[math.random(#radTbl)] this.playsnd(rand_music,vol) end end function kill_mob(e) local victim = e.victim vol = 0.5 local Ntimer2 = time_global() if Ntimer1 < Ntimer2 then Ntimer1 = Ntimer2 + 8000 if victim and IsStalker(victim) then rand_music = victimSTbl[math.random(#victimSTbl)] end if victim and IsMonster(victim) then rand_music = victimMTbl[math.random(#victimMTbl)] end this.playsnd(rand_music,vol) end end function playsnd(rand_music,vol) local Ptimer2 = time_global() if Ptimer1 < Ptimer2 then Ptimer1 = Ptimer2 + 10000 playsnd_obj = m_sound.get_safe_sound_object(rand_music) playsnd_obj:play_no_feedback(actor, sound_object.s2d, 1, vector(), vol) end end function init() event("actor_update"):register(start_talk) event("mob_death"):register(kill_mob) event("npc_death"):register(kill_mob) endПодключение окончено! Теперь этот файл можно удалять и добавлять к скриптам проекта в любое время без всяких дополнительных телодвижений, он стал абсолютно автономным и опциональным.
На вопросы остальных отвечу немного позже, в крайнем случае завтра.
-
Скриптование
Скриптование17 часов назад, phalcor сказал:давно нет респавна убитым монстрам/сталкерам
Нашёл-таки причину. Кому интересно:
Скрытый текстДело всё в том, что при поиске подходящего гулага в obj:brain():update() учитываются allspawnоские трупы, так как у них в ini есть секции
[smart_terrains]
esc_lager = true
Из-за этого такие трупы занимают свободные места в smart_terrainах, уменьшая значения self.gulag.capacity_non_exclusive.
Т.е. в методах fill_exclusives для сталков/монстров не проверяется их живость... Где-то это хорошо, а мне вот оказалось плохо - кучу времени потратил.
Решение: ждать пропажи трупов или добавить таки проверку в fill_exclusives на alive.
Купер