Скриптование - Страница 200 - Скрипты / конфиги / движок - AMK Team
Перейти к контенту

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

Тема для обсуждения скриптов всего и всех в серии игр STALKER.


Задавая вопрос (!):
1. Внимательно изучите суть вопроса. Вопрос должен соответствовать выбранной Вами темы. Это поможет сохранить порядок и читабельность темы, а также облегчит поиск и понимание сего;
2. Изучите то, что уже есть в теме (пролистайте "руками", воспользуйтесь поиском на форуме);
3. Изучите информацию которая может вам помочь:

 
 

Stalkerin. Там есть много хороших статей касательно данной темы.
Уроки по модостроению. Есть рабочие примеры готовых скриптов различного назначения.

 

Справочное руководство по языку Lua 5.1
https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual/ru
Справочник по функциям и классам. Собрано много информации по функциям и классам, не всем, но по основные сведения предоставлены.

4. Дабы не превращать обсуждение в "кашу" разной информативной направленности, задавайте несколько вопросов по порядку (в разных постах) после того, как получите ответ на предыдущий вопрос;
5. "Спасибо" и тому подобное - будьте так любезны в ПМ. Если не любите писать в ПМ, в конце вопроса напишите фразу: "Заранее спасибо!" - или что-то в этом духе;
6. ПОЖАЛУЙСТА! Указывайте, для какой игры Вам необходима информация (ТЧ, ЧН, ЗП), если стоит мод - укажите название мода;
7. Если Вы что-то сделали и результат не такой, какой Вами задумывался, то, пожалуйста, приводите коды которые Вы изменяли/писали целиком! Это поможет другим правильно ответить на Ваш вопрос, а также оградит Вас от лишней писанины.
8. Оформляйте сообщение. Пользуйтесь тегами для того, чтобы отделить код от текста. Пишите грамотно - ПОЛЬЗУЙТЕСЬ ЗНАКАМИ ПРЕПИНАНИЯ.
9. И помните: «Правильно заданный вопрос – половина ответа».

 

Какие вопросы следует задавать, а какие нет...

 

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

 

Вопросы которые будут удалятся, следовательно их задавать не нужно:
-- Где находится та или иная функция?
Для ответа используем поиск по словам среди файлов оригинальной игры или мода, если объект поиска относится к нему, при помощью программы, которая Вам наиболее симпатизирует;
-- Как сделать что-то/то-то?
С подобными вопросами, либо в "ковырялки", где Вам вероятнее всего так же не ответят, либо выдвигаем мысли, подкреплённые теорией, практикой (идеальный вариант) и здравым рассудком;
-- Вопросы со смыслом: "сделайте", "совместите" и подобными глаголами повелительного наклонения.
-- К тому же удалению будут подвергаться вопросы, в которых масштабно не используются теги, для отделения кода и цитат от основного текста, а также не вписан в спойлер код размером превышающие семь строк.
Ответ на возможно возникший вопрос: В какую тему можно обратиться по поводу логики и спавна объектов?
В тему "ковырялок" соответствующей версии игры, для которой Вы задаёте вопрос.

И последнее: очень рекомендовано к прочтению Правила форума
 


  • Спасибо 1
  • Полезно 2
Ссылка на комментарий
https://www.amk-team.ru/forum/topic/6185-skriptovanie/

Artos

Я так понял ему надо изменит нет-пакетом параметры фонарика или какого то другого инвентарного предмета.

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

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

i have make a script witch shall repswan npc

local first_spwan = false
local respwan_table = {}
local timer = 0
local timer_repswan = 0
local spwan = false

