Kirgudu 1 264 Опубликовано 14 Декабря 2016 (изменено) На самом деле, довольно легко сделать действительно случайный стартовый диалог. Пишу «вслепую», поэтому извиняйте, если накосячил или вообще предложил лажу. Где-нибудь в xr_conditions пишем такой код: local random_dialog = nil function get_random_dialog(actor, npc, p) local max_count = p and p[1] or 1 if random_dialog == nil or random_dialog.counter >= max_count then random_dialog = {dialog_set = false, counter = 1} else random_dialog.counter = random_dialog.counter + 1 end math.randomseed(time_global()) if not random_dialog.dialog_set then random_dialog.dialog_set = random_dialog.counter == max_count or math.random(random_dialog.counter, max_count) == max_count return random_dialog.dialog_set else return false end end Затем в логике пишем так (пример для трёх равнозначных диалогов): meet_dialog = {=get_random_dialog(3)} dialog1, {=get_random_dialog(3)} dialog2, {=get_random_dialog(3)} dialog3 Важно: 1. аргумент, передаваемый в функцию, должен быть равен общему числу диалогов; 2. функцию обязательно надо использовать в том числе для последнего диалога в цепочке, чтобы не сбился внутренний счётчик; 3. дополнительные условия (например инфопорции) при таком подходе использовать нельзя; 4. данная реализация может быть применима только к одному конкретному выбору случайного диалога. Если необходимо применить аналогичный подход в нескольких местах (с разным количеством диалогов для выбора), из переменной random_dialog надо делать массив, а в функцию передавать 2 аргумента - номер комплекта диалогов и кол-во диалогов в этом комплекте. Соответсвенно и код функции претерпит небольшие изменения. При таких последовательных вызовах функция случайным образом назначит активным один из диалогов. При повторной попытке заговорить счётчик диалогов сбросится и случайный выбор будет сделан заново. Изменено 14 Декабря 2016 пользователем Kirgudu 2 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 14 Декабря 2016 (изменено) @BoBaH_671, вот понятия не имею. Но не исключено. Почему бы не проверить, если есть возможность? Если сработает (сам посмотреть не могу) - это, пожалуй, будет оптимальней, чем то, что я понаписал выше. Что ж, хотя бы поупражнялся. Изменено 14 Декабря 2016 пользователем Kirgudu Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 15 Декабря 2016 (изменено) Только у меня диалог после открытия практически сразу исчезает.Это потому, что настройки диалога у тебя неправильные. Дело в том, что необходимость выбора того или иного диалога рассчитывается последовательно, а вероятности при расчёте не складываются. Смотри: meet_dialog = {~30} dialog1, {~60} dialog2, {~10} dialog3Первый диалог будет выбран с вероятностью 30% (число сравнивается со случайным числом в диапазоне от 1 до 100, если больше - сработало). 70% - вероятность, что не будет выбран. Второй диалог будет выбран с вероятностью 60%, но относительно 70% вероятности не выбора первого диалога. Общая вероятность выбора второго диалога 0.7*0.6*100% = 42%. Отсюда 30%+42% = 72% - вероятность выбора первого или второго диалога, 28% - вероятность не выбора. Третий диалог будет выбран с вероятностью 10%, но уже от этих оставшихся 28%. Общая вероятность выбора третьего диалога составит 0.1*0.28*100% = 2.8%. Отсюда 72%+2.8% = 74.8% - общая вероятность выбора одного из трёх диалогов. Получается, с вероятностью 100%-74.8% = 25.2% никакой диалог не будет выбран. И даже если у тебя получилось при начале разговора попасть в «правильные» 74.8% - на апдейте, тут ты прав, происходит выбор диалога заново, с некоей вероятностью он оказывается пуст, и в таком случае в скрипте логики происходит вызов функции restore_default_start_dialog(). Возможно, именно она и закрывает диалоговое окно - движкоправы могут сказать точнее. Чтобы условие гарантированно приводило к какому-либо диалогу, необходимо, чтобы последний диалог в цепочке от вероятности не зависел: meet_dialog = {~30} dialog1, {~60} dialog2, dialog3Но и тогда диалоговое окно теоретически может сбрасываться, если во время апдейта новый выбранный диалог будет отличаться от старого - для смены диалога в таком случае вызывается функция set_start_dialog(dialog). Вызывает ли эта функция аналогичное закрытие диалогового окна, мне неизвестно. Надо проверять. Update: Прошу считать данный пост недействительным - причина ниже. Изменено 15 Декабря 2016 пользователем Kirgudu 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 15 Декабря 2016 (изменено) А сумма вероятностей должна быть = 100?Посмотрел функцию pick_section_from_condlist более внимательно и, судя по всему, надо признать, что был неправ в своих ранних рассуждениях. Случайное число в функции берётся только один раз, при старте. А это значит, что числа в логике инкрементны, должны увеличиваться с каждым шагом и самое большое (последнее из них) не может превышать 100 (но при этом сумма может быть и больше). Например так: meet_dialog = {~20} dialog1, {~40} dialog2, {~50} dialog3, {~70} dialog4, {~90} dialog5, {~99} dialog6, dialog7В реальности первый диалог будет выбран с вероятностью 20%, второй - 20%, третий - 10%, четвёртый - 20%, пятый - 20%, шестой - 9% и седьмой - 1%. Вот уже эта сумма равна 100%. А вот в такой записи meet_dialog = {~30} dialog1, {~60} dialog2, {~10} dialog3третий диалог не будет выбран никогда (и в 40% случаев не будет выбран ни один диалог), так как попадает в диапазон вероятности первого диалога. Поэтому совет насчёт отсутствия числа в последнем элементе остаётся в силе. Изменено 15 Декабря 2016 пользователем Kirgudu 2 2 4 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 28 Февраля 2017 (изменено) @Х_и_м_и_к, active = sr_idle [sr_idle] on_actor_inside = {+top_bor} nil %=xr_effects.hana_ano%вот этот вот "nil" завершает работу данной логики. Окончательно и бесповоротно.Соответственно, раз зайдя в рестриктор, ты сам же запрещаешь повторное его срабатывание. Изменено 28 Февраля 2017 пользователем Kirgudu 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 28 Июня 2017 2 часа назад, AndrewMor сказал: Отец Диодор на Складах. Перерыл все, но никак не могу найти файл, где его логика описывается Нет у него персональной логики. 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 29 Июня 2017 @Akello автор вопроса уже за меня ответил. Я тоже не вижу там никакой логики. Но если ты знаешь то, что не знаем мы - ткни носом, будь любезен. Мало ли кому пригодится. @AndrewMor, возможно, всё дело во флагах (0xffffffbf). Не исключено, что это как раз установка «не двигаться»; навскидку значения не помню. Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 14 Ноября 2017 В 12.11.2017 в 20:59, UriZzz сказал: если в координатах рестриктора понятно что за скобками находятся вертексы то вот у кошки целых 3 числа - 1, 44, 2 вот эти числа мне и не понятны 1 и 44 - как уже было выше отвечено, вертексы, а 2 - это кол-во спавнящихся в одном месте кошек. Ты б заглянул в саму функцию proceed_spawn, сразу стало бы всё понятно, хотя бы даже по названиям входных аргументов. 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 12 Марта 2018 @AndrewMor, лично делал для этого мода, взяв за основу более простой вариант от @Shoker. Это, конечно, ЧН. Но дам наводку: в ТЧ, насколько я знаю, в биндере актора тоже есть коллбэк trade_sell_buy_item (в аргументах - текущий объект торговли, булевый признак покупка/продажа, стоимость), на который по дефолту зацеплено только изменение статистики движения денег. Не слишком сложно прикрутить к этому событию свой обработчик торговли, в котором проверять состояние предмета (а также, по желанию, другие условия) и при необходимости делать возврат во время ближайшего апдейта с выдачей соответствующего сообщения на худ или как-то иначе. Важный нюанс: коллбэк trade_sell_buy_item срабатывает непосредственно перед реальной передачей предметов, то есть у каждого предмета в этот момент ещё старый владелец (obj:parent()). При этом в тот же момент коллбэка деньги за покупку/продажу уже засчитаны актору или торговцу. Это надо учитывать при написании возврата. 1 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 16 Июля 2018 9 часов назад, Graff46 сказал: Некоторые объекты имеют флаг used_ai_location, выставляется он в СДК. А где хранятся он? В нетпакетах не нашел... Если адресоваться к пакету m_netpk, следует смотреть в свойстве net_cse_alife_object.st_props.object_flags. Нужный тебе флаг имеет значение 128 и, кстати, при подключении модуля выводится глобально в составе _G.object_flags. @dsh, синхронно. Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 25 Сентября 2018 Если по-простому, то в функции drop_manager:create_release_item() добавляем в нужном месте что-то вроде if ranks.get_obj_rank_name(self.npc) == 'novice' then -- 'novice'|'experienced'|'veteran'|'master' -- do something end А если хочется реализовать полноценное решение через конфиг, то необходимо добавить, например, файл "misc\death_items_by_ranks.ltx", заполнить его аналогично конфигу "death_items_by_communities.ltx" значениями вероятностей для каждого ранга [novice] ;Указывается вероятность заспаунить или нет af_medusa = 0.015 ; и т. д. заинклудить новый конфиг в "death_generic.ltx", затем поработать с модулем drop_manafer.script: организовать чтение в новую таблицу множителей вероятности из нового конфига в init_drop_settings(), дополнить drop_manager:create_release_item() учётом значений из новой таблицы. Работа муторная, но при желании сделать можно за вменяемое время. 1 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 21 Декабря 2023 @div, изменив нужное свойство в абстрактной части нет-пакета объекта. Например, можно воспользоваться модулем m_netpk от Артоса (если мы говорим о ванильном движке; в модифицированных это, возможно, сделать куда проще). Модуль можно взять здесь: Авторский пример изменения координат см. в описании внутри архива с модулем. 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 21 Декабря 2023 @div, в readme_m_netpk.txt есть раздел "Про специальный нет-пакет 'abstract'". Инструкции из него выполнены? Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 22 Декабря 2023 @div, нет, я писал про пункты 1), 2) и 3) чуть пониже процитированной строки. Но это действительно может быть совершенно не важно. Речь-то, как справедливо тут заметили, о версии 1.0004, а я на это не обратил внимания. Модуль Артоса предназначен для 1.0006. 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 22 Декабря 2023 1 час назад, div сказал: В readme_m_netpk версия 1.0004 вроде подходит Может и так, не проверял. Правда, внутри самого модуля она в шапке не упомянута. 11 часов назад, Zander_driver сказал: Интересно, а как модуль это на 1.0004 сделает? Возможно я уже плохо помню, но без подключения к апдейту, там это нетривиальная задача, разве нет? @Zander_driver, кстати, там level.add_call под капотом, см. do_switchings и execute_switchings. Так что очень может быть, что заработает. 1 час назад, div сказал: переключить примерно так нужно: Не нужно. При изменении абстрактной части нет-пакета модуль проделывает необходимые манипуляции автоматически, как и написано в readme. Если интересно, см. упомянутые выше функции модуля do_switchings и execute_switchings, там всё уже есть. 1 час назад, div сказал: значит нужно еще файл se_item.script проверить / изменить. Для NPC - скорее se_stalker.script 1 час назад, div сказал: выше поверхности карты и не стоял на каком-то объекте Не уверен, что подействует на живой объект, но можно попробовать при спавне НПС снять флаг use_ai_locations = 128 (привязка к сетке). Делается это в том же модуле m_netpk, примеры есть на форуме, например этот из свежих: В общем, дальше надо экспериментировать. 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 22 Декабря 2023 1 час назад, Zander_driver сказал: Но, что при этом отвалится в логике НПС? Любопытный вопрос, на который у меня нет ответа. Но памятуя о том, что в коде обслуживающем действия НПС, обращения к АИ-сетке встречаются на каждом шагу, подозреваю что будут проблемы. Тоже не знаю. Убирал флаги перехода в оффлайн у БТР, сбрасывал какие-то флаги у физ. объектов - проблем не было. НПС спавнить в воздухе в голову не приходило. 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 22 Декабря 2023 @div готовый тестовый пример с вентилятором:https://disk.yandex.ru/d/T2v4KZ0WfBOp4g Внутри сейвы у Сидоровича и в подвале деревни после переноса (сделаны на Steam версии ТЧ, поэтому скорее всего не загрузятся), скриншоты для визуального подтверждения. Для лёгкости понимания вставок упаковал 2 папки: оригинальную из Steam-версии и уже с изменениями. WinMerge или аналог покажет разницу между изменёнными файлами. Не мудрствуя лукаво, повесил запуск телепорта вентилятора на апдейт актора, через 10 секунд после первого апдейта (чтобы успеть сбросить начальный ролик и увидеть телепорт глазами). Дальше самостоятельно, код писать больше не буду. Имхо, технических сведений вполне достаточно, может просто не хватило внимательности при реализации. 1 3 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 22 Декабря 2023 @div, ну тут одно из двух: либо дьявол в неучтённых мелочах, либо, как мы раньше писали, для NPC это не сработает. Изучать и экспериментировать. Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 22 Декабря 2023 (изменено) 10 минут назад, div сказал: я наверно не тот флаг снимаю data.object_flags = bit_and(data.object_flags, bit_not(128)) -- сброс UsedAI_Locations Полный список флагов можно посмотреть в том же m_netpk в конце файла, где "_G.object_flags = ..." и далее. 10 минут назад, div сказал: так же должно быть? Или так, наверное. Только что-то одно. Изменено 22 Декабря 2023 пользователем Kirgudu Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 22 Декабря 2023 (изменено) 1 час назад, Zander_driver сказал: прокомментируй Ну конечно. Иначе как раз переключение оффлайн-онлайн работать не будет. А class_registrator в большинстве случаев нужен только затем, чтобы посмотреть, какой биндер и где искать. 1 час назад, div сказал: data.object_flags = bit_xor(data.object_flags, 128) data.object_flags = bit_or(data.object_flags, 128) Потому что вызов данных команд в паре приводит к исходному положению дел. Ведь даже в комментарии поста сказано, что первая - сброс флага, тогда как вторая - поднятие оного. В итоге флаг привязки к сетке после парного выполнения остаётся установленным. Аптечки... честно говоря, не помню, есть ли у них биндер в принципе. Изменено 22 Декабря 2023 пользователем Kirgudu Инструмент Поделиться этим сообщением Ссылка на сообщение