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

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


Svoboда

Рекомендуемые сообщения

@Romz, тут нужны, наверное, специалисты по аномалиям именно в ЗП, так как мои знания ограничиваются только ЧН.

Например,

Ещё у меня возникает некоторое сомнение по поводу anom_t.field, потому что оно или "_zone", или nil

для ЧН это применяется при спавне аномальных полей, и может принимать значение "field", а не "_zone".

В целом же любые манипуляции с нет-пакетом аномалий преследуют, как правило, 2 цели:

1. установка нужного размера (через радиус сферы);

2. установка кастом даты (как раз "field" для аномальных полей в ЧН, и, возможно, что-то другое для аномалий в других частях игры).

Этим целям удовлетворяет, на мой взгляд, как первый скрипт, так и два других, явных ошибок я не вижу. Разве что, как уже писал выше, поменять строчки записи в пакет и установки позиции чтения из него местами. Но это уже на всякий случай; не могу сказать точно, является ли это ошибкой в действительности.

 

Возможно, кто-нибудь сможет оказать бОльшую помощь.

  • Спасибо 1

Поделиться этим сообщением


Ссылка на сообщение

@Romz, в ЧН спавн аномалий происходит аналогичным образом. На текущей локации всё путём, а если пытаешься завпавнить на другой локации - возникают проблемы. Найти решение не удалось. Поэтому аномалии я спавню только на текущей локации.
Что касается сохранения дополнительных данных. Настоятельно рекомендую прикрутить таки какое-либо универсальное хранилище, например уже упомянутый тобой модуль Артоса. Дело в том, что пстор обязан уложиться в нет-пакет ГГ, размер которого в ЗП равен 16 килобайтам. Мало того, что туда уже пишутся всяческие данные из оригинала, так ещё и ты будешь добавлять, и не факт, что ограничишься данной задачей. Это в один прекрасный момент может привести к переполнению нет-пакета и, как следствие, к потере данных, вылетам или даже порче сохранений.

Ничего сложного в прикручивании универсального хранилища нет, тот же модуль Артоса прекрасно работает в моде для ЧН, думаю и для ЗП будет то же самое.

  • Согласен 2

Поделиться этим сообщением


Ссылка на сообщение

 

 

Как его правильно к ЗП прикрутить? А то там 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_ST

3. Следует добавить в файл class_registrator.script в конец функции 'register' строки:
if se_stor then
cs_register (object_factory, "CGameObject", "se_stor.se_custom_storage", "CUST_ST", "custom_storage")
end

4. В скрипте биндера актора (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) могут быть самыми различными, да и мною ужк давались различные варианты.
В данной сборке даны минимальные варианты для удобства настройки и проверки функционала модуля хранилища.

 

Поделиться этим сообщением


Ссылка на сообщение

 

 

local clstp = sobj:CLASS_TYPE()

Попробуй так:

local clstp = sobj and type(sobj.CLASS_TYPE) == 'function' and sobj:CLASS_TYPE()

На тот случай, если для данного конкретного объекта не сработало «if SOBJ then».

Поделиться этим сообщением


Ссылка на сообщение

@Romz, проверь каким-нибудь чекером, что lua_extensions.script не имеет ошибок. Маловероятно, но возможно, что он из-за этого не загружается.

Кроме того, до и после после prefetch попробуй проверить (например, выводом в лог) тип переопределяемого метода. Если всё в порядке, type(table.size) должно выдать значение 'function'.

  • Нравится 1

Поделиться этим сообщением


Ссылка на сообщение

Он сподобился, но выложил как раз от 09.09, а потом вроде удалил.

Даже и не знаю, что посоветовать. Объективных причин скрытию lua_extension я не вижу... в ЧН цепляется без проблем.


Попробуй вместо prefetch("lua_extension") использовать if lua_extension then end


И да, что показала проверка типа table.size до и после префетча?

Поделиться этим сообщением