function spwawn()
local levels = {[0] = "marsh", [1] = "l01_escape", [2] = "l02_garbage", [3] = "l03_agroprom", [4] = "l04_darkvalley", [5] = "l05_bar", [6] = "l06_rostok", [7] = "l07_military", [8] = "l08_yantar"}
local level_name = level.name()
if spwan == false then
    if timer == 0 then timer = time_global() + math.random(36, 60) end

        if db.actor:alive() then

            if time_global() > timer then

            timer = 0 
                for indx, lvl in pairs(levels)do
                    if level_name == lvl then
                    ws = indx
                    spwan = true            
                        if spwan == true then
                                if ws == 0 then
                                spawn = 
                                alife():create("mar_clear_sky_respawn_1", vector():set(-61.996055603027, 0.92057931423187, 293.67742919922), db.actor:level_vertex_id(), db.actor:game_vertex_id())
                                alife():create("mar_clear_sky_respawn_2", vector():set(-61.996055603027, 0.92057931423187, 293.67742919922), db.actor:level_vertex_id(), db.actor:game_vertex_id())
                                alife():create("mar_clear_sky_respawn_3", vector():set(-61.996055603027, 0.92057931423187, 293.67742919922), db.actor:level_vertex_id(), db.actor:game_vertex_id())
                                respwan_table[spawn.id] = true
                                first_spwan = true
                                end
                        end
                    end
                end
            end
        end
    end    
if first_spwan == true then
if type(respwan_table) == "table" then
local obj,count,tbl_cnt = nil,0,#respwan_table 

for k,v in pairs(respwan_table) do
obj = alife():object(k)

if obj == nil then
k = respwan_npc_name
v = nil   
if timer_repswan == 0 then timer = time_global() + math.random(36, 60) end
    if db.actor:alive() then
        if time_global() > timer_repswan then
            timer_repswan = 0  
            spawn = alife():create(respwan_npc_name, vector():set(-61.996055603027, 0.92057931423187, 293.67742919922), db.actor:level_vertex_id(), db.actor:game_vertex_id())
            respwan_table[spawn.id] = true
        end
    end
end
end
end
end
end

but when i kill a npc the npc donґt respwan but why?

can anyoen help me?

thank you

 

No errors, except for some discrepancies.

It is not clear assignment script.

Describe your idea - what do you want to do?

ColR_iT

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

Artos

1. А для чего переводить в оффлайн находящуюся в рюкзаке у актора, например, аптечку иль иной предмет?

Как Shoker и предположил, для изменения нет-пакетом параметров фонарика. Очень хочу попробовать скриптово его вкл\выкл. Состояние его получить могу (исп. Ваш модуль) а вот изменить...

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

Сообщение. Для этого в Вашем модуле временно добавил в local execute_switchings = function():

..........................
else --/ object in 'offline' - phase-2:
local msg = "объект в офф-лайн"
news_manager.send_tip(db.actor, msg, nil, nil, 30000)
..........................

инициирую в игре перевод он-офф-он, сообщение не приходит. Пробовал, для теста, и с обычной аптечкой - то-же не получается. Похоже, Shoker прав насчет того, что надо вывести предмет из инвентаря\слота и тогда он будет доступен для перевода он-офф-он ?

 

Shoker

А как у Вас в общих чертах выглядит

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

Как выкинуть из слота\инвентаря мне понятно, а вот как назад забрать ?

 

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

Sorry that i make a new psot but i donґt knwo how i can at it on my

i will make a script what respwan npc

i have write a script first what all npcґs spwant and then are this npcґs incold in a table

local first_spwan = false
local respwan_table = {}
local timer = 0
local timer_repswan = 0
local spwan = false

function spwawn()
local levels = {[0] = "marsh", [1] = "l01_escape", [2] = "l02_garbage", [3] = "l03_agroprom", [4] = "l04_darkvalley", [5] = "l05_bar", [6] = "l06_rostok", [7] = "l07_military", [8] = "l08_yantar"}
local level_name = level.name()
if spwan == false then
    if timer == 0 then timer = time_global() + math.random(36, 60) end

        if db.actor:alive() then

            if time_global() > timer then

            timer = 0 
                for indx, lvl in pairs(levels)do
                    if level_name == lvl then
                    ws = indx
                    spwan = true            
                        if spwan == true then
                                if ws == 0 then
                                spawn = 
                                alife():create("mar_clear_sky_respawn_1", vector():set(-61.996055603027, 0.92057931423187, 293.67742919922), db.actor:level_vertex_id(), db.actor:game_vertex_id())
                                alife():create("mar_clear_sky_respawn_2", vector():set(-61.996055603027, 0.92057931423187, 293.67742919922), db.actor:level_vertex_id(), db.actor:game_vertex_id())
                                alife():create("mar_clear_sky_respawn_3", vector():set(-61.996055603027, 0.92057931423187, 293.67742919922), db.actor:level_vertex_id(), db.actor:game_vertex_id())
                                respwan_table[spawn.id] = true
                                first_spwan = true
                                end
                        end
                    end
                end
            end
        end
    end    
