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

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


Svoboда

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

Мож не сюда, но попробую. Существует мод, отображающий метки объектов, типа сталкеров, монстров, аномалий, на экране, ака HUD.

В нём есть функция, рассчитывающая местположение метки на экране, но она нормально работает только при FOV = 55. Если FOV поменять, то метки будут на месте, только если смотреть непосредственно на объект, отмеченный меткой. Если начать отворачиваться от объекта, то метка уплывает с него. Автор мода дал примерное место внесения поправки. Собственно, функция, где собираются параметры, и считаются поправки

 

function update_mark()
    --Базовые параметры о ГГ
    act_pos = db.actor:position()
    act_dir = device().cam_dir
    cam_pos = device().cam_pos
    hud = get_hud()
    
    --Убрать все метки если проигрывается катсцена или есть инфопорция "hide_all_ui_mark"
    hide_all_mark = false
    if not db.actor:object("detector_fenix") or (act_pos:distance_to_sqr(cam_pos) > 4) or (has_alife_info("hide_all_ui_mark")) then hide_all_mark = true end
    
    --Угол обзора ГГ
    fov = math.floor(device().fov+0.02)

    --Коэффициент растягивания изображения меток по горизонтали (3:4 = 1, 9:16 = 0,75 )
    rise = (device().height*1024)/(device().width*768)

    --Функции обновления меток на экране
    update_npc()
    update_anom()
    update_art()
    update_monstr()
end

 

И функция расчёта положения и вывода метки. Для других объектов - аналогично

 

function update_npc()
    local index_mark = 1
    
    --Обновление/добавление меток НПС
    if not hide_all_mark then
    for id_base, npc_base_pos in pairs(npc_base_table) do
        local dist = act_pos:distance_to_sqr(npc_base_pos)
        if dist < 900 then
            local npc_pos = vector():set(npc_base_pos.x,npc_base_pos.y,npc_base_pos.z)
            local npc_dir = npc_pos:sub(act_pos)
            local yaw = yaw_degree3d(act_dir, npc_dir)
            if yaw < 35 then
                if index_mark < 33 then
                    anglI = math.atan2(act_dir.z, act_dir.x) - math.atan2(npc_dir.z, npc_dir.x)
                    anglII = math.atan2(math.sqrt(npc_dir.x*npc_dir.x+npc_dir.z*npc_dir.z), npc_dir.y) - math.atan2(math.sqrt(act_dir.x*act_dir.x+act_dir.z*act_dir.z), act_dir.y)
                    Xcoord = math.floor(512 + 512*math.tan(anglI)/math.cos(anglII)*512/360*rise)
                    Ycoord = math.floor(384 + 384*math.tan(anglII)*384/200)
                    if index_mark > npc_last_mark then
                        hud:AddCustomStatic("npc_hud_mark_"..tostring(index_mark))
                        npc_mark_table[index_mark] = hud:GetCustomStatic("npc_hud_mark_"..tostring(index_mark)):wnd()
                    end
                    npc_mark_table[index_mark]:SetWndRect(Frect():set(Xcoord-8,Ycoord-8,Xcoord+8,Ycoord+8))
                    index_mark = index_mark + 1
                end
            end
        end
    end
    end
    
    npc_last_mark = index_mark - 1
    
    --Удаление лишних меток НПС
    if index_mark < 33 then
        for i=index_mark,32 do
            if npc_mark_table[i] then
                hud:RemoveCustomStatic("npc_hud_mark_"..tostring(i))
                npc_mark_table[i] = nil
            end
        end
    end
    
    --Очистка таблицы НПС
    if index_mark == 1 then
        npc_nul_mark_time = npc_nul_mark_time + 1
        if npc_nul_mark_time > 100 then
            npc_base_table = {}
            npc_nul_mark_time = 0
        end
    else
        npc_nul_mark_time = 0
    end
    
end

 

Автор мода советует вносить поправку в переменную rise. Я экспериментально выяснил, что при rise = 0.55 метка находится на своём месте. Только не могу сообразить, как этого добиться при различном FOV.

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

 

Автор мода, к сожалению, не имеет больше желания им заниматься.

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

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

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


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

@Zander_driver, Спасибо, попробую применить

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

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

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

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


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

@Zander_driver, Ну и вообще, кто может... Нужна подсказка по применению. В каком виде должно в point_projection(point) должна передаваться эта самая point?

