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

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


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

@ted.80 так подставь то, что ты взял из полной функции, в своё условие.

local actor = db.actor
+
actor:object=="gen_document_1354" and actor:object=="gen_document_1355"
=
db.actor:object=="gen_document_1354" and db.actor:object=="gen_document_1355"

db.actor:object - это функция. Мало того, что ты сравниваешь её (не результат выполнения функции, а саму функцию) со строкой, так ещё и применяешь синтаксис, характерный для вызова метода (указание функции после двоеточия), без собственно вызова (забыл про круглые скобки). Это приведёт к немедленному отказу в загрузке такого скрипта движком, потому что его синтаксис некорректен.
И даже такое написание, хоть синтаксически и правильное, будет неверным:

db.actor:object()=="gen_document_1354" and db.actor:object()=="gen_document_1355"

поскольку вызов этой функции требует передачи аргумента: db.actor:object("строка"), см. пример парой сообщений выше.

Так-то по смыслу твоё предложение верно. Правильная же реализация будет такая:

elseif ln=="l15_generators" and actor:object("gen_document_1354") and actor:object("gen_document_1355") then

 

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

А что нужно дописать, чтобы при выпадении с мутантов было больше частей тел? И чтоб с того же кабана можно было всегда по разному выбить 4, 3, 2, 1

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

@Juk_Bers0vik , что используется в качестве базы для правок? Если не изменяет память,  в ЧН оригинальной версии выпадение, вообще, изначально не предусмотрено.

Просто чтобы было понятно, от чего отталкиваться.


Простой правкой конфигов не обойтись, придётся добавлять скриптовый спаун в тело мутанта. Примеры релизации пожно подсмотреть в FS моде, старых версиях OGSM, например, или поискать отдельно smart_monser_part мод. И доработать под собственные нужды :biggrin:.

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

@Juk_Bers0vik Спавн имеет то же описание в движке и те же конфиги, только вероятность везде указана 0.

Для нескольких предметов надо делать обработчик в [bind_monster.script] update.

  • Нравится 1

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

Шпаргалка

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

А зачем update коллбек у мутанта дёргать? "Одноразовый" on_death, по-моему, более чем достаточно. Или net_spawn, например.

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

  

Спавню НПС в скваде в смарт террейн.

Сквад:

Спойлер

[yan_ryaboy]
faction = stalker
npc = yan_ryaboy

Собственно, а как этому скваду/НПС назначить story id?

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

Ссылка на комментарий
11 часов назад, imcrazyhoudini сказал:

как этому скваду/НПС назначить story id

Отряду никак, story_id может быть присвоен только объекту, но не группе объектов.

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

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

Для этого можно модифицировать следующую цепочку функций (см. места с комментариями, оформленными --<< ... >>):

Скрытый текст
function create_squad(actor, obj, p)
	if obj ~= nil then
		printf("pl:creating_squad from obj [%s] in section [%s]", tostring(obj:name()), tostring(db.storage[obj:id()].active_section))
	end
	local squad_id = p[1]
	if squad_id == nil then
		abort("Wrong squad identificator [NIL] in create_squad function")
	end
	local smart_name = p[2]
	if smart_name == nil then
		abort("Wrong smart name [NIL] in create_squad function")
	end

	--<< добавляем чтение третьего параметра, в котором опционально может быть передан story_id >>
	local first_npc_story_id = p[3]

	local ltx = sim_board.squad_ltx

	if not ltx:section_exist(squad_id) then
		abort("Wrong squad identificator [%s]. Squad descr doesnt exist.", tostring(squad_id))
	end

	local player_name = utils.cfg_get_string(ltx, squad_id, "faction", self, true, "")

	local board = sim_board.get_sim_board()
	local player = board.players[player_name]
	if player == nil then
		abort("Wrong player_name [%s] for squad [%s]", tostring(player_name), tostring(squad_id))
	end
	local smart = board.smarts_by_names[smart_name]
	if smart == nil then
		abort("Wrong smart_name [%s] for [%s] faction in create_squad function", tostring(smart_name), tostring(player_name))
	end
	--!!!!!!!!!!! Зыс из затычка против вылета, если кто-то пытается спаунить отряд с комьюнити отличным от того которым занят смарт!!!!!!
	if smart.player_name ~= player_name and smart.player_name ~= "none" then
	return
	end

	local squad
	local is_autogenerated_id = utils.cfg_get_bool(ltx, squad_id, "auto_id", self, false, false)

	--<< передаём параметр со story_id дальше, в симуляционный скрипт >>
	if is_autogenerated_id then
		squad = board:create_squad(player.player_name, sim_squad_scripted.sim_squad_scripted, smart, nil, squad_id, first_npc_story_id)
	else
		squad = board:create_squad(player.player_name, sim_squad_scripted.sim_squad_scripted, smart, squad_id, nil, first_npc_story_id)
	end

	board:enter_smart(squad, smart.id)

	for k,v in pairs(squad.squad_npc) do
		local obj = alife():object(k)
		board:setup_squad_and_group(obj)
	end

	squad:update()