if first_spwan == true then
if type(respwan_table) == "table" then
local obj,count,tbl_cnt = nil,0,#respwan_table 

for k,v in pairs(respwan_table) do
obj = alife():object(k)

if obj == nil then
k = respwan_npc_name
v = nil   
if timer_repswan == 0 then timer = time_global() + math.random(36, 60) end
    if db.actor:alive() then
        if time_global() > timer_repswan then
            timer_repswan = 0  
            spawn = alife():create(respwan_npc_name, vector():set(-61.996055603027, 0.92057931423187, 293.67742919922), db.actor:level_vertex_id(), db.actor:game_vertex_id())
            respwan_table[spawn.id] = true
        end
    end
end
end
end
end
end

in the next part of the script the table checked wether the npc is dead

is the nc dead a timmer start and after the timer the npc will respwan

i hope anyone can understand this

sorry for my bad englisch

but when i kill a npc ,the npc dont respwan but why?

can anyoen help me?

thank youolaf1, olaf1, olaf1,

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

Цитата из мануало о том, как задавать вопросы:

Описывайте цель, а не отдельный шаг

 

Если вы пытаетесь разобраться, как что-либо сделать (а не сообщаете об ошибке), начинайте с описания цели. И только потом описывайте конкретный шаг на пути к ней, который вы не смогли выполнить.

 

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

*Shoker*, мною был задан адресный вопрос и суфлерство в данном случае как раз неуместно (и перепрочти цитату).

 

AndreySol, вот желание скриптово вкл/выкл фонарик - еще как то можно назвать целью, а потуги с нет-пакетами и офф/онлайном - это средства. СтОит это все же различать.

(отвечу пока с конца)

1. Учитывая, что фонарик актору достается нахаляву (спавнится в инвентарь автоматом), попадает в слот автоматом и не виден в слоте (в оригинале игры) то спрашивается - а какого лешего фонарик светит во лбу 'голого' актора? А зачем его включать/отключать(,), если можно просто взять и удалить, а когда нужно заспавнить! (ну иль переместить куда-нить во вне актора, например в ящик)

Т.о. если целью является лишить актора возможности светить изо лба (фонариком) - то совсем необязательно управлять фонариком, а достаточно просто удалять фонарик или добавлять его актору. В отличии от иных типов предметов (оружие, КПК, ...) свойства фонарика типа "исправность" иль иные никак не влияют ни на что. Учитывая п.3 (см.ниже) - это вполне позволяет достичь желаемой цели.

 

2. Учитывая, что в ТЧ имеется баг с визуалом актора (вид от 3-го лица) и при получении в инвентарь любого костюма/броника визуал приходится "подправлять" снимая его и надевая - как раз самое удобное и проверять - имеется ли у костюма шлем и если да - переспавнивать фонарик. Ну а если нет на голове ничего - то и фонарик можно не спавнить. Ну это так ... мысли о вообще "что делает на голом лбу фонарик".

 

3. Если "вспомнить", что игра (сингл) возможна только при условии нахождения актора в онлайне, и движек и скрипты контролируют это - то спрашивается, а вообще как это возможно, что основной объект (родитель/владелец) в онлайне, а его часть (предмет из инвентаря) - в оффлайне? Кто-то может мне это объяснить на пальцах? Ну а если предмет "в слоте" - то вообще неясно, что же игрок/модмейкер подразумевает под перевод предмета в оффлайн так, чтобы он не покидал слот ...

Вспоминаем, что телепортируя актора куда-то, мы НЕ занимаемся телепортацией его всего барахла, а это делает движек автоматом!

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

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

Artos, извиняюсь за 5 копеек, но боюсь, что Вы оба думаете о разных вещах.

Осмелюсь предположить, что AndreySol, хочет именно вкл/выкл фонарик и именно скриптами. Я приблизительно догадываюсь для чего это вообще нужно - батарейки для фонаря, так ведь, AndreySol? :)

Если не ошибаюсь, то фонарик принадлежит классу CTorch, если это так, то набор методов для него скудный и метода вкл/выкл я там не наблюдаю...

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

ColR_iT, я не зря первоначально задал 'глупые' вопросы и привел цитату. Не мне бы нужно адресовать твой пост, а AndreySol ...