Переделал скрипт, добавил в него функцию point_projection(point) и немного переписал имеющиеся...

function update_mark()
    --Базовые параметры о ГГ
    local cam_pos = device().cam_pos
    local act_pos = db.actor:position()
    local act_dir = device().cam_dir
    local hud = get_hud()
    
    --Убрать все метки если проигрывается катсцена или есть инфопорция "hide_all_ui_mark"
    hide_all_mark = false
    if not db.actor:object("detector_fenix") or (act_pos:distance_to_sqr(cam_pos) > 4) or (has_alife_info("hide_all_ui_mark")) then hide_all_mark = true end
    
    --Угол обзора ГГ
    local fov = math.floor(device().fov+0.02)

    --Коэффициент растягивания изображения меток по горизонтали (3:4 = 1, 9:16 = 0,75 )
--    rise = (device().height*1024)/(device().width*768)
    
    --Функции обновления меток на экране
    update_npc( act_pos, act_dir, fov, hud)
--[[    update_anom()
    update_art()
    update_monstr()]]--
end

 

function update_npc( act_pos, act_dir, fov, hud)
    local index_mark = 1
    local fov_y = fov/2

    --Обновление/добавление меток НПС
    if not hide_all_mark then
    for id_base, npc_base_pos in pairs(npc_base_table) do
        local dist = act_pos:distance_to_sqr(npc_base_pos)
        if dist < 900 then
            local npc_pos = vector():set(npc_base_pos.x,npc_base_pos.y,npc_base_pos.z)
            local npc_dir = npc_pos:sub(act_pos)
            local yaw = yaw_degree3d(act_dir, npc_dir)
            if yaw < fov_y then
                if index_mark < 33 then
                    local p_coord = point_projection(npc_base_pos)
                    local Xcoord = p_coord.x
                    local Ycoord = p_coord.y
                    if index_mark > npc_last_mark then
                        hud:AddCustomStatic("npc_hud_mark_"..tostring(index_mark))
                        npc_mark_table[index_mark] = hud:GetCustomStatic("npc_hud_mark_"..tostring(index_mark)):wnd()
                    end
                    npc_mark_table[index_mark]:SetWndRect(Frect():set(Xcoord-8,Ycoord-8,Xcoord+8,Ycoord+8))
                    index_mark = index_mark + 1
                end
            end
        end
    end
    end
    
    npc_last_mark = index_mark - 1
    
    --Удаление лишних меток НПС
    if index_mark < 33 then
        for i=index_mark,32 do
            if npc_mark_table[i] then
                hud:RemoveCustomStatic("npc_hud_mark_"..tostring(i))
                npc_mark_table[i] = nil
            end
        end
    end
    
    --Очистка таблицы НПС
    if index_mark == 1 then
        npc_nul_mark_time = npc_nul_mark_time + 1
        if npc_nul_mark_time > 100 then
            npc_base_table = {}
            npc_nul_mark_time = 0
        end
    else
        npc_nul_mark_time = 0
    end
    
end

 

НПЦ складируются в npc_base_table = {}, которая наполняется

function npc_update(object)
    --Добавить НПС в таблицу
    npc_base_table[object:id()] = object:position()
end

 

Так вот, при приближении к НПЦ происходит вылет

 

 * Game rkleshchev - начало игры.scop is successfully saved to file 'c:\users\public\documents\stalker-cop\savedgames\rkleshchev - начало игры.scop'
! [SCRIPT ERROR]: c:\gam\s-cop\gamedata\scripts\ui_mark.script:93: attempt to perform arithmetic on local 'Xcoord' (a nil value)
 
FATAL ERROR
 
[error]Expression    : fatal error
[error]Function      : CScriptEngine::lua_error
[error]File          : ..\xrServerEntities\script_engine.cpp
[error]Line          : 193
[error]Description   : <no expression>
[error]Arguments     : LUA error: c:\gam\s-cop\gamedata\scripts\ui_mark.script:93: attempt to perform arithmetic on local 'Xcoord' (a nil value)

 


Пробовал так же в point_projection(point) передавать npc_pos - тот же результат... Или же я неправильно из неё координаты пытаюсь получить?

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

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

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


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

@Карлан, Да там фигня какая-то получается. В point_projection(point) координаты точки экрана высчитываются. Я LOG засунул в скрипт и значения в логе получил.