end

 

Скрытый текст
--<< добавляем в параметры функции ещё один для передачи story_id >>
function sim_board:create_squad(player_id, squad_class, spawn_smart, sq_id, settings_id, first_npc_story_id)
		printf("create squad called")
        local squad_id = tostring(sq_id or self.id_generator:get_id())

        if self.squads[squad_id] ~= nil then
        		printf("---------------------------")
        		print_table(self.squads)
        		printf("------------------------last_id %s", self.id_generator.m_last_id)
        		print_table(self.id_generator.m_given)
        		printf("---------------------------")
        		print_table(self.id_generator.m_free)
        		printf("---------------------------")
        		abort("Two or more squad with id[%s] found!!!", squad_id)
        end

        local squad = squad_class(self, player_id, squad_id, settings_id)
        squad:init_squad(spawn_smart)
        printf("Creating squad[%s] in smart[%s]", squad_id, spawn_smart:name())
        self.squads[squad_id] = squad

        --' Определяем в каком смарте создать новый отряд
        --<< передаём добавленный параметр далее в функцию создания НПС >>
        squad:create_npc(spawn_smart, first_npc_story_id)
        squad:set_squad_sympathy()
        squad:set_squad_relation()
        self:assign_squad_to_smart(squad, spawn_smart.id)

        --' Пересчитываем Team, Squad, Group
        for k,v in pairs(squad.squad_npc) do
                local obj = alife():object(k)
                squad.board:setup_squad_and_group(obj)
        end
        --' Регистрануть новый отряд в его группировке.
        self.players[player_id]:register_squad(squad)
        self.players[player_id]:faction_brain_update()
        return squad
end

 

Скрытый текст
--<< добавляем в параметры функции ещё один для передачи story_id >>
function sim_squad_generic:create_npc(spawn_smart, first_npc_story_id)
	self.squad_power = 0

	--' Высчитываем базовую позицию спауна
	local base_spawn_position = spawn_smart.position
	local base_lvi = spawn_smart.m_level_vertex_id
	local base_gvi = spawn_smart.m_game_vertex_id
	if spawn_smart.spawn_point ~= nil then
		base_spawn_position = patrol(spawn_smart.spawn_point):point(0)
		base_lvi = patrol(spawn_smart.spawn_point):level_vertex_id(0)
		base_gvi = patrol(spawn_smart.spawn_point):game_vertex_id(0)
	end

	local custom_resource = nil
	local min_npc, max_npc = 3,5
	if self.player_id == "monster" then
		local level_name = alife():level_name(game_graph():vertex(spawn_smart.m_game_vertex_id):level_id())
		local min, max = 0,5
		if monster_resource_by_level[level_name] ~= nil then
			min = monster_resource_by_level[level_name][1]
			max = monster_resource_by_level[level_name][2]
		end
		custom_resource = math.random(min,max)

		min_npc = monster_num_by_resource[custom_resource][1]
		max_npc = monster_num_by_resource[custom_resource][2]
	end

	local player = self.board.players[self.player_id]

	local npc_in_squad = math.random(min_npc,max_npc)

	--<< определяем необходимость присвоения story_id (параметр передан или нет) >>
	local need_story_id = (type(first_npc_story_id) == "number")

	for i=1,npc_in_squad do
		local position = base_spawn_position
		position.x = position.x + math.random(-2,2)
		position.z = position.z + math.random(-2,2)

		local spawn_section = player:get_spawn_section(spawn_smart, custom_resource)
		local obj =  alife():create(spawn_section,
									position,
									base_lvi,
									base_gvi)

		--<< если необходимо присвоить story_id, делаем это посредством редактирования net-пакета >>
		if need_story_id and obj then
			local pk = get_netpk(obj, 1)
			if pk:isOk() then
				local data = pk:get()
				data.story_id = first_npc_story_id
				pk:set(data)
			end
			--<< сбрасываем признак необходимости story_id, так как присвоить можно только один раз первому НПС из отряда >>
			need_story_id = false
			--<< добавляем id НПС и story_id в онлайн таблицу объектов, получивших связку со story_id уже после загрузки >>
			if not db.id_by_story_id then db.id_by_story_id = {} end
			db.id_by_story_id[first_npc_story_id] = obj.id
		end

		obj.squad_id = self.squad_id
		self.squad_npc[obj.id] = obj.id

		self.sound_manager:register_npc(obj.id)

		if self.commander_id == nil then
			self.commander_id = obj.id
		end
		self.npc_count = self.npc_count + 1
		--printf("sim_squad_generic: npc_count is [%s], obj:rank is [%s], obj:name is [%s], self.squad_power is [%s]", tostring(self.npc_count), tostring(obj:rank()), obj:name(), tostring(self.squad_power))
		self.squad_power = self.squad_power + 5*obj:rank()/1000
	end
	self.smart_id = spawn_smart.id
	self:refresh()

	if self.squad_power > 25 then
		abort("Squad power couldnt be over 25!!!")
	end