Я, пока ничего не думаю, точнее предполагаю любой вариант цели попыток AndreySol, но все они именно сводятся к тому, что:

а) свойства объекта напрямую зависят от свойств его владельца, если таковой есть. И глупо пытаться перевести в онлайн гранату из рюкзака находящегося в оффлайне непися или наоборот. Даже если методы для объекта имеются доступны, то движек все одно контролирует подобное и или блокирует/игнорирует или разрешает ...

б) цель может достигаться различными способами и зашориваться на одном каком-то - неразумно (мягко выражаясь).

Повторю, если хочется именно скриптово управлять - читаем п.а). Нельзя же от скриптов требовать невозможного.

Если хочется включать/выключать не давя на кнопки (т.е. через скрипты) включать/выключать - то вариант с переспавном именно это и позволяет делать. Игрок все равно не видит своего фонарика в игре и то, что он гаснет иль загорается - это и есть цель, а то, что фонарика нет в слоте не важно и не заметено! Ну если вес иль объем рюкзака важен(!) - то ничего не мешает внести в алгоритмы расчетов нужные поправки.

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

 

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

 

Добавлено через 8 мин.:

P.S. ColR_iT, метод включения и выключения для фонариков имеется, и о чем упомянуто на предыдущей странице (torch_flags.Active = 1). Управляя флагами через нет-пакеты можно включать/выключать фонарики у неписей (о(в)тключая схему sr_light). Но именно к актору это не применимо, т.к. а) для перечтения измененных флагов фонарик требуется или засэйвить и залоадить или перевести офф-олайн (о чем и речь!) и именно это для актора невозможно. И б) игрок всегда может перебить скрипты имея забинденную <L> ...

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

ColR_iT

Осмелюсь предположить, что AndreySol, хочет именно вкл/выкл фонарик и именно скриптами. Я приблизительно догадываюсь для чего это вообще нужно - батарейки для фонаря, так ведь, AndreySol?

Именно так.

 

Artos

А зачем его включать/отключать(,), если можно просто взять и удалить, а когда нужно заспавнить! (ну иль переместить куда-нить во вне актора, например в ящик)

Это бы работало, если-бы разрабы не связали "движково" фонарик с ПНВ. А так как, по игровой логике, ПНВ связан все-таки с наличием соответствующего бронекостюма, то я и хотел сделать раздельное батарейное питание для ПНВ и фонарика. Но видимо придется принять вариант "одна батарея для фонарика и ПНВ".

 

по п.3 - оно то понятно, насчет родительского объекта, но ведь движок все-же изменяет свойства объектов в слотах\инвентаре актера(ГГ) (к примеру - износ оружия в процессе стрельбы) без изъятия (перевода он-офф-он) их из этих самых слотов\инвентаря. И делает он это явно с использованием нет-пакетов, так как это, видимо, единственный способ синхронизации состояния клиентской и серверной частей объекта. Вот я и думал, что возможно менять свойства путем изменения нет-пакетв объектов даже в инвентаре\слотах актера(ГГ).

 

Я только начал изучать работу с нет-пакетами, и модуль для работы с ними от Artos очень помог. А то, что меня попрекают якобы не знанием "элементарных базовых" основ, это все-же не моя вина - уж очень пахабно движок разрабами писан. И с этим (на мой взгляд) очень тяжело поспорить.

AndreySol, не ставь телегу перед лошадью ...

1. Ты опять перемешал понятия и никак не поймешь разницу между клиентским объектом и серверным.

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

Нет-пакеты, по сути, возможность изменить свойства объекта И в онлайне через "задний проход", и хотя этот способ вполне действенен, но все же не для всего, не всегда и конечно же нужно его использовать с умом.

2.

AndreySol: ... то, что меня попрекают якобы не знанием "элементарных базовых" основ, это все-же не моя вина - уж очень пахабно движок разрабами писан. И с этим (на мой взгляд) очень тяжело поспорить.
Мда-а-а, спорить тут бесполезно ... в таких случаях говорят - "это диагноз". Почему то все другие модмейкеры с этой "похабщиной" работают и создают моды, не сваливая на разработчиков свои проблемы ...

can anyone help me??

i have write a script wich shll respwan npcґs in any level