Но вот здесь должны считаться координаты

                    local p_coord = point_projection(npc_base_pos)
                    local Xcoord = p_coord.x
                    local Ycoord = p_coord.y

А они не считываются. Xcoord и Ycoord почему-то равны nil

    return {x, y} в point_projection(point) должна вернуть координаты, а она этого не делает... Или я не так их пытаюсь получить.

  • Полезно 1

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

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

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


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

@Charsi, Я затупил, признаю. Поправил, теперь всё работает.


 

 

Romz, дублирую, математика там школьная, да. Скрипт приведенный тобою - плохой.
А видео, которое ты привёл, это что за мод? Или скрипт? Где его откопать, для посмотреть на предмет вывода метки на высоте роста непися...
  • Полезно 1

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

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

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


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

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

function point_projection(point, cfix)
--[[
взято с амк-форума
]]
local dev = device()
local scr_w = dev.width
local scr_h = dev.height

local fov2 = (dev.fov/2) * (math.pi/180)
local scr_dist = 0.5 * scr_h / math.tan(fov2)

local ppp = vector():sub(point, dev.cam_pos)
ppp.y = ppp.y + cfix -- поправка на высоту объекта
local dp = dev.cam_dir:dotproduct(ppp)

local x = 512 + dev.cam_right:dotproduct(ppp) * scr_dist / dp * (1024/scr_w)
local y = 384 - dev.cam_top:dotproduct(ppp) * scr_dist / dp * (768/scr_h)

return {x, y}
end
--Функция учитывает возможное разрешение экрана, режим зума и то, что камера может наклоняться. Можно использовать в различных целеуказателях.

 

function update_mark()
--Базовые параметры о ГГ
local cam_pos = device().cam_pos
local act_pos = db.actor:position()
local act_dir = device().cam_dir
local hud = get_hud()

--Убрать все метки если проигрывается катсцена или есть инфопорция "hide_all_ui_mark"
local hide_all_mark = false
if not db.actor:object("detector_fenix") or (act_pos:distance_to_sqr(cam_pos) > 4) or (has_alife_info("hide_all_ui_mark")) then
hide_all_mark = true
end

--Угол обзора ГГ
local fov = math.floor(device().fov+0.02)

--Функции обновления меток на экране
update_npc( act_pos, act_dir, fov, hud, hide_all_mark)
update_anom( act_pos, act_dir, fov, hud, hide_all_mark)
update_art( act_pos, act_dir, fov, hud, hide_all_mark)
update_monstr( act_pos, act_dir, fov, hud, hide_all_mark)
end

 

И, собственно, функция вывода метки объекта

function update_npc( act_pos, act_dir, fov, hud, hide_all_mark)
local index_mark = 1
local cfix = 1.7 -- поправка на высоту объекта

--Обновление/добавление меток НПС
if not hide_all_mark then
for id_base, npc_base_pos in pairs(npc_base_table) do
local dist = act_pos:distance_to_sqr(npc_base_pos)
if dist < 900 then
local npc_pos = vector():set(npc_base_pos.x,npc_base_pos.y,npc_base_pos.z)
local npc_dir = npc_pos:sub(act_pos)
local yaw = yaw_degree3d(act_dir, npc_dir)
if yaw < fov then
if index_mark < 33 then

local p_coord = point_projection(npc_base_pos, cfix)
local Xcoord = math.floor(p_coord[1])
local Ycoord = math.floor(p_coord[2])

if index_mark > npc_last_mark then
hud:AddCustomStatic("npc_hud_mark_"..tostring(index_mark))
npc_mark_table[index_mark] = hud:GetCustomStatic("npc_hud_mark_"..tostring(index_mark)):wnd()
end
npc_mark_table[index_mark]:SetWndRect(Frect():set(Xcoord-8,Ycoord-8,Xcoord+8,Ycoord+8))
index_mark = index_mark + 1
end
end
end
end
end

npc_last_mark = index_mark - 1

--Удаление лишних меток НПС
if index_mark < 33 then
for i=index_mark,32 do
if npc_mark_table[i] then
hud:RemoveCustomStatic("npc_hud_mark_"..tostring(i))
npc_mark_table[i] = nil
end
end
end

--Очистка таблицы НПС
if index_mark == 1 then
npc_nul_mark_time = npc_nul_mark_time + 1
if npc_nul_mark_time > 100 then
npc_base_table = {}
npc_nul_mark_time = 0
end
else
npc_nul_mark_time = 0
end

