Перейти к контенту

Kirgudu

Жители
  • Число публикаций

    1 636
  • Регистрация

  • Последнее посещение

  • Дней в топе

    27
  • AMKoin

    15,865 [Подарить AMKoin]

Весь контент пользователя Kirgudu

  1. Kirgudu

    Скриптование

    Скорее решение наоборот. Не отсеивание ненужного с избыточными проверками "а то ли это", а адресная обработка нового параметра, который, разумеется, будет добавлен только там, где нужно. Впрочем, условия для этой "нужности" достаточно специфические, почти разовые, так что решил сделать по-другому - и ладно. @monk в Final Stroke вообще пошёл третьим путём: сократил расстояние (чтоб Левша не орал издалека) и убрал субтитры (за ненужностью, ибо лицом к лицу). Подходов может быть много, главное чтобы выбранный способ удовлетворял автора.
  2. Kirgudu

    Скриптование

    Возможно. В xr_meet.init_meet(npc, ini, section, st, scheme) добавить новый параметр для идентификатора кастомного сообщения, указав в соотв. блоках как дефолтное значение "nil", так и парсинг строки из конфига. В xr_meet.action_meet_wait:execute() при ненулевом значении прочитанного выше параметра добавить вывод сообщения параллельно со звуком и с учётом его условий. Оригинальное сообщение при этом отвязать от звука, а в секцию логики [meet@1] добавить строку с новым параметром. Это, конечно, не действия только с логикой, как, вероятно, хотелось, зато универсальное решение, которым можно будет воспользоваться и в других случаях.
  3. Kirgudu

    Скриптование

    @Norman Eisenherz могу предположить только одно. В той же функции check_task немного выше есть условие if self.state == "counter_attack", в котором выдаётся ровно то же самое сообщение. Раз break и отсечка по флагу не срабатывает, единственное, что приходит в голову - это что последовательно срабатывает выдача сообщений из разных частей условия, с действующей контратакой и без оной. Рекомендую расставить флаги и логирование в обеих частях и проверить. Если я прав, дальше надо будет подумать, почему сначала запускается контратака, потом (видимо) практически сразу отменяется. Могу ошибиться, но на ранних этапах работы над OGSM CS 1.8 (народный патч) что-то такое мы встречали... но в последнее время это уже не проявлялось. Точно уже не помню, давно это было.
  4. Чтобы обезопасить себя от теоретически возможных ошибок, но при этом сохранить значения таймаутов хотя бы для находящихся в онлайне торговцев, можно записать переинициализацию таблицы примерно так: --' 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
  5. @SWEAW, пример приведён верно, но это, конечно, только один из возможных вариантов. Обычно, если хотят посмотреть, что происходит с переменной, то смотрят её значение (читай логируют) непосредственно до изменения и сразу после, перед сравнением (if) с другой переменной и перед любым использованием. Это если брать по максимуму. Естественно, если такое логирование будет в update функции, файл лога забьётся однотипными строками, но это не страшно. А вообще, хочешь заниматься этим - экспериментируй, мы все делаем это в той или иной степени.
  6. @SWEAW просто мало активных специалистов по ЗП осталось, вот сюда никто и не заглядывает, а кто заглядывает - мало пишет. Попробую сузить тебе задачу вдвое. trade_manager вообще не обновляет список продаваемых товаров. Всё, что он делает - это раз в какое-то время вычитывает из конфигурации текущий тип списка товаров, примерно такого вида: current_buy_supplies = supplies_generic, а потом методом npc:buy_supplies() передаёт его движку. Внутри движка и происходит взвешивание вероятностей появления того или иного объекта в продаже и составление конечного списка. Могу ошибаться, конечно, но это то, как я сейчас сумел наискосок понять написанное в менеджере торговли и других связанных с этим скриптах. И если прав, то без модификации движка смену после загрузки из сейва списка торгуемых предметов не побороть. Что же касается вывода в лог, добавь себе в _g.script в самом его конце что-то такое: local console to_log = function(fmt,...) if not console then console = get_console() end console:execute("load ~:"..string.format(fmt,...)) end -- пример записи (в любом скрипте) local st = "test" to_log("Message: %s", st) -- где %s - место подстановки значения твоей строковой (числовой, булевой) переменной Пример использования также приведён. После чего смотри, чему у тебя при торговле становятся равны всякие tt.update_time, tt.resuply_time и иже с ними и думай, почему не срабатывает то, что ты делаешь. Да, и соглашусь с @abramcumner, без логов сразу понять, что происходит, можно только в редких случаях. Поэтому прежде чем что-то под себя править, научись логировать.
  7. Эммм... "с учётом вложенных папок" пойдёт? ) Если не ошибаюсь, user.ltx сохраняется в "$app_data_root$".
  8. Первый параметр - рекурсия включена/выключена (для операций с массивом файлов, например, чтением их списка в папке), второй - уведомление (движка) об изменениях включено/выключено. Где и в каких сценариях используется второй параметр, сказать не могу, не изучал.
  9. @abramcumner я бы уточнил, что речь идёт (скорее всего) о псевдониме "$app_data_root$". Он ведь не обязан идти первой строкой. @dPlayer мануала не встречал, но он вроде как и не требуется особо. Есть фиксированный и не описанный явно псевдоним "$fs_root$", путь для которого берётся движком. Все остальные псевдонимы в оригинальном fsgame являются дочерними по отношению к "$fs_root$". Упомянутый выше псевдоним "$app_data_root$" может и наследовать и быть самостоятельным - в зависимости от источника игры и частных настроек. А вообще, ограничений там никаких нет, и любой псевдоним можно описывать как по относительному пути, так и по абсолютному. Для портативности нужно чтобы пути всех псевдонимов были относительными.
  10. Дико плюсую, ибо я уже почти набил отличающийся ответ по оригиналу ТЧ.
  11. Точную причину мы, не общаясь с разработчиками, не узнаем, но очень похоже на правду. Я бы тоже так сделал.
  12. @WinCap, судя по скриптам, так оно и в оригинале. Смотрим xr_walker.script: action_walker_activity:activate_scheme(loading, npc) --> action_walker_activity:reset_scheme(loading, npc) --> self.move_mgr:reset(...) Далее в move_mgr.script: move_mgr:reset(...) --> сброс self.current_point_index = nil (плюс self.can_use_get_current_point_index = false до окончания экстраполяции в extrapolate_callback) --> move_mgr:setup_movement_by_patrol_path() где видим такую развилочку: if self.current_point_index then self.object:set_start_point(self.current_point_index) self.object:set_patrol_path(self.path_walk, patrol.next, patrol.continue, true) else -- наш случай self.object:set_patrol_path(self.path_walk, patrol.nearest, patrol.continue, true) end
  13. Проблем с игрой не было, а вот у потенциального разработчика-последователя, который ожидает при получении объекта по имени, что там всего один такой экземпляр, причём конкретный, хотя их на самом деле два, - проблемы будут. @Balavnik, дополню ответ коллеги по цеху. Гарантированным способом дождаться момента, когда клиентский объект уже точно есть, является использование функционала класса level.client_spawn_manager(), в экземпляр которого добавляется коллбэк (функция, вызываемая при некоем событии), срабатывающий при выходе только что заспавненного объекта в онлайн. Пример (отформатировал вызов построчно для наглядности): local sobj = alife():create(section, position, lvid, gvid) if sobj ~= nil then level.client_spawn_manager():add( sobj.id, -- id известного нам серверного объекта 65535, -- параметр игнорируется, обычно ставлю такое значение для простоты function (id, obj) -- функция-коллбэк, здесь job - клиентский объект, id - его id, равный sobj.id -- что-то делаем с obj end ) end Важно при этом помнить, что коллбэк этот существует ровно до момента ближайшей загрузки из сэйва/перехода на другую локацию, после которых уже не сработает. Поэтому применять этот метод получится при спавне только на той же локации, что и герой, ну и желательно в alife-радиусе. Подробнее про класс client_spawn_manager(), в том числе про альтернативную перегрузку метода add(), рекомендую почитать в уже много раз упоминавшемся "справочнике" здесь и здесь.
  14. Параметр name можно менять произвольно, это то внутреннее имя объекта, которое в игре будет возвращаться при вызове метода obj:name(). Единственное вероятное (не проверял) требование - имя должно быть уникальным. Параметр section_name, как можно догадаться из названия, должен совпадать с секцией нужного типа.
  15. Kirgudu

    Инструмент

    Обновление Инструмента от 2024-05-22 1. Во всех комплектах в разделе Переход добавлен подраздел Поиск объекта. Здесь можно осуществить поиск объектов по их серверному или человекопонятному имени, а также переместиться к выбранному объекту (поддерживается двойной клик на элементе списка). Поиск можно осуществить по всем локациям или только по текущей, а также с учётом или без учёта содержимого любых контейнеров. Для поиска доступны: НПС (сталкеры и торговцы), монстры, оружие, броня, патроны, медикаменты, еда, детекторы и артефакты. 2. В ряде комплектов восстановлена ранее случайно потёртая и требуемая для поиска функция приведения строк к нижнему регистру.
  16. Kirgudu

    Скриптование

    @Balavnik function spawn_remkom(first_speaker, second_speaker) local sobj = alife():story_object(5003) alife():create("vodka", vector(), 0, 0, sobj.id) end Примечание: при спавне в контейнере точные координаты и вертексы указывать не обязательно, можно обойтись значениями по умолчанию.
  17. Kirgudu

    Скриптование

    В OGSR тоже есть. Везде есть, кроме оригинала ТЧ и основанных на нём без расширения или редактирования движка модов.
  18. string.sub(input, 42, 55) Больше о работе со строками: https://lua-users.org/wiki/StringLibraryTutorial
  19. Kirgudu

    Инструмент

    Новая версия Инструмента от 2024-05-17 В готовых комплектах для оригинала ТЧ и Фотографа, а также в конструкторе для ТЧ исправлена критическая ошибка, которая на некоторых системах (если имя пользователя содержит символы в верхнем регистре) приводила к почти гарантированному вылету. Пользователям Инструмента на данных платформах настоятельно рекомендую взять себе исправление. Другие комплекты также перезалиты с учётом накопившихся улучшений и оптимизаций. Приятного использования!
  20. Они действительно служат примерно одним и тем же целям, только xr_motivator используется для сталкеров, тогда как bind_stalker - для героя. См. разницу между bind_stalker.init() и bind_stalker.actor_init(), которые прописаны в свойстве script_binding в, соответственно, m_stalker.ltx и actor.ltx
  21. Я тоже не знал до поры до времени. В своё время полез внутрь для исправления разных выявленных недочётов, ну и заметил. В модулях Артоса есть довольно много полезных вещей, не выставленных публично и не описанных ни в какой инструкции, но для того, чтобы их найти, надо, конечно, изучить модули глазами от и до. @Balavnik, дополню свой предыдущий ответ, поскольку вчера забыл о ещё одной возможности m_netpk. Как я уже сказал, можно использовать встроенный метод print() (также не забыть при этом подключить lua_extension/lua_helper от Артоса для поддержки table.print): local pk = get_netpk(obj) pk:print() Таким способом ты выведешь в лог все текущие значения свойств данного конкретного нет-пакета. Но что если тебе нужно узнать не текущее содержимое, а полный возможный состав нет-пакета данного типа объекта и какого типа каждое его свойство? Для этого существует метод dumpDesc(), явно описанный в инструкции к модулю (см. пункт 3.2). Этот метод возвращает строку с полным читабельным описанием нет-пакета, которую, в свою очередь, можно самостоятельно вывести в лог. Но так как строка скорее всего будет слишком длинной для вывода в один приём, потребуется дополнительная обвязка для разбиения на части: local pk = get_netpk(obj) -- получаем нет-пакет объекта local description = pk:dumpDesc() -- получаем его описание -- бьём на части по 200 символов максимум и выводим в лог local console = get_console() local pattern = "(."..string.rep(".?", 199)..")" for line in description:gmatch("[^\n]+") do for part in line:gmatch(pattern) do console:execute("load ~:"..part) end end Результат:
  22. Можно проще. В m_netpk есть встроенный метод print, который выведет в лог все имеющиеся свойства конкретного нет-пакета: local pk = get_netpk(obj) pk:print() Единственное, для вывода в лог там используется метод table.print. Если правильно помню, в штатном lua его нет, поэтому потребуется также подключить артосовский расширитель lua_extension (lua_helper) или аналог.
  23. @Norman Eisenherz куда именно добавлял второй класс: в <character> (npc_profile.xml) или <specific_character> (например, character_desc_garbage.xml)? В упомянутом посте речь идёт о втором.
  24. Kirgudu

    Инструмент

    @tihik спасибо, вечером внесу по-тихому в публичный архив, пусть будет. Кому надо - заменит на свои точки впоследствии.
  25. Kirgudu

    Инструмент

    2024-05-08: Обновил все конструкторы и готовые сборки Инструмента. Из важного снаружи, помимо разных оптимизаций и улучшений "под капотом": Ссылка на хранилище всё та же. Приятного использования!
×
×
  • Создать...