i hope you can see what for what is and i hope that anyone help me.

when you have question to my script the ask me.

local respwan_table = {}
local timer = nil
local levels = {marsh=            {x=-61.996055603027,y=0.92057931423187,z=293.67742919922}
                }
                
local respwan_npc = {
mar_clear_sky_respawn_1 = true,
mar_clear_sky_respawn_2 = true,
mar_clear_sky_respawn_3 = true,
}


function spwan()
if db.actor:alive() == false then return end
            local level_name = level.name()
                    if timer == nil then
                            timer = level.get_time_hours() + math.random(3, 6)
                            if timer > 23 then timer = timer - 24 end
                    end
                    if time_global() > timer then
                            timer = nil
                            for lvl, pos in pairs(levels) do
                                if level_name == lvl then 
                                            local pos = vector():set(pos.x, pos.y, pos.z)
                                            local lvi = db.actor:level_vertex_id()
                                            local gvi = db.actor:game_vertex_id()
                                    for npc,spwan in pairs(respwan_npc)do
                                        if spwan == true then
                                               respwan_table[alife():create("mar_clear_sky_respawn_1", pos, lvi, gvi).id] = true
                                            table.insert(respwan_npc,2,false)
                                           end
                                    end
                                end
                            end
                            
           end   
           local tbl_count,obj = 1,nil
           for k,v in pairs(respwan_table) do
                   obj = db.storage[k] and db.storage[k].object
                        if obj and obj:alive() == false and v == true then
                       table.insert(respwan_npc,2,true)   
                       end
          end
end

but when i start the game i get a crash but in the log are nothing

can anyone help me away?

thank you.

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

olaf1

Sorry for English:)

Firstly, you have logical error in your timer. You have used level.get_time_hours() and time_global() which return not the same type of time. If you open the Referenceща Function and classes (you can find it on our forum) you will see, that level.get_time_hours() returns time in hours,which show which hour now in game, but time_global() returns time in milliseconds,which show how many milliseconds have passed since starting the program. So, you must change underlying code:

if timer == nil then
    timer = level.get_time_hours() + math.random(3, 6)
    if timer > 23 then timer = timer - 24 end
end
if time_global() > timer then

on this code:

if timer == nil then
    timer = level.get_time_hours() + math.random(3, 6)
    if timer > 23 then timer = timer - 24 end
end
if level.get_time_hours() = timer then

 

Secondly, what this code must do? It so.... I can't translate what I think, but it's realy strange code:

for npc,spwan in pairs(respwan_npc)do
    if spwan == true then
        respwan_table[alife():create("mar_clear_sky_respawn_1", pos, lvi, gvi).id] = true
        table.insert(respwan_npc,2,false)
    end
end

Please, explain:)

 

And the last for now, May be I now why you have crash witout log. In for construction you use 'spwan' which already name of function. Change

for npc,spwan in pairs(respwan_npc)do
    if spwan == true then

on

for npc,myspwan in pairs(respwan_npc)do
    if myspwan == true then

and try again. Replay after check

Изменено пользователем _Призрак_

olaf1, _Призрак_, давайте придерживаться общепринятых норм и правил. Это русскоязычный форум и сообщения на нем пишутся на русском языке(!). В сложных случаях можно писать и дублированием сообщения на оригинальном языке, но не следует этим злоупотреблять!

 

olaf1, уже не первый раз пишешь в тему с нарушением правил. Ничто не мешает тебе использовать онлайн-переводчики. Потрудись, плз, это делать в дальнейшем.

- Считаю, пусть лучше пишет, как пишет: и на английском-то плохо, а с переводчиком будет совсем кошмар и никто ничего не поймет. Cyclone

 

P.S. Именно для "понимания написанного" и применяется вариант с дублированием на общепринятом и родном!

Ну а коды olaf1, уже не раз тут появляющиеся - сложно понять и на Lua-шном языке. ;-) --/Artos

 

И, если интересует ответ на свой вопрос, то переведешь самостоятельно текст ниже:

1. Собственно код написан без синтаксических ошибок и не должен приводить к фатальным ошибкам при запуске игры. Но код очень абсурден, что уже показал _Призрак_, и может приводить к переполнению стека при постоянном использовании table.insert(respwan_npc,2,false) при вызовах.