end

 

 

  • Полезно 1

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

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

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


Ссылка на сообщение
(изменено)

МЭй би, пост прибьют, конеш, но попробую...

 

 

Есть скрипт, под ЗП, не мой, для спавна динамических аномалий. Реально динамических, по рандомным координатам.

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

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

Дык, можа, кто сподобится помочь?

Заодно посоветует, как аномалии спавнить с начала игры, а не после выброса.

Если кто-то возьмётся, дальнейшее общение - через ЛС, плиз...

 

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

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

 

 

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

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

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

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


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

@naxac, То есть, собираем в таблицу список укрытий, вида

{cover_name,cover_pos}

А потом перебором по этой таблице сравниваем позицию спавна с расстоянием до укрытия?

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

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

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


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

 

 

Romz, куда лучше, сделать рестрикторы на локации
Это ты щас кому сказал?.. :blink:

Ещё циклом, да перебором, я смогу, наверное, сделать... Может быть... Наверное...

А это вот всё для меня лес тёмный... Я, вообще, хотел ЗП перепройти, только оригинал мало-мало надоел, а существующие сборки-моды не понравились... Вот и решил модиков накидать... Второй месяц пошёл...

 

Со списочком запретных для аномалий зон...anoms.ltx.
Есть в ЗП surge_manager.ltx, дык в нём перечислены все укрытия, поимённо. Но без координат. Его нельзя как-то применить? Только чтоб попроще...

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

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

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


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

Товарищи. Может, конечно, совсем нубский вопрос, но всё же.

Как получить количество строк в табличке?

Ну вот, допустим, есть табличка covers. В ней, соответственно, сложены укрытия на локации, с учетом кондишнов и инфопоршней. Дык вот как, сопсна получить число укрытий, которые там сложены? Подсмотрел, что можно написать #covers, но чегось не взлетает... По крайней мере, в лог не пишет, т.е. nil. Табличка заведомо заполнена. Не, ну можно нагородить конструкцию при заполнении, чтоб считало,но должен же быть способ...

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

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

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


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

 

 

чегось не взлетает...
Внезапно - взлетело :)

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

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

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


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

Нужна подсказка по циклам

имеется вот такая конструкция

 

	for _, level_t in pairs(levels) do 
		for i = 1, level_t.count do 
			local tab_1 = {}
			pos_new= {}
			tab_1.game_vertex = level_t.game_vertex
			tab_1.level_vertex = math.random(1571597)
			repeat
				pos_new = level.vertex_position(tab_1.level_vertex)
			until pos_check(pos_new) == false
			tab_1.x = pos_new.x
			tab_1.y = pos_new.y
			tab_1.z = pos_new.z
			table.insert(items_q, tab_1)
		end
	end 

 

Функция pos_check возвращает true если pos_new не попадает в некие границы, и false, если попадает.

Почему-то repeat / until приводит к бесконечному циклу...

Я пробовал ставить

и

pos_check(pos_new) == true

и

pos_check(pos_new) ~= true

 

 

Всегда получаю зависание игры.

Или как ещё можно добиться, чтобы итерация не пропала зря. Потому что если сгородить конструкцию

 

pos_new = ...
if pos_check (pos_new) == true then
...
table.insert
end

 


то цикл

		for i = 1, level_t.count do 

срабатывает, но  координаты в таблицу не кладутся, т.к. они неверные.

Мож чего невнятно объяснил, скажите, попробую разжевать...

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

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

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


Ссылка на сообщение
(изменено)

Уважаемые скриптеры! Опять нужна ваша помощь...

Есть скрипт, под ЗП, спавнящий аномалии. С самим размещением аномалий - никаких проблем, вроде бы, но...

Есть в этом скрипте функция, которая работает с net-пакетами

 

