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

Полтергейст

Опытные
  • Число публикаций

    318
  • Регистрация

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

  • AMKoin

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

Весь контент пользователя Полтергейст

  1. Пути по-любому (вообще) нужны - как-то ведь нужно хранить последовательности точек. Если от них отказаться, придётся делать альтернативу, в итоге получится то же самое по смыслу, и не факт, что вновь изобретённый велосипед будет лучше старого. Проблема не в самих путях, а в возможностях работы с ними - в движке нет штатной возможности создавать дополнительные пути из скриптов, чтобы потом обращаться к ним также, как к путям из all.spawn. Кроме этого, без путей невозможно перемещение в оффлайне. С другой стороны, полноценного перемещения по путям в оффлайне в движке тоже нет (если точнее, оно заблокировано) - можно послать кого-то в любую точку пути, но узнать, какая точка прописана следующей - нельзя. И раз уж начал об оффлайне, то по моему мнению, offline alife всё-таки нужен. Если жизнь будет останавливаться за пределами онлайн-радиуса, играть будет намного менее интересно. Думаю, что вместо переписывания заново лучше дополнить существующую реализацию - вместо имитации оффлайн-торговли (то есть, по сути - уничтожения лишнего лута) можно сделать, чтобы NPC не только брали что-то из тайников, но и клали туда излишки. Это помогло бы сильно упростить treasure_manager - так можно частично вырезать спавн вещей в тайник при нахождении информации о нём, а если ещё информацию выдавать только с тех NPC, которые реально туда что-то положили - это вообще отлично. Что до оффлайн-боёв - это тоже можно оставить и подправить. В оригинале NPC при выборе смарта не учитывают соотношение уже находящихся в нём дружественных/враждебных сил (а также просто находящихся поблизости), поэтому постоянно попадают в переделки. Ну а то, что они возле переходов между уровнями попадают в пробку и устраивают в ней побоище - это скорее проблема навигации между уровнями, чем offline alife. Увеличение количества переходов (доступных для NPC, а не только для игрока) частично решит эту проблему. Частично - потому что при наличии нескольких точек перехода с уровня A на уровень B повлиять на выбор точки перехода скриптами не так-то просто.
  2. Dennis_Chikin То есть опять всё сводится к тому, что нужен набор дописанных, переписанных и новых скриптов, которые сделали бы код более универсальным. А с адаптациями проблема в том, что в модах изменения общих скриптов не отделены от изменений скриптов, привязанных логике объектов и локаций - всё слишком переплетено, чтобы отделить. И ещё treasure_manager.script function CTreasure:dialog( npc ) local comm = npc.character_community() Там должно быть двоеточие вместо точки, надо поправить. Упс ! Спасибо. Что-то не проверил эту ветку. dc Мда, поправил, так поправил... Закинул вместо ООПшного от соли обезжиренной. Ну и черт с ним, с ООПшным... Все равно уже ни кому не нужен.
  3. Насколько я понимаю, здесь обсуждается переписывание оригинальных игровых скриптов, которые кочуют из мода в мод либо копипастой, либо с очень мелкими изменениями. На мой взгляд, проблема намного шире, чем просто оптимизация. Во-первых, надо обозначить, с какого набора скриптов (то есть - оригинал или какой-то мод, какая версия и т.д.) начинать, чтобы осилить и не "забуксовать", но в то же время чтобы изменения были заметными. Во-вторых, надо знать, какие вносятся правки - оптимизация и повышение производительности, правка багов, упрощение отладки, или же более глубокое переписывание механизмов игры. Если с этими вопросами не определиться, в правках не будет порядка.
  4. Так из биндера её и надо читать, а не из внешнего скрипта. local my_mob_binder = obj:binded_object() if my_mob_binder.initialized then (где obj - объект, с биндера которого надо прочитать переменную)
  5. Выкладываю все накопившиеся скриптовые правки, т.к. времени на доработку всё меньше. Может понадобится кому. http://rghost.ru/59995539 Кому интересно, можете потестить или использовать правки в своих модах. Небольшое описание того, что я там накодил и зачем это может понадобиться (вчера времени хватило только на readme, поэтому пишу сейчас). В архиве лежит папка с правлеными скриптами оригинала ТЧ 1.0006 со скриптами от мода "AI вертолётов" (тоже правлеными). Изменения: Из-за введения отдельного скриптового планировщика могут возникнуть сложности с адаптацией схем поведения NPC, но по примерам существующих схем можно разобраться. Что можно просто взять и перетащить к себе в мод почти без адаптации: - скрипт для добавления и удаления меток (файл mapspots.script и строки в bind_stalker.script с отсылками к нему) - файл class_registrator.script - намного упрощает поиск названий серверных и клиентских классов, а также их clsid и конфиговых имён. - функции check_gvid и validate_accessibility из файла move_mgr - функции add_call_source_marker и remove_call_source_marker и используемые в них таблицы - для отлавливания зависших вызовов и измерения времени работы вызываемых функций.
  6. [error]Expression : ai().level_graph().valid_vertex_id(vertex->data().level_vertex_id()) [error]Function : CPatrolPathManager::select_point [error]File : E:\stalker\sources\trunk\xr_3da\xrGame\patrol_path_manager.cpp [error]Line : 164 [error]Description : patrol path[имя_пути], point on path [имя_точки_пути],object [объект_использующий_этот_путь] Причина: указанная точка пути имеет недопустимый (чаще всего отрицательный) level_vertex_id. Лечение: распаковать all.spawn, найти этот путь и отредактировать либо удалить эту точку пути так, чтобы level_vertex_id.для нее был задан правильно. Правильность level_vertex_id имеет значение для всех путей, по которым кто-то передвигается (за исключением вертолетов).
  7. Не так давно столкнулся со странными вылетами на локации "Управление монолитом". Вылеты были самые разные - без логов, с логами (каждый раз с разными), иногда игра просто зависала. Причина оказалась в скрипте bind_physic_object и партиклах. В оригинальном скрипте в методе update биндера есть такой код: local particle = utils.cfg_get_string(self.st.ini, self.st.section_logic, "particle", self.object, false, "", nil) if particle ~= nil then self.particle = particles_object(particle) self.particle:play_at_pos(self.object:position()) end он выполняется на каждом обновлении биндера. Это приводило к тому, что при каждом выполнении кода объект партикла создавался заново, если задано имя партикла. Добавление проверки на наличие self.particle полностью избавило от этой проблемы.
  8. К моменту добавления условий соответствующие эвалуаторы уже должны быть добавлены в планировщик. То есть все схемы, условия которых добавляются через add_precondition, должны быть загружены. Поэтому лучше поставить загрузку схемы последней в функции enable_generic_schemes. Кроме того, во всех схемах, загрузка которых вызывается из enable_generic_schemes, надо также заменить вызов addCommonPrecondition (если он там есть) на содержимое этой функции, но без добавления условия схемы npc_trade. Иначе они будут добавлять еще не существующее условие.
  9. Самая главная ошибка - в xr_motivator.addCommonPrecondition добавляется условие if npc_trade then action:add_precondition (world_property(npc_trade.property_need_to_trade,false)) end которое применяется к действию созданной схемы. Получается, что к нему добавляются 2 взаимоисключающих условия: action:add_precondition (world_property(npc_trade.property_need_to_trade,false)) action:add_precondition(world_property(property_need_to_trade, true)) поэтому и вылетает. В фунции add_to_binder надо вместо вызова функции xr_motivator.addCommonPrecondition просто скопировать ее содержимое, за исключением условия, которое приводит к вылету.
  10. Был куратором в этой теме Готово.
  11. В следующих версиях было бы желательно сделать дописывание своих параметров для объектов в all.spawn. То есть, например, записан там некий NPC, и после всех параметров его движкового класса (cse_alife_human_stalker) все параметры наследуемого класса se_stalker были бы перечислены в виде таблички, в которых указываются типы параметров и их значения. Как-то так: { bool param1 = false bool param2 = false u8 param3 = 3 u16 param4 = 1043 } Для чего это нужно? Допустим, поменяю я функции чтения/записи в классе se_stalker, тогда и в all.spawn нужно соответственно поменять записанные данные, чтобы подходили под новый формат. К тому же, так можно будет использовать программу под абсолютно любые моды - для упаковки/распаковки программе нужно будет знать только соответствия между секциями и серверными классами, остальное запишется как набор параметров, назначение которых известно только модмейкеру.
  12. С работы в любом случае уйдёт при вызове gulag:prepare_jobs_for_new_state(), то есть сразу же после смены состояния гулага. После этого на следующем обновлении планировщика (brain) NPC должен уйти из гулага/смарта, потому что вызов se_smart_terrain:enabled() вернет false.
  13. Да вот не пойму что-то, там для получения длины хеш-таблицы почему-то используется table.getn, а не увеличение количества в цикле pairs. Это имелось в виду? Ещё один недостаток - после загрузки объекты не проверяются на нахождение внутри рестриктора, хотя сохраняемые NPC могли запросто в оффлайне куда-нибудь уйти. На "Арене" такого всё равно не происходит, а в остальных случаях проверку делать надо обязательно. У меня нет под рукой скриптов от ЗП, а в интернете я нигде не нашёл упоминаний такой правки для ТЧ.
  14. Нашёл способ включить эти коллбеки для обычных рестрикторов, чтобы не возиться с созданием новой секции и биндера. Для этого в файле class_registrator.script заменить эту строку cs_register(object_factory, "CSpaceRestrictor", "se_zones.se_restrictor", "SPC_RS_S", "script_restr") на эту: cs_register(object_factory, "ce_script_zone", "se_zones.se_restrictor", "SPC_RS_S", "script_restr") Тогда можно будет создавать списки всех, кто находится в этой зоне, добавлять функцию работы с этими списками в xr_conditions и использовать в логике обычных рестрикторов. Кроме этих коллбеков у биндера рестрикторов появятся свои обновления, то есть уже не нужно будет их вызывать из биндера игрока.
  15. Проблема в том, что эти методы (точнее коллбеки) для обычных рестрикторов не работают. Поэтому единственным способом остается перебор всех с проверкой на вхождение. Что до аномалий - мне проще было сделать так, поскольку мой вариант сделан для чистой игры, а вариант amk привязан к скрипту создания динамических аномалий.
  16. Можно, но тогда придётся перебирать всех (!) NPC на уровне и проверять на вхождение в зону с помощью функции utils.npc_in_zone. Это будет съедать ресурсы и может привести к существенным тормозам. Проблема в том, что для обычного рестриктора нельзя отследить момент, когда нпс попадает в зону или выходит из неё. Для этого там через каждые пройденные 15 метров также перебирается список всех аномалий на уровне.Хоть и не на каждом update, но всё равно. Для всего количества аномалий на уровне - не так уж и много, во всяком случае, заметных тормозов и глюков не вызывает. Зато не нужно заморачиваться с расчётом расстояний до каждой аномалии. Нечто подобное разрабы сделали с кострами - каждому костру добавили дополнительную внешнюю оболочку, только добавляются они как default in restrictor, а не динамически.
  17. Например, для открывания дверей можно было бы использовать. Или добавлять зону в рестрикторы при входе в неё, например создать такую скрипт-зону вокруг аномалии и всем, кто в неё входит, запрещать идти в аномалию (у себя я так и сделал). На обычных рестрикторах эти коллбеки не работают, поэтому и нужна другая секция. Вот, кстати, тот вопрос
  18. В этой теме где-то раньше задавали вопрос о том, как отслеживать попадание любого NPC в рестриктор. Есть один способ сделать это без перебора всех NPC с последующей проверкой на вхождение (inside). Для этого в system.ltx или любом включенном в него конфиге нужно создать секцию, содержимое которой будет совпадать с секцией [script_zone], за исключением строки script_binding. Дальше надо написать биндер, в котором обрабатываются коллбеки на вход/выход из зоны (можно подсмотреть, как это делается в xr_zones.script). Остается только одна проблема: обрабатывать эти события непосредственно в биндере не очень удобно, а подключать к этому делу логику (xr_logic) не получится, т.к. там для переключения секций нет такого условия, как вхождение любого NPC в заданную зону.
  19. При вызове метода patrol_path_make_inactual() почему-то не всегда убирается путь, то есть непосредственно после вызова и даже на следующих апдейтах метод patrol() продолжает возвращать имя того пути, который был установлен. path_completed() возвращает false. Самое интересное в том, что после вызова patrol_path_make_inactual путь заново нигде не устанавливается, то есть set_patrol_path нигде не вызывается. Что ещё можно попробовать сделать, чтобы путь обнулился?
  20. Не совсем. С одной стороны, причина была в изменениях, внесенных в скрипт респавнеров. Баг "вылечил" тем, что сделал наличие db.actor обязательным условием, что исключило слишком ранний скриптовый спавн, а именно - ДО той стадии, на которой метод on_register будет вызван для всех обЪектов, загруженных из all.spawn. С другой стороны, любой скрипт, в котором до этой стадии будет вызван скриптовый спавн какого-либо обЪекта, вернёт проявление бага.
  21. ВНИМАНИЕ! Если у вас игра ДО появления главного меню без всяких причин стала вылетать без лога, или с логом, в конце которого есть строки такого содержания попробуйте отключиться от интернета, либо любым известным вам способом заблокируйте доступ к домену под именем возможно, после этого игра заработает.
  22. Возможно это баг шестого патча, на остальных не проверял. Описание бага тут. В любом случае, скриптами on_register нигде явно не вызывается. Баг проявляется в начале загрузки игры, между стадиями "Сервер: Загрузка симуляции жизни" и "Сервер: Соединяемся". Под спойлером кусок свежего лога с использованием той правки, что в описании.
  23. Замечал нечто похожее с on_register, причем только для скриптового спавна - написал об этом баге в справочнике функций и классов. Там же выложено решение - вывод в лог записи о том, что функция вызвана второй раз и немедленное прекращение её выполнения. P.S. Попробуй выводить не id объекта, а его имя. Предполагаю, что там не будет имен предметов, которые создаются через all.spawn.
  24. Классы и функции, используемые для оффлайн передвижения Классы: Как это всё работает: Каждому NPC соответствует свой объект класса CALifeMonsterBrain (или наследуемого от него CALifeHumanBrain), который можно получить так: local brain = se_obj:brain() где se_obj - серверный объект NPC. Вызов brain:can_choose_alife_tasks(true/false) включает или отключает автоматический выбор точки, в которую NPC пойдёт (подробности ниже). Далее, можно получить объект класса CALifeMonsterMovementManager, соответствующий данному серверному объекту: local movement_mgr = brain:movement() По непонятным причинам вызов movement_mgr:start_type() приводит к зависанию. Сам по себе этот объект не позволяет управлять передвижением NPC, зато с помощью него можно получить объекты классов CALifeMonsterPatrolPathManager и CALifeMonsterDetailPathManager: local patrol_mgr = movement_mgr:patrol() local detail_mgr = movement_mgr:detail() Класс CALifeMonsterPatrolPathManager позволяет задать имя пути методом path(path_name), а также точку, с которой начинать движение по пути, вызовом start_vertex_index(vertex_index). Однако это ни на что не влияет, т.к. тип пути и другие параметры невозможно установить из-за того, что нижеперечисленные методы (не важно, с аргументами или без) просто зависают при вызове и вызывают вылеты "Error in error handling" или "C stack overflow": Реально же управлять оффлайн-передвижением позволяют классы CALifeMonsterDetailPathManager и CALifeSmartTerrainTask. Чтобы послать NPC в заданную точку пути, необходимо сначала создать объект класса CALifeSmartTerrainTask: local my_task = CALifeSmartTerrainTask(path_name, point_index) где path_name - имя пути, point_index - индекс точки пути. В ТЧ объект этого класса не может быть создан для произвольной точки, не привязанной к какому-либо пути. Чтобы узнать положение уже созданного объекта CALifeSmartTerrainTask в пространстве, можно использовать значения, возвращаемые при вызове level_vertex_id(), position() и game_vertex_id(). Далее нужно установить эту точку для NPC в качестве целевой. Это делается методом target() класса CALifeMonsterDetailPathManager: detail_mgr:target(my_task) В lua_help описаны ещё 2 варианта использования этого метода: Если в первом требуется передать game_vertex_id, level_vertex_id и координаты точки, то непонятно, в каком порядке передавать game_vertex_id и level_vertex_id. В каком бы порядке я их не передавал, игра вываливалась c ошибкой "There is no proper graph point neighbour". Во втором непонятно, что за число туда передавать. Возможно это game_vertex_id, я не проверял. Далее, метод completed() возвращает true, если NPC дошёл до точки, иначе false. А вот с методом failed() не совсем понятно. Нередко он возвращает true тогда, когда completed() тоже возвращает true. Метод actual() возвращает true, если completed() и failed() возвращают false. Метод speed () недоступен из-за опечатки, т.к. в конце его имени стоит символ табуляции. Судя по названию, должен возвращать скорость передвижения. Теперь подробности о том, как всё это работает. Оффлайн-передвижение в оригинальной игре завязано на smart_terrain (или просто "смарты") - объектах класса se_smart_terrain, наследуемого от cse_alife_smart_zone. У каждого серверного объекта NPC (людей или зверюшек) есть свойство m_smart_terrain_id - id смарта, в котором прописан NPC. У каждого смарта есть метод task(), который возвращает объект класса CALifeSmartTerrainTask. Обновление оффлайн-передвижения происходит при вызове метода se_obj:brain():update(), где se_obj - серверный объект NPC. Также он вызывается движком при вызове se_obj:update(). Стоит отметить, что se_obj:update() периодически вызывается движком для всех NPC, а вот вызывать его искусственно (например, из биндера клиентского объекта) не стоит, будут ошибки "There is no proper graph point neighbour". Алгоритм его работы примерно таков: Вот вроде бы и всё. Непонятно, зачем разрабы оставили этот алгоритм в самом движке, когда проще было бы делать всё вышеописанное скриптами. В ТЧ в оригинальной игре автовыбор смартов всегда включен, поэтому если вам нужно послать NPC в какую-то заданную точку (например, перевести через уровень), то автовыбор надо отключать, чтобы не возиться с созданием временных smart_terrain.

AMK-Team.ru

×
×
  • Создать...