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

[CoP] Ковыряемся в файлах


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

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

  • Полезно 1
Ссылка на комментарий
6 часов назад, Kirgudu сказал:

Всё, что он делает - это раз в какое-то время вычитывает из конфигурации текущий тип списка товаров, примерно такого вида: current_buy_supplies = supplies_generic, а потом методом npc:buy_supplies() передаёт его движку.

Спасибо, стало чуть яснее назначение конкретно этих переменных. Но update_time и особенно resuply_time конечно все равно очень напрягают, особенно вторая, название буквально кричит о том, что она должна отвечать как раз за то самое время обновления. Попробую этим самым логированием проверить-таки назначение, поиграюсь еще с разными значениями.

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

Пардон за эту простыню ненужной инфы, просто обидно, что такая, по сути, мелочь закрыта там, куда можно соваться только во всеоружии в контексте моддинга.

Хотел еще уточнить насчет примера использования логирования, вот, допустим, часть кода пресловутого trade_manager:

if tt.update_time ~= nil and tt.update_time < time_global() then
		return
	end
	tt.update_time = time_global() + 3600000

Чтобы залогировать tt.update_time должно быть так:
 

    if tt.update_time ~= nil and tt.update_time < time_global() then
        return
    end
    tt.update_time = time_global() + 3600000

    to_log("Message: %s", tt.update_time)

?

И в каком именно месте скрипта можно это прописать, конкретно вот в таких местах манипуляции с нужными переменными, или в любом месте до последнего end, кроме всяких if и for?

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

@SWEAW, пример приведён верно, но это, конечно, только один из возможных вариантов. Обычно, если хотят посмотреть, что происходит с переменной, то смотрят её значение (читай логируют) непосредственно до изменения и сразу после, перед сравнением (if) с другой переменной и перед любым использованием. Это если брать по максимуму. Естественно, если такое логирование будет в update функции, файл лога забьётся однотипными строками, но это не страшно.

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

  • Спасибо 1
  • Согласен 1
Ссылка на комментарий
9 часов назад, SWEAW сказал:

Правда, если привязка к сейв-лоаду зашита в движок

tt.resuply_time явно движковый параметр, в скриптах он задан как= time_global() + 24*3600000 ,т.е. раз в 24 часа обновляется ассортимент , в с сейв он пишется как (tt.resuply_time - текущее время), а при лоаде к этому значению сохранённом наоборот добавляется текущее время, хотя я не помню в ЗП же вроде как и в ТЧ все равно этот баг/фича остался, что ассортимент все равно полностью обновляется при сейв-лоаде.

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

@WinCap я помню в некоторых модах на ЗП делали так что ассортимент не менялся по несколько дней в том же Дед Эйре

31 минуту назад, WinCap сказал:

Дополнительно отмечу, что причина, по которой ПЫСы закомментировали этот код, неизвестна

наверно потому и закоментили потому что это вызывало  "Если отойти подальше и сделать save/load, то он обновится", а отходить там есть куда локи то Юпитер, Затон большие

Ссылка на комментарий
2 часа назад, WinCap сказал:

И, может быть, его активация вызовет ещё какие-нибудь ошибки.

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

--'	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

 

  • Нравится 2
  • Полезно 1
Ссылка на комментарий

@WinCap спасибо за очень подробное разжевывание, попробую и это протестить.

 

А за дистанцию перехода в оффлайн\онлайн,

 

4 часа назад, WinCap сказал:

только для тех торговцев кто online. Если отойти подальше

 

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

 

Но если сугубо теоретически - можно же на относительно небольшой локации разместить торгаша так, чтобы при увеличенном радиусе а-лайфа и нормально работающем скрипте он и не обновлялся на ф5-ф9 в пределах уровня, и игра бы работала удобоваримо?

Ссылка на комментарий
3 часа назад, SWEAW сказал:

Только это, как я слышал, чревато проблемами с производительностью?

Формально да, на слабых ПК могут быть проблемы. Но у нас тестили вариант, когда алайф задается таким чтобы заведомо любая локация была в онлайне полностью вся.

И на современных производительных ПК, (И я сейчас не про свой. Скромнее), сталкер в таком режиме работает даже лучше, т.к. нет лагов на загрузке объектов в онлайн, они все всегда в онлайне.

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

  • Полезно 2

