Старлей 88 Опубликовано 22 Сентября 2013 Поделиться Опубликовано 22 Сентября 2013 (изменено) Если вылет при перезапуске сэйва (не выходя из игры) связан Он с этим не связан, я могу перезапустить сейв и играть себе спокойно дальше, хоть всю игру пройти, НО если я начну диалог после которого спавнится вертолет, то будет вылет. И параметр 'startup_animation' я изменил, как сказал Shoker, если раньше вылеты были практически всегда, то сейчас только так, как я описал выше. P.S. По этому поводу у меня только одна мысль, что дело в том что, как ты сказал из-за того что попадает "лишний" байт, завтра я попробую принудительно "очистить" пакет, как ты написал, думаю поможет Изменено 22 Сентября 2013 пользователем Старлей Ray Of Hope - кооператив сталкера OldStory Ссылка на комментарий
*Shoker* 322 Опубликовано 22 Сентября 2013 Поделиться Опубликовано 22 Сентября 2013 (изменено) @Старлей, я немного перепутал, motion_name можно вернуть как было, из за того что ты используешь какой то старый скрипт (видимо прямиком из ТЧ) и там параметр startup_animation назван как cse_alife_helicopter__unk1_sz поэтому я его и не увидел. Тебе советую сделать вот что:Попросить у Artos-а свежий скрипт для работы с нэт-пакетами (т.к его ссылка мертва): Либо взять тут прошлую версию, но я не гарантирую что там нету косяков. И спавнить вертолёт через него. Всё как раз таки похоже что твой скрипт нэт-пакета криво спавнит вертёшку, видимо иногда игра это переваривает, а иногда нет. Как минимум советую тебе оставить для теста лишь один вертолёт, и вообще использовать две функции обе которые спавнят вертолёт и с нуля пишут ему нэт пакет это извращенство %)Нужно функцию спавна вертолёта сделать одну общую, а потом просто вызвать её два раза передав нужные параметры вертолётов. Изменено 22 Сентября 2013 пользователем *Shoker* Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О Мастер аномалий на свою заднюю точку. Ссылка на комментарий
Artos 99 Опубликовано 22 Сентября 2013 Поделиться Опубликовано 22 Сентября 2013 (изменено) [spoiler=Актуальная версия модуля "Интерфейс чтения/записи net-пакетов" (m_netpk)] Название: Модуль "Интерфейс чтения/записи net-пакетов" (m_netpk) Автор(ы): Artos (по материалам: bardak, Red75, Sokol_jack, KD87 (uACDC), xStream (xs_netpk)) Версия/Дата: - (20.09.2013) Платформа: Универсальный (ТЧ/ЧН/ЗП), начиная с ТЧ 1.0004 Сложность подключения: Простая Модуль (скрипт) реализует в игре интерфейс чтения и изменения параметров игровых объектов посредством net_packet'ов. Интерфейс чтения/записи net-пакетов (SHoC:6/7(118),CS:8(124),SCoP:12(128)) m_netpk.script ============================================================================================== "Правильная" работа с нет-пакетами. (© xStream) ------------------------------------------------ Интерфейс работы с классами нет-пакетов: 0) Что это вообще такое и с чем едят? 0.1) 'Нет-пакет' (net_packet) - это специальный объект (бинарный буфер), который содежит информацию, которой серверные объекты в игре обмениваются со своими клиентскими копиями, изменяя соответствующие параметры/свойства друг-друга. Позиция в пространстве, поворот, текущий режим стрельбы у оружия и т.п. Просто так эта информация не доступна стандартныи средствами из скриптов. 0.2) Нет-пакет для каждого объекта в игре имеет две части/типа, независимых друг от друга: 'state' и 'update'. Возможна работа с каждым типом по отдельности или с обоими вместе. Все, что представлено в этом модуле (скрипте) - специальные классы, которые позволяют организовать ПРОСТОЙ доступ к этим данным и, в случае надобности, их изменять. Итак... 1) Сначала необходимо создать объект необходимого класса, передав серверный или клиентский объект: В случае интеграции модуля в глобальную таблицу скриптов (модуль инициализирован): а) local pk = get_netpk(obj,flag) -- по классу переданного объекта будет автоматически подобран нужный класс нет-пакета. При прямых обращених к модулю и/или классу пакета: б) local pk = m_netpk.get(obj,flag) -- аналогично а). в) local pk = m_netpk.net_XXXXXX(obj,flag) -- указываем КОНКРЕТНЫЙ класс требуемого пакета, как подобрать, см. ниже Использование дополнительного аргумента (flag) при вызове модуля позволяет использовать один из трех вариантов получения типов пакетов для любого объекта игры или получить доступ к управлению специальным пакетом: а) flag: nil (опущен) - 'полный' пакет, т.е. оба типа пакетов 'state' и 'update' в едином объекте (нет-пакете); б) flag: 1 - пакет типа 'state'; в) flag: 2 - пакет типа 'update'. г) flag: 0 - пакет для управления свойствами 'abstract' (об этом ниже); Учитывая, что в большинстве модификаций игры используется в основном работа со свойствами из 'state' пакетов, гонять в холостую коды обработки получения изменения и записи полного пакета (с 'update' частью) - расточительно. 1.1) Чтобы узнать, все ли прошло хорошо, можно вызвать pk:isOk(), он вернет true, если класс пакета успешно создан. false - в случае неудачи. 1.2) Все прочитанные/записываемые свойства (параметры) пакета расположены в таблице data (см. п.2). Если класс пакета содержит тип 'update' - все свойства этого пакета расположены в суб-таблице data.upd. 1.3) Имеется возможность: Даже если пакет не создался правильно, можно это проигнорировать, так как функция возвращает специальный пакет net_dummy, с ним можно производить те же операции, что и с остальными, только просто он ничего не делает. Зачем он нужен? Он полезен при условных обработках пакетов. Пример: local pk = m_netpk.net_se_monster(obj,2) if not pk:isOk() then pk = m_netpk.net_se_stalker(obj,2) end local data = pk:get() data.upd.health = health -- свойство в 'update' пакете pk:set(data) Здесь НЕ проверяется, правильный ли пакет получился, когда и НЕ монстр и НЕ сталкер. Потому что в результате получаем net_dummy и работаем как с обычным пакетом. Меньше кода и проверок. Но злоупотреблять этим свойством не рекомендуется. Используйте лучше isOk() в критичных на ошибки местах. (Код, приведенный в примере, станет понятен ниже) 2) Чтение данных из пакета: local data = pk:get() -- в результате получаем таблицу, содержащую ВСЕ свойства объекта (в зависимости от запрошенных типов!) -- напоминание: все свойства пакета 'update' расположены в суб-таблице data.upd 3) Меняем нужные нам свойства: data.xxx = yyy -- простое присваивание значения нужному элементу таблицы 3.1) Для некоторых сложных свойств (custom_data, shapes, ...) имеются встроенные классы со своим интерфейсом доступа/изменения. local tbl = data.custom_data:getTable() -- получения массива из строки кастом-даты local status = data.custom_data:setTable(tbl) -- запись таблицы в строку кастом-даты с возможностью контроля выполнения 3.2) Если мы не знаем, какие свойства есть у объекта, то используем функцию: local description = pk:dumpDesc() -- возвращает строку, содержащую читабельное описание пакета (его можно, например, вывести в лог) 4) После изменения, данные записываем в собственно нет-пакет объекта: pk:set(data) 5) А все Работа сделана. Дополнительный профит: такие "пакеты" - это объекты, их можно передавать в разные функции, хранить в таблицах и т.д. Они "помнят", с каким игровым объектом они связаны. 6) Существует специальный пакет 'abstract', о котором читаем ниже. http://yadi.sk/d/Am1xc1tN9dBpZ P.S. Рабочий пример спавна вертолета при помощи модуля m_netpk: function Create_Vehicle(section, pos, idLv, idGv, custom_data) local class_id = system_ini():line_exist(section,"class") and system_ini():r_clsid(section,"class") if class_id and class_id == clsid.script_heli and m_netpk then local sobj = alife():create(section, pos, idLv, idGv) local pk = m_netpk:get(sobj,1) --/ запрос пакета if pk:isOk() then --/ если получен доступ к пакету local data = pk:get() --/ считываем параметры в таблицу --/> заполняем параметры if custom_data and type(custom_data) == 'string' then data.custom_data:setString(custom_data) end --data.object_flags = bit_and(data.object_flags,bit_not(5)) --/#x# сброс флагов: UseSwitches(1) + SwitchOffline(4) (выполняется в m_netpk) --data.skeleton_name = "idle" --/#x# (выполняется в m_netpk) --data.startup_animation = "idle" --/#x# (выполняется в m_netpk) data.engine_sound = "alexmx\\helicopter" --/ опционально pk:set(data) --/< запись return sobj --/> end end return nil --/> end Изменено 22 Сентября 2013 пользователем Artos 1 "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
Карлан 1 049 Опубликовано 22 Сентября 2013 Поделиться Опубликовано 22 Сентября 2013 (изменено) ув. @Artos, использую Ваши таймеры сейчас, и ловлю небольшую проблему, а именно - действие происходит очень быстро, мне нужно что-бы действие воспроизводилось циклично пока не выполнятся мои условия, и в начало функции ставлю: if start_real_timer(3) then Условия выполняются явно быстрее, чем 3 секунды. Судя по мануалу я возможно не правильно делаю, возможно нужно вот так: start_real_timer(3):set_name("my_timer_name") if not timer_exists("my_timer_name") then Изменено 22 Сентября 2013 пользователем Карлан Ссылка на комментарий
Artos 99 Опубликовано 22 Сентября 2013 Поделиться Опубликовано 22 Сентября 2013 (изменено) @Карлан, по пртведенной строке и пояснениям невозможно понять сути и причины...Сама строка: if start_real_timer(3) then - неверна и непонятна! Для запуска таймера требуется в качестве аргументов указать:- время (в секундах);- функцию, которая будет вызвана таймером по окончании времени, указанную 1-м аргументом;- параметры для функции, которая указана во 2-ом аргументе.Примечание: 2-ой аргумент может быть nil, т.е. seyrwbz не указывается, но в этом случае должны быть указаны параметры для внутреннего обработчика (читаем readme к модулю).Т.о. ты просто не запустил таймер, т.к. указал время и НИЧЕГО для того, чтобы таймер хоть как-то сообщил о событии 'окончания времени'. Вот пример запуска таймера реального времени на 8 секунд, после чего будет вызвана функция OnTimer_Test: ... start_real_timer(8,OnTimer_Test,{id=21249}) --/ запуск таймера ~8sec [time(sec),func,params] ... function OnTimer_Test(t) log("OnTimer_Test: %s", tostring(t.id)) --/#~# end Если требуется проверить запустился ли таймер (и заодно время), то делать это можно так: ... local timer = start_game_timer(3*60, nil, {info_id = "my_infoportion"}) --/ через 3 game-minutes выдать инфопоршень if timer then --/ запущен ли таймер? (получент ли объект таймера) local time_rest = timer:get_time_rest() --/ оставшееся время ... Название: Модуль "Универсальные таймеры" (m_timers)Автор(ы): Artos & Gr1ph00nВерсия/Дата: - (21.09.2013)Платформа: Универсальный (ТЧ/ЧН/ЗП), начиная с ТЧ 1.0004Сложность подключения: Простая Модуль (скрипт) реализует в игре удобный интерфейс для работы с таймерами различного назначения (реального и игрового времени).Для работы требуется подключить скрипты "Расширения Lua", "Общие функции" (см. выше).Для хранения в сэйвах игры табличных данных запущенных таймеров может использоваться модуль "Универсальное хранилище" (см. выше),в противном случае данные сохраняются в pstor актора (что может вызвать переполнение при интенсивном использовании таймеров).Примеры использования имеются в самом скрипте модуля и в описании (внутри архива). Менеджер универсальных таймеров (SHoC:6/7(118),CS:8(124),SCoP:12(128))m_timers.script==============================================================================================Модуль (скрипт) реализует в игре удобный интерфейс для работы с таймерами различного назначения (реального и игрового времени).Для работы требуются скрипты "Расширения Lua"(lua_extension) и "Общие полезные функции" (lua_helper).Для хранения в сэйвах игры табличных данных запущенных таймеров может использоваться модуль "Универсальное хранилище" (se_stor),в противном случае данные сохраняются в pstor актора (что может вызвать переполнение при интенсивном использовании таймеров). --/---------------------------------------------------------------------Подключение:1. Скопировать в папку скриптов игры скрипт: m_timers.script;2. Добавить в биндер актора (см. bind_stalker.script) вызовы событий "сохранение игры", "загрузки сохранения" и запуска обновлений модуля;3. Добавить в _g.script инициализацию дополнительного функционала (lua_extension и lua_helper).4. (настоятельно рекомендуется) Подключить модуль "Универсальное хранилище" (se_stor). Примечание:В комплекте файл '_g_ADD.script является строками, которые требуется добавить в исходный _g.script.Файл bind_stalker.script от оригинальной версии игры SHoC v.1.0006 дан в качестве рабочего примера.В файл bind_stalker.script добавляются строки (в три разных метода биндера) отмеченные знаком --/#+# и имеющие подстроки 'm_timers.' Использование:1. Запрос существования (запущенного) таймера (по имени): timer_exists("my_timer_name") --/ boolean2. Получение объекта таймера (по имени): get_timer("my_timer_name") --/ object from class 'RealTimer|GameTimer'3. Получение текущего значения таймера: get_timer("my_timer_name"):get_time_rest()4. Удаление запущенного таймера: get_timer("my_timer_name"):remove()5. Таймер на игровом экране (HUD-Timer) допускается в единственном экземпляре: get_hud_timer() --/ object 'HUD-Timer' from class 'RealTimer'6. quick-таймеры не имеют имен и недоступны извне.7. Имена таймерам выдаются автоматически и эксклюзивны.При необходимости имя может быть задано при запуске таймера (см.ниже). http://yadi.sk/d/C9O1qHTx9dBq2 Изменено 22 Сентября 2013 пользователем Artos 1 "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
Карлан 1 049 Опубликовано 22 Сентября 2013 Поделиться Опубликовано 22 Сентября 2013 (изменено) @Artos, а как им воспользоватся при таком запросе: Если прошло 3 секунды то выполняем функцию завершить Я понимаю, что при таком запросе ему надо выписать экшн вторым аргументом, но мне в данном случае не подходит, т.к. функции срабатывают по свои флагам, и их удобнее загнать именно под вышеприведенное условие... Если никак не получится, то тогда уже перепишу код под твои таймеры, это тоже не сложно, просто хотел узнать Еще вопрос, таймер по умолчанию цикличен? Т.е. мне для своих нужд делать как-то так? start_multi_timer(2*60, "my_file.my_func") --/ я так понял, что цикличны только мульти-таймеры И что-то я не совсем понял, после выполнения всех моих условий таймер отключится, или так и будет крутится вечно? А, по моему до меня дошло...сейчас проверю и отпишусь, чето туплю под вечер start_real_timer(2, "my_file.my_func") Мне нужно чтобы моя функция выполнялась каждые две секунды, взвожу такой таймер. Ничего почему-то не происходит. Тестировал свои функции на обычном time_global(), все как часы. Походу неправильно все таки как-то я их, таймеры, применяю... Можно конечно все на нем и оставить(time_global())... но не хочется. Изменено 22 Сентября 2013 пользователем Карлан Ссылка на комментарий
Artos 99 Опубликовано 22 Сентября 2013 Поделиться Опубликовано 22 Сентября 2013 (изменено) @Карлан, 1. Твое "если прошло 3 секунды то -> выполняем функцию -> завершить" полностью эквивалентно собственно запуску таймера: "запуск таймера с выполнением через 3 секунды функции". Т.е. когда пройдут 3 секунды с момента запуска таймера будет вызвана указанная функция и таймер завершит свою работу. Что тебе не подходит - непонятно, унифицировать для таймеров подстройку под всевозможные "пользовательские" наборы аргументов для каждой функции по сути невозможно (нереально). Если твои функции требуют указания неких своих аргументов со своим порядком следования, то не сложно написать функцию отрабатываемую таймеров, в которой вызывается твоя с необходимым набором аргументов. 2. Таймеры по определению НЕ цикличны. Только класс MultiTimer (само название подсказывает) цикличен. На то и назван модуль "универсальные таймерЫ", что под почти любую задачу можно выбрать и подстроить нужный таймер. Реализовать все это на одном классе - не разумно, вместо выбора таймера тебе все одно пришлось бы задавать кучу параметров, подстраивая под свои нужды. Практика показывает, что проще выбрать из набора, чем помнить и путаться в параметрах запуска единственного... Если ты его запустишь как указал, то твой таймер будет "крутиться вечно" (пока не выйдешь из игры), срабатывая каждые 2 реальные минуты (по дефолту время реальное, но можно указать и игровое). Изменено 22 Сентября 2013 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
Карлан 1 049 Опубликовано 22 Сентября 2013 Поделиться Опубликовано 22 Сентября 2013 (изменено) Если твои функции требуют указания неких своих аргументов со своим порядком следования, то не сложно написать функцию отрабатываемую таймеров, в которой вызывается твоя с необходимым набором аргументов. Именно так и сделал, даже вот код: function my_update() --/ update start_real_timer(2, "my_file.my_func1") start_real_timer(2, "my_file.my_func2") start_multi_timer(2, "my_file.my_func3", nil, true) end И ни одна из моих функций не выполняется, причем(еще раз укажу) с time_global() у меня все работает(все условия моих функций выполняются). Изменено 22 Сентября 2013 пользователем Карлан Ссылка на комментарий
Artos 99 Опубликовано 22 Сентября 2013 Поделиться Опубликовано 22 Сентября 2013 (изменено) @Карлан, что-то ты действительно "тупишь под вечер"... Мне нужно чтобы моя функция выполнялась каждые две секунды, взвожу такой таймер. Ничего почему-то не происходит. Говоришь о цикличности, а запускаешь: start_real_timer(2, "my_file.my_func") - одноразовый таймер реального времени. И чего ты ждешь?! Включи режим отладки в модуле (local __DEBUG__ = true), позаботившись о рабочем выводе в лог и посмотри - у тебя вообще модуль работает(?), таймеры вообще запускаются ли? Не стОит засорять топик... И не нужно поминать про time_global() - это всего лишь функция возвращающая время и она тоже испльзуется и в универсальных таймерах (если потребно). Если твои таймеры (по твоим алгоритмам/кодам) работают и устраивают тебя - то и используй их. Изменено 22 Сентября 2013 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
*Shoker* 322 Опубликовано 22 Сентября 2013 Поделиться Опубликовано 22 Сентября 2013 (изменено) @Карлан, В твоём коде на каждом апдейте игрока (если я правильно понял название функции) либо стартует сразу 3 таймера (тоесть несколько раз в секунду ты создаёшь по 3 таймера) либо каждый из этих таймеров перезапускается (таймерами не пользовался так что хз как они работают точно) т.к ты их постоянно вызываешь. Ты не понял суть таймера, ты вызываешь его один раз local bStarted = false function my_update() --/ update if not bStarted then start_multi_timer(2, "my_file.my_func3", nil, true) bStarted = true end end И дальше таймер уже сам будет вызывать функцию my_file.my_func3 каждые 2 секунды\минуты или что там. Это мульти-таймер. Если ты используешь обычный таймер, то он вызовет функцию один раз а потом остановится, что впрочем не мешает тебе в функции, которую он вызывает, вставить запуск этого же таймера снова, и получишь такой же цикличный вариант. UPD: Поправил код. Изменено 22 Сентября 2013 пользователем *Shoker* Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О Мастер аномалий на свою заднюю точку. Ссылка на комментарий
Карлан 1 049 Опубликовано 22 Сентября 2013 Поделиться Опубликовано 22 Сентября 2013 (изменено) @*Shoker*, разумеется, я это все понимаю Твой флаг бесполезен, т.к. таймеру дается каждый раз новое имя. @Artos, таймеры у меня работают(тестовый из bind_stalker по крайней мере), так что проблема явно не в модуле, и явно не в моих функциях. Пока я считаю, что проблема в моих руках, т.к. они модуль не так как-то используют... Ладно, пойду поковыряюсь, больше не буду засорять топик. Upd: Да, да, сейчас дошло. Только все равно у меня мои функции не работают, чорт с ним, что-нибудь другое напишу. Изменено 22 Сентября 2013 пользователем Карлан Ссылка на комментарий
Artos 99 Опубликовано 22 Сентября 2013 Поделиться Опубликовано 22 Сентября 2013 (изменено) @*Shoker*, можно даже проще, если задать таймеру свое эксклюзивное имя, или получить с уже запущенного и контролировать его: function my_update() --/ update if not timer_exists("MY_TIMER") then start_multi_timer(2, "my_file.my_func3", nil, true):set_name("MY_TIMER") end end @Карлан, ты действительно "тупишь" (без обид, плз). В варианте Shoker'а используется флаг запуска таймера (bStarted), и если какой-либо таймер из апдейта был запущен (с любым именем) - то уже не будет других запусков. Но(!) это в течении игры, но после перезапуска игры - будет запущен новый таймер... Изменено 22 Сентября 2013 пользователем Artos 1 "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
Карлан 1 049 Опубликовано 22 Сентября 2013 Поделиться Опубликовано 22 Сентября 2013 (изменено) Так, стоп, давайте по порядку. А то я запутался, если я и сейчас тупану, то хоть баньте(и посты потрите, если нужно). 1 Я установил таймеры и все работает нормально: --/ Пример запуска таймера: start_real_timer(15, nil, {tip = {self.object, "Text test_RT"}}, "RT_test") --/ 15 real-seconds + set name --/< это отрабатывается. 2 Я создал свой скрипт my_file. Написал туда следующее: function t1() news_manager.send_tip(db.actor, text, 0, "Hello", 10000) end local bStarted = false function update() --/ update if not bStarted then start_multi_timer(1, "my_file.t1", nil, true) bStarted = true end end 3 В update биндера актора написал следующее: ... function actor_binder:update(delta) object_binder.update(self, delta) my_file.update() -- DEBUG slowdown ... И у меня нихрена не работает. По идее, как я понял, должен вылетать типс с текстом "Hello" каждую секунду, но у меня ничего не происходит. Изменено 22 Сентября 2013 пользователем Карлан Ссылка на комментарий
Artos 99 Опубликовано 22 Сентября 2013 Поделиться Опубликовано 22 Сентября 2013 (изменено) Обновил модуль "Универсальные таймеры": - добавлена возможность получения имени таймера и др. - обновлено описание (добавлены описания доступных методов) --/ для объекта таймера доступны: timer:id() --/ чтение(получение) идентификатора запущенного таймера (не путать с игровыми идентификаторами объектов!) timer:name() --/ чтение(получение) имени запущенного таймера timer:set_name(timer_name) --/ установка/изменение имени таймера timer:restart(time_sec, action, properties, timer_name) --/ перезапуск работающего таймера (аргументы аналогичгы запуску) timer:get_time_rest() --/ получение оставшегося времени работающего таймера (real mseconds or game seconds) timer:get_time_end() --/ получение времени (число mseconds), когда таймер сработает timer:get_time_end(true) --/ получение времени (строка), когда таймер сработает timer:get_property(property) --/ чтение значения параметра заданного таймеру timer:set_property(property,value) --/ установка/замена параметра заданного таймеру timer:remove() --/ удаление таймера (ссылка прежняя, указана тут) @Карлан, поставь перед (и после) строки запуска таймера вывод информации в лог или на экран и смотри - у тебя вообще делается ли попытка запуска таймера... И вообще вызывается ли твоя функция из апдейта актора? (как понимаю, с логами ты не дружишь ) Изменено 22 Сентября 2013 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
Shredder 49 Опубликовано 23 Сентября 2013 Поделиться Опубликовано 23 Сентября 2013 Я универсальные таймеры пока не использовал, но вот вопрос, почему не передавать сразу функцию: start_multi_timer(1, my_file.t1, nil, true) Ссылка на комментарий
Malandrinus 615 Опубликовано 23 Сентября 2013 Поделиться Опубликовано 23 Сентября 2013 почему не передавать сразу функцию:Встречный вопрос. Как таймер узнает после загрузки игры, какую функцию ему передали до этого? Плагины Total Commander для работы с игровыми архивами: Архиваторный плагин (для работы с одиночным архивом): link1 link2 Системный плагин (для распаковки установленной игры): link1 link2 Ссылка на комментарий
Artos 99 Опубликовано 23 Сентября 2013 Поделиться Опубликовано 23 Сентября 2013 (изменено) почему не передавать сразу функцию: Пояснение: (пока не отраженное в описании) В игре модмейкеры могут использовать таймеры которые должны восстанавливаться после сэйв-лоад, т.е. запоминаться в сэйвах. Но могут и наоборот, запускать таймеры, которые этого не требуют или не должны запоминаться. Для последнего случая предназначены QUICK-таймеры, которые никогда не запоминаются. Все остальные таймеры (real/game/multi/hud) обязательно запоминаются при условии(!) что заданная таймеру функция задана строкою (string)! В противном случае, таймер не будет сохранен. Собственно сохранить в сэйве функцию заданную прямым линком на нее (или даже телом/кодом) - уж очень проблематично, можно сказать - невозможно (но, если покопаться в коде, то и это с издержками, но можно реализовать...). Т.о. при запуске любого (кроме quick) таймера можно непосредственно типом данных линка на задаваемую функцию устанавливать свойство таймера: должен он запоминаться в сэйвах или нет. Примечание: Если функция вообще не задана (nil), но заданы параметры для внутреннего обработчика таймеров (выдача инфопоршня/типса/...) - такой таймер обязательно будет сохранен в сэйве. Чтобы такой таймер не запоминался - используем quick-timer. Так что ответ на вопрос: "Задавай как тебе хочется, исходя из потребностей, но учитывая возможности..." (универсальность в действии ) Изменено 23 Сентября 2013 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
Старлей 88 Опубликовано 28 Сентября 2013 Поделиться Опубликовано 28 Сентября 2013 Подскажите пожалуйста, еще вот в чем: требуется от ГГ передать НПС 2 артефакта. Для этого я использую функции ColR_iT(в посте под спойлером), однако от ГГ передается НПС только 1 артефакт, сделал не большую эхо-печать в лог, для проверки счетчика - все правильно, вот только вылазиет одна строчка странная: ! Cannot find saved game ~:psi:__i_=_1,_count_=_2 * Log file has been saved successfully! ! Cannot find saved game ~:psi:__i_=_2,_count_=_2 * Log file has been saved successfully! ! ERROR: SV: can't find children [39427] of parent [270253968] ! Cannot find saved game ~:psi:__i_=_1,_count_=_2 * Log file has been saved successfully! ! Cannot find saved game ~:psi:__i_=_2,_count_=_2 * Log file has been saved successfully! ! ERROR: SV: can't find children [39425] of parent [270253968] Я нашел в этой же теме, год назад такой вопрос задавал *Shoker*, только он пытался переместить предмет с земли нпс, и у предмета не было родителя и т.д., поэтому как сказали и вылазили эти ошибки. Но у меня 2 вопроса: 1. Почему перемещается только 1 предмет. 2. Почему вылазиют сообщения, ведь изначально родитель артефакта ГГ, потом НПС? P.S. Или поделитесь своими функциями Ray Of Hope - кооператив сталкера OldStory Ссылка на комментарий
Shredder 49 Опубликовано 28 Сентября 2013 Поделиться Опубликовано 28 Сентября 2013 (изменено) Я могу ошибаться, но возможно в цикле who:object(section) возвращает один и тот же предмет. Т.е. только на следующем апдейте после who:transfer_item метод who:object(section) вернёт другой предмет. Т.е. по сути, в цикле будет попытка передать один и от же предмет count раз, из-за этого и запись в лог. Это предположение. Да, это действительно так. Для правильного функционирования нужно итерировать инвентарь на предмет одинаковых предметов и их передавать. Доберусь до домашнего ПК, посмотрю осталось ли доделанная функция... ну или доделаю. ColR_iT Изменено 28 Сентября 2013 пользователем ColR_iT Ссылка на комментарий
Artos 99 Опубликовано 28 Сентября 2013 Поделиться Опубликовано 28 Сентября 2013 (изменено) @Shredder, ты прав, именно в данном случае, когда цикл НЕ привязан к итерации по инвентарю, who:object(section) может возвращать один и тот же предмет, т.к. who:transfer_item(...) ассинхронна и предмет исчезнет из инвентаря 'who' только на следующем апдейте. Т.о. подобные операции с передачей/удалением инвентарных нескольких предметов нужно обязательно делать в цикле итерации по инвентарю, в котором перебираются предметы, и их секция уже проверяются для конкретного предмета, а не "из кучи". Как вариант, можно использовать и не iterate_inventory, а получать кол-во объектов в инвентаре: local count = npc:object_count() и сразу перебирать предметы используя (но это опять же итерация): for i = 0, count - 1 do local item = npc:object(i) ... Есть, правда, один "хитрый" способ, который вероятно задумывался разработчиками GSC, для обхода подобных ситуаций, для чего были добавлены методы: npc:mark_item_dropped(item) --/ отметка предмета с которым совершается действие (удаление/передача) npc:marked_dropped(item) --/ проверка наличия метки о совершенном действии над предметом (уже удаляется/передается) но... уж очень капризный этот способ (что сами отказались (см. death_manager.script), но все же пользоваться можно, где, например, подобное разнесено по разным скриптам. @Старлей, строка в логе "! ERROR: SV: can't find children [ХХХХХ] of parent [ХХХХХХ]" - вполне может говорить о том, что предмету уже дана команда трансфера и движок удалил информацию о владельце... Повторное обращения к нему (предмет все еще в инвентаре у 'who') приводит к подобной информации об ошибке (без вылета!). Если есть желание покопаться и поэкспериментировать то можешь поискать подходящее (например, Relocate_Items) в этой "полезняшке" из моего набора: Название: Скрипт "Общие функции" (m_helper) Автор: Artos (сборка с использованием материалов STALKER-community) Версия/Дата: - (27.09.2013) Платформа: Универсальный (ТЧ/ЧН/ЗП), начиная с ТЧ 1.004 Сложность подключения: Простая Скрипт, добавляет в игру различные часто употребляемые и/или полезные функции, которые могут использоваться модмейкерами. Модуль(скрипт) различных автономных 'общих' функций (SHoC:6/7(118),CS:8(124),SCoP:12(128)) lua_helper.script ============================================================================================== Скрипт, добавляет в игру различные часто употребляемые и/или полезные функции которые могут использоваться модмейкерами. --/--------------------------------------------------------------------- Подключение: 1. Скопировать в папку скриптов игры скрипт: lua_helper.script; 2. Добавить в конец _g.script строку инициализации: prefetch("lua_helper") --/#+# подключение модуля 'общих' хелп-функций --/--------------------------------------------------------------------- Список функций добавляемых в глобальное пространство _G: --/----------------------------------------------------- HasVar - проверка наличия переменной в хранилище 'storehouse' DelVar - удаление переменной из хранилища 'storehouse' SetVar - запись/изменение переменной в хранилище 'storehouse' GetVar - чтение переменной из хранилище 'storehouse' has_info - проверка наличия инфопоршня у актора has_info_portions - проверка наличия инфопоршней у актора has_any_info_portions - проверка наличия какого-либо из инфопоршней у актора check_info_portions - проверка наличия/отсутствия инфопоршней у актора give_info - установка инфопоршня для актора give_info_portions - установка инфопоршней для актора disable_info - удаление инфопоршня у актора disable_info_portions - удаление инфопоршней у актора Get_CheckedFunc - GetVarA - проверка наличия переменной в pstor'e актора GetVarA_Table SetVarA DelVarA GetVarObj - проверка наличия переменной в pstor'e объекта GetVarObj_Table SetVarObj DelVarObj GetSizeVar - размер переменной в pstor'ах или в хранилище (в байтах) Get_MobClass Dlg_AddPhrase Get_Actor_NPC Get_Actor Get_NPC ReadFromIni Get_AmmoList Get_GrenadeList Get_IniSection Get_IniSections Get_Cfg_String Get_Cfg_Bool Get_Cfg_Number Get_Cfg_Num32 Get_Cfg_2Prm Get_InvName Get_InvShortName Get_WeightSection Get_CostSection Get_ClassSection Get_CharName Get_Community get_object_community IsSobjOb Release_Obj, Spawn_Obj Spawn_NPC create_ammo SendTip Send_ReceivedInfo SpellingBeginning SpellingTermination Spelling Has_Item Has_Items Has_AnyItems SwitchToOffLine SwitchToOnLine Clear_Inventory Spawn_AmmoInInv Spawn_ItemInInv Spawn_ItemsInInv Give_Money Lost_Money Relocate_Money Relocate_Items Relocate_AnyItems Reload_Item Take_Item Lost_Items Add_MapSpot Del_MapSpot Get_MapIdObj Get_MapNameObj VecToStr Parse_Names Parse_StrToTbl Parse_CustomData Fill_CustomData Dir2TabRad Dir2TabDeg Deg2Rad Rad2Deg AngleDiffRad AngleDiffDeg Get_StrTime Get_StrTimeOrDate set_seconds2ctime Get_RestSeconds Set_RestSeconds Add_RestSeconds Get_PastSeconds Get_PastMinutes Get_PastHours ms2string sec2string ... и др. http://yadi.sk/d/30CiySp_9dBpB Изменено 28 Сентября 2013 пользователем Artos 3 "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
Рекомендуемые сообщения
Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий
Комментарии могут оставлять только зарегистрированные пользователи
Создать аккаунт
Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!
Зарегистрировать новый аккаунтВойти
Есть аккаунт? Войти.
Войти