end

 

Скрытый текст
--<< добавляем в параметры функции ещё один для передачи story_id >>
function sim_squad_scripted:create_npc(spawn_smart, first_npc_story_id)
	local spawn_sections = utils.parse_names(utils.cfg_get_string(sim_board.squad_ltx, self.settings_id, "npc", self, true, ""))

	self.squad_power = 0

	local spawn_point = utils.cfg_get_string(sim_board.squad_ltx, self.settings_id, "spawn_point", self, false, "")

	--print_table(debug.getinfo(1))
	printf("SPAWN SMART %s", spawn_smart:name())
	--' Высчитываем базовую позицию спауна
	local base_spawn_position = spawn_smart.position
	local base_lvi = spawn_smart.m_level_vertex_id
	local base_gvi = spawn_smart.m_game_vertex_id
	if spawn_point ~= nil then
		base_spawn_position = patrol(spawn_point):point(0)
		base_lvi = patrol(spawn_point):level_vertex_id(0)
		base_gvi = patrol(spawn_point):game_vertex_id(0)
	elseif spawn_smart.spawn_point ~= nil then
		base_spawn_position = patrol(spawn_smart.spawn_point):point(0)
		base_lvi = patrol(spawn_smart.spawn_point):level_vertex_id(0)
		base_gvi = patrol(spawn_smart.spawn_point):game_vertex_id(0)
	end

	local player = self.board.players[self.player_id]
	local spawn_sections_ltx = system_ini()

	--<< определяем необходимость присвоения story_id (параметр передан или нет) >>
	local need_story_id = (type(first_npc_story_id) == "number")

	for k,v in pairs(spawn_sections) do
		local custom_data = utils.cfg_get_string(spawn_sections_ltx, v, "custom_data", self, false, "", "stalker_custom_data.ltx")
		if custom_data ~= "stalker_custom_data.ltx" then
			abort("INCORRECT npc_spawn_section USED [%s]. You cannot use npc with custom_data in squads", v)
		end

		local position = base_spawn_position
		position.x = position.x + math.random(-2,2)
		position.z = position.z + math.random(-2,2)

		local obj =  alife():create(v,
									position,
									base_lvi,
									base_gvi)

		--<< если необходимо присвоить story_id, делаем это посредством редактирования net-пакета >>
		if need_story_id and obj then
			local pk = get_netpk(obj, 1)
			if pk:isOk() then
				local data = pk:get()
				data.story_id = first_npc_story_id
				pk:set(data)
			end
			--<< сбрасываем признак необходимости story_id, так как присвоить можно только один раз первому НПС из отряда >>
			need_story_id = false
			--<< добавляем id НПС и story_id в онлайн таблицу объектов, получивших связку со story_id уже после загрузки >>
			if not db.id_by_story_id then db.id_by_story_id = {} end
			db.id_by_story_id[first_npc_story_id] = obj.id
		end

		obj.squad_id = self.squad_id
		self.squad_npc[obj.id] = obj.id

		self.sound_manager:register_npc(obj.id)
		if self.commander_id == nil then
			self.commander_id = obj.id
		end
		self.npc_count = self.npc_count + 1
		self.squad_power = self.squad_power + 5*obj:rank()/1000
	end
	self.smart_id = spawn_smart.id
	self:refresh()
end

 

Скрытый текст
--<< модифицируем оригинальную функцию поиска объекта по story_id, чтобы она учитывала свежесозданные (на этом же апдейте) объекты >>
function level_object_by_sid( sid )
	local sim = alife()

	if sim then
		local se_obj = sim:story_object( sid )
		if se_obj then
			return level.object_by_id( se_obj.id )
		end
		--<< серверный объект не найден, ищем среди добавленных после загрузки >>
		local se_obj_id = db.id_by_story_id and db.id_by_story_id[sid]
		if se_obj_id then
			return level.object_by_id( se_obj_id )
		end
	end

	return nil
