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

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

Только обычно...  

Ты спрашивал об окончании загрузки - тогда  <= 1.

У меня выглядит примерно так:

local is_loaded = false -- объявили переменную-флаг
далее, в ф-ции апдейта
if device().precache_frame <= 1 then
     if not is_loaded then
          ...... это будет выполнено однократно .....
 
          is_loaded = true
     end
end

 

 

 

Стандартные аномалии - возможно. А вот динамически добавленные - видны через всю локу.

Ну так выставь для них соответствующие флаги(подробнее об этом тут), и будут они вести себя так-же как и стандартные(это ты имел ввиду, те что через all.spawn созданы ?)

Изменено пользователем UnLoaded
  • Спасибо 1
Ссылка на комментарий
Ты спрашивал об окончании загрузки - тогда <= 1.

Ну в  той конструкции, что я привёл, как я понял, пока device().precache_frame > 1 функция не выполняется совсем.

 

Ну так выставь для них соответствующие флаги

Ок, гляну. Этот пост, вообще, читал, но не рассматривал в контексте аномалий.

 

стандартные(те что через all.spawn созданы ?)

Ну да. В ЗП же одиночных аномалий нет. Все сосредоточены в т.н. аномальных зонах. А динамические я скриптом спавню

Щас проверил. В ЗП все аномалии видны через локу. Отошёл специально от "Котла" к "Соснодубу" - "Котёл" прекрасно видно :(

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

Шаман - СисАдмин

Всяко-разно: для ЧН

Ссылка на комментарий

Вообще в сталкере, будь то ТЧ, ЧН или ЗП, все аномалии на текущей локации - всегда онлайн, если не делать каких либо дополнительных телодвижений. Они игнорируют онлайн-радиус.

 

 

Блин, ну неужели нет никакой информации по переводу ЛЮБЫХ объектов в онлайн\офлайн? Про неписей понаписано дофига, а вот про остальное...

А зачем? там все то же самое. Методы онлайн/оффлайн операций для всех серверных объектов одни и те же, не важно нпс это или аномалия.

  • Спасибо 1

Мод, где не бывает одинаковых путей - Судьба Зоны. (Лучшее, что у меня получилось на X-Ray) На базе модифицированного движка OGSR Engine.

Бывший мододел на X-Ray / Начинающий игродел на Unreal Engine. Программист.

AMD Ryzen 9 7950X (16 ядер, 32 потока, 5.75 ГГц); RTX 3080; 128 ГБ DDR5; Arctic Liquid Freezer II-420; 3 ТБ SSD PCIe 4.0; 4ТБ HDD.

Ссылка на комментарий

Блин, чё-та я торможу...

Есть таблица вида

 

local levels = {
	["zaton"] = {
		["game_vertex"] = 292,
		["count"] = 150,
	},
	["jupiter"] = {
		["game_vertex"] = 317,
		["count"] = 150,
	},
	["pripyat"] = {
		["game_vertex"] = 666,
		["count"] = 150,
	},
}

 

Далее по скрипту, в функции, она перебирается

 

	for _, level_t in pairs(levels) do

	local level_name = ?????????

 

Как мне получить в level_name имя локации???

Все мои попытки приводят или к level_name = nil или к тому, что в неё записывается содержимое ячейки...

level_name = levels.level_t

level_name = levels[level_t]

level_name = levels[levels.level_t]

i= i+1
level_name = levels[i]

i= i+1
level_name = levels.i

 

 

Шаман - СисАдмин

Всяко-разно: для ЧН

Ссылка на комментарий

Снова вопрошаю к уважаемому сообществу...

Как отследить, что ГГ перешёл на другую локу? В процессе штудирования статей вроде попадалось что-то, но сейчас не могу найти. Поиск "смена уровня" и "смена локации" тоже ничего не даёт...

Пробовал использовать

		new_level_name = level.name()
		level_changed = false
		cur_level_name = new_level_name
		if cur_level_name ~= old_level_name then
			level_changed = true
		end

 

но безуспешно...

Шаман - СисАдмин

Всяко-разно: для ЧН

Ссылка на комментарий

@Romz, можно что-то вроде этого сделать:

local level_changed = false
local last_level = xr_logic.pstor_retrieve(db.actor, "llvl", "")
if last_level ~= level.name() then
  level_changed = true
  xr_logic.pstor_store(db.actor, "llvl", level.name())
end
Изменено пользователем naxac
  • Спасибо 1
  • Полезно 1

Аддон для ОП-2.09.2: Яндекс/Google/GitHub

naxac.gif

Ссылка на комментарий

@naxac, А можно ли таким образом хранить свои переменные? Нужно сохранять между загрузками/переходами, был ли выброс и генерировались ли уже аномалии на уровне.

Или лучше для этого использовать модуль @Artos? А как его под ЗП настроить, а то он же, вроде, под ТЧ 1.0006...

Хотя @Artos, написал, что он, вроде, под ЗП и ЧН тоже работает...

 

Собственно, вопрос к знатокам. Я таким образом пытаюсь решить проблему. Аномальки у меня генерируются и складываются в табличку anomaly_queue

	for _, level_t in pairs(levels) do
		for i = 1, level_t.count do
			local anom_t = {}
			local pos_new = {}
			anom_t.game_vertex = level_t.game_vertex
			repeat
				anom_t.level_vertex = math.random(1571597)
				pos_new = level.vertex_position(anom_t.level_vertex)
			until anom_check(pos_new) == true
			anom_t.x = pos_new.x
			anom_t.y = pos_new.y
			anom_t.z = pos_new.z
			anom_t.section = anomaly_sections[math.random(1, #anomaly_sections)].anom_section
			if	string.find(anom_t.section, "zone_mine_gravitational") or
				string.find(anom_t.section, "_field_") or
				string.find(anom_t.section, "zone_radioactive") then
				anom_t.field = "field"
			else
				anom_t.field = nil
			end
			table.insert(anomaly_queue, anom_t)
		end
	end

 

А затем, через ещё одну функцию, которая просто берёт параметры из anomaly_queue и передаёт в функцию спавна, спавнятся на всех локациях ЗП. Я её раньше показывал уже, но продублирую

 

function create_anom(section, rad_anom, x, y, z, lv, gv, mode)

	if gv == nil then
		gv = db.actor:game_vertex_id()
	end
	if lv == nil then
		lv = db.actor:level_vertex_id()
	end
	local pos = db.actor:position()
	if x == nil then
		x = pos.x
	end
	if y == nil then
		y = pos.y
	end
	if z == nil then
		z = pos.z
	end

	local p_obj = alife():create(section, vector():set(x, y, z), lv, gv)
	local packet = net_packet()

---------------------Читаем нет-пакет----------------
	packet:w_begin(0)
	p_obj:STATE_Write(packet)
	packet:r_seek(2)

	local game_vertex_id			= packet:r_u16()
	local distance				= packet:r_float()
	local direct_control			= packet:r_s32()
	local level_vertex_id			= packet:r_s32()
	local object_flags			= packet:r_s32()
	local custom_data			= packet:r_stringZ()
	local story_id				= packet:r_s32()
	local spawn_story_id			= packet:r_s32()
	local shape_count			= packet:r_u8()

	for i = 1,shape_count do
		local shape_type		= packet:r_u8()
		if shape_type == 0 then
			local center		= packet:r_vec3()
			local radius		= packet:r_float()
		else
			local box		= packet:r_matrix()
		end
	end

	local restrictor_type			= packet:r_u8()
	local max_power				= packet:r_float()
	local owner_id				= packet:r_s32()
	local enabled_time			= packet:r_u32()
	local disabled_time			= packet:r_u32()
	local start_time_shift			= packet:r_u32()
	local offline_interactive_radius	= packet:r_float()
	local artefact_spawn_count		= packet:r_u16()
	local artefact_position_offset		= packet:r_s32()
	local last_spawn_time			= packet:r_u8()

---------------------Меняем данные пакета---------------------

	local new_center			= vector():set(0, 0, 0)
	owner_id				= bit_not(0)
	offline_interactive_radius		= 30
	if mode ~= nil then
		custom_data			= mode
	end
	if rad_anom ~= nil then
		radius				= rad_anom
	end

---------------------------Пишем в пакет---------------------

	packet:w_begin( 0 )

	packet:w_u16(game_vertex_id)
	packet:w_float(distance)
	packet:w_s32(direct_control)
	packet:w_s32(level_vertex_id)
	packet:w_s32(object_flags)
	packet:w_stringZ(custom_data)
	packet:w_s32(story_id)
	packet:w_s32(spawn_story_id)
	packet:w_u8(1)
	packet:w_u8(0)
	packet:w_vec3(new_center)
	packet:w_float(radius)
	packet:w_u8(restrictor_type)
	packet:w_float(max_power)
	packet:w_s32(owner_id)
	packet:w_u32(enabled_time)
	packet:w_u32(disabled_time)
	packet:w_u32(start_time_shift)
	packet:w_float(offline_interactive_radius)
	packet:w_u16(artefact_spawn_count)
	packet:w_s32(artefact_position_offset)

	if mode == nil then
		packet:w_u8(last_spawn_time)
	end

	packet:r_seek(2)
	p_obj:STATE_Read(packet, packet:w_tell())

	return p_obj
end

 

Так вот, аномальки на локации, где находится в текущий момент ГГ, спавнятся нормально. То есть, как положено, на "земле"/"полу".

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

Пока я думаю решать эту проблему путём индивидуального спавна для каждой локации. То есть, устанавливать три флага (был_выброс, уже_есть_аномалии и смена_локи), запоминать их в псторе и проверять их на апдейте (либо актора, либо менеджера выбросов).

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

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

Шаман - СисАдмин

Всяко-разно: для ЧН

Ссылка на комментарий

@Romz, проще всё это "повесить" на инфопоршни - по одному на каждую локацию (например, "<имя_уровня>_info"). При заходе на локу проверяешь поршень, если его нет, то спавнишь аномалии и выдаёшь поршень. При начале выброса все инфо дисаблишь и удаляешь все аномалии на всех уровнях. По завершении выброса - делаешь как при заходе на локацию.

  • Спасибо 1

Аддон для ОП-2.09.2: Яндекс/Google/GitHub

naxac.gif

Ссылка на комментарий

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

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

  • Согласен 2
Ссылка на комментарий

 

 

проще всё это "повесить" на инфопоршни - по одному на каждую локацию (например, "<имя_уровня>_info").

Как-то так к примеру.

function start_скрипт()
if level.name()=="predbannik" and not has_alife_info("info_pred") then db.actor:give_info_portion(info_pred")
......
......
elseif level.name()=="hiding_road" and not has_alife_info("info_road") then db.actor:give_info_portion("info_road")
    end
end

Ну может скрипто_гуру что-то и поновей предложат.

  • Спасибо 1
Ссылка на комментарий

@naxac, @_Val_, Я бы не хотел обращаться к инфопоршням, потому что их нужно будет раскидывать ещё по другим скриптам. Сейчас у меня всё, связанное с аномальками, крутится в surge_manager и собственно скрипте аномалек. И я бы хотел это так и оставить.

А вот хранилище от @Artos, в принципе, можно использовать. Может, ещё для чего пригодится.

Шаман - СисАдмин

Всяко-разно: для ЧН

Ссылка на комментарий

pstor (кстати, тут это уже разбиралось) имеет смысл только для актора.

В нем удобно хранить что-нибудь элементарное, типа вот как раз id уровня, с которого ушли.

 

Кстати, совершенно идиотские функции pstor_store()/pstor_retrieve() и, тем более, странные обертки к ним из amk лучше сразу заменить обращения к db.storage[0].pstor.наша_переменная, или где нибудь в net_spawn сразу вынести в хоть тот же db.pstor = db.storage[0].pstor (или сразу _G.pstor).

 

"бездонные хранилища" - они - для сохранения всего подряд в невменяемых количествах (ну, типа, коллекция порнофильмов, полное собрание переписки энгельса с каутским и т.д.). Правда, я так до сих пор и не понял, зачем сохранять в сэйвах порнофильмы. ;) Ибо, как сказал однажды один мудрый человек (и, вроде бы, этим человеком и был сам Артос) - "что можно вычислить - лучше - вычислить).

 

Если надо хранить какие-то уникальные данные для неписей или там предметов - пора таки уже думать в сторону модифицированных движков, либо, если, опять же, это единичные случаи - писать в custom_data.

 

P.S. Инфо о посещениях/уходах с уровня - явный оверкилл.

 

P.P.S. Появление/исчезновение актора в онлайне - это, внезапно, net_spawn()/net_destroy() в биндере. Соответственно, там и ставим _G.actor = объект актора/false, а где надо проверить - пишем тупо и банально if actor ...

Опять же, зная, что актор в онлайне появляется и исчезает всегда первым, такие проверки нужны только в довольно специфических местах, а во всех остальных случаях просто подумать над последовательностью запуска наших скриптов (см. в "прозекторской").

Изменено пользователем Dennis_Chikin
Ссылка на комментарий

@Dennis_Chikin, Ну, собственно, задача стоит не хранить что-то, а правильно спавнить аномальки на уровнях, на которых ГГ не присутствует. А т.к. это не получается реализовать нормально, то приходим к сохранению переменных между переходами ГГ с уровня на уровень.

 

P.S. Инфо о посещениях/уходах с уровня - явный оверкилл.

Если рассматривать в плане спавна аномалек - то нормально. Потому что, при спавне аномалек только на текущем уровне, нужно проверить, спавнились ли они тут уже после выброса, чтобы не спавнить их опять.

Кстати, может есть какой-то явный признак начала игры? А то у меня сейчас наверчено проверок... А они, походу, не работают, потому что при загрузке/переходе на другой уровень все переменные переинициализируются...


Вопрос по se_stor

Как его правильно к ЗП прикрутить? А то там bind_stalker от ТЧ лежит, и в нём куча несуществующих уже в ЗП функций и переменных. Чегось запутался малёх...

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

Шаман - СисАдмин

Всяко-разно: для ЧН

Ссылка на комментарий
Romz, Некоторым спавн-объектам (нпс, смарты, аномалии, пути) нужны точные gv\lv-vertex, что и делает компилятор (xr_ai) при сборке спавна. Но из скрипта видно, что используется начальный gv и рандомный lv, и возможно именно из-за этого возникают проблемы, хотя если создавать аномалии в самом спавне (пакуя его acdc) и используя начальные gv\lv - то никаких проблем. Как пример с ошибкой, добавил с десяток смарт-коверов на янов с gv\lv = 317, 1231404 - так после смены уровня, те кто находился в них - оказывались в правом верхнем углу уровня (район аномалии "плавни"), а при переходе в онлайн - дружно бежали обратно на станцию. В тоже время, различные рестрикторы, секции physic_object и некоторые другие, данным методом нормально создаются. Возможно это зависит (чтобы точно узнать, нужно изучать исходный код игры) от стадий загрузки текущего уровня (в логе это - Сервер: Загрузка симуляции жизни... и т.д), и когда гг на одной локации, а создаёшь на другой, предполагается, что необходимые стадии выполнены (типа - Загрузка ИИ объектов... т.п). Изменено пользователем Dennis_Chikin
  • Нравится 1
Ссылка на комментарий

@h0N0r, Я немного модифицировал скрипт генерации аномалек, чтобы gv/lv подставлялись реальные, а не просто максимальные для уровня или рандомные. Но всё равно аномальки спавнятся в воздухе. Может быть, это ещё от координат зависит, и на онлайновой локе объекты "притягиваются" к террейну, а на офлайновых, вешаются чисто по координатам.

У меня так раз студни заспавнились на опорах ЛЭП, как на ёлках, а другой раз жарка появилась над Гавайцем и била вниз.

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

Шаман - СисАдмин

Всяко-разно: для ЧН

Ссылка на комментарий

 

 

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

 

Ссылка на комментарий

@Romz, с помощью функции level.vertex_position(lv_id) ты можешь получить позицию левел-вертекса только на текущей локации.

Поэтому на других локациях аномалии оказываются в тех позициях, которые соответствуют позициям левел-вертексов текущей локации. 

  • Согласен 1
  • Полезно 1
Ссылка на комментарий

@Romz, если еще актуально, для отлова переходов между уровнями и соответственно выполнения действий если актор на данном уровне впервые после последнего выброса, у меня такой вот код:

 

нетспавн актора

local old_level_name = se_stor.get("levelname","predbannik")
    local new_level_name = string.lower(level.name())
    if old_level_name ~= new_level_name then
        events.actor_change_location(old_level_name, new_level_name) -- вызываем наш "колбек перехода", передавая, откуда и куда пришли. там уже делаем что надобно.
        se_stor.set("levelname", new_level_name)
    end

Для сохранения "а был ли на этой локе выброс?" - просто записываю через запятую все локи на которых побывал актор, в отдельное поле того же se_stor. а при собственно выбросе - очищаю этот список. таким образом, если запросить список и поискать в нем локацию, на которую зашел актор, то ее отсутствие там и будет означать, что с момента последнего выброса он здесь впервые.

 

 

 

У меня тут свое, к знающим... думал что вроде понял как это тикает, но видимо нет.

 

Пытаюсь серверному объекту (любому и каждому) добавить метод

 

_g.script

        local sim = alife()
        sim._object = sim.object
        sim.object = function(SELF, id)
            if not id or id > 65535 then return nil end
            local SOBJ = sim._object(SELF, id)
            if SOBJ then
            SOBJ.CLASS_TYPE = function(selfobj)
                local C = selfobj:clsid()
                return class_registrator.get_class_type(C)
            end end
            return SOBJ
        end
        
        sim.already_reloaded = true
    _G.alife = function() return sim end

потом где попало делаю так

local sim = alife()
local sobj = sim:object(id)
local clstp = sobj:CLASS_TYPE()

И получаю вылет

attempt to call method 'CLASS_TYPE' (a nil value)

что я делаю не так?

 

 


 

 

Правда, я так до сих пор и не понял, зачем сохранять в сэйвах порнофильмы

Ну, в этом есть свой плюс. Когда надо что-то где-то сохранить, просто сохраняешь и все. Не заморачиваясь о том сколько места это займет.

Конечно же не забывая позаботиться о том, чтоб по возможности занимало поменьше, а так же о том что "все что возможно вычислить, лучше вычислить а не хранить". Но тем не менее... ощущение не-связанности рук приятно.

  • Спасибо 1

Мод, где не бывает одинаковых путей - Судьба Зоны. (Лучшее, что у меня получилось на X-Ray) На базе модифицированного движка OGSR Engine.

Бывший мододел на X-Ray / Начинающий игродел на Unreal Engine. Программист.

AMD Ryzen 9 7950X (16 ядер, 32 потока, 5.75 ГГц); RTX 3080; 128 ГБ DDR5; Arctic Liquid Freezer II-420; 3 ТБ SSD PCIe 4.0; 4ТБ HDD.

Ссылка на комментарий

Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

Создать аккаунт

Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!

Зарегистрировать новый аккаунт

Войти

Есть аккаунт? Войти.

Войти
  • Недавно просматривали   0 пользователей

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