Romz 142 Опубликовано 18 Августа 2015 Мож не сюда, но попробую. Существует мод, отображающий метки объектов, типа сталкеров, монстров, аномалий, на экране, ака 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 учесть? Тут больше математики, на самом деле, чем скриптования... Автор мода, к сожалению, не имеет больше желания им заниматься. Шаман - СисАдмин Всяко-разно: для ЧН Поделиться этим сообщением Ссылка на сообщение
Romz 142 Опубликовано 18 Августа 2015 @Zander_driver, Спасибо, попробую применить @Карлан, Ну, что у автора было, то и показываю. Код, конечно, тяжеловатый, но как его исправить - моих мозгов, к сожалению, не хватает. Вот пример выше дали, завтра попробую переделать. Шаман - СисАдмин Всяко-разно: для ЧН Поделиться этим сообщением Ссылка на сообщение
Romz 142 Опубликовано 19 Августа 2015 @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 - тот же результат... Или же я неправильно из неё координаты пытаюсь получить? Шаман - СисАдмин Всяко-разно: для ЧН Поделиться этим сообщением Ссылка на сообщение
Romz 142 Опубликовано 19 Августа 2015 @Карлан, Да там фигня какая-то получается. В 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 Шаман - СисАдмин Всяко-разно: для ЧН Поделиться этим сообщением Ссылка на сообщение
Romz 142 Опубликовано 19 Августа 2015 @Charsi, Я затупил, признаю. Поправил, теперь всё работает. Romz, дублирую, математика там школьная, да. Скрипт приведенный тобою - плохой. А видео, которое ты привёл, это что за мод? Или скрипт? Где его откопать, для посмотреть на предмет вывода метки на высоте роста непися... 1 Шаман - СисАдмин Всяко-разно: для ЧН Поделиться этим сообщением Ссылка на сообщение
Romz 142 Опубликовано 20 Августа 2015 Всем спасибо, разобрался. Окончательный вариант теперь выглядит так 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 142 Опубликовано 27 Августа 2015 (изменено) МЭй би, пост прибьют, конеш, но попробую... Есть скрипт, под ЗП, не мой, для спавна динамических аномалий. Реально динамических, по рандомным координатам. У него есть небольшой недостаток - аномалии спавнятся везде, даже в укрытиях. Автор скрипта обещал сие поправить, но пропал... Моих же познаний в скриптоковырянии на подобную доработку не хватает. А это - последний, такскаать, штрих в мою сборку... Дык, можа, кто сподобится помочь? Заодно посоветует, как аномалии спавнить с начала игры, а не после выброса. Если кто-то возьмётся, дальнейшее общение - через ЛС, плиз... Теоретически, нужно собрать список укрытий на локе, взять их координаты, и при спавне аномалии, проверить, чтобы она не спавнилась на расстоянии ближе определённого от центра укрытия. Вот только, как это реализовать, я чего-то сообразить не могу... Изменено 27 Августа 2015 пользователем Romz Шаман - СисАдмин Всяко-разно: для ЧН Поделиться этим сообщением Ссылка на сообщение
Romz 142 Опубликовано 28 Августа 2015 @naxac, То есть, собираем в таблицу список укрытий, вида {cover_name,cover_pos} А потом перебором по этой таблице сравниваем позицию спавна с расстоянием до укрытия? Шаман - СисАдмин Всяко-разно: для ЧН Поделиться этим сообщением Ссылка на сообщение
Romz 142 Опубликовано 28 Августа 2015 Romz, куда лучше, сделать рестрикторы на локацииЭто ты щас кому сказал?.. Ещё циклом, да перебором, я смогу, наверное, сделать... Может быть... Наверное... А это вот всё для меня лес тёмный... Я, вообще, хотел ЗП перепройти, только оригинал мало-мало надоел, а существующие сборки-моды не понравились... Вот и решил модиков накидать... Второй месяц пошёл... Со списочком запретных для аномалий зон...anoms.ltx.Есть в ЗП surge_manager.ltx, дык в нём перечислены все укрытия, поимённо. Но без координат. Его нельзя как-то применить? Только чтоб попроще... Шаман - СисАдмин Всяко-разно: для ЧН Поделиться этим сообщением Ссылка на сообщение
Romz 142 Опубликовано 1 Сентября 2015 Товарищи. Может, конечно, совсем нубский вопрос, но всё же. Как получить количество строк в табличке? Ну вот, допустим, есть табличка covers. В ней, соответственно, сложены укрытия на локации, с учетом кондишнов и инфопоршней. Дык вот как, сопсна получить число укрытий, которые там сложены? Подсмотрел, что можно написать #covers, но чегось не взлетает... По крайней мере, в лог не пишет, т.е. nil. Табличка заведомо заполнена. Не, ну можно нагородить конструкцию при заполнении, чтоб считало,но должен же быть способ... Шаман - СисАдмин Всяко-разно: для ЧН Поделиться этим сообщением Ссылка на сообщение
Romz 142 Опубликовано 1 Сентября 2015 чегось не взлетает...Внезапно - взлетело Шаман - СисАдмин Всяко-разно: для ЧН Поделиться этим сообщением Ссылка на сообщение
Romz 142 Опубликовано 2 Сентября 2015 Нужна подсказка по циклам имеется вот такая конструкция 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 срабатывает, но координаты в таблицу не кладутся, т.к. они неверные. Мож чего невнятно объяснил, скажите, попробую разжевать... Шаман - СисАдмин Всяко-разно: для ЧН Поделиться этим сообщением Ссылка на сообщение
Romz 142 Опубликовано 2 Сентября 2015 @Shredder, Блин, точно... Затупил, признаю... Шаман - СисАдмин Всяко-разно: для ЧН Поделиться этим сообщением Ссылка на сообщение
Romz 142 Опубликовано 25 Сентября 2015 (изменено) Уважаемые скриптеры! Опять нужна ваша помощь... Есть скрипт, под ЗП, спавнящий аномалии. С самим размещением аномалий - никаких проблем, вроде бы, но... Есть в этом скрипте функция, которая работает с 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 Так вот. Похоже, что где-то что-то неправильно работает, и, возможно, в ней. Потому что периодически бьются сейвы, слетают скрипты, вылеты непонятные происходят... В данный момент я пока отключил этот скрипт совсем - нет ни вылетов, ни боя сохранений, скрипты работают нормально... Дык, если в функции ошибка, ткните, плиз, где. Или ткните носом в аналогичную функцию, гарантированно работающую в ЗП. Поиском по темам пробежался - как-то ничего похожего не нашлось... Изменено 25 Сентября 2015 пользователем Romz Шаман - СисАдмин Всяко-разно: для ЧН Поделиться этим сообщением Ссылка на сообщение
Romz 142 Опубликовано 28 Сентября 2015 (изменено) Ну и непонятно, какие аргументы передаёшь ты в функцию извне. Сама функция вызывается из другого места в этом же скрипте 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 Это самый конец функций. Может ли это влиять? Изменено 28 Сентября 2015 пользователем Romz Шаман - СисАдмин Всяко-разно: для ЧН Поделиться этим сообщением Ссылка на сообщение
Romz 142 Опубликовано 28 Сентября 2015 (изменено) для ЧН это применяется при спавне аномальных полей, и может принимать значение "field", а не "_zone". А, ну да, "_field_", конечно-же. Извиняюсь за дезинформацию. И без подчёркиваний! Kirgudu Изменено 28 Сентября 2015 пользователем Kirgudu Шаман - СисАдмин Всяко-разно: для ЧН Поделиться этим сообщением Ссылка на сообщение
Romz 142 Опубликовано 28 Сентября 2015 (изменено) И без подчёркиваний! 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 Погонял в таком виде, некоторое количество раз сохранился-загрузился, попереходил между локациями. Вроде бы теперь всё работает, как должно. Вылетов на загрузке сохранений нет, просто вылетов тоже нет, скрипты вроде не слетают. Вопрос возник такого плана: возможно ли аномалии переводить в офлайн при удалении от них ГГ на определённое расстояние, и выдёргивать их оттуда при приближении ГГ к ним? Смысл сего действа - повысить производительность. Просто НПЦ такое проделывают, может и для других объектов возможно? Изменено 28 Сентября 2015 пользователем Romz Шаман - СисАдмин Всяко-разно: для ЧН Поделиться этим сообщением Ссылка на сообщение
Romz 142 Опубликовано 30 Сентября 2015 Блин, ну неужели нет никакой информации по переводу ЛЮБЫХ объектов в онлайн\офлайн? Про неписей понаписано дофига, а вот про остальное... Ладно, другой вопрос. Как проверить, что ГГ заспавнился на локе? Типа if db.actor:что_то_там then? А что? Нужно получить информацию о том, что локация и все объекты загрузились, при переходе на другую локу, начале игры, загрузке сохранения. Поиском по ресурсам пробежался - не нашёл. Не, ну можно, конечно, намутить инфопоршней там всяких и из разных биндов их вызывать и проверять. Но... Ради одной проверки такое городить не хочется. Нужно проверить это один раз в surge_manager.script, на апдейте этого самого CSurgeManager и вызвать определённое действие. Шаман - СисАдмин Всяко-разно: для ЧН Поделиться этим сообщением Ссылка на сообщение
Romz 142 Опубликовано 30 Сентября 2015 (изменено) Пробуй if device().precache_frame <= 1 then, Ок, попробую. Только обычно if(device().precache_frame > 1) then return end Это так в CSurgeManager:update. То есть, внутри этой конструкции можно поставить флаг, а сразу после - вызвать функцию, которая проверит этот флаг, сделает какую-то работу, которую нужно сделать только один раз за загрузку, а в конце CSurgeManager:update сбросить этот флаг. А разве они и так не переходят в он\офф в зависимости от alife-расстояния ? Стандартные аномалии - возможно. А вот динамически добавленные - видны через всю локу. По крайней мере - в ЗП. Изменено 30 Сентября 2015 пользователем Romz Шаман - СисАдмин Всяко-разно: для ЧН Поделиться этим сообщением Ссылка на сообщение
Romz 142 Опубликовано 30 Сентября 2015 (изменено) Ты спрашивал об окончании загрузки - тогда <= 1. Ну в той конструкции, что я привёл, как я понял, пока device().precache_frame > 1 функция не выполняется совсем. Ну так выставь для них соответствующие флаги Ок, гляну. Этот пост, вообще, читал, но не рассматривал в контексте аномалий. стандартные(те что через all.spawn созданы ?) Ну да. В ЗП же одиночных аномалий нет. Все сосредоточены в т.н. аномальных зонах. А динамические я скриптом спавню Щас проверил. В ЗП все аномалии видны через локу. Отошёл специально от "Котла" к "Соснодубу" - "Котёл" прекрасно видно Изменено 30 Сентября 2015 пользователем Romz Шаман - СисАдмин Всяко-разно: для ЧН Поделиться этим сообщением Ссылка на сообщение