2. Не знаю что за идея у тебя с 'timer', но если ее выкинуть, то вероятно должно получиться что-то в этом роде:

local respwan_table = {}
local timer = nil
local levels = {marsh= {x=-61.996055603027,y=0.92057931423187,z=293.67742919922} }

local respwan_npc = {
  ["mar_clear_sky_respawn_1"] = true,
  ["mar_clear_sky_respawn_2"] = true,
  ["mar_clear_sky_respawn_3"] = true,
}


function spwan()
  if db.actor:alive() == false then return end
  --[[ --/ абсурд! (nonsense!)
  if timer == nil then
    timer = level.get_time_hours() + math.random(3, 6)
    if timer > 23 then timer = timer - 24 end
  end
  if time_global() > timer then
    timer = nil
  --]]
    local level_name = level and level.name()
    local coordinates = levels[level_name]
    if coordinates then
      local pos = vector():set(coordinates.x, coordinates.y, coordinates.z)
      local lvi = db.actor:level_vertex_id()
      local gvi = db.actor:game_vertex_id()
      for section,flag in pairs(respwan_npc)do
        if flag == true then --/ если разрешен спавн
          local se_obj = alife():create(section, pos, lvi, gvi) --/ спавн НПС по координатам
          respwan_table[se_obj.id] = section --/ запоминаем ID и секцию заспавненного НПС
          respwan_npc[section] = false --/ ставим метку запрета повторного спавна
        end
      end
    end
  --end
  
  for id,section in pairs(respwan_table) do
    local obj = db.storage[id] and db.storage[id].object
    if not obj or obj:alive() == false then --/ если нет НПС или он мертв:
      respwan_npc[section] = true --/ метка разрешения спавнить
      respwan_table[id] = nil --/ чистка (clear)
    end
  end
end

 

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

Artos, привет. Извини, но возможно опять глупый вопрос. Не подскажешь, возможно ли организовать две таблички - аналоги db.storage , но что бы одна была сталкеров, а другая для мутантов?

Есть ли наработки по этому поводу что бы посмотреть?

 

Объясняю для чего мне это нужно. Для поиска сендера в новостях у меня используется перебор вида:

function GetStalkers(ThisObj,RadMin,RadMax,who)
    for k, v in pairs(db.storage) do
    local obj = level.object_by_id(k)
        if (obj) and (IsStalker(obj)) and (obj:alive()) and (obj:id() ~= who:id()) then
        local ComThisObj = ThisObj:character_community()
        local ComSender = obj:character_community()
        if CommunityChenalStatus(ComSender,1) then
            if (ComThisObj ~= ComSender)  then --Данным методом ищем  сталкера.
            if ValNpc(obj)~=true then --Отсекаем квестовых нпс
            local Pos = ThisObj:position()
            local Dist = Pos:distance_to(obj:position())
            if (Dist < RadMax) and (Dist > RadMin) then
                table.insert(StkLevelTbl, obj)
                end
                end
                end
                end
        end