Ссылка на сообщение

Ещё предложение.

В lua_extension есть функция fStringExtraFormat, в комплекте se_stor от 09.2013 она идёт в самом начале.
В функции в двух местах есть шаблон '%\%[s|d|f]' (строки 65 и 78) и в одном месте шаблон '%\%[d|s|f]' (строка 72). Попробуй убрать в этих шаблонах вертикальную черту.

@Charsi говорит, что после такого изменения lua_extension у него в ЗП загрузился (а до того также не был виден).

Изменено пользователем Kirgudu

Поделиться этим сообщением


Ссылка на сообщение

Тогда как рабочий вариант могу посоветовать взять из lua_extension только используемые функции и вставить их куда-то ещё, да хоть в тот же _g.script.

Это exformat, table.size и, возможно, что-то ещё, что вызывается в se_stor, а также вызывается уже из этих функций.

Конечно, это довольно ёмкая и, вероятно, ненужная исходя из твоих задач работа. Но чисто ради спортивного интереса я бы попробовал и рассказал о результатах здесь - вдруг кому поможет в аналогичной ситуации. Заодно, может быть, при последовательном переносе обнаружится причина, по которой полный модуль не хочет в ЗП грузиться.

К сожалению, сам я не смогу этим заняться как минимум неделю, а то и больше.

Изменено пользователем Kirgudu
  • Согласен 2

Поделиться этим сообщением


Ссылка на сообщение

Функция в функции - это нормально?

Хоть десяток функций друг в друга вкладывай. Тут дело в другом... надо думать.

Пока предложение следующее.

 

Вариант 1.

Функция fStringExtraFormat (она же exformat в глобальном пространстве _G) используется только для вывода отладочной информации в модуле хранилища.

Закомментируй её целиком, также закомментируй:

  • lua_extension: строки 874-876, 929-931
  • se_stor: строки 47-49

При добавлении из _g_ADD.script не надо добавлять строки 53-67.

Всё должно заработать, но без вывода возможной отладочной информации.

 

Вариант 2.

Попробуй вместо комментирования всего и вся поменять в шаблонах этой функции %\% на %% (в четырёх местах).

Изменено пользователем Kirgudu
  • Согласен 1
  • Полезно 1

Поделиться этим сообщением


Ссылка на сообщение
Только заменил %\% на %:%

Вариант с %/%, я думаю, тоже бы прокатил.

В корне неверное решение. Лучше б тогда просто закомментировал по первому варианту.

Тут надо понимать, что и для чего было сделано.

@Artos написал шаблоны вида '%\%[s|d|f]', чтобы работало такое формирование строки, выводимой в лог:

exformat("something %s something else %d something else 2]", param1, param2) 

То есть берётся исходная строка, в которую в подстановочные места, обозначенные %s, %d или %f, добавляются значения дополнительных аргументов.

Строго говоря, артосовский шаблон тоже не совсем верен - как справедливо заметил в кулуарной беседе @Charsi, в нём должно быть экранирование процента процентом же, а не escape-символ. Но, как ни странно, в ТЧ и ЧН шаблон Артоса не приводит к «невидимости» модуля и нормально работает.

Ты же добавляешь ещё один символ, который приводит к неправильной работе указанного выше вывода в лог. Функция в твоей редакции просто не найдёт %s и др. и выведет исходную строку в лог как есть, без подстановки аргументов.

Правильным вариантом шаблона должен быть именно тот, что приведён выше: '%%...' и без вертикальных чёрточек между символами в квадратных скобках. Например, '%%[sdf]' или '%%'.

Изменено пользователем Kirgudu
  • Полезно 1

Поделиться этим сообщением


Ссылка на сообщение

@Карлан, у меня более старая версия 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.

Изменено пользователем Kirgudu
  • Полезно 1

Поделиться этим сообщением


Ссылка на сообщение