Мод, где не бывает одинаковых путей - Судьба Зоны. (Лучшее, что у меня получилось на 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.

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

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

 

9 часов назад, WinCap сказал:

Можно раскомментировать условие

 

В общем, сделал по совету, это

 

6 часов назад, Kirgudu сказал:

можно записать переинициализацию таблицы примерно так:

 

тоже добавил, логи выставил сначала только на конечные значения переменных с "_time", плюс изначально в скрипте были printf на некоторые параметры сохранения\загрузки, еще заменил-таки time_global() на game.time(), потому что эмпирическим путем получилось, что ведут они себя абсолютно одинаково (не работают и ни на что не влияют, по крайней мере исходя из конечных цифр). Потом еще зачем-то выставил логи на buy_supplies и ей подобные, хотя их значения вообще, как оказалось, про другое.

 

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

 

Скрытый текст
local trade_manager = {}

function trade_init(npc, cfg)
	printf("TRADE INIT[%s]", npc:name())
	if trade_manager[npc:id()] == nil then
		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

	trade_manager[npc:id()].cfg_ltx = cfg
	trade_manager[npc:id()].config = ini_file(cfg)

	-- коэфициенты покупки
	local str = utils.cfg_get_string(trade_manager[npc:id()].config, "trader", "buy_condition", npc, true, "")
	if str == nil then
		abort("Incorrect trader settings. Cannot find buy_condition. [%s]->[%s]", npc:name(), cfg)
	end
	trade_manager[npc:id()].buy_condition = xr_logic.parse_condlist(npc, "trade_manager", "buy_condition", str)

	-- коэфициенты продажи
	str = utils.cfg_get_string(trade_manager[npc:id()].config, "trader", "sell_condition", npc, true, "")
	if str == nil then
		abort("Incorrect trader settings. Cannot find sell_condition. [%s]->[%s]", npc:name(), cfg)
	end
	trade_manager[npc:id()].sell_condition = xr_logic.parse_condlist(npc, "trade_manager", "sell_condition", str)

	-- список закупки
	str = utils.cfg_get_string(trade_manager[npc:id()].config, "trader", "buy_supplies", npc, false, "")
	if str ~= nil then
		trade_manager[npc:id()].buy_supplies = xr_logic.parse_condlist(npc, "trade_manager", "buy_supplies", str)
	end
	to_log("Definition of trade_manager[npc:id()].buy_supplies 1: %s", trade_manager[npc:id()].buy_supplies)

-- buy_item_condition_factor
	str = utils.cfg_get_string(trade_manager[npc:id()].config, "trader", "buy_item_condition_factor", npc, false, "", "0.7")
	if str ~= nil then
		trade_manager[npc:id()].buy_item_condition_factor = xr_logic.parse_condlist(npc, "trade_manager", "buy_item_condition_factor", str)
	end
end


function update(npc)
	local tt = trade_manager[npc:id()]

	if tt == nil then
		printf("TRADE [%s]:  tt is nil", npc:name())
		return
	end

	if tt.update_time ~= nil and tt.update_time < game.time() then
		return
	end
	
	tt.update_time = game.time() + 60000
	to_log("Definition of tt.update_time 1: %s", tt.update_time)

	local str = xr_logic.pick_section_from_condlist(db.actor, npc, tt.buy_condition)
	if(str=="" or str==nil) then
		abort("Wrong section in buy_condition condlist for npc [%s]!", npc:name())
	end
	if tt.current_buy_condition ~= str then
		--'printf("TRADE [%s]: buy condition = %s", npc:name(), str)
		npc:buy_condition(tt.config, str)
		tt.current_buy_condition = str
	end

	str = xr_logic.pick_section_from_condlist(db.actor, npc, tt.sell_condition)
	if(str=="" or str==nil) then
		abort("Wrong section in buy_condition condlist for npc [%s]!", npc:name())
	end
	if tt.current_sell_condition ~= str then
		printf("TRADE [%s]: sell condition = %s", npc:name(), str)
		npc:sell_condition(tt.config, str)
		tt.current_sell_condition = str
	else
		printf("TRADE [%s]: current = %s   sell = %s", npc:name(), tostring(tt.current_sell_condition), tostring(str))
	end

	str = tonumber(xr_logic.pick_section_from_condlist(db.actor, npc, tt.buy_item_condition_factor))
	if tt.current_buy_item_condition_factor ~= str then
		npc:buy_item_condition_factor(str)
		tt.current_buy_item_condition_factor = str
	end

	if tt.buy_supplies == nil then
		return
	end

	str = xr_logic.pick_section_from_condlist(db.actor, npc, tt.buy_supplies)
	if(str=="" or str==nil) then
		abort("Wrong section in buy_condition condlist for npc [%s]!", npc:name())
	end
	if tt.current_buy_supplies ~= str then
		if tt.resuply_time ~= nil and tt.resuply_time < game.time() then
			return
		end
		--'printf("TRADE [%s]: buy_supplies = %s", npc:name(), str)
		npc:buy_supplies(tt.config, str)
		tt.current_buy_supplies = str
		to_log("Definition of tt.current_buy_supplies 1 %s", tt.current_buy_supplies)
		tt.resuply_time = game.time() + 120000
		to_log("Definition of tt.resuply_time 1 %s", tt.resuply_time)
	end
end


function save(obj, packet)
	local tt = trade_manager[obj:id()]
	set_save_marker(packet, "save", false, "trade_manager")
	--' Сохраняем присутствует ли инициализированная торговля в принципе.
	if tt == nil then
		printf("TRADE SAVE [%s]: ignored", obj:name())
		packet:w_bool(false)
		return
	else
		packet:w_bool(true)
	end

	packet:w_stringZ(tt.cfg_ltx)

	printf("TRADE SAVE [%s]: current_buy_condition = %s", obj:name(), tostring(tt.current_buy_condition))
	if tt.current_buy_condition == nil then
		packet:w_stringZ("")
	else
		packet:w_stringZ(tt.current_buy_condition)
	end

	printf("TRADE SAVE [%s]: current_sell_condition = %s", obj:name(), tostring(tt.current_sell_condition))
	if tt.current_sell_condition == nil then
		packet:w_stringZ("")
	else
		packet:w_stringZ(tt.current_sell_condition)
	end

	printf("TRADE SAVE [%s]: current_buy_supplies = %s", obj:name(), tostring(tt.current_buy_supplies))
	if tt.current_buy_supplies == nil then
		packet:w_stringZ("")
	else
		packet:w_stringZ(tt.current_buy_supplies)
	end

	local cur_tm = game.time()

	if tt.update_time == nil then
		packet:w_s32(-1)
	else
	 	packet:w_s32(tt.update_time - cur_tm)
	end

	if tt.resuply_time == nil then
		packet:w_s32(-1)
	else
	 	packet:w_s32(tt.resuply_time - cur_tm)
	end
	set_save_marker(packet, "save", true, "trade_manager")
end

function load(obj, packet)
	set_save_marker(packet, "load", false, "trade_manager")
	local a = packet:r_bool()
	if a == false then
		printf("TRADE LOAD [%s]: ignored", obj:name())
		return
	end

	trade_manager[obj:id()] = {}

	local tt = trade_manager[obj:id()]

	tt.cfg_ltx = packet:r_stringZ()
	printf("TRADE LOAD [%s]: cfg_ltx = %s", obj:name(), tostring(tt.cfg_ltx))

	tt.config = ini_file(tt.cfg_ltx)

	a = packet:r_stringZ()
	printf("TRADE LOAD [%s]: current_buy_condition = %s", obj:name(), tostring(a))
	if a ~= "" then
		tt.current_buy_condition = a
		obj:buy_condition(tt.config, a)
	end

	a = packet:r_stringZ()
	printf("TRADE LOAD [%s]: current_sell_condition = %s", obj:name(), tostring(a))
	if a ~= "" then
		tt.current_sell_condition = a
		obj:sell_condition(tt.config, a)
	end

	a = packet:r_stringZ()
	printf("TRADE LOAD [%s]: current_buy_supplies = %s", obj:name(), tostring(a))
	if a ~= "" then
		tt.current_buy_supplies = a
		to_log("Definition of tt.current_buy_supplies 2: %s", tt.current_buy_supplies)
	end

	local cur_tm = game.time()

	a = packet:r_s32()
	if a ~= -1 then
		tt.update_time = cur_tm + a
	end
	
	to_log("Definition of tt.update_time 2: %s", tt.update_time)

	a = packet:r_s32()
	if a ~= -1 then
		tt.resuply_time = cur_tm + a
	end
	
	to_log("Definition of tt.resuply_time 2: %s", tt.resuply_time)
	
	set_save_marker(packet, "load", true, "trade_manager")
end
----------- NOT TO DELETE!!!!!!!!! called from engine
function get_buy_discount(npc_id)
	local str = utils.cfg_get_string(trade_manager[npc_id].config, "trader", "discounts", nil, false, "", "")
	if(str=="") then
		return 1
	end

	local sect = xr_logic.pick_section_from_condlist(db.actor, nil, xr_logic.parse_condlist(nil, "trade_manager", "discounts", str))
	str = utils.cfg_get_number(trade_manager[npc_id].config, sect, "buy", nil, false, 1)
		return str
end
----------- NOT TO DELETE!!!!!!!!! called from engine
function get_sell_discount(npc_id)
	local str = utils.cfg_get_string(trade_manager[npc_id].config, "trader", "discounts", nil, false, "", "")
	if(str=="") then
		return 1
	end

	local sect = xr_logic.pick_section_from_condlist(db.actor, nil, xr_logic.parse_condlist(npc, "trade_manager", "discounts", str))
	str = utils.cfg_get_number(trade_manager[npc_id].config, sect, "sell", nil, false, 1)

	return str
end

 

 

И примерно спустя часа полтора чистки 50к+ строк лога от лишней инфы, которая не касается Бороды, с которым все и проверялось (троеточия как раз заменяют не относящиеся к делу логи или бесконечные увеличения tt.update_time 1):

 

Скрытый текст

--Загрузка игры

--...

[LUA]  filling npc_info for obj [zat_a2_stalker_barmen2464]

--...

[LUA]  registering stalker zat_a2_stalker_barmen2464

--...

[LUA]  _objectzat_a2_stalker_barmen2464: set load marker: 299
[LUA]  _objectzat_a2_stalker_barmen2464: LOAD DIF: 239
[LUA]  _trade_manager: set load marker: 540
[LUA]  TRADE LOAD [zat_a2_stalker_barmen2464]: cfg_ltx = misc\trade\trade_zat_a2_barmen.ltx
[LUA]  TRADE LOAD [zat_a2_stalker_barmen2464]: current_buy_condition = trade_generic_buy
[LUA]  TRADE LOAD [zat_a2_stalker_barmen2464]: current_sell_condition = trade_generic_sell
[LUA]  TRADE LOAD [zat_a2_stalker_barmen2464]: current_buy_supplies = supplies_start
! Cannot find saved game ~:Definition of tt.current_buy_supplies 2: supplies_start
! Cannot find saved game ~:Definition of tt.update_time 2: 4261173416
! Cannot find saved game ~:Definition of tt.resuply_time 2: 4261853856
[LUA]  _trade_manager: LOAD DIF: 96

--...

[LUA]  TRADE INIT[zat_a2_stalker_barmen2464]
! Cannot find saved game ~:Definition of trade_manager[npc:id()].buy_supplies 1: table: 0x071d64a29c40

--...

--Постоянно увеличивающийся tt.update_time 1

[LUA]  TRADE [zat_a2_stalker_barmen2464]: current = trade_generic_sell   sell = trade_generic_sell
! Cannot find saved game ~:Definition of tt.update_time 1: 4261207416

--...

[LUA]  TRADE [zat_a2_stalker_barmen2464]: current = trade_generic_sell   sell = trade_generic_sell
! Cannot find saved game ~:Definition of tt.update_time 1: 4261209646

--...

--Первое сохранение

[LUA]  _motivator_binder: set save marker: 4502
[LUA]  _objectzat_a2_stalker_barmen2464: set save marker: 4502
[LUA]  _objectzat_a2_stalker_barmen2464: SAVE DIF: 239
[LUA]  _trade_manager: set save marker: 4743
[LUA]  TRADE SAVE [zat_a2_stalker_barmen2464]: current_buy_condition = trade_generic_buy
[LUA]  TRADE SAVE [zat_a2_stalker_barmen2464]: current_sell_condition = trade_generic_sell
[LUA]  TRADE SAVE [zat_a2_stalker_barmen2464]: current_buy_supplies = supplies_start
[LUA]  _trade_manager: SAVE DIF: 96

--Закупка припасов

[LUA]  on_item_take [vodka]
item place [3]
[LUA]  on_item_take [vodka]
item place [3]
[LUA]  on_item_take [vodka]
item place [3]
[LUA]  on_item_take [kolbasa]
item place [3]
[LUA]  on_item_take [kolbasa]
item place [3]
[LUA]  on_item_take [kolbasa]
item place [3]
[LUA]  on_item_take [kolbasa]
item place [3]
[LUA]  on_item_take [bread]
item place [3]
[LUA]  on_item_take [bread]
item place [3]
[LUA]  on_item_take [energy_drink]
item place [3]

--Второе сохранение

[LUA]  _objectzat_a2_stalker_barmen2464: set save marker: 4502
[LUA]  _objectzat_a2_stalker_barmen2464: SAVE DIF: 239
[LUA]  _trade_manager: set save marker: 4743
[LUA]  TRADE SAVE [zat_a2_stalker_barmen2464]: current_buy_condition = trade_generic_buy
[LUA]  TRADE SAVE [zat_a2_stalker_barmen2464]: current_sell_condition = trade_generic_sell
[LUA]  TRADE SAVE [zat_a2_stalker_barmen2464]: current_buy_supplies = supplies_start
[LUA]  _trade_manager: SAVE DIF: 96

--Загрузка второго сохранение для проверки обновления ассортимента: не обновился

[LUA]  _motivator_binder: set load marker: 399
[LUA]  _objectzat_a2_stalker_barmen2464: set load marker: 399
[LUA]  _objectzat_a2_stalker_barmen2464: LOAD DIF: 239
[LUA]  _trade_manager: set load marker: 640
[LUA]  TRADE LOAD [zat_a2_stalker_barmen2464]: cfg_ltx = misc\trade\trade_zat_a2_barmen.ltx
[LUA]  TRADE LOAD [zat_a2_stalker_barmen2464]: current_buy_condition = trade_generic_buy
[LUA]  TRADE LOAD [zat_a2_stalker_barmen2464]: current_sell_condition = trade_generic_sell
[LUA]  TRADE LOAD [zat_a2_stalker_barmen2464]: current_buy_supplies = supplies_start
! Cannot find saved game ~:Definition of tt.current_buy_supplies 2: supplies_start
! Cannot find saved game ~:Definition of tt.update_time 2: 4261479076
! Cannot find saved game ~:Definition of tt.resuply_time 2: 4261907516
[LUA]  _trade_manager: LOAD DIF: 96

--...

[LUA]  TRADE INIT[zat_a2_stalker_barmen2464]
! Cannot find saved game ~:Definition of trade_manager[npc:id()].buy_supplies 1: table: 0x071d55c0af00

--Отбежал далеко от Скадовска, сделал третий сейв, прибежал обратно проверить обновление: не обновилось

[LUA]  TRADE INIT[zat_a2_stalker_barmen2464]
! Cannot find saved game ~:Definition of trade_manager[npc:id()].buy_supplies 1: table: 0x071d66c89a00

--Загрузил третий сейв, снова прибежал на Скадовск: ассортимент обновился

[LUA]  TRADE INIT[zat_a2_stalker_barmen2464]
! Cannot find saved game ~:Definition of trade_manager[npc:id()].buy_supplies 1: table: 0x071d654a1f40

--...

--Здесь единожды за весь лог всплыла tt.resuply_time 1

[LUA]  TRADE [zat_a2_stalker_barmen2464]: sell condition = trade_generic_sell
! Cannot find saved game ~:Definition of tt.current_buy_supplies 1 supplies_start
! Cannot find saved game ~:Definition of tt.resuply_time 1 4262900846
! Cannot find saved game ~:Definition of tt.update_time 1: 4262000846

--...

--Контрольная закупка, контрольный четвертый сейв

[LUA]  _motivator_binder: set save marker: 4805
[LUA]  _objectzat_a2_stalker_barmen2464: set save marker: 4805
[LUA]  _objectzat_a2_stalker_barmen2464: SAVE DIF: 239
[LUA]  _trade_manager: set save marker: 5046
[LUA]  TRADE SAVE [zat_a2_stalker_barmen2464]: current_buy_condition = trade_generic_buy
[LUA]  TRADE SAVE [zat_a2_stalker_barmen2464]: current_sell_condition = trade_generic_sell
[LUA]  TRADE SAVE [zat_a2_stalker_barmen2464]: current_buy_supplies = supplies_start
[LUA]  _trade_manager: SAVE DIF: 96

--Загрузка четвертого сейва, ассортимент: не обновился

[LUA]  _motivator_binder: set load marker: 349
[LUA]  _objectzat_a2_stalker_barmen2464: set load marker: 349
[LUA]  _objectzat_a2_stalker_barmen2464: LOAD DIF: 239
[LUA]  _trade_manager: set load marker: 590
[LUA]  TRADE LOAD [zat_a2_stalker_barmen2464]: cfg_ltx = misc\trade\trade_zat_a2_barmen.ltx
[LUA]  TRADE LOAD [zat_a2_stalker_barmen2464]: current_buy_condition = trade_generic_buy
[LUA]  TRADE LOAD [zat_a2_stalker_barmen2464]: current_sell_condition = trade_generic_sell
[LUA]  TRADE LOAD [zat_a2_stalker_barmen2464]: current_buy_supplies = supplies_start
! Cannot find saved game ~:Definition of tt.current_buy_supplies 2: supplies_start
! Cannot find saved game ~:Definition of tt.update_time 2: 4262320966
! Cannot find saved game ~:Definition of tt.resuply_time 2: 4262963126
[LUA]  _trade_manager: LOAD DIF: 96

--...

[LUA]  TRADE INIT[zat_a2_stalker_barmen2464]
! Cannot find saved game ~:Definition of trade_manager[npc:id()].buy_supplies 1: table: 0x071d4b5214c0

 

 

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

Ссылка на комментарий
1 час назад, SWEAW сказал:

В общем, сделал по совету, это

Не правильно. Нужно было ИЛИ раскоментировать стандартный код ИЛИ изменить его, как посоветовал @Kirgudu.

Посмотри внимательно, как написано в его посте.

 

В функции "trade_manager.update" в условиях для переменных "tt.update_time" и "tt.resuply_time" нужно поменять знак сравнения на "больше" - ">".

При использовании "game.time()" значения времени 60000 и 120000 чрезвычайно малы.

Изменено пользователем WinCap
  • Нравится 1

S.T.A.L.K.E.R. CoP Objects (upd 15.11.24)

Ссылка на комментарий
01.06.2024 в 01:01, WinCap сказал:

Нужно было ИЛИ раскоментировать стандартный код

 

01.06.2024 в 01:01, WinCap сказал:

В функции "trade_manager.update" в условиях для переменных "tt.update_time" и "tt.resuply_time" нужно поменять знак сравнения на "больше" - ">".

 

Это сделал, касаемо этого:

 

01.06.2024 в 01:01, WinCap сказал:

При использовании "game.time()" значения времени 60000 и 120000 чрезвычайно малы.

 

специально ставил малые значения (игровую минуту и 2 соответственно), чтобы было быстрее проверять, что меняется. Поменял на игровой час и два соответственно, но по итогу с этим кодом:

 

Скрытый текст
local trade_manager = {}


function trade_init(npc, cfg)
	printf("TRADE INIT[%s]", npc:name())
	if trade_manager[npc:id()] == nil then
		trade_manager[npc:id()] = {}
	end

	trade_manager[npc:id()].cfg_ltx = cfg
	trade_manager[npc:id()].config = ini_file(cfg)

	-- коэфициенты покупки
	local str = utils.cfg_get_string(trade_manager[npc:id()].config, "trader", "buy_condition", npc, true, "")
	if str == nil then
		abort("Incorrect trader settings. Cannot find buy_condition. [%s]->[%s]", npc:name(), cfg)
	end
	trade_manager[npc:id()].buy_condition = xr_logic.parse_condlist(npc, "trade_manager", "buy_condition", str)

	-- коэфициенты продажи
	str = utils.cfg_get_string(trade_manager[npc:id()].config, "trader", "sell_condition", npc, true, "")
	if str == nil then
		abort("Incorrect trader settings. Cannot find sell_condition. [%s]->[%s]", npc:name(), cfg)
	end
	trade_manager[npc:id()].sell_condition = xr_logic.parse_condlist(npc, "trade_manager", "sell_condition", str)

	-- список закупки
	str = utils.cfg_get_string(trade_manager[npc:id()].config, "trader", "buy_supplies", npc, false, "")
	if str ~= nil then
		trade_manager[npc:id()].buy_supplies = xr_logic.parse_condlist(npc, "trade_manager", "buy_supplies", str)
	end
	to_log("Definition of trade_manager[npc:id()].buy_supplies 1: %s", trade_manager[npc:id()].buy_supplies)

-- buy_item_condition_factor
	str = utils.cfg_get_string(trade_manager[npc:id()].config, "trader", "buy_item_condition_factor", npc, false, "", "0.7")
	if str ~= nil then
		trade_manager[npc:id()].buy_item_condition_factor = xr_logic.parse_condlist(npc, "trade_manager", "buy_item_condition_factor", str)
	end
end


function update(npc)
	local tt = trade_manager[npc:id()]

	if tt == nil then
		printf("TRADE [%s]:  tt is nil", npc:name())
		return
	end

	if tt.update_time ~= nil and tt.update_time > game.time() then
		return
	end
	
	tt.update_time = game.time() + 3600000
	to_log("Definition of tt.update_time 1: %s", tt.update_time)

	local str = xr_logic.pick_section_from_condlist(db.actor, npc, tt.buy_condition)
	if(str=="" or str==nil) then
		abort("Wrong section in buy_condition condlist for npc [%s]!", npc:name())
	end
	if tt.current_buy_condition ~= str then
		--'printf("TRADE [%s]: buy condition = %s", npc:name(), str)
		npc:buy_condition(tt.config, str)
		tt.current_buy_condition = str
	end

	str = xr_logic.pick_section_from_condlist(db.actor, npc, tt.sell_condition)
	if(str=="" or str==nil) then
		abort("Wrong section in buy_condition condlist for npc [%s]!", npc:name())
	end
	if tt.current_sell_condition ~= str then
		printf("TRADE [%s]: sell condition = %s", npc:name(), str)
		npc:sell_condition(tt.config, str)
		tt.current_sell_condition = str
	else
		printf("TRADE [%s]: current = %s   sell = %s", npc:name(), tostring(tt.current_sell_condition), tostring(str))
	end

	str = tonumber(xr_logic.pick_section_from_condlist(db.actor, npc, tt.buy_item_condition_factor))
	if tt.current_buy_item_condition_factor ~= str then
		npc:buy_item_condition_factor(str)
		tt.current_buy_item_condition_factor = str
	end

	if tt.buy_supplies == nil then
		return
	end

	str = xr_logic.pick_section_from_condlist(db.actor, npc, tt.buy_supplies)
	if(str=="" or str==nil) then
		abort("Wrong section in buy_condition condlist for npc [%s]!", npc:name())
	end
	if tt.current_buy_supplies ~= str then
		if tt.resuply_time ~= nil and tt.resuply_time > game.time() then
			return
		end
		--'printf("TRADE [%s]: buy_supplies = %s", npc:name(), str)
		npc:buy_supplies(tt.config, str)
		tt.current_buy_supplies = str
		to_log("Definition of tt.current_buy_supplies 1 %s", tt.current_buy_supplies)
		tt.resuply_time = game.time() + 7200000
		to_log("Definition of tt.resuply_time 1 %s", tt.resuply_time)
	end
end


function save(obj, packet)
	local tt = trade_manager[obj:id()]
	set_save_marker(packet, "save", false, "trade_manager")
	--' Сохраняем присутствует ли инициализированная торговля в принципе.
	if tt == nil then
		printf("TRADE SAVE [%s]: ignored", obj:name())
		packet:w_bool(false)
		return
	else
		packet:w_bool(true)
	end

	packet:w_stringZ(tt.cfg_ltx)

	printf("TRADE SAVE [%s]: current_buy_condition = %s", obj:name(), tostring(tt.current_buy_condition))
	if tt.current_buy_condition == nil then
		packet:w_stringZ("")
	else
		packet:w_stringZ(tt.current_buy_condition)
	end

	printf("TRADE SAVE [%s]: current_sell_condition = %s", obj:name(), tostring(tt.current_sell_condition))
	if tt.current_sell_condition == nil then
		packet:w_stringZ("")
	else
		packet:w_stringZ(tt.current_sell_condition)
	end

	printf("TRADE SAVE [%s]: current_buy_supplies = %s", obj:name(), tostring(tt.current_buy_supplies))
	if tt.current_buy_supplies == nil then
		packet:w_stringZ("")
	else
		packet:w_stringZ(tt.current_buy_supplies)
	end

	local cur_tm = game.time()

	if tt.update_time == nil then
		packet:w_s32(-1)
	else
	 	packet:w_s32(tt.update_time - cur_tm)
	end

	if tt.resuply_time == nil then
		packet:w_s32(-1)
	else
	 	packet:w_s32(tt.resuply_time - cur_tm)
	end
	set_save_marker(packet, "save", true, "trade_manager")
end

function load(obj, packet)
	set_save_marker(packet, "load", false, "trade_manager")
	local a = packet:r_bool()
	if a == false then
		printf("TRADE LOAD [%s]: ignored", obj:name())
		return
	end

	trade_manager[obj:id()] = {}

	local tt = trade_manager[obj:id()]

	tt.cfg_ltx = packet:r_stringZ()
	printf("TRADE LOAD [%s]: cfg_ltx = %s", obj:name(), tostring(tt.cfg_ltx))

	tt.config = ini_file(tt.cfg_ltx)

	a = packet:r_stringZ()
	printf("TRADE LOAD [%s]: current_buy_condition = %s", obj:name(), tostring(a))
	if a ~= "" then
		tt.current_buy_condition = a
		obj:buy_condition(tt.config, a)
	end

	a = packet:r_stringZ()
	printf("TRADE LOAD [%s]: current_sell_condition = %s", obj:name(), tostring(a))
	if a ~= "" then
		tt.current_sell_condition = a
		obj:sell_condition(tt.config, a)
	end

	a = packet:r_stringZ()
	printf("TRADE LOAD [%s]: current_buy_supplies = %s", obj:name(), tostring(a))
	if a ~= "" then
		tt.current_buy_supplies = a
		to_log("Definition of tt.current_buy_supplies 2: %s", tt.current_buy_supplies)
	end

	local cur_tm = game.time()

	a = packet:r_s32()
	if a ~= -1 then
		tt.update_time = cur_tm + a
	end
	
	to_log("Definition of tt.update_time 2: %s", tt.update_time)

	a = packet:r_s32()
	if a ~= -1 then
		tt.resuply_time = cur_tm + a
	end
	
	to_log("Definition of tt.resuply_time 2: %s", tt.resuply_time)
	
	set_save_marker(packet, "load", true, "trade_manager")
end
----------- NOT TO DELETE!!!!!!!!! called from engine
function get_buy_discount(npc_id)
	local str = utils.cfg_get_string(trade_manager[npc_id].config, "trader", "discounts", nil, false, "", "")
	if(str=="") then
		return 1
	end

	local sect = xr_logic.pick_section_from_condlist(db.actor, nil, xr_logic.parse_condlist(nil, "trade_manager", "discounts", str))
	str = utils.cfg_get_number(trade_manager[npc_id].config, sect, "buy", nil, false, 1)
		return str
end
----------- NOT TO DELETE!!!!!!!!! called from engine
function get_sell_discount(npc_id)
	local str = utils.cfg_get_string(trade_manager[npc_id].config, "trader", "discounts", nil, false, "", "")
	if(str=="") then
		return 1
	end

	local sect = xr_logic.pick_section_from_condlist(db.actor, nil, xr_logic.parse_condlist(npc, "trade_manager", "discounts", str))
	str = utils.cfg_get_number(trade_manager[npc_id].config, sect, "sell", nil, false, 1)

	return str
end

 

 

с прошлого раза ничего не изменилось. Ну как, лог теперь перестал бесконечно спамить обновлением tt.update_time 1, потому что она перестала бесконечно изменяться, и tt.resupply_time 1 перестал обновляться вообще, только, как и до этого, после сейв-лоада с торгашом в оффлайне. Но какие бы значения прибавки времени я не выставлял, хоть минута, хоть десять, хоть час - Бороде вообще плевать. Просто стоял около него ждал, пробовал много дней проспать (на случай, если все-таки размерность времени не мс, а больше), ждал и отбегал в оффлайн/прибегал обратно, спал по той же схеме - ноль эмоций, как с последней покупки было товаров, так и осталось, не обновляется. Возвращал реальное время вместо игрового - те же результаты.

 

А реально ли вообще принудительно вызывать функцию npc:buy_supplies(tt.config, str) через on_game_timer в сочетании с инфопоршнями? Условно:

 

Скрытый текст

1. Игра на старте загрузила Бороду, обновила/загрузила его ассортимент

2. Выдаем инфопоршень типа wait_for_update

3. Оборачиваем вызов npc:buy_supplies в условия:

Если поршня wait_for_update нет, то

     Вызываем npc:buy_supplies

     give_alife_info (или просто give_ifo, как-то так) поршень wait_for_update

     иначе ничего не делать

енд

4. Делаем еще один поршень, чтобы таймер постоянно не обновлялся в цикле

Если wait_for_update есть И timer_started нет, то

      give_alife_info timer_started

      on_game_timer допустим 172800 (2 суток, вроде как этот таймер использует игровые секунды) disable_info wait_for_update и timer_started

      иначе ничего не делать

енд

 

Или эти функции исключительно для файлов логики/диалогов работают?

Ссылка на комментарий
23 минуты назад, SWEAW сказал:

Но какие бы значения прибавки времени я не выставлял, ... - Бороде вообще плевать. ... как с последней покупки было товаров, так и осталось, не обновляется.

Всё дело в этом кусочке кода из функции "trade_manager.update":

Скрытый текст
str = xr_logic.pick_section_from_condlist(db.actor, npc, tt.buy_supplies)
if(str=="" or str==nil) then
	abort("Wrong section in buy_condition condlist for npc [%s]!", npc:name())
end
if tt.current_buy_supplies ~= str then			-- "Собака" зарыта тут
	if tt.resuply_time ~= nil and tt.resuply_time > game.time() then
		return
	end

 

Обновление ассортимента произойдёт после истечения времени "tt.resuply_time", но только после того как изменится текущая секция в конфигурационном файле торговца.

 

Можно попробовать изменить эту часть на примерно такую:

Скрытый текст
str = xr_logic.pick_section_from_condlist(db.actor, npc, tt.buy_supplies)
if(str=="" or str==nil) then
	abort("Wrong section in buy_condition condlist for npc [%s]!", npc:name())
end
if (tt.current_buy_supplies ~= str) or
   (tt.resuply_time == nil) or
   (tt.resuply_time < game.time()) then
	--'printf("TRADE [%s]: buy_supplies = %s", npc:name(), str)
	npc:buy_supplies(tt.config, str)
	tt.current_buy_supplies = str
	to_log("Definition of tt.current_buy_supplies 1 %s", tt.current_buy_supplies)
	tt.resuply_time = game.time() + 7200000
	to_log("Definition of tt.resuply_time 1 %s", tt.resuply_time)
end

 

 

Изменено пользователем WinCap
  • Спасибо 1
  • Нравится 1

S.T.A.L.K.E.R. CoP Objects (upd 15.11.24)

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

Приветствую, имеется вопрос как можно удалить строку "Сетевая игра" из главного меню CoP? 

Потому что при удалении ее в ui_mm_main_16 выдает следующую ошибку:

 

Expression    : assertion failed
Function      : CUIMMShniaga::CreateList
File          : D:\prog_repository\sources\trunk\xrGame\ui\UIMMShniaga.cpp
Line          : 114
Description   : pF

Кто может подсказать?

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

Всем привет. Как мы знаем, в Чистом небе, когда НПС стоит на месте, то рандомно проигрывает дополнительные анимации: прикладывает руку ко лбу, разминает спину, чешет пятую точку и т.д. В КОКе, да и в обычном Зове Припяти, все НПС просто стоят, и все. Можно ли как нибудь восстановить доп. анимации покоя для них? Знаю лишь то, что это логику править надо, только вот как?

Добавлено  Опричник,

Перемещено.

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

Возможно там в way-point прописаны анимации типа ward, guard, поэтому он их и проигрывает? Такое и в ЗП можно сделать.

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

Недавно начал играть первый раз в жизни вообще в аномали (в принципе моды никогда не ставил и ни капли в этом не понимаю). Вообщем отыграл часов 5, побегал по кордону и свалке, в итоге в один прекрасный момент начинает вылетать с этой ошибкой 

Expression    : dx10BufferUtils::CreateIndexBuffer(&p_rm_Indices, data->pointer(), iCount*2)
Function      : Fvisual::Load
File          : ..\xrRender\FVisual.cpp
Line          : 188

Экземпляр устройства GPU приостановлен. Для определения соответствующего действия используйте GetDeviceRemovedReason.


stack trace:

 пробовал найти какую-то логику в настройках графики, загружать более ранние сохранки, после загрузки бегом на другую локацию, эффект один и тот же - минут 7 игры максимум и вылет, один раз даже сохранка не загрузилась.

Добавлено  Купер,

Перемещено.

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

Здравствуйте уважаемый форумчане!
Столкнулся с проблемой при переносе оружия (как я понимаю с 3д прицелом голографическим) из BAS в мою микромодификацию на основе COP Sigerous 1.7
Собственно в оригинале BAS есть одна world модель для оружия и для худа, и по модели на каждый вид прицела, я же хотел реализовать условный уникальный ствол где 1 ворлд модель и 1 модель худа с прицелом Eotech.
Проблема заключается в том что у оружия в руках одна линза как-бы отображается в воздухе рядом с оружием, при прицеливании она отображается по центру оружия, но без перекрестия
4d3665f387753d5dcbb341099ba2f093.png
f06bf494eef420062165839d1cca751c.png
(надеюсь я правильно прикреплю скриншоты)
Отмечу что,
1) в конфиге оружия scope_status  = 0 и scope_zoom_factor  = 50
2) в логах ничего нет об отсутствии каких-либо текстур
3) шейдеры я вроде как тоже не забыл перенести (при отсутствии шейдеров игра вылетала)
Наверняка я не единственный кто сталкивался с подобным, но к сожалению я не смог нагуглить решение проблемы
Может быть кто-то из вас знает возможные причины такого эффекта, или поделится ссылкой где уже решали подобную проблему?

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

В ЧН/ЗП переход от диалога к торговле считается окончанием взаимодействия, из-за чего NPC начинают повторять "Уснул, что ли?" и прочие подобные фразы при активном окне торговли.
Куда можно прописать правку логики так, чтобы не указывать условие "помолчите, мы еще не закончили" отдельно для каждого NPC в игре?

  • Полезно 1

Мини-моды: ТЧ ЧН ЗП

Шпаргалка

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

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

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

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

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

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

Войти

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

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

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