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

Malandrinus

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

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

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

  • Дней в топе

    13
  • AMKoin

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

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

  1. TimeShift, Смотря что ты имеешь в виду под остановкой времени. Сделать так, чтобы, к примеру, остановились пули, остановился обсчёт физики (типа брошенные предметы замерли в воздухе), замерли анимации и т.п., нельзя, как и замедлить всё это. Но можно изменить скорость течения календарного игрового времени, т.е. сутки будут сменяться быстрее/медленнее и соответственно изменятся все игровые события: спавн и прочее в этом роде. Это можно сделать функцией level.set_time_factor() Насчёт летать. В принципе можно это реализовать через функции set_actor_position и set_actor_direction, повешенные на апдейт. Надо только научиться управлять скоростью полёта, что в общем тоже реализуемо. Ещё можно в ЗП отключить гравитацию (насчёт ЧН не знаю точно, а ТЧ это не работает). Это делается через объект physics_world. Но это весьма корявый полёт.
  2. Unnamed Black Wolf, в сущности какая разница, соответствует игровой календарь реальному или нет? Ведь игровое время по-любому отличается от реального. Ну будет в игре лишний/недостающий день, и что с того? Надо только убедиться, что способ расчёта даты в классе CTime соответствует расчёту времени в собственно игровом времени.
  3. 7.9, Вроде как с 1/1/1, а не с 2000/1/1. И эта дата + нулевое время соответствует нулевому значению счётчика. Соответственно, если прибавить или отнять такое время (1/1/1-0:0:0:0), то ничего не изменится. Я провёл глобальное сравнение с настоящим календарём. Да, в конце каждого года непременно косяк. Чаще всего в самом деле появляется 32-е декабря. При этом иногда это просто лишний день, иногда он заменяет 1-е января следующего года (а год начинается соответственно со 2-го числа). А иногда косяк не в лишнем дне, а напротив - в отсутствии 31-го декабря. В общем, даже календарь в Зоне аномальный =) Интересно, баг это или пасхалка...
  4. TREWKO, Вот! Ключевое слово "нажать". Это лишает смысла всю затею. Специально для решения этой проблемы существует такая штука, как story_id.
  5. TREWKO, ага, теперь осталось найти метод включения =)
  6. Ирбис, Можно попробовать поискать в XML ресурсах. Вполне возможно, что это просто окно. Тогда его можно поменять, текстуры растянуть и т.д.
  7. RvP, Этот класс недоступен, как и большинство остальных из этого разряда. У меня не сработало.
  8. Все правки уже написанного сделаю позже, а пока... По диалогам ещё не всё. Остались неохваченными много функций и методов, имеющих отношение к диалогам. Так что будет третья часть. To be continued...
  9. По-моему нереально. Даже если сделать фейковые пачки, так ведь они тогда начнут тоже группироваться. Только счётчик будет не патронов, а пачек. Одинаковые предметы будут по любому группироваться. Лично у меня даже идеи нет, как бы это можно было сделать.
  10. fokstar, Сложно сделать интересные бои в узких коридорах. Даже при изощрённом AI у монстра всё равно нет выбора, только бежать к противнику по прямой. При боях с людьми это тоже сказывается. Стелс-миссии абсолютно неинтересные. Без них никак, если надо получить альтернативную концовку. Но в итоге понимаешь, что в стелс-режиме надо просто очень чётко сделать заранее предопределённую цепочку действий. На второй раз уже всё узнаваемо. На третий - просто тупо перемещаешься из одного заранее известного угла в другой, настолько всё предсказуемо. Разорвать эту цепочку, чтобы хоть как-то разнообразить игру, почти невозможно. Очень долго проходил станцию с бандитами (где Бурбона убивают). Любое отклонение от "встал в этот угол, погасил ту лампочку, навёл влево, нажал, убил, пошёл в следующий угол" чревато. Пока не разведал всю цепочку при невозможности промежуточного сохранения - потерял к уровню весь интерес.
  11. Dennis_Chikin, Получаем имя уровня для геймвертекса, при условии его валидности. Сохраняем его в локальную переменную map. Vovan0792, актор смотрит туда-же, куда и камера. Тебе нужен класс render_device. Посмотри описание в теме справочник.
  12. Внесу все правки позже, а пока продолжим основной цикл статей. На очереди диалоги в двух трёх частях. Во второй части будет подробно описана скриптовая инициализация диалогов, будут рассмотрены все функции и методы, имеющие отношение к диалогам и будет некое количество трёпа на тему построения динамических диалогов.
  13. Капрал Хикс, Тебе нужна какая-либо тулза для работы с моделями. Могу посоветовать OGF_Master. С её помощью можно разобрать модель в текстовый формат, и там будет список костей. Но вроде как и другие есть на ту-же тему.
  14. Kolmogor, Да, в самом деле. С одной стороны ненужность предварительной регистрации вроде удобна. С другой стороны урезание тегов огорчает. И вообще, только было подумал: "а как же теперь статьи в энциклопедии выдавать?", а потом дошло, что ведь вовсе нет энциклопедии в ЗП. Вырезали с концами.
  15. sapsan, подобное поведение table.remove, table.getn и # похоже на баг старой версии Lua. В новой я такого не наблюдаю, и всё работает достаточно предсказуемо. Однако, я бы сделал оргвыводы. table.remove использовать нельзя вовсе. Никакие манипуляции, изменяющие таблицу в цикле по этой же таблице, совершенно недопустимы. Возможно, стоит принять идеологию неизменения таблиц-массивов в принципе. Это будет означать, что если надо массив изменить (в смысле добавить или удалить элементы, а не изменить их значения), то надо просто склонировать его, попутно добавив или удалив нужное, а затем заменить ссылку на таблицу на свежесозданную. Это не так страшно, как звучит, поскольку в таблице хранятся не объекты, а ссылки, и клонирование будет поверхностное. Кроме того, это и не будет намного более затратно, чем тот-же insert и remove, поскольку там внутри происходит примерно тоже самое - перевыделение памяти и копирование массива ссылок на новое место. Таблицы общего вида (с нецелыми или нерегулярными ключами) менять можно, но опять же не саму себя в цикле. Это категорически нельзя. В защиту этой идеи могу добавить, что многие языки подобную идеологию навязывают (например делая итераторы только для чтения). И не зря, поскольку это существенно надёжнее.
  16. Продолжим. На очереди система профилей сталкеров, включая систему генерации имён. Если коротко, то система профилей такая: - В секции сталкера указан параметр character_profile. Если не указан, то принимается значение default. - это имя указывает на профиль из файла, который прописан в system.ltx в разделе [profiles] в параметре files. Обычно это config\gameplay\npc_profile.xml - По информации из этого профиля и по специальному алгоритму уже выбирается один из профилей, содержащих конкретную информацию о NPC. Все эти профили находятся в нескольких файлах, перечисленных в system.ltx в разделе [profiles] в параметре specific_characters_files. Теперь подробнее. Вот пример файла с двумя вариантами создания character profile: <?xml version='1.0' encoding="UTF-8"?> <xml> <character id="profile_1"> <specific_character>specific_character_profile_1</specific_character> </character> <character id="profile_2"> <class>class_name</class> <rank>500</rank> <reputation>300</reputation> </character> </xml> Два этих варианта определяют два разных алгоритма выбора конкретного specific characters profile. Первый вариант profile_1 содержит тег specific_character, который указывает на конкретный specific characters profile. В этом случае все остальные теги игнорируются. Этот вариант используется к примеру для актора. Его можно использовать для разных квестовых персонажей. Второй вариант profile_2 используется для выбора одного из многих возможных профилей, используя параметры class, rank и reputation. Алгоритм выбора будет описан далее. Пример файла с профилем персонажа: <?xml version='1.0' encoding="windows-1251"?> <xml> <specific_character id="specific_character_profile_name" no_random = "0" team_default = "1"> <class>class_name_1</class> <class>class_name_2</class> <bio>...</bio> <npc_config>...</npc_config> <icon>...</icon> <name>...</name> <panic_threshold>...</panic_threshold> <hit_probability_factor>...</hit_probability_factor> <crouch_type>...</crouch_type> <critical_wound_weights>...</critical_wound_weights> <visual>...</visual> <supplies>...</supplies> <snd_config>...</snd_config> <terrain_sect>...</terrain_sect> <community>...</community> <rank>...</rank> <reputation>...</reputation> <money min="100" max="500" infinitive="0"/> <start_dialog>...</start_dialog> <actor_dialog>...</actor_dialog> <actor_dialog>...</actor_dialog> </specific_character> </xml> no_random исключает данный профиль из списка случайного выбора (см. далее описание алгоритма выбора) team_default включает профиль в список дефолтовых при случайном выборе (см. далее описание алгоритма выбора) no_random и team_default не могут быть установлены одновременно. class - по этому параметру будет найден профиль. Этих тегов может быть несколько, т.е. разные character_profile с разными классами могут ссылаться на один и тот-же specific_character_profile. name - человеческое имя персонажа. Алгоритм генерации описан далее. icon - иконка персонажа в окне торговли panic_threshold - некое пороговое значение для паники. Непонятно, влияет ли на что-то. hit_probability_factor - фактор "меткости" сталкера. При нуле будет мазать стопроцентно. crouch_type - тип приседания: 0 - обычное, 1 - низкое (у бандитов такое), -1 - случайный выбор critical_wound_weights - какие-то весовые коэффициенты. Обычно выглядит так: <critical_wound_weights>75,25,25</critical_wound_weights> как-то управляет параметрами ранения, но как именно - не знаю. visual - путь к модели supplies - стартовый инвентарь. Примеры смотри в игре. snd_config - имя папки, из которой берутся звуки terrain_sect - ссылается на секцию в system.ltx. Пример такой секции для сталкеров. [stalker_terrain] 255,000,255,255 008,001,255,255;Разрешено ходить по опасным местам на баре 012,001,255,255;Разрешено ходить по опасным местам на Милитари Что-то это всё означает, но что - точно не знаю. community - группировка rank - ранг reputation - репутация money - количество денег. Имеют значение только атрибуты min, max и infinitive. Значение тега задавать не надо. infinitive имеет смысл задавать для торговцев. start_dialog - стартовый диалог. Это диалог, с которого всегда начинается общение. Первым в нём говорит собеседник. Стартовый диалог может быть только один. Если не задан, то устанавливается диалог с именем "hello_dialog". actor_dialog - диалог актора. В этом диалоге первую фразу говорит актор. Этот дилог можно начать после того, как закончится стартовый дилог. Их может быть несколько. читаются, но не используются bio - биография, в игре нигде не отображается. npc_config - понятия не имею, зачем нужен. Обращаю внимание на то, что часть параметров дублируются здесь и в секции спавна. Что имеет приоритет, точно не знаю. Только насчёт визуала точно знаю, что берётся именно из профиля. Теперь об алгоритме выбора профиля для варианта с тегом class. Профилей specific_character с одним классом может быть несколько. Движок находит все профайлы, в которых присутствует тег class с нужным значением (напоминаю на всякий случай, что тегов class может быть несколько). Конкретный профиль случайным образом выбирается из всех найденных. При этом имена профилей, заданные атрибутом id не важны и могут быть совершенно любыми (но не могут повторяться). Профили с включённым флажком no_random исключаются из этого алгоритма. Теперь несколько непонятных моментов. Имеется также флажок team_default и два параметра в character_profile - rank и reputation. Похоже на то, что при выборе профиля из многих подходящих по классу можно ещё и фильтровать их по этим двум параметрам. Флажок team_default также каким-то образом влияет на процесс фильтрации. Но подробностей выяснить пока не удалось. Часть из параметров, описанных в профиле, доступны со скриптовой стороны. profile_name - имя профиля. К сожалению - это имя корневого профиля character_profile, а не specific_character. Если профиль был выбран случайно, то узнать, какой именно, практически невозможно. character_name - человеческое имя, сгенерированное по описанному здесь алгоритму. character_reputation - узнать репутацию change_character_reputation - изменить репутацию character_rank - получить ранг set_character_rank - установить ранг character_community - получить имя группировки set_character_community - сменить группировку (там ещё можно менять команду и сквад) money - узнать, сколько денег transfer_money - передать деньги give_money - дать денег sound_prefix - расположение звуков (параметр, задаваемый тегом snd_config) set_start_dialog - установить новый стартовый диалог restore_default_start_dialog - вернуть исходный из профиля get_start_dialog - по идее должна вернуть строку с именем диалога, но совершенно точно не работает и возвращает nil 1. Если имя может быть транслировано функцией game.translate_string(), то это и будет имя. Так можно задавать имена уникальным персонажам. 2. Если имя имеет вид "GENERATE_NAME_<suffix>", то имя составляется из имени и фамилии так: - из system.ltx читается секция stalker_names_<suffix>, где должны быть два параметра name_cnt - количество вариантов имён, last_name_cnt - количество вариантов фамилий. - далее составляется строка вида "name_<suffix>_N", где N - случайное число в пределах [0..name_cnt] (а может до name_cnt-1). Эта строка преобразуется в локализованное имя, как если бы обрабатывалась функцией game.translate_string() (см. описание этой функции в разделе "пространства имён"). Файл с именами обычно имеет имя stable_generate_fnames.xml, но может быть и другим. И сами имена можно размещать где угодно, см. опять же описание translate_string. - аналогично получается фамилия. Составляется строка вида "lname_<suffix>_N" и получается локализованная фамилия по тому же алгоритму. - результирующее имя составляется из имени и фамилии, раделённых пробелом. 3. Если не работает ни первый, ни второй вариант, то имя принимается прямо таким, как прописано в теге name.
  17. кровоSTALKER, db.actor:kill(db.actor)
  18. Начинаю цикл статей, посвящённых вещам, необходимым для создания сюжета: профили сталкеров, инфопорции, диалоги... Все эти вещи имеют скриптовую сторону (иначе бы я не стал об этом писать здесь=). Вопреки своему обыкновению я буду расписывать и форматы файлов, иначе не будет должной полноты картины. Инфопорция (infoportion - порция информации) представляет собой нечто вроде логической переменной. Инфопорция имеет имя и связанное с ним логическое значение. Инфопорция всегда связана с каким-либо объектом. Инфопорция может быть установлена только для актора, сталкеров, монстров и торговца (иначе трейдера, единственный такой объект - Сидор). Если Инфопорция для объекта установлена в true, то говорят ещё "объект имеет инфопорцию, или объект имеет информацию". Инфопорции являются частью общего механизма построения сюжета. Комбинация выданных инфопорций у всех сюжетных персонажей, включая актора, как раз и определяет текущую точку сюжета. Инфопорции активно используются во всевозможных предусловиях в диалогах, влияют на условия торговли и т.п. Имя инфопорции регистрируется заранее. Система такая: В файле config\system.ltx есть секция [info_portions]. В этой секции единственный параметр files содержит перечень XML-файлов, содержащих описания инфопорций. Вы можете создать новый файл и вписать его в этот список, что более предпочтительно, или создать свою инфопорцию в одном из существующих файлов. <?xml version='1.0' encoding="windows-1251"?> <game_information_portions> <info_portion id="very_simple_infoportion"/> <info_portion id="simple_infoportion"> </info_portion> <info_portion id="some_infoportion"> <action>some_module.some_action1</action> <action>some_module.some_action1</action> <disable>infoportion_to_disable_1</disable> <disable>infoportion_to_disable_2</disable> <article>article_name1</article> <article>article_name2</article> <article_disable>article_name3</article_disable> <article_disable>article_name4</article_disable> <task>task_name_1</task> <task>task_name_2</task> <dialog>some_dialog_1</dialog> <dialog>some_dialog_2</dialog> </info_portion> </game_information_portions> Показаны три варианта регистрации инфопорций. Все инфопорции во всех файлах должны иметь уникальные имена. в основном это методы класса game_object: bool give_info_portion(string <имя инфопорции>); // выдать порцию информации bool disable_info_portion(string <имя инфопорции>); // забрать порцию информации bool has_info(string <имя инфопорции>); // проверка на наличие инфопорции bool dont_has_info(string <имя инфопорции>); // проверка на отсутствие инфопорции CTime* get_info_time(string <имя инфопорции>); // получить время выдачи инфопорции. В ЗП убрана Есть также два метода у класса alife_simulator: bool has_info(const alife_simulator*, id, string <имя инфопорции>); bool dont_has_info(const alife_simulator*, id, string <имя инфопорции>); Видно, что в оффлайне не получится установить/снять инфопорции, только узнать его значение. В минимальном случае для регистрации инфопорции достаточно имени, как это сделано в примере для very_simple_infoportion и simple_infoportion. В этом случае он почти подобен простой логической переменной, и часто именно так его и используют. Но, как видно из формата файла, инфопорция при установке может также делать дополнительные действия: 1. выполнить заданную скриптовую функцию, заданную тегом action. Функция должна иметь вид function action_name(who) end Где who - это клиентский объект того, кому был выдан инфопорция. 2. забрать другую инфопорцию, которая определяется тегом disable 3. активировать в PDA статью, заданную тегом article и деактивировать статью, заданную тегом article_disable 4. выдать задачу, заданную тегом task 5. добавить диалог, заданный тегом dialog К сожалению нет возможности выполнить действие при снятии инфопорции. Всех этих действий может быть произвольное количество. Естественно, не все действия имеют смысл для всех объектов, часть только для актора. Тут до конца не проверял, смотрите сами.
  19. Геймвертексы здесь точно не при чём. Здесь, кстати, редкий случай достаточно внятной расшифровки вылета. Вылет возникает если а) установлен флажок used_ai_locations, который заставляет привязываться при спавне к сетке и при этом б) вертекс уровня не валидный. В чём эта невалидность заключается - вот этого здесь не указано. Может просто нет такого. Я экспериментировал с этим флажком при скриптовом спавне. Если его установить, но по каким-то причинам под объектом нет сетки, то вылета не было, и объект просто спавнился в воздухе. Но здесь используется all.spawn. Поскольку у разрабов all.spawn появлялся из SDK, в нём по определению всё было корректно. Скорее всего при этом создание объекта происходит по упрощённому сценарию: ему просто вписываются все параметры из файла и при этом не делается никаких проверок (он как бы загружается из сохранёнки). В случае модов и собранного на коленке all.spawn-а это допущение может оказаться неверным, что и приводит к таким вылетам. Дополнение. Невалидность вертекса здесь совершенно точно означает, что такого на уровне нет. Поди из левого all.spawn-а взят...
  20. Shadows, Это скорее всего связано с кривой настройкой clipping (отсечение) в контролах. Что-то выходит за границы отображаемой области. Точнее не могу сказать.
  21. Unnamed Black Wolf, Работает вроде. Подойти к костру вплотную и выполнить вот такой код: for i=1,65535 do local s = sim:object(i) if s then local o = level.object_by_id(s.id) if o then local cf = o:get_campfire() if cf and o:position():distance_to(cact:position()) < 5 then cf:turn_off() -- turn_on end end end end Гаснет не мгновенно и не полностью, просто меняет партиклы на "тление угольков с лёгким дымком"
  22. Mechanic.92, Саму реализацию сна - нет, не выйдет, поскольку в ТЧ нет кода сна вообще. А если просто окошко нравится - так что мешает вызов сна сделать через похожее окошко? Vano_Santuri Попробуй переменную player сделать глобальной, тогда объект звука не удалится. Весь смысл функции xr_sound.get_safe_sound_object был в том, что она сохраняла получаемый объект плеера в глобальной таблице.
  23. Byurrer, Это только через нетпакеты. Там у ствола есть флажки, которые отвечают за надетость каждого аддона.
×
×
  • Создать...