end

 

Тогда, например, создание из логики уникального отряда, первому (либо единственному) НПС из состава которого будет присвоен story_id, будет выглядеть так (показано на примере Васяна со Свалки):

[sr_idle@story_messenger]
on_info = {+gar_story_searched_digger_body} sr_idle@story_messenger_dogs_spawn %=create_squad(gar_digger_messenger_man:gar_smart_terrain_8_5:731)%

где 731 - добавленный в том числе в game_story_ids.ltx персональный story_id.

 

Примечание: для модификации net-пакета и присвоения story_id в данном примере использован модуль m_netpk от Артоса:

https://www.amk-team.ru/forum/topic/13216-sborochnyj-ceh/?do=findComment&comment=971137

 

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

@Kirgudu https://dropmefiles.net/ru/UH7Gzws9V

Не работает почему-то, проверил пару раз, можешь взглянуть, авось прозевал чего?

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

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

@imcrazyhoudini придется подождать, я за компом буду уже не скоро, в лучшем случае дня через 3. Может кто быстрее подскажет.

  • Спасибо 1
Ссылка на комментарий
02.11.2024 в 22:59, imcrazyhoudini сказал:

Не работает почему-то, проверил пару раз, можешь взглянуть, авось прозевал чего?

1. Я функцию create_npc в sim_squad_scripted.script выше сначала показал с ошибкой, затем поправил почти сразу после публикации поста, но в примере выше она осталась с ошибкой. Не исключено, что по каким-то причинам эта ошибка к вылету не ведёт, но при этом и не работать не даёт правильно, такое бывает. Рекомендую снова взять себе эту функцию из моего поста, теперь она там исправлена.

2. Не показано, где и как происходит создание нужного отряда.

3. Не показано, добавлен ли новый story_id в реестр.

В остальном модификация оригинальных функций произведена правильно, кроме вышеупомянутой других ошибок не вижу.
Опять же, по такой схеме story_id добавляется Васяну и потом используется в моде Final Stroke, там это проверено не раз и успешно работает.

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

@Kirgudu 

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

Не показано, добавлен ли новый story_id в реестр.

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

game_story_ids.ltx

[story_ids]
  1 = "yan_saharov"
  2 = "yan_pribor"
  3 = "yan_ryaboy" ; нужный

 

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

2. Не показано, где и как происходит создание нужного отряда.

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

[logic]
active = sr_idle
 

[sr_idle]
on_info = {+yan_ryaboy_start} sr_idle@2 %=create_squad(yan_ryaboy:yan_ryaboy:3)%

 

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

теперь она там исправлена.

Поправил, не помогло.

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

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

@imcrazyhoudini, что такое второй параметр yan_ryaboy из твоего вызова спавна отряда? Вот этот:  

1 час назад, imcrazyhoudini сказал:

%=create_squad(yan_ryaboy:yan_ryaboy:3)%

 

И ещё вопрос: что именно не работает-то? Спавн отряда? Или назначение НПС из этого отряда story_id? Если второе - как проверял?

Изменено пользователем Kirgudu
Ссылка на комментарий
1 час назад, Kirgudu сказал:

Вот этот:  

Название смарта + название сквада.

Не работает назначение стори айди. Проверял двумя способами - одновременно со спавном НПС выдаётся квест в котором цель указана как сей НПС.

И пытался такой функцией проверить:
 

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

function spot_ryaboy()
    local obj = alife():story_object(story_ids.yan_ryaboy)
    level_tasks.add_location_by_id(obj.id, "blue_location", game.translate_string("set_spot_ban"))
end

На что получаю:
 

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

FATAL ERROR
 
[error]Expression    : !m_error_code
[error]Function      : raii_guard::~raii_guard
[error]File          : E:\GitHub\Advanced-X-Ray-Public\SourcesAXR\xrServerEntitiesCS\script_storage.cpp
[error]Line          : 748
[error]Description   : ....k.e.r. clear sky\gamedata\scripts\dialogs_yantar.script:755: attempt to index local 'obj' (a nil value)
 

stack trace:

0x00000000400CC800 AdvancedXRay.exe, Device + 544 byte(s)
 
FATAL ERROR
 
[error]Expression    : fatal error
[error]Function      : CScriptEngine::lua_error
[error]File          : E:\GitHub\Advanced-X-Ray-Public\SourcesAXR\xrServerEntitiesCS\script_engine.cpp
[error]Line          : 180
[error]Description   : <no expression>
[error]Arguments     : LUA error: ....k.e.r. clear sky\gamedata\scripts\dialogs_yantar.script:755: attempt to index local 'obj' (a nil value)

 

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

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