end
end
function GiveStalker(ThisObj,RadMin,RadMax,who)
GetStalkers(ThisObj,RadMin,RadMax,who)
if next(StkLevelTbl)  then
local obj = StkLevelTbl[math.random(#StkLevelTbl)]
return obj
else 
return nil
end
end

 

 

Первая функция делает перебор - и заносит в табличку подходящие варианты по параметрам. Вторая выбирает рандомный( если же в первую внести

 

return obj

вместо

table.insert(StkLevelTbl, obj)

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

 

У меня была идея, но опять неподкрепленная мат.частью:

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

1. если объект в оффе, то его взять мне не удается (А есть ли такой способ вообще)

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

Т.е. эта идея провалилась с потрохами.

 

Теперь воникла идея с клоном db.storage, но :

 

1. Можно ли такое реализовать.

2. Стоит ли оно такого? Т.е. прекратятся ли рывки - насколько уменьшится нагрузка при переборе?

 

И вопрос на миллион - есть ли другие варианты? Или как можно снять нагрузку при переборе?

З.Ы. Мне не нужно готовых вариантов, я готов учиться - только ткните с чего начать?

 

Artos, Спасибо, все ясно. Буду пробовать.

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

Vano_Santuri, отдельные таблички для объектов 'сталкеры' и 'мутанты' давным давно применяются, например, в Zenobian-моде.

У себя в моде (ТЧ/ЧН) тоже давным давно использую подобное, причем и для всех серверных объектов организованы таблицы (сталкеры/монстры) и и для онлайновых свои (сталкеры/монстры/аномалии/вертушки/...). Бери и смотри ...

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

1. Про отдельные таблички уже говорил. Также, в купе с модулем оффлайн-алайф (иль вырезав из него) вполе реально иметь таблички неписей монстров и пр. по локациям, что дает возможность давать новости сканируя только таблицу нужной локации.

2. Рандомность для исключения повторяемости дело конечно хорошее ... но и не оптимальное. И на локации в нужном месте вполе может оказаться всего один-два подходящих сендера (что сведет на нет весь рандом), да и рандом то "повторяем".

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

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

4. Учитывая, что сталкера/монстры НЕ ракеты и их перемещение все же имеет конечные скорости - вполне можно сканировать таблички и запоминать координаты их расположения и прочие нужные параметры с некоторой дискретностью (не чаще 1 минуты, например, а то и реже), что разгрузит затратные ресурсы на твои скрипты.

 

Т.о., учитывая, что при загрузке игры все интересующие тебя онлайновые объекты (сталкеры/монстры) регистрируются в db.storage, да и серверные объекты не сложно из метода on_register рассовывать по нужным таблицам(локациям) - то собственно 50% (и даже более) нужных данных ты можешь получить сразу при старте.

И не следует зашориваться на db.storage, это все же именно таблица онлайновых объектов и "всех в одной куче". Ни что не мешает организовывать свои таблички по нужным тебе параметрам и их использовать.

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

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

Этот код предназначен для проверки respwan_npc второй позади = истинное, если он верен ему в таблице (respwan_table) NPC gespwant вплоть до уровня

 

, а затем положил обратно в таблице respwan_npc значение ложной

 

for npc,spwan in pairs(respwan_npc)do
    if spwan == true then
        respwan_table[alife():create("mar_clear_sky_respawn_1", pos, lvi, gvi).id] = true
        table.insert(respwan_npc,2,false)
    end
end

 

olaf1, оператор table.insert действительно кладет куда указываешь, но(!) все остальные имеющиеся позиции сдвигаются!

... и кладет каждый раз только значение (т.е. false) и твоя исходная таблица превращается в это:

respwan_npc = {
  ["mar_clear_sky_respawn_1"] = true,
  [2] = false,
  [3] = false,
  ...
  [NNN] = false,
  ["mar_clear_sky_respawn_2"] = true,
  ["mar_clear_sky_respawn_3"] = true,
}

Т.о. ты постоянно наращиваешь существующую таблицу новыми полями, не уничтожая прежние.

И использовать для неиндексированной таблицы подобное НЕЛЬЗЯ! Ведь в твоей таблице respwan_npc в качестве ключей идут секции для спавна НПС, а не упорядоченные индексы 1,2,3...

 

Советую почитать материалы по работе с неиндексированными таблицами и ограничения на использование как table.insert / table/remove, так и метода ipairs для таблиц, подобных твоей respwan_npc.

 

Выше, тебе как раз дан вариант, который проверяет значение для ключа-секции спавна НПС и, если оно 'true' - разрешается спавн и этот ключ (секция) помечаются значением 'false', что и исключит повторный спавн пока не изменится это значение.

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

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

О таблице всех нпс на локе, зачем? радиус алайфа ну совсем мизерный...

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

мой пример:
function GetSender(sType, oPos, oKiller)
    local oSender = nil
    if sType == "murder" then
        local iMinDist = 30
        local iMaxDist = 100
        for k,v in pairs(db.storage) do                
            local oTrav = level.object_by_id(k)    
            if oTrav and IsStalker(oTrav) and oTrav:character_community() ~= "actor" and not ExcludedNpcs(oTrav) then
                if xr_wounded.is_wounded(oTrav) == false and oTrav:alive() then
                    if oKiller then
                        if oTrav:id() ~= oKiller:id() then fGetSender = true end
                    else
                        fGetSender = true
                    end
                    if fGetSender then
                        local DiffDist = oPos:distance_to(oTrav:position())
                        if DiffDist < iMaxDist and DiffDist > iMinDist then
                            iMaxDist = DiffDist -- я об этом
                            oSender = oTrav
                        end    
                    end
                end    
            end
        end            
    end
    return oSender
end

 

 

ЗЫ это так же логичней/реалистичней, в плане нахождения реального сендера, в добавок - намного оптимальней

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

Изменено пользователем Viнt@rь

Viнt@rь,

 

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

 

Да было дело давненько, с таблицами первый раз работал. Просто я тогда мало знал о свойствах объектов (родит, дочерные и т.п). В данный момент я практически все отрезал, совсем по другому замутил. Никогда не думал, что сначала делать алгоритм на бумажке куда полезнее, чем сразу печатать код... Но пока это все в разработке и играбельно будет не скоро...

 

Код твой заценил - теперь понятно, таким образом ты сокращаешь расстояние - неплохо. Я просто не думал о таком алгоритме. Сам придумал?

Но db.storage -- куча хлама, как сказал Artos.

Я все-таки сделаю себе пару табличек, и чтоб они так "размазано" апдейтились - будет чуток быстрее. Плюс можно будет использовать

 

for k=1,#tbl do 
local t=tbl[k]
end

 

Как я почитал - говорят быстрее будет. Нужно будет проверить...

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

Viнt@rь, Vano_Santuri в-первую очередь оптимизация определяется целями и заданными начальными условиями, а никак не "а вот у меня так, а тут так".

Viнt@rь, если ваши "новости" ограничиваются только смертями иль не только, но именно на текущей локации, то использование db.storage может быть и оправдано (зачем городить еще чего-то), но говорить об оптимизации НЕ стОит.

1. Даже многократное выпонение простенькой проверки: if oTrav and IsStalker(oTrav) ... все же лучше выполнять не 500 раз, а всего 100 (к примеру). Ведь подобное можно встретить еще в десятке скриптов ... и порою на том же апдейте ... Так зачем каждый раз проверять НЕ нужное???

2. Кто бы объяснил, ну зачем каждый раз вычислять и группировку и не принадлежность к актору и "не труп" и расстояние и т.п.? И все это делать единомоментно для всех подходящих по условиям неписей ...

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

Вспомните, что все(!) неписи имеют свои апдейты! Вспомнили?! Ну а теперь попробуйте сказать, что организовав один раз свою "новостную табличку" и (от)регистрируя в ней каждого НПС иль монстра по net_spawn/net_destroy и обновляя из уже готового для вас апдейта каждого непися в уже созданной табличке информацию и по координатам и по группировке и по "жив иль мертв" и т.п. вы не получите выигрыша? Ведь за вас движек уже распределяет собственно и процесс сканирования/апдейта и за вас актуализирует все нужные данные, не проверяя за раз всех оптом.

Остается всего лишь в нужное время по нужным критериям выбрать из готовой таблички подходящий объект.

(это конечно только для онлайновых новостей иль подобного сгодится)

 

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

 

Добавлено через 4 мин.:

И ... я не говорил что: "db.storage -- куча хлама, но для конкретной задачи типа новостей от сталкеров, в db.storage действительно для данного алгоритма "куча ненужного хлама". Легко самим посмотреть, что при старте чистой ЗП за Затоне в db.storage более 700 объектов из которых неписей на порядок меньше.

(приписывая свои слова другому стОит это делать аккуратно)

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

Artos, а разве хранение всех данных о нпс в еще одной табличке не даст той же нагрузки, что и проверка? К тому же, как я сказал ранее, радиус алайфа ну черезвычайно маленький(сделать больше - будут лаги), а ведь только онлайновые нпс обновляются... К чему я веду, к тому, что нпс в онлайне на локации мало, а убийств/смертей нпс еще меньше, тоесть проверка выполняется вообще мизерное кол-во раз(правда если ГГ не начнет гамселить всех и вся:)), так зачем же тогда создавать и заполнять еще одну табличку... если можно получить НПС из стораджа и из него уже "вытянуть" инфу...

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

 

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

 

Лично у меня, в данном случае, это наблюдатель, для новостей типа видел/слышал, потому, такой вариант мне подходит, нет, даже больше, такой вариант для меня идеален :)

 

Сорри, чет понесло в оффтоп...

Изменено пользователем Viнt@rь

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

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

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

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

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

Войти

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

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

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