_Призрак_ 11 Опубликовано 19 Августа 2012 Поделиться Опубликовано 19 Августа 2012 (изменено) 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 Изменено 19 Августа 2012 пользователем Artos Freedom Ссылка на комментарий
7.9 174 Опубликовано 19 Августа 2012 Поделиться Опубликовано 19 Августа 2012 (изменено) 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 = "Северо-Запад" Изменено 19 Августа 2012 пользователем Artos всё легко Ссылка на комментарий
Struck 61 Опубликовано 19 Августа 2012 Поделиться Опубликовано 19 Августа 2012 (изменено) _Призрак_, вот оно как , ну в геометрии я ноль абсолютной(не знаю даже что такое вектор, алгебра моя стихия...), ну так вот, а получить северо-запад например как? Все ж таки я думаю нужно использовать какие то тангенсы и магическое math.pi 7.9, dirsector как я понял это у тебя дирекция объекта? Добавлено через 61 мин.: Курю мануалы по геометрии за 7 класс ...вроде уже потихоньку доходить начинает, сейчас еще разберусь как отклонения взять, и будет то что мне надо. Изменено 19 Августа 2012 пользователем Struck Ссылка на комментарий
Artos 99 Опубликовано 19 Августа 2012 Поделиться Опубликовано 19 Августа 2012 Убедителая просьба-напоминание: 1. Использовать для "портянок" текстов кодов/логов тэг спойлера. 2. Споры и размышления о разрядности точности и т.п. вести в тематическом топике "Язык Lua. Общие вопросы программирования.". 3. Приводя примеры кодов - не забывайте включать в них существенное, без которого коды превращаются в бессмыслицу. "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
IQDDD 5 Опубликовано 19 Августа 2012 Поделиться Опубликовано 19 Августа 2012 Как-то раз malandrinus высказывал своё недовольство по поводу того, что некоторые используют слово "дирекция" вместо "направление". Правильно вообще говорил. Ссылка на комментарий
Struck 61 Опубликовано 20 Августа 2012 Поделиться Опубликовано 20 Августа 2012 (изменено) IQDDD, да не ворчи ты , для меня на сталкерских форумах "дирекция" - "направление взгляда объекта", как бы одно слово заменяет три, и вроде всем понятно о чем говорю, разве нет? P.S. Я согласен, что это неправильно, но в данном случае...можно простить. Поменьше оффтопика ... иначе будут приниматься меры без всяких "прощалок". --/Artos Всем спасибо(особенно за совет про геометрию), почитал - вдумался, повторил курс и написал что надо ...попробую еще другие варианты помусолить, хотя и этот мой работает как надо, но все же хочется найти еще какие-нибудь решения. Теперь следующий вопрос. Как создать глобальную функцию? Типа IsStalker. Смотрел моды где это реализовано...но там ничего не понял, скажите хоть что 'покурить' или куда 'копать'. Читать мануал по Lua! Именно читать, а не курить его ... --/Artos Изменено 20 Августа 2012 пользователем Artos Ссылка на комментарий
Vano_Santuri 33 Опубликовано 20 Августа 2012 Поделиться Опубликовано 20 Августа 2012 Struck, в _g.script засунь.... Вроде так. Что-то кончается, что-то начинается... Ссылка на комментарий
_Призрак_ 11 Опубликовано 20 Августа 2012 Поделиться Опубликовано 20 Августа 2012 Еще ее можно вручную сунуть в _G таблицу: _G["my_global_func"] = function () get_console():execute("my_global_func called") end Freedom Ссылка на комментарий
Vano_Santuri 33 Опубликовано 20 Августа 2012 Поделиться Опубликовано 20 Августа 2012 _Призрак_, а таким способом она будет доступна после 1го апдейта актора? Или же до актора? Что-то кончается, что-то начинается... Ссылка на комментарий
IQDDD 5 Опубликовано 20 Августа 2012 Поделиться Опубликовано 20 Августа 2012 Как по мне, так апдейты актора и пр. не имеют к этому отношения. Как засунул в _G, так сразу и будет доступна. Ссылка на комментарий
Artos 99 Опубликовано 20 Августа 2012 Поделиться Опубликовано 20 Августа 2012 (изменено) Struck, IQDDD, советую вам почитать все же мануал по Lua на тему областей видимости переменных ... лишним не будет и "прощать" за невняьные вопросы/предположения никого не придется. 1. Глобальная функция может быть как в любом конкретном скрипте/модуле, так и в глобальной метатаблице. Т.о. исходный вопрос имеет простой ответ: пишешь функцию и не определяешь ее как локальную - вот у будет она глобальной. Однако по уточнению "Типа IsStalker" - можно предположить, что Struck хочет обращаться к своей глобальной функции не через имя файла-скрипта ( my_script.my_func(...) ), а именно как my_func(...) - т.е. чтобы функция была в глобальной метатаблице (_G). Ну так и включи ее в нее. Способы бывают разные, два уже указаны: - написать свою функцию в скрипте _g.script , т.е. в полной аналагии с _g.IsStalker() - занести напрямую в таблицу: _G.my_func = function(...) <тело функции> end - имеются иные более сложные варианты с управлением и окружением для функции, но это уже ... иная тема и в данном контексте нет смысла заморачивать спращивающего. ;-) 2. Естественно, если функция имеется в глобальной метатаблице, то она доступна всегда и никакие акторы с его апдейтами на это не влияют. Т.е. как только функция определена и добавлена - она тут же доступна. Изменено 20 Августа 2012 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
Vano_Santuri 33 Опубликовано 20 Августа 2012 Поделиться Опубликовано 20 Августа 2012 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 Здесь я избавился от инзерта. Вы неоднократно говорили, что он оч медленно работает... Будет и еще выигрыш в производительности? Что-то кончается, что-то начинается... Ссылка на комментарий
IQDDD 5 Опубликовано 20 Августа 2012 Поделиться Опубликовано 20 Августа 2012 1. Все userdata'ы (в том числе и объекты game_object) являются ссылочными типами, посему когда ты пишешь obj1 = obj2 - ты копируешь только ссылку (занимает 4/8 байта) на объект. Посему выигрыша в производительности нет. 2. Лучше использовать table.insert, т.к. даже если он и чуть медленнее, всё равно лучше поступиться производительностью во благо понятности кода. Ссылка на комментарий
Vano_Santuri 33 Опубликовано 20 Августа 2012 Поделиться Опубликовано 20 Августа 2012 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 ) Что-то кончается, что-то начинается... Ссылка на комментарий
IQDDD 5 Опубликовано 20 Августа 2012 Поделиться Опубликовано 20 Августа 2012 Не надо засорять код и свою голову всякими мелочными оптимизациями. Пишите код так, чтобы было в первую очередь "понятно, чётко и лаконично". Если работает медленно, надо искать возможность оптимизировать в первую очередь - структуру алгоритма, а потом уже его написание. Ссылка на комментарий
Artos 99 Опубликовано 20 Августа 2012 Поделиться Опубликовано 20 Августа 2012 (изменено) Vano_Santuri, IQDDD, честно говоря, ваш диалог улыбает ... , каждый о своем а суть по-боку ... 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 ... Изменено 20 Августа 2012 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
proper70 74 Опубликовано 20 Августа 2012 Поделиться Опубликовано 20 Августа 2012 Господа, подскажите. Хочу заспавнить труп непися вне аи сетки (в подвале - там нет аи сетки) Я прочитал про назначения флажков, нашел этот: 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 выше, ниже - все равно непись спавнится на аи сетке. Что я сделал не так? И как мне правильно заспавнить труп непися вне аи сетки? Ссылка на комментарий
Artos 99 Опубликовано 20 Августа 2012 Поделиться Опубликовано 20 Августа 2012 proper70, ты спавнишь не труп, а обычного сталкера и движек пока (до манипуляций с нет пакетами) не ведает, что ты его хочешь "убить" - соответственно он создает твоего непися, но(!) тут же пытается засунуть его на AI-сетку. И, неясно, для чего манипуляции с "менял координату Y выше, ниже" - хоть живой, хоть трупом - все одно опустится на пол. Чтобы подвешивать - нужно нечто иное ... (сейчас на вскидку не помню уже). "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
ins33 16 Опубликовано 20 Августа 2012 Поделиться Опубликовано 20 Августа 2012 Подскажите, как запустить скрипт через определённый промежуток времени. В скрипте две функции: проверка_наличия_предмета и функция_действия. Ссылка на комментарий
IQDDD 5 Опубликовано 20 Августа 2012 Поделиться Опубликовано 20 Августа 2012 В bind_stalker'е есть функция update(delta). Она периодически вызывается через определённый промежуток времени (период delta зависит от производительности и составляет в среднем 15-20 мс). На этой основе и делай. Ссылка на комментарий
Рекомендуемые сообщения
Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий
Комментарии могут оставлять только зарегистрированные пользователи
Создать аккаунт
Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!
Зарегистрировать новый аккаунтВойти
Есть аккаунт? Войти.
Войти