Struck 61 Опубликовано 4 Января 2015 Поделиться Опубликовано 4 Января 2015 @Zander_driver, Артос не выкладывал свой рефакторинг скриптов для общего пользования (он только в симбионе, ну и местами его почерк в ЛА проглядывается), он выкладывал готовые модули с понятными инструкциями, потому их все и используют, а описывать весь его рефакторинг комменатриями я думаю занятие весьма долгое (и опять же его не каждый поймет, не говоря уже об использовании), я вот разобрался в его скриптах, и многое почерпнул, за что ему прямо могу сказать большое спасибо. Ну вот скажи, зачем перелопачивать кучи if-then-end? Там выигрыш опять же применимо для сталкера довольно не велик, вот тебе пример, возьмем простую функцию, которая режет взгляд: function compare_part(a, local l = math.min(string.len(a),string.len() if string.sub(a, 1, l) == string.sub(b, 1, l) then return true end return false end Задаемся целью убрать ненавистный тут нам всем if-then-end, я переписал вот так (конечно переписать можно под унифицированный вид, как многие любят, но пока остановимся на адекватном варианте, а именно том, который требует наша задача): function compare_part(a, local l = math.min(#a,# return rawequal(string.sub(a, 1, l),string.sub(b, 1, l)) end Мой вариант показывает явный положительный результат (выигрыш ~ 10 сотых секунды) на 80 тысячах итераций (плюс начинает появляться на >50т итераций). Собственно вывод? Смотрится красивее, скрипт будет весить на несколько килобайт меньше при полной его переработке, а для игры "плюс" и не велик вроде как, т.к. опять же, ну кто тебе будет 80т раз две строки сравнивать? Поэтому такие переделки либо для каких-нибудь любителей красивого кода, либо для таких как Денис, которые гонятся за прибылью в наносекунды. Понятно, что хорошо будет, если каждый единичный if-then перепишем на тернарный оператор, а каждые if-then-elseif на ассоциативные массивы, заменив попутно все корявые конструкции на стандартные луа-функции, но ощутимый и существенный плюс то какой, я так и не понимаю. За скоростью гнаться надо когда у тебя "синхронизация" идет минут 5 или больше. А, да, речь шла о Дезертире и Полтергейсте. Добавлено Dennis_Chikin, 5 Января 2015 Я, кстати, у обих интересного нашел. И упер к себе. Хотя лучше бы, конечно, если бы оно статьями было, а не выковыривать. Ссылка на комментарий
Nazgool 250 Опубликовано 4 Января 2015 Поделиться Опубликовано 4 Января 2015 (изменено) @Struck, Гонятся за скоростью может и нет большого смысла. Как тут говорили, - при загрузке смысла нет, да и во многом другом. Но если можно написать быстро (действительно быстро), то почему этого не сделать? Ну например если из показанного тобой кода максимально убрать вызовы функций (как затратных средств), то можно практически вдвое сократить время выполнения начальной функции function compare_part(a, local x = #a < #b a, b = x and a or b, not x and a or b -- теперь 'a' - всегда будет минимальной строкой, 'b' - максимальной return b:sub(1, #a) == a end Вроде и не нужна особо эта функция, а на душе приятно от двойной скорости. Изменено 4 Января 2015 пользователем Nazgool Добавлено Dennis_Chikin, 4 Января 2015 Нагло злоупотреблю, и вот прям здесь замечу: На душе приятно даже не столько от "двойной скорости", сколько от того, что оно "охватывается одним взглядом". Скорость то здесь можно и еще вытянуть, но уже не нужно. Ссылка на комментарий
Dennis_Chikin 3 658 Опубликовано 4 Января 2015 Автор Поделиться Опубликовано 4 Января 2015 (изменено) Ну, во-первых, как бы 1 наносекунда - я за ней и не гонюсь.Если глянуть по ссылке, про "историю пессимизации" - там вообще-то 10-15 секунд загрузки на вычищенных конфигах, и аж минуты на невычищенных. Плюс "хромота" непосредственно в игре.Плюс 10 секунд (до 2-х минут на ОПКМ) той же загрузки на "торговле", + 4 на тайниках, + 4 на ящиках, плюс 10-30 загрузки и лаги непосредственно в игре по 2 сек на звуках.Ага, вот это у нас называется нынче "гоняться за наносекундами", и "делать ничего не надо".Запуск игры по 4 минуты и перезагрузка по полторы-две после каждой смерти... На не самом древнем железе.Ну нифига ж себе - "неважно"...Не говоря о десятках и сотнях мегабайт памяти при разборах этих конфигов.Да, я понимаю, можно сказать и про "сначала конфиги зачисти". Ага, во всех солянках, всех дмх, всех опах и что там еще наплодили, я вот должен бегать и конфиги чистить. Офигеть...Это как бы во-первых.Второе - а вот действительно, объясните мне, ЗАЧЕМ нужен скрипт о 800 килобайт, если 60 там - выше крыши. Ну, нет у вас 800-килобайтных скриптов, а у других - есть. И, что теперь ?Причем, заметим, пока я разбираюсь с этими 800кб простынями, я должен наслаждаться вот этой вот самой загрузкой по 4 минуты по 20 раз за вечер ?И что такого сакрального в 800кб простыни if ... then ..., что ее и тронуть-то нельзя ?Наконец, разгоревщийся сыр-бор про по сути "А кто тебе РАЗРЕШИЛ пихать в _g.script твой богомерзкий sys_ini ?"Типа, если имеешь наглость что-то там делать - ОБЯЗАН делать под КОШЕРНЫЙ 1.0004 и ни как иначе (вот кстати со всеми его ini_file() в цикле, да еще аж по 2 раза), и если что написал под другое - снеси всю свою богомерзкую ересь обратно, и делай "как у всех", через 20 скриптов. Знаете, вот при такой постановке вопроса - ну не читайте вы мои посты, и будет вам счастье. Делов-то... Ну или идите в райотдел, и пишите заявление по "Оскорблению чуйств верующих" - нынче а аж специальную статью придумали, специально для всех оскорбившихся.Модераторское:Еще n страниц флуда ушло в более соответствующее место. Очень жаль, что надо было 6 МЕСЯЦЕВ дожидаться, пока темы перенесут из закрытого раздела в общий, дабы имевшие возможность нафлудится вдосталь, предпочли реализовать именно на публике. Еще более жаль, что имея возможность сказать много полезного, предпочли заняться выяснением "Кто разрешил ?" Изменено 3 Ноября 2015 пользователем Dennis_Chikin 1 Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
Dennis_Chikin 3 658 Опубликовано 20 Ноября 2015 Автор Поделиться Опубликовано 20 Ноября 2015 (изменено) Итак, внезапно, не смотря на все идеи в духе "форум - закрыть, всех пишущих - на лесоповал", я, все-таки, продолжу. Просто по тому, что единственный известный мне работающий метод избавиться от невыносимого ужаса - озвучить то, что его вызывает. Собственно, те куски, которые были выше - им в общем-то в _g.script вообще не место. Ну вот плохая это идея - оформлять ОДНУ строку отдельной функцией (особенно, в скриптовом языке), формировать там таблицу, возвращать в виде результата, а потом уныло разбирать возвращенную таблицу. И вообще, даже если что-то очень сильно хочется иметь в глобальном нэймспейсе - есть в конце-концов метод _G.* = Ну да ладно. Перейдем, наконец, уже к той части, которая была в оригинале и в очень классических модах. schemes = {} -- соответствие схем модулям stypes = {} -- типы схем -- Загружает схему из файла на диске и активирует в мотиваторе. function load_scheme( filename, scheme, stype ) -- имя файла без расширения schemes[scheme] = filename stypes[scheme] = stype end if not time_global then time_global = function() return device():time_global() end end function wait_game( time_to_wait ) -- игровые секунды verify_if_thread_is_running() if time_to_wait then get_game_time = game.get_game_time game_time_time = get_game_time() local time_to_stop = game.CTime() -- нужно выставить time_to_stop:setHMS( 0, 0, time_to_wait ) time_to_stop = game_time_time + time_to_stop while time_to_stop >= get_game_time() do coroutine.yield() end else coroutine.yield() end end function wait( time_to_wait ) -- реальные секунды verify_if_thread_is_running() if time_to_wait then local time_to_stop = time_global() + time_to_wait while time_to_stop >= time_global() do coroutine.yield() end else coroutine.yield() end end Ну, с первыми двумя все понятно. Как раз тот случай, когда что-то удобно вызывать из глобального пространства. Первое - просто - табличка загруженных "схем". Тут еше отдельный приятный повод для флэйма по поводу "что такое схема", и зачем оно, но для него существует отдельная тема. Про "логику", да. Второе - избавление от некоей монстровидной строки, путем определения функции с коротким именем. Сама функция - получение времени от начала загрузки игры в миллисекундах. Ну, это все знают. Единственно что, сразу возникает вопрос: а нельзя ли оное упрощение как-то еще больше упростить ? Можно, и выиграть при этом в скорости. Но про это будет позже. А вот две следующие - уже вызывают вопросы. Вот на самом деле не знаю, используются ли они где-либо, и определено ли вообще это самое verify_if_thread_is_running() и coroutine.yield(), ибо невозможно объять необъятное силами одного человека, но очевидно, что используемое в оригинале game.time() здесь не подходит, ибо рассчитано на один игровой месяц. По-этому, сразу переписал. Переписал, кстати, в весьма не самом оптимальном виде, поскольку не уверен в моменте использования этой функции. Вторая - то же самое ожидание, но уже в реальном времени и от загрузки. Поскольку реальный месяц без перезагрузки вряд-ли кто будет ждать - вполне допустимо, и вопрос сводится опять же к тому, определено ли coroutine.yield() Две следующих - реально используются, как минимум монстрами (включая, "почему-то", дохлых), БТРами и, видимо, кем-то еще. Вот лень прямо сейчас поиск делать. Привожу сразу оригинал, и попытку это как-то изменить: function action(obj,...) local arg = {...} local act = entity_action() local i = 1 while true do if (arg[i] ~= nil) then act:set_action(arg[i]) else break end i = i + 1 end if (obj ~= nil) then obj:command(act,false) end return entity_action(act) end function action_first(obj,...) local arg = {...} local act = entity_action() local i = 1 while true do if (arg[i] ~= nil) then act:set_action(arg[i]) else break end i = i + 1 end if (obj ~= nil) then obj:command(act,true) end return entity_action(act) end странным мне здесь представляется все. Во-первых, если в аргументах предусмотрена возможность получить nil - это автоматически приводит к краху таблицы, к которой пытаются обращаться по индексу. При том что аргументы в общем-то должны выглядеть как move( ... ), cond - то есть, объект акции и условие. Во-вторых, я уже поднимал этот вопрос в параллельной теме: 1. получаем новый a = entity_action() 2. выполняем для него a:set_action( arg ) 3. делаем что-то еще 4. а теперь - опять получаем entity_action( a ) - то есть, с аргументом, и тут же его возвращаем вызвавшему. Зачем ? Я бы понял, если бы это надо было зачем-то сохранить оригинал, на случай, когда с копией в дальнейшем пытаются что-то сделать. Но в том и дело, что оригинал - не сохраняется. Его уборщик убирает. Теоретически. Тут бы надо кому-то в исходники глянуть. Но вот вроде бы в таком вот виде: function action( obj, ... ) -- здесь и далее - странная фигня с entity_action( entity_action() ) local a = entity_action() for i, v in ipairs( { ... } ) do a:set_action( v ) end if obj then obj:command( a, false ) end -- return a -- entity_action( a ) -- может быть просто act ? посмотрим... return entity_action( a ) end function action_first( obj, ... ) local a = entity_action() for i, v in ipairs( { ... } ) do a:set_action( v ) end if obj then obj:command( a, true ) end -- return a -- entity_action( a ) -- аналогично предыдущему return entity_action( a ) end - у меня пока все работает без проблем. Ну да всего 2-й день гоняю. Надо, конечно, присмотреться ко всем этим крысам и прочим тушканчикам. Чем отличаются вообще action() и action_first() ? В первой - obj:command( act, false ), во второй - true. Upd: тут дополняют, что вот это вот false/true - это очередь/немедленное исполнение. Что касается entity_action( act ) - лучше все же оставить просто по принципу "как бы чего не вышло". Ибо исходники воскурению весьма таки сопротивляются. И, да, переменную переименовать. Изменено 20 Ноября 2015 пользователем Dennis_Chikin Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
Полтергейст 37 Опубликовано 20 Ноября 2015 Поделиться Опубликовано 20 Ноября 2015 (изменено) Но в том и дело, что оригинал - не сохраняется. Его уборщик убирает. Теоретически. Тут бы надо кому-то в исходники глянуть. Я так понимаю, копия нужна для защиты оригинала от изменения. После вызова obj:command( act, false) действие добавляется в очередь. А вот какие странности будут, если попытаться изменить его после добавление в очередь local new_act = action_first(obj, что-то_там) new_act:set_action(что-то_ещё) - можно только догадываться. И кстати переменную act лучше переименовать, т.к. есть одноимённый экспортированный класс. Изменено 20 Ноября 2015 пользователем Полтергейст Ссылка на комментарий
Карлан 1 049 Опубликовано 20 Ноября 2015 Поделиться Опубликовано 20 Ноября 2015 неверно, в очередь добавляется если false 1 Ссылка на комментарий
Dennis_Chikin 3 658 Опубликовано 20 Ноября 2015 Автор Поделиться Опубликовано 20 Ноября 2015 На счет act и переименования - там, кстати, дальше будет функция совершенно феерическая. Просто я до нее не дошел еще. В общем, логично, про защиту от странного. Теоретически - не нужна, на практике - вот черт ее знает. Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
Dennis_Chikin 3 658 Опубликовано 23 Ноября 2015 Автор Поделиться Опубликовано 23 Ноября 2015 (изменено) Едем дальше. function debug_get_level_object( obj_name ) function debug_get_actor() По понятной причине - не работают. Если кому не понятно - в стандартном движке нет wait(). Можно оставить как есть, можно - удалить. Если вруг, в чем я сильно сомневаюсь, случится вылет - найти, и удалить там. function distance_between( obj1, obj2 ) function distance_between_safe( obj1, obj2 ) Собственно, все очевидно, кроме того, что это исключительно для game_object, и ни как иначе. Кроме того, непонятно, зачем делать функцию, которая дает повисание при отсутсвии объекта. Опять же, про однострочные функции уже говорилось - это не тот движок, и не тот язык, где можно позволять себе подобную роскошь. Читаемости вашему коду оно не добавляет. function has_alife_info( info_id ) -- Проверка на инфопоршны, даже если игрока не существует local sim = alife() if sim then return sim:has_info( 0, info_id ) end return false end- в общем, функция много где использующаяся, но смысл ее использовать - сомнителен. По тому что и alife() и actor в абсолютном большинстве случаев - есть, а там, где их нет - там и не нужно. Где нужно - там - actor_proxy более уместен, или более другой вариант, чем info. Да, я помню про smart_terrain и респавнеры, но я не уверен в пользе их работы в ходе загрузки. Там и так есть, чем заняться. То есть, нужна ревизия. Ну а дальше у нас будет несколько классов, весьма, я бы сказал, феерических, и опять же - с неработающим кодом. Изменено 23 Ноября 2015 пользователем Dennis_Chikin Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
RayTwitty 492 Опубликовано 23 Ноября 2015 Поделиться Опубликовано 23 Ноября 2015 (изменено) @Dennis_Chikin, function has_alife_info(info_id) local sim = alife() return info_id ~= "" and sim and sim:has_info(0, info_id) endХотя смысла лишний раз проверять наличие симулятора по большому счету и нет. Изменено 23 Ноября 2015 пользователем RayTwitty Ссылка на комментарий
_Призрак_ 11 Опубликовано 23 Ноября 2015 Поделиться Опубликовано 23 Ноября 2015 это не тот движок, и не тот язык, где можно позволять себе подобную роскошь А можно ссылку на бенчмарки, исследования по этому поводу? Freedom Ссылка на комментарий
Dennis_Chikin 3 658 Опубликовано 23 Ноября 2015 Автор Поделиться Опубликовано 23 Ноября 2015 info_id ~= "" - если подобное вызвали - у нас где-то проблемы. Проверка на sim ЗДЕСЬ - по тому что если вызвали, а alife() еще нет - мы об этом все равно ни как сообщить не сможем - и висяк будет весьма загадочный. "А можно ссылку на бенчмарки, исследования по этому поводу?" - функции в сталкере не инлайнятся. Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
RayTwitty 492 Опубликовано 23 Ноября 2015 Поделиться Опубликовано 23 Ноября 2015 (изменено) Проверка на sim ЗДЕСЬ - по тому что если вызвали, а alife() еще нетЭто когда такие случаи были? До загрузки игры? Не имею возможности сейчас посмотреть места вызовов конктруктора и деструктора симулятора, но скорее всего, он доступен даже когда актор в оффлайне. function has_alife_info(info_id) return info_id ~= "" and alife():has_info(0, info_id) end info_id ~= "" - если подобное вызвали - у нас где-то проблемыНеявно может быть и пустая строка. Такое вполне вероятно, по крайней мере намного вероятнее, чем вызов из главного меню до загрузки игры Изменено 23 Ноября 2015 пользователем RayTwitty Ссылка на комментарий
Карлан 1 049 Опубликовано 24 Ноября 2015 Поделиться Опубликовано 24 Ноября 2015 (изменено) проверка алайфа все же может и нужна. так как различные деятели порой во всякие меню пихают не только смену флагов (и висяк опять-же, но это личное кому-то в прикол там где надо по сто раз одно и тоже писать), а info_id ~= "" лишнее так как невозможно написать has_alife_info(""), ну никак в моей голове не укладывается что напишут в массиве (ну не руками же) такое работая с этой функцией, если и делать что-то такое, то проверку существования инфо в массиве по переданному аргументу и выводить явно в лог что не так, ну или аборт тут кому как нравится, или вообще поддержку и создание инфо только об этом надо сообщать, а то незадачливый модмейкер слишком сильно обрадуется. и опять-же эта затычка вообще никак не локализирует проблему, а только все усугубит.так или иначе у меня вообще вот так: function has_alife_info(info_id) return sim and sim:has_info(0, info_id) end function has_info(info_id) return actor and actor:has_info(info_id) or has_alife_info(info_id) end "Читаемости вашему коду оно не добавляет." вот посмотри, откопал какую-то старую версию торговли, вот там несколько функций построено таким образом, так как в противном случае код увеличивался невероятно: tbl_sell = flag and (IsTable(vv.traders) and vv.traders) or (is_friend and (IsTable(vv.sell_stalkers_friend) and vv.sell_stalkers_friend) or (IsTable(vv.sell_stalkers) and vv.sell_stalkers)) в целом я наверное и сейчас так бы сделал, иное трудно придумать, разве что ini_file , зато т.о. вся недвижковая торговля вышла в 350 строк. и читаемость как никрути выше чем у кучи if-then-elseif Изменено 24 Ноября 2015 пользователем Карлан Добавлено Kirgudu, 24 Ноября 2015 Прошу не забывать про существование заглавных букв. Ссылка на комментарий
Dennis_Chikin 3 658 Опубликовано 24 Ноября 2015 Автор Поделиться Опубликовано 24 Ноября 2015 (изменено) Ты не понял. function return_true( v ) if v == true then return true else return false endВ лучших традициях индусского кода.Теперь, где-то, в другом скрипте, вызываем if return_true( another_var ) == true thenЧто делает вызываемое ? Правильно, ищем, где оно, и смотрим.Нет, функция НЕ бессмысленна. По тому что где-то в xr_logic.чего-то() или еше в каких диалогах требуют строго true или строго false. То есть, сей индусский код имеет право быть.В принципе. Для вот этого вот, где таки требуют.Но не ВЕЗДЕ."function has_info(info_id)return actor and actor:has_info(info_id) or has_alife_info(info_id)end"Вот опять же плохо по той же причине: в 99% случаев у тебя есть актор, и 146% гарантии, что без него до сюда не дойдет. Вот и можно писать сразу actor:has_info(info_id), не через 10 скриптов и 20 проверок.Если не уверен - alife():has_info(0, info_id) сразу. Тоже наглядно, и жрет всяко меньше, чем + 2 вызова функции плюс пачка эзотерических проверок внутри каждой."по крайней мере намного вероятнее, чем вызов из главного меню до загрузки игры" - у меня куча скриптов, где отключен вывод в лог об успешном контроле целостности. По тому как smart_terrain и иже с ним хотят их не только до алайфа, но даже до консоли.Опять же, половина level.* кучу времени выдает nil. Изменено 24 Ноября 2015 пользователем Dennis_Chikin Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
RayTwitty 492 Опубликовано 24 Ноября 2015 Поделиться Опубликовано 24 Ноября 2015 (изменено) Так как непонятно, к кому обращается @Dennis_Chikin (неплохо было бы использовать цитирование), но вроде как ко мне, отвечу: По тому что где-то в xr_logic.чего-то() или еше в каких диалогах требуют строго true или строго false. info_id ~= "" and alife():has_info(0, info_id)по твоему это не булевое?)) Вот опять же плохо по той же причине: в 99% случаев у тебя есть актор, и 146% гарантии, что без него до сюда не дойдет. Вот и можно писать сразу actor:has_info(info_id), не через 10 скриптов и 20 проверок.Если как ты говоришь, актор почти всегда есть и ты его не проверяешь, то зачем нужна проверка алайфа? В каких случаях есть алайф, но нет актора?)) а info_id ~= "" лишнее так как невозможно написать has_alife_info("")Почему ты так уверен? А если строка генерируется не вручную, а каким-нибудь генератором? Мало ли какие сбои. Если в lua правильно сделано сравнение строк, то никаких внутренних затрат на сравнения не потребуется, функция почти сразу выйдет с результатом. Изменено 24 Ноября 2015 пользователем RayTwitty Ссылка на комментарий
Карлан 1 049 Опубликовано 24 Ноября 2015 Поделиться Опубликовано 24 Ноября 2015 "Почему ты так уверен?" о том тебе и говорю, что там где есть подозрение, там и проверяй, генератор строк я думаю у тебя в паре мест (н-р диалоги, квесты), когда эта проверка в сотне. какой-то реальный смысл в этой проверке не вижу так как функция все равно вернет false даже при "" и вообще чему попало непонятному, она именно булевая и другое она вернуть не может (если конечно ты не из любителей гонятся за наносекундами которые начнут говорить что str ~= "" быстрее итерации по массиву, но в таком случае эту проверку стоит переписать хотя бы на (type(str) == 'string' and str ~= ''), а в функции например выдачи инфо эта проверка вообще понесет вред. Ссылка на комментарий
Dennis_Chikin 3 658 Опубликовано 24 Ноября 2015 Автор Поделиться Опубликовано 24 Ноября 2015 (изменено) Так как непонятно, к кому обращается Dennis_Chikin Э-эээ... Распутываю. Текст, естественно, отвечает на предыдущий пост. Кроме того места, где цитата из более раннего. В основной части текста идет речь про то, для чего может быть нужна однострочная функция в глобальном пространстве, в которой к тому же еще и проверяется наличие alife(). То есть, представим момент загрузки какого-нибудь смарта или респавнера (а они грузятся НУ ОЧЕНЬ своеобразно), в котором зачем-то добавили xr_logic.pic_section_непомнючего, которая проверяет это самое инфо. Вот в этот момент действительно есть вероятность (и я такой код ВИДЕЛ), что все встанет колом, если нашу однострочную функцию "упростить". Но при этом мы и не можем адекватно обработать и случай с несуществующим инфо на входе, так что пущай падает/вылетает/рушится и т.д. ССЗБ тот, кто написал такой странный код. В остальных 99% случаев - да, есть и актор, и инфо, и вот эту однострочную проверку лучше выполнять "на месте", явным образом. Также есть места, где нам заведомо известно, что и alife() есть, и несуществующих инфо нет, и эти места выполняются точно и при отсутствии актора. Здесь, опять же, явным образом вписать alife():has_info(0, info_id) - то есть, конструкция сама за себя говорит и о том, что делает, и об условиях, в которых работает. Впрочем, это все на любителя, конечно. Кому и 100500 строк if ... end; if ... end (даже не elseif) милее. Здесь мы вроде бы ВСЕ возможные варианты и условия для них озвучили, вместе с подводными камнями, так что цель разбора вроде как достигнута. Посты с личными разборками, которые здесь были, ушли по назначению. Не зависимо от того, что в них было кроме разборок. Изменено 24 Ноября 2015 пользователем Dennis_Chikin Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
Полтергейст 37 Опубликовано 24 Ноября 2015 Поделиться Опубликовано 24 Ноября 2015 (изменено) Мой вариант (одна функция, работающая и в online, и в offline). function has_alife_info(info_id) if not (sim and info_id and info_id:len() > 0) then -- ругаемся в лог end if actor then -- online return actor:has_info(info_id) end -- offline return sim:has_info(0, info_id) end Для избавления от лишних проверок сделать немного по-другому - написать 2 разные функции для online и offline проверке, и в биндере игрока написать что-то такое _G.has_alife_info = has_info_online -- пишем в net_spawn _G.has_alife_info = has_info_offline -- в net_destroy Изменено 24 Ноября 2015 пользователем Полтергейст 1 Ссылка на комментарий
Dennis_Chikin 3 658 Опубликовано 2 Августа 2016 Автор Поделиться Опубликовано 2 Августа 2016 (изменено) Не помню, писал, или нет, но: local set_current_time_t, set_current_time_f function set_current_time_wait() if game.get_game_time() < set_current_time_t then return false end level.set_time_factor( set_current_time_f ) set_current_time_f = false return true end function set_current_time( hour, min, sec ) -- починено, работает. game_time_time = game.get_game_time() -- полное игровое время local new_time = game.CTime() -- нужно выставить new_time:setHMS( hour, min, sec ) local hh, mm, ss _, _, _, hh, mm, ss = game_time_time:get() -- текущее время local c_time = game.CTime() c_time:setHMS( hh, mm, ss ) if new_time == c_time then return -- ничего не делаем elseif new_time < c_time then -- следующие сутки new_time:setHMS( hour + 24, min, sec ) end new_time:setHMS( 0, 0, new_time:diffSec( c_time ) ) set_current_time_t = game_time_time + new_time if not set_current_time_f then set_current_time_f = level.get_time_factor() end level.set_time_factor( 10000 ) level.add_call( set_current_time_wait, dummy_action ) end По-моему, все очевидно. И вот именно через нее надо делать сон и прочее. Для вящей пущести можно в аргументы сам таймфактор добавить, и сильно большими значениями не увлекаться. P.S. Кстати, а вот при старте игры чтение таймфактора из конфига и принудительную установку - следовало бы добавить. На случай очумелых ручек в странных местах. Изменено 3 Августа 2016 пользователем Dennis_Chikin 1 Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
Карлан 1 049 Опубликовано 3 Августа 2016 Поделиться Опубликовано 3 Августа 2016 Моя практика говорит другое, я делал две реализации тайм-фактора, и выводы такие, что ляжешь спать часов на десять, а проснешься на рабочем столе (особенно если у тебя еще какие-нибудь "универсальные" схемы стоят). Виной всему менеджер логики. Так что лично я буду делать сон как в ЗП (технически, визуально он сделан абсолютно бездарно). Ссылка на комментарий
Рекомендуемые сообщения
Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий
Комментарии могут оставлять только зарегистрированные пользователи
Создать аккаунт
Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!
Зарегистрировать новый аккаунтВойти
Есть аккаунт? Войти.
Войти