@imcrazyhoudini и не заработает таким образом. Ты пытаешься найти серверный объект по его story_id, но сервер ничего об этом номере не знает, поскольку ты вот только что его присвоил..

Обрати внимание на последний спойлер в моём примере, а именно _g.script и функцию level_object_by_sid, специально модифицированную для таких случаев. Используй её или, если нужен только id, можно вытащить кусочек функционала из функции с поиском в db таблице, куда мы положили нужную информацию при назначении story_id.

Либо производи нужные действия не на том апдейте, когда story_id присваивался, а позже.

10 часов назад, imcrazyhoudini сказал:

Название смарта + название сквада

Самодобавленный смарт, значит. Ясно. А то одно из предположений было, что отряд не спавнится из-за указания невалидного смарта.

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

Извиняюсь, если не понял, но я квест позже начал инициализировать, но всё равно не помогло:
 

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

[logic]
active = sr_idle

[sr_idle]
on_info = {+yan_ryaboy_start} sr_idle@2 %=create_squad(yan_ryaboy:yan_ryaboy:3)%

[sr_idle@2]
on_info = sr_idle@3 %=give_inited_task(storyline:yan_ryaboy_start:stalker)%

[sr_idle@3]
on_info = {+yan_contr_start} sr_idle@4 %=create_squad(yan_gorbun:yan_gorbun)%

[sr_idle@4]
on_info = nil

Плюс, если я устанавливаю стори_ид Рябому, то он больше не является членом смарт террейна и гуляет где захочет.

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

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

@imcrazyhoudini как связана инициализация квеста с использованием только что присвоенного story_id, непонятно: опять сделано что-то, что осталось за кулисами.
Когда будет время (скорее всего, в предстоящие выходные), постараюсь сам воспроизвести ситуацию на файлах чистой игры и предоставлю результат для изучения.
А пока дальше сам, мои советы на какое-то время иссякли. Не исключено, что успеешь сам найти решение проблемы раньше, метод-то вполне рабочий - подтверждается реальными опытами в существующем моде.

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

@Kirgudu имеешь в виду под "за кулисами" - квест показать? Я то могу:
 

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

[yan_ryaboy_start]
prior = 1
type = storyline
task_type = additional
icon = ui_icontask_help_icon
target_story_ids = 3
name = yan_ryaboy_name
text = yan_ryaboy_text
condlist_0 = {+yan_ryaboy_life} complete
condlist_1 = {+yan_ryaboy_dead} fail

Но вот дело в том, что ломается смарт террейн когда пытаешься назначить стори айди. И на следующую часть логики (sr_idle@3 вроде уже) не переходит.

Ещё из интересного - при сейв-лоаде до бесконечности спавнится по одному НПС (Рябой опять-таки), что даёт основание полагать, что логика рестриктора зацикливается.

Но это всё догадки.

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

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

@imcrazyhoudini всё, я понял, что у тебя за последовательность событий, раньше как-то туманно было. Ты спавнишь отряд, и из этой же логики в следующей секции запускаешь квест, целью которого является искомый story_id.
Честно говоря, я не уверен, что между двумя частями логики проходит достаточное для получения сервером информации о story_id количество апдейтов. Если это так, рекомендую попробовать сделать запуск квеста во второй секции логики не на on_info, а, например, на on_timer с таймаутом в пару секунд.
Однако если с промежутком между секциями логики всё в порядке, предлагаю посмотреть на содержимое функции task_objects.get_inited_task, где обрабатывается параметр квеста target_story_ids. Первые несколько строчек выглядят так (остальные нам не интересны):

local sid = tonumber(self.target_story_ids) -- считываем из параметра квеста story_id
if(sid) then
	self.target = id_by_sid(sid) -- находим серверный объект по story_id и берём у него id (функция в _g.script)
	if not(self.target) then -- проверяем, что полученный id не пустой
		abort("Target for storyline task doesnt exist. Story id [%s]", tostring(self.target_story_ids))
	end
...

Получается, что если бы story_id не был присвоен нашему объекту, мы неминуемо дошли бы до вызова функции abort.

Вот и думай. Может стоит обложиться выводом в лог во всех ключевых точках и попытаться понять, что конкретно происходит.

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

@Kirgudu должен признать, что когда назначаю стори айди логика рестриктора дальше не читается, Рябой в смарт не заселяется.

Куда покопать в таком случае? Могу даже мод в личку скинуть с нужным сейвом если так сказать дистанционно решить не получится.

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

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

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

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

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

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

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

Войти

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

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

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