Контент Malandrinus - Страница 57 - AMK Team
Перейти к контенту

Malandrinus

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

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

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

  • Дней в топе

    13
  • AMKoin

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

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

  1. Hagard, Ray, не понимаю, если честно, этой возни. С хедшота из почти любого приличного ствола можно почти наверняка уложить кого угодно. Монстры - это отдельный разговор, но люди в этой игре - враги вообще никакие.
  2. Garry_Galler, а держишь его горизонтально? Там в центре есть индикатор, если наклонить компас больше определённого, то его "заклинивает"
  3. Не это случайно?
  4. Malandrinus

    Моделирование в Maya

    Комрады, мне нужна консультация по скелетам. Пытаюсь понять вот какую вещь. Когда ковыряешь физику объектов в игре скриптами, то видно, что костей много, а физических элементов и соединений существенно меньше. Хочу понять, где и как задаётся соответствие костей скелета и физических элементов/соединений. Есть ли что-то на эту тему в 3D редакторе?
  5. Давно думаю. Надпись под курсором, та что с дальностью до цели - это вполне возможно статик, как и многие другие элементы худа. Если так, то зная его идентификатор можно получить его текст и таким образом использовать встроенный дальномер. Ни у кого нет информации на эту тему?
  6. Нет возможности повесить обработчик "на нажатие". Все обработчики работают по некоторым игровым событиям, которые к нажатию на конкретную кнопку относятся только косвенно. Что касается ПНВ, то я сам не знаю, как именно это отловить. Функции с vision как правило относятся к управлению зрением неписей. Вообще для управления актором функций довольно мало. В принципе это понять можно, актор же управляется непосредственно игроком, а не скриптами. Кроме того, прослеживается принцип минимализма. Разработчики экспортировали только то, что нужно было им.
  7. Starter, по изменению fov ловишь момент прицеливания и дальше рисуешь на худе нужные бантики. касательно предыдущего обсуждения насчёт утилиты перехвата нажатий. Нашел здесь. Там же исходники. Ray, что ты имеешь в виду под "базовыми скриптами"?
  8. Monnoroch, нет, там принцип такой, что ловились нажатия клавиш в системе вообще и писались в некий *.ltx . А оттуда по апдейту актора ловились в скриптах. Вот только не могу у себя найти эту утилитку. Давно было.
  9. n6260, такая утилита для перехвата нажатий есть и очень давно. Сделана неким заграничным камрадом. Найти у себя не смог =(
  10. Vano_Santuri, По-моему никак это ни на что не повлияет. Дели или объединяй скрипты как тебе удобно. На мой взгляд, реально вызвать переполнение стека только если зациклить рекурсивный вызов. Типа такого: function fun() fun() -- сама себя вызывает до бесконечности end fun() -- здесь получишь вылет с сообщением "stack overflow" Для вылета в данном случае потребовалось 16 тыс. итераций. Я думаю, можно попытаться вызвать переполнение стека, если распаковать длинную таблицу и сунуть её как список аргументов. Но это всё нетривиальные случаи, как правило такой ситуации быть не должно.
  11. в acdc есть целая секция на предмет координат создаваемых артов. Точки из этой секции вообще где-то используются?
  12. Проще всего попробовать. Если же хочется разобраться в сути, то надо взять acdc для ЗП и посмотреть там формат нетпакета и сравнить его с форматом для ЧН. =) Стек вообще означает "стопка чего-либо". Классическая иллюстрация этого понятия - это устройство в барной стойке, куда складывают мытые тарелки. В этом случае стопка подпружинена снизу и ограничена сверху, чтобы верхняя тарелка всегда была строго в одной позиции. Смысл стека в любом его понимании - это хранилище объектов, из которых всегда доступен только последний, помещённый туда: "последний зашёл - первый вышел", "Last In - First Out", LIFO. В компьютерах, в силу фундаментальности такого принципа организации данных, стеки используются повсеместно и часто поддерживаются на уровне команд процессора. В частности, на стеке основан механизм вызова функций: адрес возврата перед вызовом пишется в стек, это позволяет после завершения работы функции вернуться в точку вызова. В стек же пишутся и аргументы функции (не всегда). У Lua свой стек, не связанный со стеком процессора (точнее потоков). Написание этого слова через "Э" или через "Е" в целом достаточно произвольно и зависит от доминирующей нормы произношения =) Москвичи больше "э"кают, питерцы чаше предпочитают более мягкие варианты с "е". Впрочем, это уже могли и законодательно устаканить. Под стек заранее выделяется память. Он заполняется в одном направлении. Когда выделенная область заканчивается - это переполнение стека. Они же без логов. Как узнаешь, могут или нет =) Вылет без лога может быть при переполнении стека процессора, но это - довольно редкая ситуация в работающем и отлаженном приложении. Переполнение стека Lua - вылет может быть запросто, но обычно в этой ситуации есть лог. Причина вылетов может быть разная. Движок игры исходно не рассчитывался на все те безобразия, что вытворяют с ним модостроители. Может и нельзя 100 аномалий спавнить, может нельзя делать это слишком часто, а возможно, где-то в скрипте просто баг. Для начала, стоит попробовать поэкспериментировать. А если не 100, а 50 аномалий? Тоже вылет?
  13. Malandrinus

    [SoC] Вопросы по SDK

    Writer, скриптом можно составить полный список вертексов. Как-то так: local gg = game_graph() local i = 0 while gg:valid_vertex_id(i) do local lvl = gg:vertex(i):level_id() -- здесь имеем номер вертекса i и номер его уровня lvl i = i + 1 end Ну а дальше дело техники. Здесь делается предположение, что валидные вертексы идут непрерывным списком и заканчиваются первым невалидным вертексом. Так ли всегда - точно не знаю, но скорее всего так. Как альтернативный вариант, можно разобрать game.graph и составить список вертексов заранее. Вроде как для этого даже есть готовый утиль.
  14. Другое название этой сетки - сетка навигации. Ещё название - AI-сетка, что по сути одно и тоже, поскольку весь AI так или иначе связан с перемещениями. Проще всего понять, на что похожа сетка уровня (граф навигации уровня), если эту сетку как-то визуализировать. Есть для этого тулза, созданная IG-2007. Но я попробую словами... В общем главное, что надо понять - это что неписи в онлайне перемещаются на самом деле не по тем поверхностям, что вы видите глазами, а по узлам сетки уровня. И перемещаться могут только там, где эта сетка есть. Т.е. фактически, сетка уровня - это не столько сетка, сколько попросту альтернативная невидимая поверхность, совмещённая с видимой. Наличие такой сетки радикально упрощает навигацию, делая её вообще говоря реализуемой. Узлы этой сетки - это такие маленькие прямоугольные площадки, размером как правило 0.7 игровых метра. Если смотреть в плане, то все эти площадки строго упорядочены, как клетки шахматной доски. По высоте (т.е. по оси Y) они отличаются, чтобы воспроизводить ландшафт. В том числе в одном месте по горизонтали (т.е. в плоскости XZ) могут находиться две и более таких площадок, но с разной высотой. Ну понятно в общем - это для этажей зданий и прочего в этом роде. В некоторых местах сетки нет. Во-первых, вся сетка вообще ограничена определённым параллелепипедом в пространстве. Это связано со способом её хранения, вне этого пространства сетки попросту не может быть. Некоторых узлов нет, и сетка образует дырки, соответствующие стенам, кустам, препятствиям вообще. Эти дырки в частности используются движком игры, чтобы искать для неписей укрытия. Видели функцию level.cover_in_direction? Нетрудно представить логику её работы: найти вертекс, закрытый дыркой в определённом направлении. Если в дырке на самом деле стоит куст или дерево, то это как бы укрытие. Впрочем, до конца этот вопрос я не исследовал и думаю, что на самом деле "дырки укрытия" как-то специально промаркированы. Узлов уровня много, можете прикинуть сами, но и так ясно, что на одном уровне таких вертексов может быть порядка миллиона. Глобальный или оффлайновый граф, как ясно из его названия, нужен для навигации в оффлайне. Он уже больше похож на граф. На уровень таких узлов может быть что-то около пары сотен. Навигация в оффлайне в том числе допускает и перемещение между уровнями. Непись, которому сказали идти на узел глобального графа, находящийся на другом уровне, сначала строит свой путь по локальной сетке уровня до подходящего геймвертекса, дойдя до него - переходит в оффлайн и дальше уже перемещается по глобальному графу на нужный уровень. Насчёт необходимости указывать эти значения при спавне. В принципе, геймвертекс - единственная привязка к уровню, поскольку координаты указываются локальные. Без геймвертекса будет неясно, на каком уровне создан объект. Левел вертекс однозначно нужен для неписей, иначе может возникнуть ситуация, что непись стоит невесть где и не знает, как дойти, куда ему там надо. Хотя в ряде случаев я согласен, указание левелвертекса выглядит избыточным. Например, для физических объектов, которые по сетке не ходят, а определяются физикой. Но зачем-то это движку надо. Я подозреваю, что в ряде случаев допустимы отклонения от точности указания этих параметров.
  15. Да есть он там! Кто сказал что нет? Даже в lua_help остался. Можно создать машину, хотя и не получается на ней поездить.
  16. Monnoroch, ну хорошо, не в большинстве случаев, а иногда (предыдущий пост поправил). Вроде бы nil в с точки зрения Lua должен быть не значением, а его отсутствием. Поэтому вызов функции fun(nil) вроде как эквивалентен вызову fun(), но так ли происходит всегда, я не знаю. Но такие случаи я точно встречал. К примеру вызов level.object_by_id(nil), как и без аргумента возвращает объект с нулевым идентификатором, т.е. актора. А вызов alife():object(nil) приводит к вылету. А вызов db.actor:object(nil), который вроде как должен вернуть объект по индексу, возвращает вместо этого число 0. В итоге, ситуация еще хуже, поскольку реакция функций игры на вызов без аргумента (или с nil) попросту непредсказуемая. Так что мой предыдущий спич полностью остаётся в силе =)
  17. Garry_Galler, избыточный код. Зачем так сложно? У тебя по коду на входе функции и так подразумевается серверный объект. Зачем по нему получать серверный ещё раз? Ничего другого не получишь, уж точно =) Этого достаточно: function get_parent_id(obj) if obj then return sobj.parent_id end end И потом, с точки зрения безопасности и надёжности проверка if obj then ... на самом деле ничего не даёт. Ну проверил, что объекта на самом деле нет, а дальше что? Функция в этом случае возвращает nil. Хуже всего, что этот nil в последствие приводит к непредсказуемым результатам (и не обязательно сразу к вылету). И в итоге ты получаешь отложенную ошибку, которая естественно приведёт к сбою, но совсем не там, где надо, не там где можно понять её источник. На самом деле эту проверку надо делать до вызова этой функции. Именно то место, где вызывается подобная функция - это место, где можно принять решение, что делать с этой ошибкой. Так что без всяких функций: if obj then --делать что-то с obj.parent_id else --обрабатывать ошибку end В современных языках программирования эти вопросы решаются с использованием механизма исключений: ошибка выявляется в одном месте, а механизм исключений переправляет её обработку в вышестоящий уровень, где имеются полномочия для принятия решения. В Lua исключений в явном виде нет (хотя некое подобие в виде pcall есть), так что придётся по старинке, самому выявлять нужное место обработки ошибки.
  18. dimos, Это «Отбойник» - автоматический дробовик из ЗП. Секция wpn_protecta в файле configs\weapons\w_protecta.ltx. Я думаю, что не получится сделать оружие, стреляющее двумя типами патронов. При выстреле из подствольника спавнится граната, обрабатывается её физика и т.д. Это не превратить в выстрел из дробовика. Ну по крайней мере я не знаю, как это сделать. W_GLAUNC - это вообще никак не поможет, поскольку это объект подствольника, а все аддоны - это просто инвентарные предметы. Они не стреляют, стреляют стволы. При надевании аддона сам объект аддона исчезает, а у ствола просто устанавливается соответствующий флажок.
  19. Это вопрос к моему ответу про ящики? Если так, то не знаю, что добавить. Мой ответ и так конкретней некуда. Или о чём другом речь? Чтобы определить, что предмет в ящике? А чем по parent_id не устраивает? Вообще, нетпакеты - это последний аргумент. По возможности лучше избегать. Какое самодостаточное наблюдение =)
  20. Real Wolf, parent_id предмета совпадает с id ящика.
  21. Разбираем систему клиентских классов. Сначала немного лирики. Довольно лирики. Далее представлена система клиентских классов. Используются те-же соглашения, что и раньше: конструктор не показан, если класс не добавляет своих методов, то показан одной строкой. Иерархия клиентских классов Сперва базовые интерфейсы. Их не так много, как у серверных. Все остальные классы имеют своим предком CGameObject Классы, производные от CGameObject Рисовать картинку с иерархией наследования смысла нет, поскольку и так всё довольно очевидно. За исключением малого числа классов остальные к CGameObject ничего не добавляют. Соответственно и описывать нечего. Названия классов более или менее говорят о том, для каких объектов они предназначены. Где мог, указал точные сигнатуры функций (CCar, CHelicopter и hanging_lamp). Для новых классов и методов по сравнению с ТЧ такой информации к сожалению нет.Несколько рассуждений на тему взаимодействия серверного и клиентского объектов. Попробуем рассуждать логически. Есть сервер, есть клиент. Это в общем случае разные компьютеры. Каким может быть взаимодействие объектов, находящихся по разную сторону сети? Могут ли они, к примеру, вызывать методы друг друга, или непосредственно читать данные своего "напарника"? Очевидно нет. Моё мнение такое, что их взаимодействие сводится в основном к посылке данных друг другу. При этом, данные посылаются "пачкой", т.е. обо всём состоянии сразу. То, что я наблюдал, выглядит так: при переходе в онлайн создаётся клиентский объект, серверный его инициализирует, посылая ему при создании нетпакет. Этот момент можно отловить в биндере клиентского класса. Все дальнейшие движения происходят от клиентского объекта к серверному. Это означает, что периодически клиентский затирает данные серверного. Точные моменты, когда это происходит, периодичность, а также механизм передачи данных мне лично понять пока не удалось. По крайней мере на серверной стороне ничего не видно, просто тихо меняются данные, и понять, когда это происходит, крайне непросто.Однако некоторые выводы таки можно сделать. Если взаимодействие классов примерно такое, как я здесь предположил, то совместимость классов определяется совместимостью бинарных данных, которые они друг другу посылают. Ну в общем классы должны друг другу соответствовать, хотя, как далее будет видно, это правило на практике (очень редко) нарушается. Если не забыли ещё, то зарегистрированные пары классов задаются идентификаторами класса. В файлах конфигурации (в секциях объектов) этим идентификаторам соответствует параметр class. В скриптах - это один из членов clsid. В движке уже зарегистрированы соответствующие пары классов, и вы можете добавлять свои пары с помощью класса object_factory. Я это всё описывал здесь.Далее я привожу таблицу соответствия классов. Для полноты картины в ней указаны классы, которые не экспортированы в Lua. Если класс не экспортирован, то это означает, что вам не удастся зарегистрировать на его основе свою пару классов. Однако это не мешает (теоретически) создавать объекты этого класса при условии, что имеется и известен его идентификатор.Приведённая таблица собрана из разных источников, в том числе основана на примерах регистрации классов из игры. Видно, что иногда клиентский класс использует в качестве "напарника" серверный, который является базовым для своего "родного" серверного. Видимо, это технически в норме вещей и так можно поступать и нам. Из этого ряда выбивается CZombie, для которого вроде бы родным должен быть серверный класс cse_alife_monster_zombie, а регистрируют его с cse_alife_monster_base. Это вроде как нарушает вышеописанную логику, поскольку cse_alife_monster_base не является базовым для cse_alife_monster_zombie. С другой стороны, он так зарегистрирован в самом движке. Возможно cse_alife_monster_zombie попросту не задействован и никакого отношения к CZombie на самом деле не имеет. Таблица соответствия серверных и клиентских классов
  22. 7.9, всё верно, только не 40 млн., а 4 мрд., точнее максимальное 32-х разрядное беззнаковое целое: 4294967295 что в миллисекундах составляет примерно 1193 часа, т.е. 49 дней. Это известная проблема: после примерно месяца игрового времени часть функций, связанных с использованием этого счётчика, начинают работать неправильно. Вроде как это даже лечили. Хотя если этот счётчик используется не только скриптами, но и движком, то всё не вылечить.
  23. Полагаю, красивая картинка никому не помешает. Вот вам диаграмма серверных классов с высоты птичьего полёта =) Обращаю внимание на нотацию записи: большая пустая стрелка означает отношение обобщения (или наследования иными словами) и направлена от унаследованного класса к базовому. Включение абстрактного интерфейса обозначается стрелкой с кружочком и указанием, какой интерфейс наследуется. Это сокращённая форма записи, позволяющая избавиться от нагромождения линий и лучше понять основную линию наследования.
  24. Введение Итак. Все игровые сущности (сталкеры, монстры, предметы и пр.) в общем случае существуют одновременно на двух сторонах - на сервере и на клиенте. На каждой стороне для этого есть соответствующие классы. На серверной - это классы, имя которых начинается на "cse". С некоторыми поправками можно считать, что все серверные классы происходят от cse_abstract. На клиентской стороне есть соответствующая иерархия классов. Можно считать, что все они происходят от CGameObject. На клиентской стороне есть ещё и game_object, который также является интерфейсом к клиентским объектам, причём основным интерфейсом. Его описание уже начато, но оно далеко от завершения. Классы как серверные, так и клиентские образуют иерархию наследования классов. На самом примитивном уровне можно считать, что наследование означает включение всех членов базового класса (т.е. свойств и методов) в производный класс. В свою очередь это означает, что нет необходимости описывать унаследованные члены для всех производных классов, достаточно это сделать один раз для базового. Кроме того я ввожу важное соглашение для описания классов: я не буду приводить полный список членов класса для каждого из них, а только список методов и свойств, которые добавляет конкретный класс сверх унаследованных. Поэтому, если по описанию в классе нет ничего, то смотрите на классы от которых он унаследован и смотрите список их методов и список методов их базовых классов и т.д. Я вынужден так сделать во-первых в силу ограничения форума, во вторых для убирания избыточности при описании. Я также буду пользоваться спойлерами: после описания класса будет идти спойлер с его производными классами, в них спойлеры с их производными и т.д. (наподобие матрёшки =) Начнём с серверных. Можно обратить внимание, что имеется некоторое количество базовых классов и интерфейсов, которые вообще не содержат никаких методов или свойств. Наследование от них не даёт конкретной информации о свойствах серверного класса, но парадоксальным образом может дать некоторые догадки о применимости методов game_object. Вот список этих базовых интерфейсов: Базовые интерфейсы Несколько предваряющих комментариев к дальнейшему материалу. Вся иерархия серверных классов
  25. Garry_Galler, зря ты длинные пути используешь для установки. Чревато необъяснимыми глюками. Не факт, что в этой ситуации как-то сказалось, но вообще лучше ставить в папку попроще. Диск значения не имеет, а путь лучше дать без выкрутасов типа такого "d:\games\shoc\"
×
×
  • Создать...