function create_anom(section,rad_anom,x,y,z,lv,gv,mode,time1,time2)
	if gv==nil then gv=db.actor:game_vertex_id() end
	if lv==nil then lv=db.actor:level_vertex_id() end
	if pos==nil then pos=db.actor:position() end
	local p_obj = alife():create(section,vector():set(x,y,z),lv,gv)
	local packet = net_packet()
	packet:w_begin(0)
	packet:r_seek(2)
	p_obj:STATE_Write(packet)
	local game_vertex_id = packet:r_u16()
	local cse_alife_object__unk1_f32 = packet:r_float()
	local cse_alife_object__unk2_u32 = 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 cse_alife_object__unk3_u32 = 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 cse_alife_custom_zone__unk1_f32 = packet:r_float()
	local cse_alife_custom_zone__unk2_u32 = packet:r_s32()
	local on_off_mode_enabled_time = packet:r_s32()
	local on_off_mode_disabled_time = packet:r_s32()
	local on_off_mode_shift_time = packet:r_s32()
	local offline_interactive_radius = packet:r_float()
	local artefact_spawn_places_count = packet:r_u16()
	local cse_alife_anomalous_zone__unk1_u32 = packet:r_s32()
	local last_spawn_time_present = packet:r_u8()
	packet:w_u16(game_vertex_id)
	packet:w_float(cse_alife_object__unk1_f32)
	packet:w_s32(cse_alife_object__unk2_u32)
	packet:w_s32(level_vertex_id)
	packet:w_s32(object_flags)
	if mode~=nil then custom_data = mode end
	packet:w_stringZ(custom_data)
	packet:w_s32(story_id)
	packet:w_s32(cse_alife_object__unk3_u32)
	packet:w_u8(1)
	packet:w_u8(0)
	local sphere_center = vector()
	sphere_center:set(0, 0, 0)
	packet:w_vec3(sphere_center)
	radius = rad_anom
	packet:w_float(radius)
	packet:w_u8(restrictor_type)
	packet:w_float(cse_alife_custom_zone__unk1_f32)
	cse_alife_custom_zone__unk2_u32 = bit_not(0)
	packet:w_s32(cse_alife_custom_zone__unk2_u32)
	if time1 ~= nil then
		packet:w_s32(time1)
	else
		packet:w_s32(on_off_mode_enabled_time)
	end
	if time2 ~= nil then
		packet:w_s32(time2)
	else
		packet:w_s32(on_off_mode_disabled_time)
	end
	packet:w_s32(on_off_mode_shift_time)
	packet:w_float(offline_interactive_radius)
	packet:w_u16(artefact_spawn_places_count)
	packet:w_s32(cse_alife_anomalous_zone__unk1_u32)
	if mode==nil then
	  	packet:w_u8(last_spawn_time_present)
	end
	p_obj:STATE_Read(packet, packet:w_tell()-packet:r_tell())
	return p_obj
end

 

Так вот. Похоже, что где-то что-то неправильно работает, и, возможно, в ней.

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

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

Дык, если в функции ошибка, ткните, плиз, где. Или ткните носом в аналогичную функцию, гарантированно работающую в ЗП.

Поиском по темам пробежался - как-то ничего похожего не нашлось...

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

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

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

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


Ссылка на сообщение
(изменено)
Ну и непонятно, какие аргументы передаёшь ты в функцию извне.

Сама функция вызывается из другого места в этом же скрипте

