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

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

Struck

Эм....

local where = ""
if y>point.y then
   where = where .."северо-"
else
   whene = where.."юго-"
end
if x>point.x then
   where = where.."восток"
else
   where = where.."запад"
end

Не?

Тут конечно нужно еще поработать с таким моментом, что объект может находится с небольшим смещением по х или у относительно нашей точки и его можно считать условно "ровно на севере". Тут так-же просто - высчитать угол (геометрия 7 класс) и сравнить его с каким-то углом, например с 22,5

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

Freedom

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

IQDDD, в Сталкере -- 2^23, из-за этого данный алгоритм, прямо в таком виде, скорее всего не подойдёт (непроверено). Поэтому я стал делать альтернативный счёт годов-дней-секунд.... правда пока не доделал (начал 2010) :) -- геймплей отвлёк.

 

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

Struck, правильно работающий код из STCO:

-- если dirsector - направление на объект в градусах, ему же потом присваивается текстовое значение

    elseif dirsector < 22.5 then
        dirsector = "Север"
    elseif dirsector > 337.5 then
        dirsector = "Север"
    elseif dirsector < 67.5 and dirsector > 22.5 then
        dirsector = "Северо-Восток"
    elseif dirsector < 112.5 and dirsector > 67.5 then
        dirsector = "Восток"
    elseif dirsector < 157.5 and dirsector > 112.5 then
        dirsector = "Юго-Восток"
    elseif dirsector < 202.5 and dirsector > 157.5 then
        dirsector = "Юг"
    elseif dirsector < 247.5 and dirsector > 202.5 then
        dirsector = "Юго-Запад"
    elseif dirsector < 292.5 and dirsector > 247.5 then
        dirsector = "Запад"
    elseif dirsector < 337.5 and dirsector > 292.5 then
        dirsector = "Северо-Запад"

 

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

всё легко

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

_Призрак_, вот оно как :), ну в геометрии я ноль абсолютной(не знаю даже что такое вектор, алгебра моя стихия...), ну так вот, а получить северо-запад например как? Все ж таки я думаю нужно использовать какие то тангенсы и магическое math.pi

 

7.9, dirsector как я понял это у тебя дирекция объекта?

 

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

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

Изменено пользователем Struck
Ссылка на комментарий

Убедителая просьба-напоминание:

1. Использовать для "портянок" текстов кодов/логов тэг спойлера.

2. Споры и размышления о разрядности точности и т.п. вести в тематическом топике "Язык Lua. Общие вопросы программирования.".

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

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

Как-то раз malandrinus высказывал своё недовольство по поводу того, что некоторые используют слово "дирекция" вместо "направление". Правильно вообще говорил. :)

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

IQDDD, да не ворчи ты :), для меня на сталкерских форумах "дирекция" - "направление взгляда объекта", как бы одно слово заменяет три, и вроде всем понятно о чем говорю, разве нет?

 

P.S. Я согласен, что это неправильно, но в данном случае...можно простить.

 

Поменьше оффтопика ... иначе будут приниматься меры без всяких "прощалок". --/Artos

 

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

 

Теперь следующий вопрос.

 

Как создать глобальную функцию? Типа IsStalker.

 

Смотрел моды где это реализовано...но там ничего не понял, скажите хоть что 'покурить' или куда 'копать'.

 

Читать мануал по Lua! Именно читать, а не курить его ... --/Artos

Изменено пользователем Artos
Ссылка на комментарий

Еще ее можно вручную сунуть в _G таблицу:

_G["my_global_func"] = function () get_console():execute("my_global_func called") end

Freedom

Ссылка на комментарий
_Призрак_, а таким способом она будет доступна после 1го апдейта актора? Или же до актора?

Что-то кончается, что-то начинается...

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

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

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

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

1. Глобальная функция может быть как в любом конкретном скрипте/модуле, так и в глобальной метатаблице.

Т.о. исходный вопрос имеет простой ответ: пишешь функцию и не определяешь ее как локальную - вот у будет она глобальной.

Однако по уточнению "Типа IsStalker" - можно предположить, что Struck хочет обращаться к своей глобальной функции не через имя файла-скрипта ( my_script.my_func(...) ), а именно как my_func(...) - т.е. чтобы функция была в глобальной метатаблице (_G). Ну так и включи ее в нее. Способы бывают разные, два уже указаны:

- написать свою функцию в скрипте _g.script , т.е. в полной аналагии с _g.IsStalker()

- занести напрямую в таблицу: _G.my_func = function(...) <тело функции> end

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

 

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

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

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

Artos, Теперь возвращаюсь к производительности.

 

    for k=1,65535 do
        local obj = level.object_by_id(k)
        if obj then
            local Cid= get_clsid(obj)
                if Cid == "artefact_s"
                    table.insert(ArtsTbl, k) -- записываем k, а не объекты как таковые 
                end
        end
    end

 

 

