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

Malandrinus

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

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

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

  • Дней в топе

    13
  • AMKoin

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

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

  1. В данной теме собраны сведения по скриптовой модели сталкера: функции и классы, методы и свойства, взаимосвязь классов и последовательность работы с ними, связь работы классов и файлов конфигураций. К наполнению темы приглашаются все желающие. В наполнении темы непосредственно участвовали и существенно мне помогли: @Monnoroch, @Kolmogor, @Unnamed Black Wolf, @меченый(стрелок), @IQDDD, @Kirag, @Taroz, @dan, @7.9, @Garry_Galler, @AKKK1, @Bak и много других людей. Представление материала в моих статьях оптимизировано для онлайнового просмотра. Если кому не хочется лазить по спойлерам, а нужно просмотреть текст какого-либо поста "потоком", то могу рекомендовать просмотр в режиме "текстовая версия". В этом же режиме удобно сохранять содержимое темы на диск. (прим. Malandrinus)
  2. wallmark_section - хитмарк, текстура отметины от взрыва force_explode_time - по логике вещей должно быть время принудительного взрыва. Это если не от удара, а улетела ракета в молоко. А вполне возможно, что это просто время, через которое ракета удаляется. up_throw_factor - что-то отвечающее за подкидывание вверх от взрыва.
  3. Как минимум, ошибка здесь. В скобках должен стоять базовый класс. Т.е. должно быть так: class "grenade_binder" (object_binder) добавлено: Взял тут поэкспериментировал сам. Добавил к гранате биндер и выяснил интересную вещь. Да, в самом деле когда кидаешь гранату она исчезает с концами. Однако вместо неё появляется другой объект-граната. И что самое интересное, у этого объекта нет серверной части. ещё добавлено: После экспериментов выяснилось, что этот второй объект ведёт себя в соответствии с параметрами explode_duration и destroy_time из профиля гранаты. destroy_time - это время от броска до взрыва в миллисекундах explode_duration - это время жизни гранаты после взрыва. Странный параметр. Собственно на взрыв не влияет никак. Но после взрыва граната ещё существует, хотя и не видна, идет апдейт. Только когда проходит указанное время вызывается её net_destroy и второй объект тоже исчезает. Вероятно, это надо для дымовых и газовых гранат. Зачем было создавать вторую? Тоже непонятно. Возможно, так проще было сделать, что гранату нельзя после броска поднять.
  4. Сетки нет, возможно? Координаты есть. Ну или я что-то не понимаю. Вот на скринах левел едитора отчётливо видны всякие координаты=)
  5. Как раз не обязательно у каждой, sid - это дополнительный необязательный идентификатор, что-то вроде специальной метки. Я проверил и выяснил, что для всех объектов, у которых sid не установлен, и sobj.m_story_id, и cobj:story_id() выдают значение 4294967296. Если посмотреть на шестнадцатеричное представление этого числа, то увидим 0x100000000. Т.е. вообще говоря число выходит за пределы 32-х разрядов, однако младшие 32 разряда равны нулю. Ну вот скорее всего и выходит, что передаёшь ты в функцию почти всегда 0. Только при чём здесь sid? Тебе нужен id коробки, а не sid. А как я ранее предложил, чем не устраивает? У меня работает. Метки ставятся на всё, в чём оставишь предмет: на ящики, на живых сталкеров (после продажи им), на тушки. Осталось только проверить, что id принадлежит коробке, и твоя задача решена. Партиклы - это визуальные эффекты такие. Что это такое можно почитать здесь. А как их создавать именно в сталкере написано здесь Вообще говоря в списке коллбеков есть и action_particle (т.е. имеется константа callback.action_particle). Вот только не знаю, куда этот коллбек вешать. Примеров нет, надо экспериментировать. Разрабы, очевидно, расставляли всё в редакторе. Возможно, стоит найти декомпилированный уровень и снимать координаты с него.
  6. А откуда у тебя в этом коллбеке box взялся? Ну да ладно. Я попробовал это сделать в колбеке on_item_drop. Вышло что-то в этом роде: function actor_binder:on_item_drop(obj) ... local sobj = alife():object(obj:id()) -- получаем серверный объект level.map_add_object_spot_ser(sobj.parent_id, "treasure", "test test test") end Обращаю внимание, что если попытаться получит здесь id родительского объекта через клиентский объект obj:parent():id(), то мы получим всегда 0. т.е. id актора. Если предмет съеден или просто выброшен на землю, то его родитель будет 65535. Вроде бы map_add_object_spot_ser в этом случае не сбивается, но вероятно надо бы проверять это и не делать лишнего. Ну а проверить, что выложили именно в ящик - дело техники. У меня же начали ставиться метки на всё подряд =)
  7. Сделал плагин для распаковки игровых архивов для Total Commander-а. Живёт здесь. Протестируйте пожалуйста. Автоустановка не работает? Заходишь в архив с плагином тоталом и он спрашивает, установить ли его. Если отказался, то спрашивать при повторном заходе не будет вплоть до перезапуска тотала.
  8. Сделал плагин для распаковки игровых архивов для Total Commander-а. Живёт здесь. Протестируйте пожалуйста.
  9. Разумеется в стандарте XML нет никаких инклюдов. Я так понимаю, что движок сначала прогоняет файлы через свой препроцессор, который собирает файлы в памяти, а только потом его парсит. Это относится и к LTX, и к XML файлам.
  10. Я полагаю, надо просто определить, какое оружие в руках у киллера в момент смерти жертвы. У АМК есть фунция amk_offline_alife.get_npc_weapon(npc), но во-первых она полагается на готовые таблицы из мода АМК, а кроме того там алгоритм выбирает оружие исходя из его огневой мощи, которую вычисляет там же находящейся функцией get_weapon_firepower(wpn). Так что не не факт, что этот выбор будет соответствовать действительности. И вообще, это похоже преимущественно для оффлайновых неписей. Если знаешь способ узнать точно, какой ствол держит онлайновый NPC в руках, то это и будет лучшим ответом. По-моему, это обсуждалось не раз. Стоит наверное поискать.
  11. Monnoroch, если граната у ГГ точненько под ногами, то ему уже не нужен колбек на её взрыв. Ему нужна последняя сохранёнка. Кроме того, координаты двух объектов не могу совпадать с точностью, в любом случае есть некоторая разница.
  12. Тогда уж надо рассчитывать урон в зависимости от расстояние до гранаты. И как здесь учесть возможность того, что ГГ сидит в укрытии?
  13. Вот только не получится узнать, нанесла ли урон ГГ. Колбек на хит актору сделать ещё никому не удалось. Колбек в биндере на смерть ставится в xr_motivator.script и bind_monster.script. Там вторым параметром идет объект - причина смерти.
  14. Не уверен, есть ли способ поймать именно факт получения денег. Но допустим на получение предмета и торговлю есть в биндере актора или сталкера колбеки: on_item_drop on_item_take take_item_from_box trade_perform_operation trade_sell_buy_item ну вот допустим купил ты пачку патронов и проверяешь в этом колбеке, сколько их там. Если меньше определённого, то выполняем некое действие. Это к какому вопросу относится? =) А где ты видел сталкера, у которого есть методы get_anomaly_power() и enable_anomaly() ? Да, вот так вот сделано, что для всех онлайновых объектов есть общий интерфейс в виде объекта одного класса game_object. Это поначалу сложно понять. Ещё сложнее понять, зачем так сделано. Я могу лишь предположить, что это вероятно имеет смысл в контексте мультиплеера. В общем имеем монструозный класс, у которого есть куча методов, и из этих методов применительно к конкретно взятому игровому объекту работают только некоторые. К примеру упомянутые get_anomaly_power и enable_anomaly для сталкеров работать не будут, скорее всего просто ничего не делают, а hide_weapon скорее всего не окажет никакого действия на аномалию или монстра. Посмотри в папке scripts, может найдёшь примеры с этой функцией в родных скриптах. Я обычно использую поиск в Total Commandere файлов, содержащих нужную строку. в данном случае particles_object или play_at_pos.
  15. 1. Почему только до 65500, а не до 65534? Впрочем, ошибки это не даст, просто пропустишь несколько объектов. 2. level.object_by_id(i) возвращает онлайновый объект, а alife():object(i) - офлайновый. С ними потом категорически не выйдет работать одинаково. Методы и свойства у них разные. Будет вылет на первом же не найденном свойстве/методе. Не совсем понятно, что ты имеешь в виду. Свои в каком смысле? self - это объект, метод которого вызван. Вообще, конструкция вида: class_name:method_name(<список аргументов>) self ... end Синтаксически эквивалентна такой: class_name.method_name(self, <список аргументов>) self ... end Т.е. self - это на самом деле скрытый первый аргумент А делать с ним можно всё, что вздумается =) Почти у всех клиентский объектов класс один и тот же - game_object. Не стоит забывать ещё про класс биндера. который в некотором смысле расширяет game_object. Для АМК биндер находится в скрипте amk_anoms.script Вообще партикл проигрывается с помощью класса particles_object. Собственно проигрывание начинается методом play_at_pos Пример использования можно посмотреть в скрипте amk_particle.script
  16. Для этого есть специальные функции. Вот например: level.vertex_in_direction(lvid, dir, rad) game_object:vertex_in_direction(lvid, dir, rad) lvid - вертекс, от которого ищем dir - вектор направления rad - радиус поиска Похоже, что эта функция как раз и существует, чтобы решать обозначенную задачу. Впрочем, я её не использовал. =) чтобы дать строгие определения, надо процитировать пару главок из учебника по объектно-ориентированному программированию. Ну может здесь можно посмотреть некое краткое изложение. Если по-простому: Класс - это сложный (составной) тип данных. Наподобие сишной структуры или паскалевской записи, только содержащий не только переменные, но и функции. Объект - это переменная типа класс. Свойство - это переменная, содержащаяся в объекте Метод - это функция, содержащаяся в объекте Классы являются основной строительной конструкцией многих современных языков программирования. В Lua поддержки классов на уровне языка нет, но они там неплохо имитируются благодаря невероятной гибкости Lua. Если кому интересно, то в сталкере для этого используется технология Luabind Хороший пример - класс vector. Имя класса - vector Чтобы завести объект типа vector, надо выполнить конструкцию: vec = vector() здесь vec - это объект теперь можно обращаться к свойствам объекта x_coord = vec.x vec.y = 4 или к его методам vec:set_length(3.5) Это с точки зрения использования уже готовых классов. С точки зрения создания классов всё немного сложнее и вообще говоря сильно привязано к конкретной реализации в конкретном языке.
  17. Я попробовал ещё раз. К сожалению должен констатировать: для ЧН методика работает плохо. Такое ощущение, что проблема в самом вызове pcall. Т.е. чанк из файла загружается, компилируется, а вот его выполнение с помощью защищённого вызова с pcall вызывает у игры тихую панику с непредсказуемыми последствиями. Вызов pcall заменить нечем - в нём сама суть методики. Проблема также в том, что реакция на один и тот же код бывает разная. Ведёт себя как капризная невеста: иногда срабатывает, иногда тихо не срабатывает, иногда сразу после выполнения чанка идёт вылет без лога. Всё это весьма огорчительно. То, что в ТЧ работало как часы и экономило мне кучу времени, здесь не работает. level.vertex_position(id) Но по идее, вертекс актора - это и должен быть ближайший к нему. Впрочем. ничто не мешает просто перебрать все вертексы на одном уровне с актором и проверить их расстояние до ГГ. Загляни в комментарии к этой программе LVID Viewer (автор IG-2007) Да вроде универсальный комбат так и называется combat. Откровенно говоря, не до конца я разобрался с логикой. Но по моему разумению универсальные схемы срабатывают автоматом. Их там регистрируют в xr_logic.script и где-то там-же происходит их переключение по эвалуаторам. Не думаю, что правильно будет пытаться переключать универсальные схемы вручную, но наверное можно дописать дополнительные условия в эвалуатор.
  18. Если надо определить принадлежность значения id к некоторому множеству (id1, id2, id3, ...), то наиболее эффективно это можно сделать так: arr = { id1 = true, id2 = true, id3 = true, ... } if arr[id] then конструкция arr[id] возвращает true если такой ключ есть, и nil в противном случае. А nil в условных конструкциях интерпретируется как false.
  19. Rezonance, Вас не затруднит объяснить, в чём смысл Вашей подписи?
  20. Ну вот например у game_object есть свойство health. Неужели нужен подробный хелп, для того чтобы понять, что это свойство отвечает за здоровье? Есть конечно и менее очевидные ситуации, но часто достаточно просто заглянуть туда. Хотя конечно, подробный хелп бы не помешал. Кто бы ещё его составил? =) 1. Дизассемблером вестимо 2. Очень хлопотно 3. Кому это надо?
  21. Про торговцев смотри шпаргалку из шапки.
  22. Поставь "treasure_item" Вроде бы в Zenobian моде. Но я также слышал, что это не просто так получилось. Zen для этого движок ковырял, чтобы научить стрелять бинокль. А одними конфигами или скриптами не выйдет.
  23. Здесь как раз всё намного проще. у game_object есть свойство health. Так что делаем так: cobj.health = value -- именно так, с точкой вот только для убийства этот метод ненадёжно работает. Даже если поставить health = -1, дохнут далеко не всегда, а иногда не сразу. Кроме того, если непись валяется и аптечку просит, то даже если его health поднять - валяться не перестанет. Для этого есть метод game_object:wounded(boolean). З.Ы.: Вообще-то, не грех бы за такими вопросами заглядывать в файл lua_help.script
  24. Так ведь таймеры и сделаны на апдейте актора. Но в придачу ещё и грузят нетпакет актора, который вовсе не резиновый и забит и так под завязку.
  25. Если ты имеешь в виду сохранение переменных, то такой способ годится разве что для сохранения глобальных настроек мода. Кстати, работает ли тестовый полигон для ЧН? Если работает, то надо будет оба варианта прописать в уроках по модостроению. Искал-искал... нашёл только \gamedata\config\gameplay\character_desc_....xml Может лучше по clsid? Что-то вроде: if obj:clsid() == clsid.obj_medkit) then Выходит, без залезания в апдейт актора никак. Таймеры - это наверное уж слишком, но придётся делать подобно тому, как сделано в перепаковщике патронов. Там, помнится, при взятии предмета устанавливался глобальный флажок. И по этому флажку в ближайшем апдейте шла перепаковка. Можно попробовать также и здесь: 1. по дропу предмета, если это аптечка, то ставим флажок и запоминаем id, возможно дописываем в массив. Можно ведь сразу много выкинуть. 2. в апдейте проверяем, если такого предмета нет - значит съели, если есть - значит просто выкинули. Вот только не уверен, достаточно ли ближайшего апдейта. Может и нет. Возможно, придётся несколько циклов сделать.
×
×
  • Создать...