function spawn_anomaly_from_queue()
	local anom_t = anomaly_queue[#anomaly_queue]
	create_anom(anom_t.section, 4, anom_t.x, anom_t.y, anom_t.z, anom_t.level_vertex, anom_t.game_vertex, anom_t.field)
	table.remove(anomaly_queue, #anomaly_queue)
end

 

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

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

Так же, раскопки в различных модах дали ещё два варианта похожих скриптов

function rewrite_anomaly(obj, in_custom_data, in_radius)
--	dbglog("level_anomaly.rewrite_anomaly()")
	packet:w_begin(0)
	packet:r_seek(2)
	obj:STATE_Write(packet)
	local game_vertex_id = packet:r_u16()
	local cse_alife_object__unk1_f32 = packet:r_float()
	local cse_alife_object__unk2_u32 = 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 cse_alife_object__unk3_u32 = 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 cse_alife_custom_zone__unk1_f32 = packet:r_float()
	local cse_alife_custom_zone__unk2_u32 = packet:r_s32()
	local on_off_mode_enabled_time = packet:r_s32()
	local on_off_mode_disabled_time = packet:r_s32()
	local on_off_mode_shift_time = packet:r_s32()
	local offline_interactive_radius = packet:r_float()
	local artefact_spawn_places_count = packet:r_u16()
	local cse_alife_anomalous_zone__unk1_u32 = packet:r_s32()
	local last_spawn_time_present = packet:r_u8()
	if packet:r_elapsed() ~= 0 then abort("left=%d", packet:r_elapsed()) end
	packet:w_begin(0)
	packet:w_u16(game_vertex_id)
	packet:w_float(cse_alife_object__unk1_f32)
	packet:w_s32(cse_alife_object__unk2_u32)
	packet:w_s32(level_vertex_id)
	packet:w_s32(object_flags)
	if in_custom_data ~= nil then custom_data = in_custom_data end
	packet:w_stringZ(custom_data)
	packet:w_s32(story_id)
	packet:w_s32(cse_alife_object__unk3_u32)
	packet:w_u8(1)			
	packet:w_u8(0)			
	local sphere_center = vector()
	sphere_center:set(0, 0, 0)
	packet:w_vec3(sphere_center)
	if in_radius ~= nil then radius = in_radius end
	packet:w_float(radius)
	packet:w_u8(restrictor_type)
	packet:w_float(cse_alife_custom_zone__unk1_f32)
	cse_alife_custom_zone__unk2_u32 = bit_not(0)
	packet:w_s32(cse_alife_custom_zone__unk2_u32)
	packet:w_s32(on_off_mode_enabled_time)
	packet:w_s32(on_off_mode_disabled_time)
	packet:w_s32(on_off_mode_shift_time)
	packet:w_float(offline_interactive_radius)
	packet:w_u16(artefact_spawn_places_count)
	packet:w_s32(cse_alife_anomalous_zone__unk1_u32)
	packet:w_u8(last_spawn_time_present)
	packet:r_seek(2)
	obj:STATE_Read(packet, packet:w_tell())
	return obj
end

 

и

function create_anomaly( zone_name, zone_radius, position, lv, gv )

----------------------------Создаём объект-аномалию
	
    local sobj = alife():create( zone_name, position, lv, gv )
	
    local packet = net_packet()
    packet:w_begin( 0 )
	
-------------------------------------Читаем нет-пакет   
	sobj: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 )
	restrictor_type	= 3
	max_power = 0
	offline_interactive_radius	= 30
	artefact_spawn_count	= 32
	last_spawn_time = 0
	
------------------------------------------------Пишем в пакет	
	
	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( zone_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 )
	packet:w_u8( last_spawn_time )

	packet:r_seek( 2 )
	sobj:STATE_Read( packet, packet:w_tell() )
 	return sobj
end

 

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

Upd

По различиям. Я вижу из различий:

В том скрипте, что у меня есть сейчас

	if mode==nil then
		packet:w_u8(last_spawn_time_present)
	end
	p_obj:STATE_Read(packet, packet:w_tell()-packet:r_tell())
	return p_obj
end

 

А в тех, что я нарыл -

	packet:w_u8( last_spawn_time )
	packet:r_seek(2)
	obj:STATE_Read(packet, packet:w_tell())
	return obj
end

 

и

	packet:w_u8( last_spawn_time )

	packet:r_seek( 2 )
	sobj:STATE_Read( packet, packet:w_tell() )
 	return sobj
end

 

Это самый конец функций.

Может ли это влиять?

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

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

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

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


Ссылка на сообщение
(изменено)

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

А, ну да, "_field_", конечно-же. Извиняюсь за дезинформацию.

 

И без подчёркиваний! Kirgudu

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

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

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

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


Ссылка на сообщение
(изменено)
И без подчёркиваний! Kirgudu

Само собой.

 

Переписал функцию.

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

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

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

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


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

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

Ладно, другой вопрос.

Как проверить, что ГГ заспавнился на локе? Типа if db.actor:что_то_там then? А что?

Нужно получить информацию о том, что локация и все объекты загрузились, при переходе на другую локу, начале игры, загрузке сохранения. Поиском по ресурсам пробежался - не нашёл.

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

Нужно проверить это один раз в surge_manager.script, на апдейте этого самого CSurgeManager и вызвать определённое действие.

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

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

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


Ссылка на сообщение
(изменено)
Пробуй if device().precache_frame <= 1 then,

Ок, попробую. Только обычно

	if(device().precache_frame > 1) then
		return
	end

Это так в CSurgeManager:update.

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

А разве они и так не переходят в он\офф в зависимости от alife-расстояния ?

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

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

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

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

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


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

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

 

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

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

 

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

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

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

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

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

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

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


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

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

AMK-Team.ru

×
×
  • Создать...