Функция вызывается разок в 3 игровых часа. Что лучше? Вернее менее громоздко - заносить ключ k, или же копию obj? а потом работать с ними. Выигрыш в производительности будет? Или нет?

 

Так же есть такой вариант

local t = 0
    for k=1,65535 do
        local obj = level.object_by_id(k)
        if obj then
            local Cid= get_clsid(obj)
                if Cid == "artefact_s"
                t=t+1
                ArtsTbl[t] = k
                end
        end
    end

 

 

Здесь я избавился от инзерта. Вы неоднократно говорили, что он оч медленно работает... Будет и еще выигрыш в производительности?

Что-то кончается, что-то начинается...

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

1. Все userdata'ы (в том числе и объекты game_object) являются ссылочными типами, посему когда ты пишешь obj1 = obj2 - ты копируешь только ссылку (занимает 4/8 байта) на объект. Посему выигрыша в производительности нет.

2. Лучше использовать table.insert, т.к. даже если он и чуть медленнее, всё равно лучше поступиться производительностью во благо понятности кода.

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

IQDDD, понятно.

 

2. Лучше использовать table.insert, т.к. даже если он и чуть медленнее, всё равно лучше поступиться производительностью во благо понятности кода.

 

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

 

А чтоб не лагало, это нужно или вообще избавиться от работы с объектами в оффлайне, или же свисти к минимуму затраты на такие циклы.

 

Artos, вот пытаюсь приспособить твой чудо-скрипт для оптимизации сканирования объектов. Но что-то мало не понимаю. Можешь почеркать то, что не нужно для работы? (выводы в лог и т.д)

 

И да, что должна делать эта функция?\

        --/ -- обработка объекта ----------------
        this.Build_TableObj(soObj,iCurID)
        --/ -------------------------------------

Как я понял, она должна заносить в таблицу искомый объект и его id?

 

local iPrgScan =  25  --/ периодичность сканирования Зоны (25ms => ~15 минут)

function OnUpdate(uo,delta)
  --/ непрерывное циклическое сканирование локаций по всему диапазону ID объектов (1...65534)
  if coroutine.status(CoScan) == 'suspended' then --/ статус сопрограммы: приостановлена?
    local bFlg,Result = coroutine.resume(CoScan, iPrgScan) --/ (пере)запуск сопрограммы
    if not bFlg then --/ ошибка при выполнении сопрограммы
      printf("OnUpdate:Error_CoScan=[%s]:<%s>", Result, "Error!")
    end
  end
end
--
local tOAMain,tTmpMain = {},{} --/ дин.массив основных объектов (используется в m_news.script)
local tOwners,tTmpOwn  = {},{} --/ дин.массив владельцев предметов

local CoScan = coroutine.create( --/ сопрограмма сканирования объектов игры
  function(iTimeLimit) --/ функция сканирования объектов игры с ограничением времени работы
--    log("%s:CoScan:TimeLimit=[%s]:[%s]", sModule, iTimeLimit, ">") --/#~#
    local oPTimer,iTimeStop,soObj = nil,nil,nil
    local iCurID = 65535 --/ начальный ID
    while true do
      if iCurID >= 65534 then --/ проверка: цикл закончен (или предустановка)?
        --coroutine.yield(iCurID) --/ приостановка (опционально)
        if iCurID == 65534 then
          tOAMain,tOwners = tTmpMain,tTmpOwn --/ обновляем основные массивы
          log("%s:CoScan:Owners=[%s]:Time=[%s]%s", sModule, GetSizeTable(tOwners), Get_StrTime(), "") --/#~#
          --Print_Tables_OffLineAlife() --/#~# for Debug
        end
        --/ предустановки для нового цикла:
        tTmpMain,tTmpOwn = {},{} --/ временные массивы
        iCurID = 0 --/ начальный ID (опускаем 0-actor)
        iTimeStop = iTimeLimit --/ начальная установка для таймера
        oPTimer = profile_timer() --/ (пере)создаем объект таймера
      end
      iCurID = iCurID +1 --/ переход к следующему ID
      soObj = sim:object(iCurID) --/ очередной серверный объект игры
      if soObj then --/ объект в игре? ('пустышки' пропускаются и таймером)
        oPTimer:start() --/ старт таймера (на продолжение)
        --/ -- обработка объекта ----------------
        this.Build_TableObj(soObj,iCurID)
        --/ -------------------------------------
        oPTimer:stop() --/ (при)остановка таймера
        if oPTimer:time() > iTimeStop then --/ проверка: не закончен ли лимит времени?
          coroutine.yield(iCurID) --/ приостановка цикла
          iTimeStop = oPTimer:time() + iTimeLimit --/ обновляем для текущего подцикла сканирования
        end
      end
    end
    printf("%s:DoScan:<Error!>")
    return 65535 --/>
  end
)

 

