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

Artos

Жители
  • Число публикаций

    1 635
  • Регистрация

  • Последнее посещение

  • Дней в топе

    7
  • AMKoin

    24 [Подарить AMKoin]

Весь контент пользователя Artos

  1. Чтобы КПК получил имя владельца, в его (КПК) параметр 'original_owner' должен быть прописан игровой идентификатор (id) владельца, а в 'specific_character' - профиль владельца (это вторично). Тогда имя КПК будет персональным и соответствовать имени сталкера с этим идентификатором. Собственно этот параметр заполняется автоматом, когда сталкер спавнится в игру и следом ему его именной КПК. Но, можно и заменить или добавить (если отсутствует) сам КПК (обычный!) и перезаписью net-пакетом установить требуемые значения. Примечание: Секция для именных КПК должна быть ТОЛЬКО штатной, т.е. [device_pda], все остальное - по вкусу...
  2. @Хемуль36рус, судя по приведенной информации, твой ствол должен заспавниться, т.к. основные параметры для спавна указаны корректно. Кроме 'upd:condition = 1', все остальные 'upd:xxx = x' - излишни (указывать не обязательно), т.к. являются дефолтными и их движок при спавне просто проигнорирует. Если твой uACDC не ругнулся ошибками при компиляции all.spawn'а, то остается предположить (т.к. не указано: чистая игра иль с модами!), что у тебя или может работать какой-то чистильщик объектов локаций или работать схема собирательства, и кто-то успел подобрать ствол... Кстати, не помню даже для чистой игры - нет ли там поблизости неписей? Если есть, то даже оригинальная движковая схема подбора предметов может сработать, т.к. в отличии от оригинального винтореза, который не все подбирают (зависит от ранга), на твой mp5 позариться любой новичок... Если кто подобрал, то можно проверять, а вообще заспавнен ли ствол, получив его серверный объект: alife():object("mil_wpn_mp5") и выведя в лог иль на экран соотв. инфу. Совет: обнови версию uACDC, чтобы "мусор" не беспокоил.
  3. @ins33, нет штатных инфопоршней, сообщающих о "актор за рулем", но есть функция для объекта машин: obj:get_car():engaged() - которой можно это проверять. Загляни в топик "Справочник по функциям и классам" или посмотри примеры использования в модах с машинами (например, в OGSE).
  4. , залог успеха любого мода или куска из него - в правильном и полном составлении алгоритма (что-когда-почему-делать). Смею предположить, что все можно сделать гораздо проще, хотя для этого нужно знать логику схем... Но зато у тебя не будет ситуаций, когда иль непись не удаляется иль испаряется на глазах у игрока. Твой НПС наверняка под своей логикой, а значит, вполне ему в эту логику можно добавить ситуацию с диалогом, после которой он не удаляется сразу (иль по таймеру, т.к. актор/игрок может это время и глазеть на него), а удалится по условию, например, "актор отошел на некоторое расстояние и не видит его" ... (все это есть в оригинальной игре). Т.о. и результат будет получен и игрок не будет тебя пугать за "чудеса с испарениями" в игре.
  5. Artos

    Скриптование

    @Старлей, мною дан все же скрипт из набора (т.е. ориентирован на работу в комплекте), который еще только подготавливаю к публикации, но из которого уже можно использовать большинство наработок (немного подумав и порою кое-где подстроив под-себя). Кастрировать функции не рекомендовал бы, т.к. функции данного скрипта позиционируются как "общие", т.е. для самых различных ситуаций и решения разных задач. Получив в локальной ситуации желаемый результат, усеченная функция будет "врать/ошибаться" в каких-то других. Тебе проще взять отдельную функцию и, увидев непонятную переменную 'idActor' посмотреть в этом же скрипте что она означает и заменить на db.actor:id(), тем самым и получив результат и сохранив весь функционал. А вообще, обновил этот скрипт (архив), пополнив описание и добавив ему автономности.
  6. Artos

    Скриптование

    @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) в этой "полезняшке" из моего набора:
  7. Все, спасибо за помощь, общими усилиями сделали, все работает как нужно! Спасибо всем кто откликнулся. Если проблема была именно из-за диалога, то все же стОит уточнить для тех, кто порой нарывается на "нерабочесть" вроде как рабочих функций. Особенность вызова функций (action) из диалогов в том, что движок игры обращается к глобальной метатаблице '_G' и, если там нет необходимых функций, может ничего не делать, а может и выдать ошибку. Т.о. если вы добавляете свои файлы (и функции из них) и используете в диалогах - требуется позаботиться, чтобы ваш файл/функция заранее (до диалога) попали в глобальную метатаблицу. Это можно сделать или простым обращением к файлу/функции (if my_file then ...) или prefetch("my_file"). В общем читаем мануалы по Lua.
  8. @_Val_, 1-ая функция, указанная 'ом, полностью рабочая. Если alife() был бы недоступен, то это не неработало бы, а давало бы вылет. Ну а удалять (получать объект для удаления) в ТЧ можно и по имени (а не секции!), и по игровому идентификатору (id) и по стори-ид'у (story_id)... нужно просто не гадать и не тупо копипастить, а понимать то, что пишешь в коде. Ну и читать(!) почаще топики: "Справочник по функциям и классам" и "Скриптование", а не ждать подсказки по банальным вопросам, поминавшимся и разъясненным тысячи раз в сотнях ФАКов...
  9. @AndrewMor, не нужно путать: ты не видишь в игре новых неписей, которые должен заспавнить тобою создаваемый респавнер, с тем, что он их вообще не спавнит. Один и тот же результат может иметь разные причины. Главным условием, чтобы ты в игре увидел своих заспавненных неписей является или независимость твоих неписей от гулагов ("smart_terrains = none") или наличие доступной для них работы в каком-либо гулаге. В противном случае, они просто после спавна будут сразу же удалены из игры. Понять, спавнит ли респавнер или нет, или спавнит, но объекты сразу же удаляются, можно только по логам, для чего требуется, например, в файле se_respawn.script в методе se_respawn:create(prob) реанимировать строки вывода в лог, начинающиеся с "printf("SPAWNING"... Нужно еще иметь ввиду, что респавнерам находящимся на текущей локации в оригинале игры запрещено спавнить, т.е. актор должен уйти на др.локацию. Так что, если ты создап респавнер на Кордоне и ждешь, не уходя с локации, когда кто-нибудь из него появится - бессмысленно. Примечание: Статья хорошая и правильная, но в комментах ("Обязательные условия респавна") пункты 1 и 3 излишни. Уточнения: п.1. Наличие "хоть одного гулага" на локации, где создается респавнер, не обязательно. Респавнер будет пытаться (периодически или одноразово) спавнить объект(ы) в соответствии с заданными ему параметрами. Однако, главным условием появления в игре заспавненного объекта является наличие свободной работы в каком-либо гулаге и не важно на какой локации, или его независимость от гулагов (о чем написано выше). Иной вопрос, дойдет ли непись до другой локации, если нет связей, но это уже вопрос к game.graph. п.3. Если какой-либо уровень запрещен для нахождения на нем объекта с неподходящим рангом, это не запрещает респавнеру спавнить объекты, которые будут уходить с неразрешенных для них локаций.
  10. Artos

    Скриптование

    Пояснение: (пока не отраженное в описании) В игре модмейкеры могут использовать таймеры которые должны восстанавливаться после сэйв-лоад, т.е. запоминаться в сэйвах. Но могут и наоборот, запускать таймеры, которые этого не требуют или не должны запоминаться. Для последнего случая предназначены QUICK-таймеры, которые никогда не запоминаются. Все остальные таймеры (real/game/multi/hud) обязательно запоминаются при условии(!) что заданная таймеру функция задана строкою (string)! В противном случае, таймер не будет сохранен. Собственно сохранить в сэйве функцию заданную прямым линком на нее (или даже телом/кодом) - уж очень проблематично, можно сказать - невозможно (но, если покопаться в коде, то и это с издержками, но можно реализовать...). Т.о. при запуске любого (кроме quick) таймера можно непосредственно типом данных линка на задаваемую функцию устанавливать свойство таймера: должен он запоминаться в сэйвах или нет. Примечание: Если функция вообще не задана (nil), но заданы параметры для внутреннего обработчика таймеров (выдача инфопоршня/типса/...) - такой таймер обязательно будет сохранен в сэйве. Чтобы такой таймер не запоминался - используем quick-timer. Так что ответ на вопрос: "Задавай как тебе хочется, исходя из потребностей, но учитывая возможности..." (универсальность в действии )
  11. Artos

    Скриптование

    Обновил модуль "Универсальные таймеры": - добавлена возможность получения имени таймера и др. - обновлено описание (добавлены описания доступных методов)
  12. Artos

    Скриптование

    @*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), и если какой-либо таймер из апдейта был запущен (с любым именем) - то уже не будет других запусков. Но(!) это в течении игры, но после перезапуска игры - будет запущен новый таймер...
  13. Artos

    Скриптование

    @Карлан, что-то ты действительно "тупишь под вечер"... Говоришь о цикличности, а запускаешь: start_real_timer(2, "my_file.my_func") - одноразовый таймер реального времени. И чего ты ждешь?! Включи режим отладки в модуле (local __DEBUG__ = true), позаботившись о рабочем выводе в лог и посмотри - у тебя вообще модуль работает(?), таймеры вообще запускаются ли? Не стОит засорять топик... И не нужно поминать про time_global() - это всего лишь функция возвращающая время и она тоже испльзуется и в универсальных таймерах (если потребно). Если твои таймеры (по твоим алгоритмам/кодам) работают и устраивают тебя - то и используй их.
  14. Artos

    Скриптование

    @Карлан, 1. Твое "если прошло 3 секунды то -> выполняем функцию -> завершить" полностью эквивалентно собственно запуску таймера: "запуск таймера с выполнением через 3 секунды функции". Т.е. когда пройдут 3 секунды с момента запуска таймера будет вызвана указанная функция и таймер завершит свою работу. Что тебе не подходит - непонятно, унифицировать для таймеров подстройку под всевозможные "пользовательские" наборы аргументов для каждой функции по сути невозможно (нереально). Если твои функции требуют указания неких своих аргументов со своим порядком следования, то не сложно написать функцию отрабатываемую таймеров, в которой вызывается твоя с необходимым набором аргументов. 2. Таймеры по определению НЕ цикличны. Только класс MultiTimer (само название подсказывает) цикличен. На то и назван модуль "универсальные таймерЫ", что под почти любую задачу можно выбрать и подстроить нужный таймер. Реализовать все это на одном классе - не разумно, вместо выбора таймера тебе все одно пришлось бы задавать кучу параметров, подстраивая под свои нужды. Практика показывает, что проще выбрать из набора, чем помнить и путаться в параметрах запуска единственного... Если ты его запустишь как указал, то твой таймер будет "крутиться вечно" (пока не выйдешь из игры), срабатывая каждые 2 реальные минуты (по дефолту время реальное, но можно указать и игровое).
  15. Artos

    Скриптование

    @Карлан, по пртведенной строке и пояснениям невозможно понять сути и причины... Сама строка: 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() --/ оставшееся время ...
  16. Artos

    Скриптование

    [spoiler=Актуальная версия модуля "Интерфейс чтения/записи net-пакетов" (m_netpk)] Название: Модуль "Интерфейс чтения/записи net-пакетов" (m_netpk) Автор(ы): Artos (по материалам: bardak, Red75, Sokol_jack, KD87 (uACDC), xStream (xs_netpk)) Версия/Дата: - (20.09.2013) Платформа: Универсальный (ТЧ/ЧН/ЗП), начиная с ТЧ 1.0004 Сложность подключения: Простая Модуль (скрипт) реализует в игре интерфейс чтения и изменения параметров игровых объектов посредством net_packet'ов.
  17. Artos

    Скриптование

    @Старлей, это уже начинаются погадалки... Если вылет при перезапуске сэйва (не выходя из игры) связан с: MODEL: can't find cycle - то тебе ясно расписано что требуется изменить параметр 'startup_animation' (помимо других) в момент спавна вертушки. Если вылет иной, то и приводи строки лога, в которых пишется о причине ошибки, дабы не гадать на кофейной гуще. Вполне вероятно, что у тебя проблемы с деревом диалога(ов), которое сохраняется со "старой" игры (НЕ пересоздается заново), т.к. треды диалогов обновляются/пересоздаются только при выходе из игры в ОС и загрузке сэйва. Проверяй прекондишены и пр. для твоих диалогов...
  18. Artos

    Скриптование

    @Старлей, конечно можно пробовать и кое-как заставить работать то, о чем пишешь, но вероятность будет отлична от 100%, т.к. в работе с net_packet'ами в ЧН и ЗП есть нюанс и его требуется учитывать: При получении чистого пакета: local packet = net_packet() - из-за особенностей движка в ЧН и ЗН позиция записи может быть установлена не на начало и последующая запись в такой "чистый" пакет может происходить НЕ с начала. Далее, после записи своих данных, ты устанавливаешь позицию чтения в начало: packet:r_seek(0) - т.о. при записи параметров в объект могут попасть "лишние" байты, присутствовавшие в пакете, исказив все параметры... Чтобы этого не происходило, требуется при получении "чистого" пакета принудительно выставлять позицию записи полученного нового нет-пакета в начало (т.е. принудительно "очищать" его). local packet = net_packet() --/ получение "чистого" пакета packet:w_begin(0) --/ установка: начальная позиция записи данных (+2) obj:STATE_Write(packet) ... packet:r_seek(2) --/ установка: читать 'с начальной позиции записанных данных' (+2) - тут из-за отсутствия метода w_seek(number) используется метод w_begin(0), который устанавливает позицию записи в начало и прописывает 2 байта, которые при чтении следует пропустить: r_seek(2). (обо всем этом не раз уже писалось, хотя и давно...) Примечание: Актуальная версия m_netpk автоматически все это делает и заодно автоматом изменяет и критически важные дефолтные параметры (motion_name, startup_animation) и устанавливает флаги, остается, если требуется, добавить/изменить 'engine_sound'. P.S. @Старлей, твой вылет (MODEL: can't find cycle) связан с параметром 'startup_animation', который аналогично 'motion_name' нужно устанавливать в 'idle'. Ну а вылет при загрузке сэйва - вполне может быть связан и с другими причинами, например, в логике включаешь звук вертушке, а сам не потрудился его ей прописать...
  19. Artos

    Полезные скрипты

    Официально прошу куратора данного топика (или модератора раздела), разместившего в своем посте материалы за моим авторством и не получившего разрешение на это, а точнее даже получившего запрет - УДАЛИТЬ описания, файл-архивы и линки на них. Данные материалы (за исключением по модулю нет-пакетов) мною так и не были опубликованы и считаю неприемлемым для себя их публикацию в данном топике, тем более с отсылками типа: "Спрашивать у автора." (модератор раздела получил в ЛС просьбу с аналогичным содержанием)
  20. Artos

    Zones Editor

    Спасибо за пояснения. Собственно замену get_go_float уже попытался реализовать, но именно предположения о возможных искажениях при сдвигах объекта дали повод сомнениям. Вот как выглядит заглушка:
  21. @Капрал Хикс, решение проблемы: забыть про метод game.time() и все что имеется на нем - перевести на game.get_game_time().
  22. Судя по алгоритмам выдачи и контроля заданий, факт выдачи хранится у актора. Как минимум индекс (иль иная метка) выданного таска движок где-то у него запоминает ( db.actor:give_task(obj_task, ms, false) ). Вот еще бы проверить назначение 3-го аргумента (boolean) - не позволит ли он анулировать... Сами объекты тасков и их составляющие (SGameTaskObjective) как минимум должны сохраняться в сэйвах, а значит от этих клиентских объектов сервер получает некие нет-пакеты при записи сэйва и восстанавливает при загрузке игры. Если получить доступ к этим передачам - то может и можно будет подменять на некое подобие заглушек иль даже удалять... Но, конечно же, это все умозаключения и, если будет время и настроение, попробую копнуть в эту сторону.
  23. Artos

    Zones Editor

    @Malandrinus, правки движка (помимо колбэков на клавиши) необходимы для добавления двух функций, обеспечивающих получение данных объекта: obj.get_go_float и matrix().mul_43. Если бы ты дал немного больше информации о том, что можно было бы сделать скриптами (т.е. что требуется от доп.функций) то можно реализовать это уже доступными способами. obj.get_go_float - мною уже почти реализовано при помощи нет-пакетов, неясны остались индексы 1,4,5,6 (из 0...15). Можешь, уточнить что они должны означать в контексте векторов позиции и направления? И уточни, плз, что должен делать метод matrix().mul_43 по сравнению с уже имеющимся mul. Тогда можно сделать не привязанный к движку вариант zone-информера (даже под CS/CoP), позволяющего в игре наблюдать размеры/положения различных зон-объектов, что при тестах/отладках игры порою сильно помогает (особенно когда не известны параметры заспавненных зон/аномалий, а справляться в all.spawn'e иль SDK - потеря времени).
  24. @Malandrinus, то, что нет доступного скриптового метода сброса задания - согласен, но... (мысли вслух) объект(ы) таска (SGameTaskObjective/SGameTask) в общем-то доступны в игре и сохраняются в сэйвы и можно попытаться помудрить с нет-пакетами иль даже с подменой на "чистый" таск. Но это конечно только предполагалка... и проверка возможности изменения требует и времени и навыков. ;-)
  25. Artos

    Скриптование

    @boryan67, суть внешнего (точнее универсального) хранилища - сохранять все, что помещено в db.storehouse и восстанавливать при загрузках игры. Соответственно если помещать в эту таблицу свои "простые" таблички и/или другие "простые" данные - то никаких проблем не возникнет. В последней версии сохранять можно гораздо больше типов данных (помимо строк, чисел, таблиц, ... можно сохранять вектора, таймеры, ...) и если получится вырезать из общего мода - к вечеру/ночи дам полный вариант". "Отрегулированность и надежность" данного метода (хранения) проверена уже годами на SIMBION'e и месяцами в LA (в несколько измененном виде). Однако замечу, что и надежность и оптимальность зависят от степени интегрированности кодов в весь скриптовой набор игры. В вышеуказанных модах все данные из пакета актора вынесены именно во внешнее хранилище, что исключило любые ошибки с переполнениями или невалидными данными. Т.о. если говорить о " зависимости успешности трудов многих людей за несколько лет" - то посоветую взглянуть все же на полный вариант использования хранилища. Если будет время - то дам два варианта: а) только хранилище с минимальными правками исходных кодов игры SoC и б) хранилище с рекомендованными расширениями. Второй вариант все же потребует работы головы и рук... ;-)
×
×
  • Создать...