Kirgudu 1 264 Опубликовано 28 Сентября 2015 @Romz, тут нужны, наверное, специалисты по аномалиям именно в ЗП, так как мои знания ограничиваются только ЧН. Например, Ещё у меня возникает некоторое сомнение по поводу anom_t.field, потому что оно или "_zone", или nilдля ЧН это применяется при спавне аномальных полей, и может принимать значение "field", а не "_zone". В целом же любые манипуляции с нет-пакетом аномалий преследуют, как правило, 2 цели: 1. установка нужного размера (через радиус сферы); 2. установка кастом даты (как раз "field" для аномальных полей в ЧН, и, возможно, что-то другое для аномалий в других частях игры). Этим целям удовлетворяет, на мой взгляд, как первый скрипт, так и два других, явных ошибок я не вижу. Разве что, как уже писал выше, поменять строчки записи в пакет и установки позиции чтения из него местами. Но это уже на всякий случай; не могу сказать точно, является ли это ошибкой в действительности. Возможно, кто-нибудь сможет оказать бОльшую помощь. 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 5 Октября 2015 @Romz, в ЧН спавн аномалий происходит аналогичным образом. На текущей локации всё путём, а если пытаешься завпавнить на другой локации - возникают проблемы. Найти решение не удалось. Поэтому аномалии я спавню только на текущей локации.Что касается сохранения дополнительных данных. Настоятельно рекомендую прикрутить таки какое-либо универсальное хранилище, например уже упомянутый тобой модуль Артоса. Дело в том, что пстор обязан уложиться в нет-пакет ГГ, размер которого в ЗП равен 16 килобайтам. Мало того, что туда уже пишутся всяческие данные из оригинала, так ещё и ты будешь добавлять, и не факт, что ограничишься данной задачей. Это в один прекрасный момент может привести к переполнению нет-пакета и, как следствие, к потере данных, вылетам или даже порче сохранений. Ничего сложного в прикручивании универсального хранилища нет, тот же модуль Артоса прекрасно работает в моде для ЧН, думаю и для ЗП будет то же самое. 2 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 5 Октября 2015 Как его правильно к ЗП прикрутить? А то там bind_stalker от ТЧ лежит, и в нём куча несуществующих уже в ЗП функций и переменных. Чегось запутался малёх... bind_stalker от ТЧ в комплекте хранилища - всего лишь пример. Читай readme от автора, там подробно расписан принцип использования, в том числе Использование: 1. Скопировать в папку скриптов игры основной скрипт se_stor.script;2. Добавить в конфиги (например в system.ltx) секцию [custom_storage];3. Добавить новый класс CUST_ST <-> clsid.custom_storage в class_registrator.script;4. Добавить в биндер актора алгоритм вызова события "сохранение игры" или функцию сохранения хранилища;5. Добавить в _g.script инициализацию дополнительного функционала (lua_extension и доп.функций).Примечание: В комплекте файлы с суффиксом '_ADD' являются строками, которые требуется добавить в соответствующие 'коренные' файлы.--/---------------------------------------------------------------------Пояснения (по пунктам):1. Собственно сам модуль se_stor.script:1.1 Скрипт se_stor.script имеет настройки, позволяющие использовать хранилище в разных версиях игры/модов (SoC|CS|CoP).В данной версии комплекта скрипт полностью настроен на использование с оригинальной версией SoC (ТЧ патчи v1.0004 и выше).1.2. Выводы в лог-файл дебаговой информации частично закомментированы.При необходимости можно отключить полностью или наоборот, раскомментировав нужные строки.1.3. Упоминаемая в комментариях опциональная 'система сигналов/событий' (event) используется в моде SIMBION (и возможно останется в LA),и позволяет наиболее полно использовать все возможности хранилища и работы с ним.2. Дополнительная секция 'custom_storage' может быть добавлена в любой файл с конфигами игры, читаемый движком на старте игры.[custom_storage]class = CUST_ST3. Следует добавить в файл class_registrator.script в конец функции 'register' строки:if se_stor thencs_register (object_factory, "CGameObject", "se_stor.se_custom_storage", "CUST_ST", "custom_storage")end4. В скрипте биндера актора (bind_stalker.script/bind_actor.script) требуется внести изменения помеченный в примере знаком #+#.4.1. В методы 'save' и 'load' биндера необходимо добавить строки вызова соотв. функций (save/load) скрипта хранилища.4.2. Если не предполанается изменение алгоритма хранения внешних модулей (погода, ...), то требуется организовать внешний доступ к биндеру актора.4.3. В данном комплекте хранение данных модулями заданий, тайников, пси-зон вынесены в отдельные бинарные последовательности (chunks), что позволяет не вносить изменения в эти модули.Однако необходимо описать в настройках хранилища (в таблице tPkChunks) внешние модули, в которых требуется сохранение данных в чанках (chunks).Посоветовал бы все же сменить алгоритм хранения данных на хранение в виде субтаблиц в общей таблице 'storehouse'.5. В _g.script ОБЯЗАТЕЛЬНО необходимо добавить строку (можно в самое начало) инициализации расширителя Lua-функционала (lua_extension.script):prefetch("lua_extension")- из Lua-расширителя модуль хранилища используется различные функции (но не все, остальное может использоваться и другими модулями).5.1. Функции интерфейса доступа к данным в хранилище (SetVar|GetVar|...) добавляются в конец файла или даже могут быть портированы в другой модуль (helper).5.2. Также, для возможности хранения данных объектов типа вектор/таймер требуется добавить функции isVector|isCTime|isChunk.5.3. Функции вывода в лог-файл и прерывания игры (abort) могут быть самыми различными, да и мною ужк давались различные варианты.В данной сборке даны минимальные варианты для удобства настройки и проверки функционала модуля хранилища. Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 6 Октября 2015 local clstp = sobj:CLASS_TYPE() Попробуй так: local clstp = sobj and type(sobj.CLASS_TYPE) == 'function' and sobj:CLASS_TYPE() На тот случай, если для данного конкретного объекта не сработало «if SOBJ then». Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 6 Октября 2015 @Romz, проверь каким-нибудь чекером, что lua_extensions.script не имеет ошибок. Маловероятно, но возможно, что он из-за этого не загружается. Кроме того, до и после после prefetch попробуй проверить (например, выводом в лог) тип переопределяемого метода. Если всё в порядке, type(table.size) должно выдать значение 'function'. 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 6 Октября 2015 Он сподобился, но выложил как раз от 09.09, а потом вроде удалил. Даже и не знаю, что посоветовать. Объективных причин скрытию lua_extension я не вижу... в ЧН цепляется без проблем. Попробуй вместо prefetch("lua_extension") использовать if lua_extension then end И да, что показала проверка типа table.size до и после префетча? Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 6 Октября 2015 (изменено) Ещё предложение. В lua_extension есть функция fStringExtraFormat, в комплекте se_stor от 09.2013 она идёт в самом начале.В функции в двух местах есть шаблон '%\%[s|d|f]' (строки 65 и 78) и в одном месте шаблон '%\%[d|s|f]' (строка 72). Попробуй убрать в этих шаблонах вертикальную черту. @Charsi говорит, что после такого изменения lua_extension у него в ЗП загрузился (а до того также не был виден). Изменено 6 Октября 2015 пользователем Kirgudu Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 6 Октября 2015 (изменено) Тогда как рабочий вариант могу посоветовать взять из lua_extension только используемые функции и вставить их куда-то ещё, да хоть в тот же _g.script. Это exformat, table.size и, возможно, что-то ещё, что вызывается в se_stor, а также вызывается уже из этих функций. Конечно, это довольно ёмкая и, вероятно, ненужная исходя из твоих задач работа. Но чисто ради спортивного интереса я бы попробовал и рассказал о результатах здесь - вдруг кому поможет в аналогичной ситуации. Заодно, может быть, при последовательном переносе обнаружится причина, по которой полный модуль не хочет в ЗП грузиться. К сожалению, сам я не смогу этим заняться как минимум неделю, а то и больше. Изменено 6 Октября 2015 пользователем Kirgudu 2 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 6 Октября 2015 (изменено) Функция в функции - это нормально? Хоть десяток функций друг в друга вкладывай. Тут дело в другом... надо думать. Пока предложение следующее. Вариант 1. Функция fStringExtraFormat (она же exformat в глобальном пространстве _G) используется только для вывода отладочной информации в модуле хранилища. Закомментируй её целиком, также закомментируй: lua_extension: строки 874-876, 929-931 se_stor: строки 47-49 При добавлении из _g_ADD.script не надо добавлять строки 53-67. Всё должно заработать, но без вывода возможной отладочной информации. Вариант 2. Попробуй вместо комментирования всего и вся поменять в шаблонах этой функции %\% на %% (в четырёх местах). Изменено 6 Октября 2015 пользователем Kirgudu 1 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 7 Октября 2015 (изменено) Только заменил %\% на %:% Вариант с %/%, я думаю, тоже бы прокатил. В корне неверное решение. Лучше б тогда просто закомментировал по первому варианту. Тут надо понимать, что и для чего было сделано. @Artos написал шаблоны вида '%\%[s|d|f]', чтобы работало такое формирование строки, выводимой в лог: exformat("something %s something else %d something else 2]", param1, param2) То есть берётся исходная строка, в которую в подстановочные места, обозначенные %s, %d или %f, добавляются значения дополнительных аргументов. Строго говоря, артосовский шаблон тоже не совсем верен - как справедливо заметил в кулуарной беседе @Charsi, в нём должно быть экранирование процента процентом же, а не escape-символ. Но, как ни странно, в ТЧ и ЧН шаблон Артоса не приводит к «невидимости» модуля и нормально работает. Ты же добавляешь ещё один символ, который приводит к неправильной работе указанного выше вывода в лог. Функция в твоей редакции просто не найдёт %s и др. и выведет исходную строку в лог как есть, без подстановки аргументов. Правильным вариантом шаблона должен быть именно тот, что приведён выше: '%%...' и без вертикальных чёрточек между символами в квадратных скобках. Например, '%%[sdf]' или '%%'. Изменено 7 Октября 2015 пользователем Kirgudu 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 7 Октября 2015 (изменено) @Карлан, у меня более старая версия se_stor встроена в мод (платформа ЧН), причём с изменениями, так что выковыривать оттуда будет сложно. @Romz, всё намного проще. Если ты глянешь в se_stor таблицу tPkChunks, то увидишь, что в ней для ЗП перечислены модули, которые Артос предлагал сохранять в чанках. В том числе и level_weathers. А этот модуль у тебя либо отсуствует, либо в нём нет метода save - отсюда и принудительный вылет в функции сохранения чанков. Проверь для начала это. Если судить по ЧН, в модуле level_weathers действительно нет публичного метода save. Там надо сначала получить экземпляр класса, у которого уже этот метод будет. Стандартно этот экземпляр класса сохраняется в экземпляре класса актора. Поэтому level_weathers мы из tPkChunks удаляем, вместо этого возвращаем в actor_binder:save() такую строчку: self.weather_manager:save(packet)Также надо вернуть аналогичную строчку в actor_binder:load() Затем надо проверить остальные модули, которые Artos добавил в чанки для ЗП. sr_psy_antenna и treasure_manager имеют публичные методы save и load (повторяю на всякий случай, пишу для ЧН! ЗП нет в наличии, но там по аналогии), их оставляем в чанках. task_manager в ЧН публичных save и load не имеет - его из чанков убираем, возвращая в actor_binder:save() и actor_binder:load() (если в ЗП по-другому, действовать соответственно). bind_actor - тут Artos для ЧН ошибся, этот модуль называется bind_stalker. Возможно, для ЗП это тоже так. Публичные методы save и load в него ты добавляешь согласно инструкции se_stor. Внутри них дёргаются опять же добавленные ext_save и ext_load, а там - пишутся/читаются данные ещё кое-каких внешних модулей. Записываемые/читаемые в ext_save и ext_load модули надо не тупо взять из примера se_stor (который, как мы знаем, сделан для ТЧ), а сверить с оригинальными save и load ЗП. Надеюсь, понятно расписал. Уверен на 99%, если внести все эти поправки, se_stor заработает. И это стало бы хорошим взносом для всех будущих пользователей хранилища в любых частях игры. Возможно, на следующей неделе у меня самого будет время посидеть и соорудить готовые примеры использования модуля для всех платформ, а не только для ТЧ, как это сделано в оригинальном комплекте. Поправка насчёт weather_manager. Его сохранение/загрузку Artos прописал и в таблицу чанков, и в доп. методы ext_save и ext_load. Это, понятное дело, избыточно (разве только в ЗП в этом модуле есть публичные save и load). Поэтому делаем что-то одно - либо оставляем в ext_save/load и убираем из таблицы чанков, либо убираем и из таблицы и из ext_save/load, но возвращаем в save/load. Изменено 7 Октября 2015 пользователем Kirgudu 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 7 Октября 2015 (изменено) @Romz, почему только Артосу? Он дал необходимый инструмент и пояснения, дальше тебе всё доступно, надо только понять принцип. Приведу пример из своей практики. Данные модуля проводников guiders.script, как и многих других, в ЧН сохраняются в нет-пакет актора, раздувая его без необходимости: function actor_binder:save(packet) ... guiders.save(packet) ... endДанных немного и в оригинале они представляют из себя простой набор переменных, одна из которых является плоской таблицей: function save(package) set_save_marker(package, "save", false, "guiders") package:w_stringZ(selected_point) package:w_bool(teleported_to_another_level) if temp_points_table[selected_point] then package:w_stringZ(temp_points_table[selected_point].level) package:w_stringZ(temp_points_table[selected_point].point) package:w_stringZ(temp_points_table[selected_point].look) else package:w_stringZ("nil") end set_save_marker(package, "save", true, "guiders") endОставим в стороне вероятную избыточность этих данных, так как перед нами не стоит сейчас цель оптимизировать всё. Надо всего лишь перенести эти данные из пстора актора в подключённое универсальное хранилище.Для этого переписываем метод save в модуле guiders примерно так: function save() local tSav = { teleported_to_another_level = teleported_to_another_level } if selected_point and selected_point:len() > 0 then tSav.selected_point = selected_point end if temp_points_table[selected_point] then tSav.temp_points_table = temp_points_table[selected_point] end SetVar("Guiders",tSav) endОсталось поправить вызов метода в биндере актора, удалив передачу в качестве аргумента нет-пакета актора: function actor_binder:save(packet) ... guiders.save() ... endАналогичным образом делаем правку чтения данных при загрузке.guiders.script было: function load() set_save_marker(package, "load", false, "guiders") selected_point = package:r_stringZ() teleported_to_another_level = package:r_bool() temp_points_table = {} local str = package:r_stringZ() if str~="nil" then temp_points_table[selected_point] = {} temp_points_table[selected_point].level = str temp_points_table[selected_point].point = package:r_stringZ() temp_points_table[selected_point].look = package:r_stringZ() end set_save_marker(package, "load", true, "guiders") end guiders.script стало: function load() local tSav = GetVar("Guiders",{}) if next(tSav) then DelVar("Guiders") else return end selected_point = tSav.selected_point or "" teleported_to_another_level = tSav.teleported_to_another_level temp_points_table = {} if tSav.temp_points_table then temp_points_table[selected_point] = table.clone(tSav.temp_points_table) --/ здесь table.clone() - аналог соотв. функции из lua_extension, полное копирование таблицы end end bind_stalker.script было: function actor_binder:load(packet) ... guiders.load(packet) ... end bind_stalker.script стало: function actor_binder:load(packet) ... guiders.load() ... endВсё это при условии, что методы SetVar, GetVar и DelVar добавлены в глобальном _g.script при внедрении комплекта se_stor. Если нет - можно воспользоваться методами se_stor.set() и se_stor.get(). Профит! Теперь все данные модуля guiders.script записываются в универсальном хранилище и читаются оттуда же. При этом нет необходимости записывать эти данные через чанки, а пстор актора освобождается от лишней информации. Изменено 8 Октября 2015 пользователем Kirgudu 1 3 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 8 Октября 2015 (изменено) @Romz, я сейчас с мобильного вошёл, посмотреть не могу. ЕМНИП, при загрузке данные (кроме чанков) читаются в другом месте. Глянь функцию read_tail_packet (как-то так) и откуда она вызывается.Если надо будет, уточню завтра.Что же касается вылета, видать твоя функция printf вовсе не так уж везде доступна. И при удалении, как ты говоришь, "самопальной" скрипту становится нечего вызывать.Посмотрел. Да, так и есть, я правильно запомнил. Во время загрузки данные в глобальную таблицу хранилища читаются функцией read_tail_packet, которая вызывается при регистрации каждого кастомного объекта, используемого для сохранения данных в файле. Изменено 8 Октября 2015 пользователем Kirgudu 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 8 Октября 2015 Честно говоря, я тоже других переопределений prinf (кроме как в комментируемой тобой строчке) не нашёл, не могу без предметного теста сказать, откуда берётся эта ошибка. Да пусть у тебя в его модулях выводится через консоль, какая разница? На самом деле, после отладки вывод в лог вообще можно убрать. Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 8 Октября 2015 (изменено) @abramcumner, об этом я уже писал здесь. @Romz, если подождёшь несколько дней, ориентировочно со вторника по пятницу на следующей неделе я постараюсь подготовить рабочий пример встраивания в чистый ЗП. Все файлы присутствуют, именно так называются, методы save и load в них присутствуют. В модуле level_weathers нет публичных функций save и load. Ну нету! Есть save и load, описанные только как методы класса WeatherManager. se_stor же ни о каких классах в подключаемых для сохранения модулях не знает. Поэтому тупо пользоваться примером из se_stor нельзя. Подробнее смотри по ссылке выше. Изменено 8 Октября 2015 пользователем Kirgudu 1 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 8 Октября 2015 (изменено) @Romz, а мы с @abramcumner тебе о чём? Похоже, ты просто не понимаешь разницы между публичной функцией модуля и методом класса в этом модуле. Допустим, есть у нас некий модуль module.script. В нём может быть это: function func() -- do something end и это: class "MyClass" function MyClass:__init() -- do something end function MyClass:func() -- do something end Чтобы вызвать функцию func из другого модуля в первом варианте, достаточно написать: module.func() Чтобы сделать то же самое во втором варианте, потребуется больше действий: local my_class = module.MyClass() --/ тут получили экземпляр класса my_class:func() --/ и только тут дёрнули метод se_stor умеет вызывать только публичные функции, как описано в варианте 1.Дык se_stor же, вроде, пытается методы тупо напрямую вызывать? Типа level_weathers.load?Да! Но их там нет, так как save и load в этом модуле существуют только в контексте класса. Изменено 8 Октября 2015 пользователем Kirgudu 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 8 Октября 2015 То есть, всё, что не имеет публичных вызовов save и load убираем из чанков. А что имеет - добавляем (так как список в примере se_stor неточный). А если есть необходимость хранить их отдельно, переносим их вызовы save и load из actor_binder:save и actor_binder:load в ext_save и ext_load. Примерно так. В примере из se_stor такие модули уже указаны в ext_save и ext_load. Надо только актуализировать список согласно реалиям ЗП. Либо - переделать таки эти модули на хранение данных в глобальной таблице хранилища, как я уже расписывал выше. Точнее сейчас сказать не могу, если это требуется - жди неделю. 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 9 Октября 2015 (изменено) @Romz, скорее всего, даные self.weather_manager у тебя сейчас не сохраняются. И вот почему. Методы ext_save/load вызываются из публичных (добавляемых комплектом se_stor) bind_stalker.save/load, которые, в свою очередь, должны вызываться при сохранении тех самых чанков. Но сейчас ты оставил в таблице tPkChunks, судя по всему, только sr_psy_antenna. ИМХО, для описанного тобой выше частного случая всё должно выглядеть так: bind_stalker.script function actor_binder:ext_save(pk) self.weather_manager:save(pk) end function actor_binder:ext_load(pk) self.weather_manager:load(pk) endтам же обязательно должно быть сделано (как и сказано в инструкции) это: --[[ --/#x# отключено! function actor_init (npc) --npc:bind_object(actor_binder(npc)) end --]] --/ ----------------------------------------------------------------- --/#+# организуем внешний доступ к биндеру актора: --/ ----------------------------------------------------------------- function actor_init(npc) _G.g_bind_actor = this.actor_binder(npc) npc:bind_object(g_bind_actor) end function save(...) _G.g_bind_actor:ext_save(...) end function load(...) _G.g_bind_actor:ext_load(...) end se_stor.script local tPkChunks = {} --/ таблица нет-пакетов с чанками внешних модулей (option for SIMBION mod) if iSSVer < 8 then --/ for SHoC -- ... для ЗП можно оставить без изменений elseif iSSVer < 12 then --/ for CS -- ... для ЗП можно оставить без изменений else --/ for CoP tPkChunks["bind_actor" ] = { file = "bind_stalker" } --/ ext_save/load в bind_stalker.script tPkChunks["psy_antenna" ] = { file = "sr_psy_antenna" } --/ зоны пси-излучения endСобственно, ext_save/load были сделаны как раз для того, чтобы данные внешних модулей, у которых отсутствуют публичные save/load, но есть класс с этими методами, инициализируемый в биндере актора, с минимальными изменениями перенести из нет-пакета актора в чанки.Почему у тебя вырос объём данных, записываемых в нет-пакет актора, сказать не могу, тут надо смотреть, что ты пишешь. Если беспокоит или просто интересно, для анализа организуй сам дополнительный вывод в лог соответствующей информации, это не сложно. Но, в принципе, в случае ЗП объем 8000 байт не страшен, в ЗП и ЧН безопасно записывать в нет-пакет до 16000-16200 байт. Это, кстати, учитывается в механизме se_stor. Изменено 9 Октября 2015 пользователем Kirgudu 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 9 Октября 2015 Ну так это se_actor, там свои данные пишутся. Сейчас тебя больше должно интересовать всё, что касается сохранения в bind_stalker, а там, как я смотрю, порядок. «SAVE DIF» показывает объём записанных за одно действие данных, а «set save marker» - результирующий объём нет-пакета. Вроде всё сходится. Единственное, что слегка настораживает: c:\gam\s-cop\se_stor:(165):save_storehouse:key[xr_statistic],type_key[string],type_chunk[boolean]~not saved:<Warning!> Я бы на твоём месте глянул, что пишется в этом модуле и почему se_stor выдаёт это предупреждение. Не факт, что что-то критичное, но удостовериться в этом надо. Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 9 Октября 2015 Что странно, никаких предпосылок к этому я не вижу. Имя чанка никак не участвует в формировании технологического нет-пакета (только как ключ таблицы), а ошибка в логе говорит о том, что вместо нет-пакета во временную таблицу было записано значение типа boolean. Чего быть не может, судя по коду se_stor.Ну да ладно. 1 Инструмент Поделиться этим сообщением Ссылка на сообщение