Что-то кончается, что-то начинается...

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

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

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

Vano_Santuri, IQDDD, честно говоря, ваш диалог улыбает ... :D , каждый о своем а суть по-боку ...

 

1. Во-первых, если в вопросе стоИт уточнение именно по производительности, то и нужно говорить в этом контексте, а не о "понятности кода". Задачи бывают разные, и уж в циклах по перебору тысяч вариаций - красивость и понятность кода все же на 2-ом плане! ИМХО.

 

2. Вот то, что грубые ошибки совершенно не замечены, а вроде как говорится о почти рабочих вариантах - вот это вы упускаете.

Ну как может вообще работатть такое:

if Cid == "artefact_s"

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

Вероятно тут должно быть: if Cid == clsid.artefact_s then

 

3. Я никогда не говорил что table.insert "оч медленно работает". Конечно прямое заполнение поля выигрывает в скорости, но ... тут ведь в первую очередь важен формат таблицы, и во вторую - к такому прямому заполнению искуственно привязываются операции по переберу индексов (t) что смазывает возможно весь выигрыш.

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

IQDDD, ну никак не пойму, чем "понятливость" вставки в таблицу больше, чем заполнение поля таблицы ...

 

4. Никакой по сути разницы по скорости нет если записывать в таблицу идентификаторы иль ссылки на об'екты, а вот для дальнейшей работы с полученной таблицей (о чем ничего не сказано) это уже может играть роль. С одной стороны хранение об'ектов, которые могут и исчезать из игры - чревато последствиями, с другой, получать по идентификатору об'екты - затраты по времени ... Тут только комплексный подход и анализ может решать что же оптимальнее записывать в таблицу.

 

5. Если уж говорить о понятливости и простоте кода, то во-первых, зачем идентификатор (ID) обзывать переменной 'k'? Может 'id' будет более понятнее?! Ну и второе, для номеров/индексов чем 't' проще нормального названия 'idx' или 'index'?! Производительность от таких названий не повышается, а вот понятность/читабельность кода - хромает.

 

6. Ну и по this.Build_TableObj(soObj,iCurID) - видно ты плохо смотрел Симбион, ведь в нем это применено в рабочем скрипте m_oflife.script и это собственно ссылка на функцию, которой передаются аргументами уже полученные серверный об'ект и его идентификатор и функция составляет множество (суб)таблиц для этого об'екта, которые затем используются в алгоритмах оффлайн алайфа.

 

Т.о. ответ по производительности дать не могу, т.к. в отрыве от требований к формату таблицы и пояснений о ее дальнейшем использовании - вопрос по скорости заполнения таблицы достаточно бессмысленен и малосущественен. Ну а если вопрос для CoP - то вообще зачем перебирать весь диапазон игровых ID, если артефакты биндятся и онлайновые достаточно быстро ищутся в db.storage ...

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

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

Господа, подскажите. Хочу заспавнить труп непися вне аи сетки (в подвале - там нет аи сетки)

Я прочитал про назначения флажков, нашел этот: flUsedAI_Locations (8-й бит) и написал так:

    local obj = alife():create("forest_nebo_veteran",vector():set(-180.48532104492,5.3024110794067,-317.11584472656),50507,3365)
    local tbl = amk.read_stalker_params(obj)
        tbl.oflags = tbl.oflags-128 -- сброс восьмого бита - flUsedAI_Locations
        tbl.health = 0
        tbl.updhealth = 0
    amk.write_stalker_params(tbl, obj)

Флаг сбрасывается, я проверял. Приходит -65 (=1110111111) а записывается -193 (=1100111111). Как видно, восьмой бит сброшен. Но непись все равно спавнится на полу, где идет аи сетка. Я менял координату Y выше, ниже - все равно непись спавнится на аи сетке.

 

Что я сделал не так? И как мне правильно заспавнить труп непися вне аи сетки?

 

 

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

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

И, неясно, для чего манипуляции с "менял координату Y выше, ниже" - хоть живой, хоть трупом - все одно опустится на пол. Чтобы подвешивать - нужно нечто иное ... (сейчас на вскидку не помню уже).

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

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

Подскажите, как запустить скрипт через определённый промежуток времени. В скрипте две функции: проверка_наличия_предмета и функция_действия.

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

В bind_stalker'е есть функция update(delta).

Она периодически вызывается через определённый промежуток времени (период delta зависит от производительности и составляет в среднем 15-20 мс). На этой основе и делай.

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

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

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

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

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

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

Войти

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

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

AMK-Team.ru

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