@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 записываются в универсальном хранилище и читаются оттуда же. При этом нет необходимости записывать эти данные через чанки, а пстор актора освобождается от лишней информации.

 

Изменено пользователем Kirgudu
  • Спасибо 1
  • Полезно 3

Поделиться этим сообщением


Ссылка на сообщение

@Romz, я сейчас с мобильного вошёл, посмотреть не могу. ЕМНИП, при загрузке данные (кроме чанков) читаются в другом месте. Глянь функцию read_tail_packet (как-то так) и откуда она вызывается.
Если надо будет, уточню завтра.
Что же касается вылета, видать твоя функция printf вовсе не так уж везде доступна. И при удалении, как ты говоришь, "самопальной" скрипту становится нечего вызывать.

Посмотрел. Да, так и есть, я правильно запомнил. Во время загрузки данные в глобальную таблицу хранилища читаются функцией read_tail_packet, которая вызывается при регистрации каждого кастомного объекта, используемого для сохранения данных в файле.

Изменено пользователем Kirgudu
  • Спасибо 1

Поделиться этим сообщением


Ссылка на сообщение

Честно говоря, я тоже других переопределений prinf (кроме как в комментируемой тобой строчке) не нашёл, не могу без предметного теста сказать, откуда берётся эта ошибка.

Да пусть у тебя в его модулях выводится через консоль, какая разница? На самом деле, после отладки вывод в лог вообще можно убрать.

Поделиться этим сообщением


Ссылка на сообщение

@abramcumner, об этом я уже писал здесь.

@Romz, если подождёшь несколько дней, ориентировочно со вторника по пятницу на следующей неделе я постараюсь подготовить рабочий пример встраивания в чистый ЗП.


 

 

Все файлы присутствуют, именно так называются, методы save и load в них присутствуют.

В модуле level_weathers нет публичных функций save и load. Ну нету! Есть save и load, описанные только как методы класса WeatherManager. se_stor же ни о каких классах в подключаемых для сохранения модулях не знает. Поэтому тупо пользоваться примером из se_stor нельзя.

Подробнее смотри по ссылке выше.

Изменено пользователем Kirgudu
  • Спасибо 1
  • Согласен 1

Поделиться этим сообщением


Ссылка на сообщение

@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 в этом модуле существуют только в контексте класса. Изменено пользователем Kirgudu
  • Спасибо 1

Поделиться этим сообщением


Ссылка на сообщение

 

 

То есть, всё, что не имеет публичных вызовов save и load убираем из чанков.

А что имеет - добавляем (так как список в примере se_stor неточный).

 

 

А если есть необходимость хранить их отдельно, переносим их  вызовы save и load из actor_binder:save и actor_binder:load в ext_save и ext_load.

Примерно так. В примере из se_stor такие модули уже указаны в ext_save и ext_load. Надо только актуализировать список согласно реалиям ЗП.

Либо - переделать таки эти модули на хранение данных в глобальной таблице хранилища, как я уже расписывал выше.

Точнее сейчас сказать не могу, если это требуется - жди неделю.

  • Спасибо 1

Поделиться этим сообщением


Ссылка на сообщение

@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.

Изменено пользователем Kirgudu
  • Полезно 1

Поделиться этим сообщением


Ссылка на сообщение

Ну так это 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 выдаёт это предупреждение. Не факт, что что-то критичное, но удостовериться в этом надо.

Поделиться этим сообщением


Ссылка на сообщение

Что странно, никаких предпосылок к этому я не вижу. Имя чанка никак не участвует в формировании технологического нет-пакета (только как ключ таблицы), а ошибка в логе говорит о том, что вместо нет-пакета во временную таблицу было записано значение типа boolean. Чего быть не может, судя по коду se_stor.
Ну да ладно.

  • Согласен 1

Поделиться этим сообщением


Ссылка на сообщение
  • Недавно просматривали   0 пользователей

    • Ни один зарегистрированный пользователь не просматривает эту страницу.
×
×
  • Создать...